Skip to content

Commit

Permalink
Install operator/base image according to the target architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
tdiesler committed Mar 7, 2024
1 parent 1f51a53 commit 853be0a
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 42 deletions.
4 changes: 3 additions & 1 deletion build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

FROM eclipse-temurin:17-jdk as base

ARG IMAGE_ARCH

ARG MAVEN_DEFAULT_VERSION="3.8.6"
ARG MAVEN_HOME="/usr/share/maven"
ARG MAVEN_DIST_URL="https://archive.apache.org/dist/maven/maven-3/${MAVEN_DEFAULT_VERSION}/binaries/apache-maven-${MAVEN_DEFAULT_VERSION}-bin.zip"
Expand Down Expand Up @@ -59,7 +61,7 @@ RUN chgrp -R 0 ${MVN_REPO} \

USER 1001:0

ADD build/_output/bin/kamel /usr/local/bin/kamel
ADD build/_output/bin/kamel-${IMAGE_ARCH} /usr/local/bin/kamel

FROM golang:1.20 as go

Expand Down
52 changes: 52 additions & 0 deletions pkg/util/kubernetes/node.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kubernetes

import (
"context"
"github.com/apache/camel-k/v2/pkg/client"
"github.com/apache/camel-k/v2/pkg/util/sets"
"github.com/apache/camel-k/v2/pkg/util/slice"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// NodeListLookup lookup the list of nodes in the cluster
func NodeListLookup(ctx context.Context, c client.Client) ([]corev1.Node, error) {
nodes, err := c.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
if err != nil {
return nil, err
}
return nodes.Items, err
}

// NodeArchsLookup lookup the set of node architectures in the cluster
func NodeArchsLookup(ctx context.Context, c client.Client) ([]string, error) {

nodes, err := NodeListLookup(ctx, c)
if err != nil {
return nil, err
}

nodeArchs := slice.SliceMap(nodes, func(n corev1.Node) string {
return n.Status.NodeInfo.Architecture
})

archSet := sets.NewSet(nodeArchs...)
return archSet.List(), err
}
38 changes: 38 additions & 0 deletions pkg/util/kubernetes/node_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kubernetes

import (
"context"
"fmt"
"github.com/apache/camel-k/v2/pkg/client"
"github.com/stretchr/testify/assert"
"testing"
)

func TestNodeArchLookup(t *testing.T) {

c, err := client.NewClient(true)
assert.Nil(t, err)

archs, err := NodeArchLookup(context.Background(), c)

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / builder-it (Jib)

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / common-it-advanced

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / knative-test

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / non-olm

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / builder-it (Spectrum)

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / common-it

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / olm

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / yaks-test

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / upgrade

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

undefined: NodeArchLookup

Check failure on line 33 in pkg/util/kubernetes/node_test.go

View workflow job for this annotation

GitHub Actions / telemetry-it

undefined: NodeArchLookup
assert.Nil(t, err)
assert.Equal(t, 1, len(archs))

fmt.Printf("Arch: %s\n", archs[0])
}
6 changes: 4 additions & 2 deletions pkg/util/sets/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ type Set struct {
}

// NewSet creates an empty Set.
func NewSet() *Set {
return &Set{
func NewSet(items ...string) *Set {
set := &Set{
keys: make(map[string]bool),
}
set.Add(items...)
return set
}

// Union creates a Set from the union of two.
Expand Down
47 changes: 47 additions & 0 deletions pkg/util/slice/slice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package slice

// SliceFilter retain elements for which the given predicate returns true
func SliceFilter[T any](elements []T, predicate func(T) bool) []T {
var result []T
for _, e := range elements {
if predicate(e) {
result = append(result, e)
}
}
return result
}

// SliceFold folds elements into a single value determined by the given function
func SliceFold[T any, R any](elements []T, function func(T, R) R) R {
var res R
for _, e := range elements {
res = function(e, res)
}
return res
}

// SliceMap maps elements to another value according to the given function
func SliceMap[T any, R any](elements []T, function func(T) R) []R {
var mappedValues = make([]R, len(elements))
for n, e := range elements {
mappedValues[n] = function(e)
}
return mappedValues
}
48 changes: 48 additions & 0 deletions pkg/util/slice/slice_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package slice

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestSliceFilter(t *testing.T) {

input := []int{1, 2, 3, 4, 5}
was := SliceFilter(input, func(item int) bool { return item%2 == 0 })

exp := []int{2, 4}
assert.Equal(t, exp, was)
}

func TestSliceFold(t *testing.T) {

input := []int{1, 2, 3, 4, 5}
was := SliceFold(input, func(item, res int) int { return res + item })
assert.Equal(t, 15, was)
}

func TestSliceMap(t *testing.T) {

input := []int{1, 2, 3, 4, 5}
was := SliceMap(input, func(item int) int { return item * 2 })

exp := []int{2, 4, 6, 8, 10}
assert.Equal(t, exp, was)
}
66 changes: 27 additions & 39 deletions script/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ OPM_VERSION := v1.24.0
BASE_IMAGE := eclipse-temurin:17
LOCAL_REPOSITORY := /etc/maven/m2
IMAGE_NAME ?= docker.io/apache/camel-k
# Default value, change to your architecture accordingly
IMAGE_ARCH ?= amd64
# Test for arm64, fall back to amd64
PLATFORM_ARCH := $(if $(filter arm64,$(shell uname -m)),arm64,amd64)
ARCHITECTURES := amd64 arm64
#
# Situations when user wants to override
# the image name and version
Expand Down Expand Up @@ -237,9 +238,15 @@ ifeq (, $(shell command -v gotestfmt 2> /dev/null))
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
endif

# Build images without running unit tests
# NOTEST=1 make images
test: do-build
ifndef NOTEST
@echo "####### Running unit test..."
go test ./... $(COVERAGE_OPTS)
else
@echo "####### Skipping unit test..."
endif

#
# Common tests that do not require any customized operator setting. They can leverage a unique namespaced operator installation to reduce
Expand Down Expand Up @@ -350,11 +357,13 @@ test-quarkus-native-high-memory: do-build
STAGING_RUNTIME_REPO="$(STAGING_RUNTIME_REPO)" \
go test -timeout 180m -v ./e2e/native -tags=integration,high_memory $(TEST_QUARKUS_RUN) $(GOTESTFMT)

build-kamel:
@echo "####### Building kamel CLI for $(GOOS) $(IMAGE_ARCH) architecture..."
CGO_ENABLED=0 GOARCH=$(IMAGE_ARCH) go build $(GOFLAGS) -o build/_output/bin/kamel-$(IMAGE_ARCH) ./cmd/kamel/*.go
build-kamel: $(addprefix build-kamel-, $(ARCHITECTURES))
# Symbolic link to a local CLI
ln -sf build/_output/bin/kamel-$(IMAGE_ARCH) ./kamel
ln -sf build/_output/bin/kamel-$(PLATFORM_ARCH) ./kamel

build-kamel-%:
@echo "####### Building kamel CLI for $(*) architecture..."
CGO_ENABLED=0 GOARCH=$(*) go build $(GOFLAGS) -o build/_output/bin/kamel-$(*) ./cmd/kamel/*.go

build-resources:
./script/get_catalog.sh $(DEFAULT_RUNTIME_VERSION) $(STAGING_RUNTIME_REPO)
Expand Down Expand Up @@ -424,57 +433,36 @@ maven-overlay:
mkdir -p build/_maven_overlay
./script/maven_overlay.sh build/_maven_overlay

kamel-overlay:
mkdir -p build/_output/bin
ifeq ($(shell uname -s 2>/dev/null || echo Unknown),Linux)
@echo "####### Copying Linux platform arch $(IMAGE_ARCH) CLI into output build directory..."
else
@echo "####### (Re)Building a Linux platform arch $(IMAGE_ARCH) CLI "
@echo "####### Likely you're on a non Linux host, so I need to build a Linux CLI to bundle in the container image"
GOOS=linux GOARCH=$(IMAGE_ARCH) go build $(GOFLAGS) -o build/_output/bin/kamel-$(IMAGE_ARCH) ./cmd/kamel/*.go
endif
cp build/_output/bin/kamel-$(IMAGE_ARCH) build/_output/bin/kamel

TARGET_STAGE := base
ifeq ($(DEBUG_MODE),true)
TARGET_STAGE := debug
CUSTOM_IMAGE := $(CUSTOM_IMAGE)-debug
endif

DOCKER_TAG := $(CUSTOM_IMAGE):$(CUSTOM_VERSION)
ifneq ($(IMAGE_ARCH), amd64)
DOCKER_TAG := $(DOCKER_TAG)-$(IMAGE_ARCH)
endif

images: build kamel-overlay maven-overlay bundle-kamelets
package_maven_artifacts:
ifneq (,$(findstring SNAPSHOT,$(DEFAULT_RUNTIME_VERSION)))
./script/package_maven_artifacts.sh -s "$(STAGING_RUNTIME_REPO)" -d "$(CAMEL_K_RUNTIME_DIR)" $(DEFAULT_RUNTIME_VERSION)
endif
@echo "####### Building Camel K operator arch $(IMAGE_ARCH) container image..."
mkdir -p build/_maven_output
docker buildx build --target $(TARGET_STAGE) --platform=linux/$(IMAGE_ARCH) -t $(DOCKER_TAG) -f build/Dockerfile .

# Mainly used for internal CI purposes
image-push:
docker push $(CUSTOM_IMAGE):$(CUSTOM_VERSION)
images: build maven-overlay bundle-kamelets package_maven_artifacts $(addprefix image-build-, $(ARCHITECTURES))

images-all: images
make IMAGE_ARCH=arm64 images
image-build-%:
$(eval DOCKER_TAG := $(CUSTOM_IMAGE):$(CUSTOM_VERSION)-$(*))
@echo "####### Building Camel K operator arch $(*) container image..."
mkdir -p build/_maven_output
docker buildx build --target $(TARGET_STAGE) --platform=linux/$(*) --build-arg IMAGE_ARCH=$(*) -t $(DOCKER_TAG) -f build/Dockerfile --load .

images-push:
docker push $(CUSTOM_IMAGE):$(CUSTOM_VERSION)
docker push $(CUSTOM_IMAGE):$(CUSTOM_VERSION)-amd64
docker push $(CUSTOM_IMAGE):$(CUSTOM_VERSION)-arm64
docker manifest create $(CUSTOM_IMAGE):$(CUSTOM_VERSION) --amend $(CUSTOM_IMAGE):$(CUSTOM_VERSION)-amd64 --amend $(CUSTOM_IMAGE):$(CUSTOM_VERSION)-arm64
docker manifest push $(CUSTOM_IMAGE):$(CUSTOM_VERSION)

images-push-staging:
docker tag $(CUSTOM_IMAGE):$(CUSTOM_VERSION) $(STAGING_IMAGE_NAME):$(CUSTOM_VERSION)
docker tag $(CUSTOM_IMAGE):$(CUSTOM_VERSION)-amd64 $(STAGING_IMAGE_NAME):$(CUSTOM_VERSION)-amd64
docker tag $(CUSTOM_IMAGE):$(CUSTOM_VERSION)-arm64 $(STAGING_IMAGE_NAME):$(CUSTOM_VERSION)-arm64
docker push $(STAGING_IMAGE_NAME):$(CUSTOM_VERSION)
docker push $(STAGING_IMAGE_NAME):$(CUSTOM_VERSION)-amd64
docker push $(STAGING_IMAGE_NAME):$(CUSTOM_VERSION)-arm64
# TODO: we can evaluate the usage of manifest and try the following
# docker manifest create $(CUSTOM_IMAGE):$(CUSTOM_VERSION) \
# --amend $(CUSTOM_IMAGE):$(CUSTOM_VERSION)-amd64 \
# --amend $(CUSTOM_IMAGE):$(CUSTOM_VERSION)-arm64
# docker manifest push --purge $(CUSTOM_IMAGE):$(CUSTOM_VERSION)

get-image:
@echo $(CUSTOM_IMAGE)
Expand Down

0 comments on commit 853be0a

Please sign in to comment.