From 17a5bfec3e8f4e197d8069e97603b38505fff69b Mon Sep 17 00:00:00 2001 From: Guillaume Le Biller Date: Tue, 15 Feb 2022 14:51:29 +0100 Subject: [PATCH] Build multi-arch images (#693) * Build multi-arch images * Reduce CPU requirements for jenkins instances in e2e tests * Bump Jenkins LTS & plugins versions --- Dockerfile | 4 +- Makefile | 56 ++++++++++++-------- api/v1alpha2/jenkins_types.go | 18 +++---- chart/jenkins-operator/crds/jenkins-crd.yaml | 6 +-- chart/jenkins-operator/values.yaml | 22 ++++---- config/crd/bases/jenkins.io_jenkins.yaml | 6 +-- pkg/constants/constants.go | 2 +- pkg/plugins/base_plugins.go | 14 ++--- test/e2e/configuration_test.go | 12 ++++- test/e2e/jenkins_test.go | 2 +- test/e2e/restorebackup_test.go | 2 +- test/e2e/test_utility.go | 4 +- test/helm/helm_test.go | 2 +- 13 files changed, 86 insertions(+), 64 deletions(-) diff --git a/Dockerfile b/Dockerfile index ff840ea4..236f85b5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,8 @@ ARG GO_VERSION # Build the manager binary FROM golang:$GO_VERSION as builder ARG CTIMEVAR +ARG TARGETOS +ARG TARGETARCH WORKDIR /workspace # Copy the Go Modules manifests @@ -21,7 +23,7 @@ COPY version/ version/ COPY main.go main.go # Build -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -ldflags "-w $CTIMEVAR" -o manager main.go +RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH GO111MODULE=on go build -ldflags "-w $CTIMEVAR" -o manager main.go # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details diff --git a/Makefile b/Makefile index 84e653b6..e3d97e6e 100644 --- a/Makefile +++ b/Makefile @@ -95,9 +95,9 @@ e2e: deepcopy-gen manifests ## Runs e2e tests, you can use EXTRA_ARGS -jenkins-api-hostname=$(JENKINS_API_HOSTNAME) -jenkins-api-port=$(JENKINS_API_PORT) -jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) $(E2E_TEST_ARGS) .PHONY: helm-e2e -IMAGE_NAME := $(DOCKER_REGISTRY):$(GITCOMMIT) +IMAGE_NAME := $(DOCKER_REGISTRY):$(GITCOMMIT)-amd64 -helm-e2e: helm container-runtime-build ## Runs helm e2e tests, you can use EXTRA_ARGS +helm-e2e: helm container-runtime-build-amd64 ## Runs helm e2e tests, you can use EXTRA_ARGS @echo "+ $@" RUNNING_TESTS=1 go test -parallel=1 "./test/helm/" -ginkgo.v -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" -image-name=$(IMAGE_NAME) $(E2E_TEST_ARGS) @@ -207,46 +207,56 @@ endif container-runtime-login: ## Log in into the Docker repository @echo "+ $@" -.PHONY: container-runtime-build -container-runtime-build: check-env deepcopy-gen ## Build the container +.PHONY: container-runtime-build-% +container-runtime-build-%: ## Build the container @echo "+ $@" - $(CONTAINER_RUNTIME_COMMAND) build \ - --build-arg GO_VERSION=$(GO_VERSION) \ - --build-arg CTIMEVAR="$(CTIMEVAR)" \ - -t $(DOCKER_REGISTRY):$(GITCOMMIT) . \ - --file Dockerfile $(CONTAINER_RUNTIME_EXTRA_ARGS) + $(CONTAINER_RUNTIME_COMMAND) buildx build \ + --output=type=docker --platform linux/$* \ + --build-arg GO_VERSION=$(GO_VERSION) \ + --build-arg CTIMEVAR="$(CTIMEVAR)" \ + --tag $(DOCKER_REGISTRY):$(GITCOMMIT)-$* . \ + --file Dockerfile $(CONTAINER_RUNTIME_EXTRA_ARGS) + +.PHONY: container-runtime-build +container-runtime-build: check-env deepcopy-gen container-runtime-build-amd64 container-runtime-build-arm64 .PHONY: container-runtime-images container-runtime-images: ## List all local containers @echo "+ $@" $(CONTAINER_RUNTIME_COMMAND) images $(CONTAINER_RUNTIME_EXTRA_ARGS) +## Parameter is version +define container-runtime-push-command +$(CONTAINER_RUNTIME_COMMAND) buildx build \ + --output=type=registry --platform linux/amd64,linux/arm64 \ + --build-arg GO_VERSION=$(GO_VERSION) \ + --build-arg CTIMEVAR="$(CTIMEVAR)" \ + --tag $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(1) . \ + --file Dockerfile $(CONTAINER_RUNTIME_EXTRA_ARGS) +endef + .PHONY: container-runtime-push -container-runtime-push: ## Push the container +container-runtime-push: check-env deepcopy-gen ## Push the container @echo "+ $@" - $(CONTAINER_RUNTIME_COMMAND) tag $(DOCKER_REGISTRY):$(GITCOMMIT) $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(BUILD_TAG) $(CONTAINER_RUNTIME_EXTRA_ARGS) - $(CONTAINER_RUNTIME_COMMAND) push $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(BUILD_TAG) $(CONTAINER_RUNTIME_EXTRA_ARGS) + $(call container-runtime-push-command,$(BUILD_TAG)) .PHONY: container-runtime-snapshot-push -container-runtime-snapshot-push: container-runtime-build +container-runtime-snapshot-push: check-env deepcopy-gen @echo "+ $@" - $(CONTAINER_RUNTIME_COMMAND) tag $(DOCKER_REGISTRY):$(GITCOMMIT) $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(GITCOMMIT) $(CONTAINER_RUNTIME_EXTRA_ARGS) - $(CONTAINER_RUNTIME_COMMAND) push $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(GITCOMMIT) $(CONTAINER_RUNTIME_EXTRA_ARGS) + $(call container-runtime-push-command,$(GITCOMMIT)) .PHONY: container-runtime-release-version -container-runtime-release-version: ## Release image with version tag (in addition to build tag) +container-runtime-release-version: check-env deepcopy-gen ## Release image with version tag (in addition to build tag) @echo "+ $@" - $(CONTAINER_RUNTIME_COMMAND) tag $(DOCKER_REGISTRY):$(GITCOMMIT) $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(VERSION_TAG) $(CONTAINER_RUNTIME_EXTRA_ARGS) - $(CONTAINER_RUNTIME_COMMAND) push $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(VERSION_TAG) $(CONTAINER_RUNTIME_EXTRA_ARGS) + $(call container-runtime-push-command,$(VERSION_TAG)) .PHONY: container-runtime-release-latest -container-runtime-release-latest: ## Release image with latest tags (in addition to build tag) +container-runtime-release-latest: check-env deepcopy-gen ## Release image with latest tags (in addition to build tag) @echo "+ $@" - $(CONTAINER_RUNTIME_COMMAND) tag $(DOCKER_REGISTRY):$(GITCOMMIT) $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(LATEST_TAG) $(CONTAINER_RUNTIME_EXTRA_ARGS) - $(CONTAINER_RUNTIME_COMMAND) push $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(LATEST_TAG) $(CONTAINER_RUNTIME_EXTRA_ARGS) + $(call container-runtime-push-command,$(LATEST_TAG)) .PHONY: container-runtime-release -container-runtime-release: container-runtime-build container-runtime-release-version container-runtime-release-latest ## Release image with version and latest tags (in addition to build tag) +container-runtime-release: container-runtime-release-version container-runtime-release-latest ## Release image with version and latest tags (in addition to build tag) @echo "+ $@" # if this session isn't interactive, then we don't want to allocate a @@ -528,6 +538,6 @@ uninstall-cert-manager: minikube-start kubectl delete -f https://github.com/jetstack/cert-manager/releases/download/v1.5.1/cert-manager.yaml # Deploy the operator locally along with webhook using helm charts -deploy-webhook: container-runtime-build +deploy-webhook: container-runtime-build-amd64 @echo "+ $@" bin/helm upgrade jenkins chart/jenkins-operator --install --set-string operator.image=${IMAGE_NAME} --set webhook.enabled=true --set jenkins.enabled=false diff --git a/api/v1alpha2/jenkins_types.go b/api/v1alpha2/jenkins_types.go index 28598ef6..92e4b038 100644 --- a/api/v1alpha2/jenkins_types.go +++ b/api/v1alpha2/jenkins_types.go @@ -346,20 +346,20 @@ type JenkinsMaster struct { // BasePlugins contains plugins required by operator // +optional // Defaults to : - // - name: kubernetes - // version: "1.30.11" - // - name: workflow-job - // version: "1145.v7f2433caa07f" - // - name: workflow-aggregator - // version: "2.6" + // - name: configuration-as-code + // version: "1346.ve8cfa_3473c94" // - name: git - // version: "4.10.0" + // version: "4.10.3" // - name: job-dsl // version: "1.78.1" - // - name: configuration-as-code - // version: "1.55" + // - name: kubernetes + // version: "1.31.3" // - name: kubernetes-credentials-provider // version: "0.20" + // - name: workflow-aggregator + // version: "2.6" + // - name: workflow-job + // version: "1145.v7f2433caa07f" BasePlugins []Plugin `json:"basePlugins,omitempty"` // Plugins contains plugins required by user diff --git a/chart/jenkins-operator/crds/jenkins-crd.yaml b/chart/jenkins-operator/crds/jenkins-crd.yaml index cad76ae5..33b373fc 100644 --- a/chart/jenkins-operator/crds/jenkins-crd.yaml +++ b/chart/jenkins-operator/crds/jenkins-crd.yaml @@ -157,10 +157,10 @@ spec: type: object basePlugins: description: 'BasePlugins contains plugins required by operator - Defaults to : - name: kubernetes version: "1.30.11" - name: + Defaults to : - name: kubernetes version: "1.31.3" - name: workflow-job version: "1145.v7f2433caa07f" - name: workflow-aggregator version: - "2.6" - name: git version: "4.10.0" - name: job-dsl version: - "1.78.1" - name: configuration-as-code version: "1.55" - name: + "2.6" - name: git version: "4.10.3" - name: job-dsl version: + "1.78.1" - name: configuration-as-code version: "1346.ve8cfa_3473c94" - name: kubernetes-credentials-provider version: "0.20"' items: description: Plugin defines Jenkins plugin. diff --git a/chart/jenkins-operator/values.yaml b/chart/jenkins-operator/values.yaml index 7cce7198..cf95f245 100644 --- a/chart/jenkins-operator/values.yaml +++ b/chart/jenkins-operator/values.yaml @@ -30,7 +30,7 @@ jenkins: # image is the name (and tag) of the Jenkins instance # Default: jenkins/jenkins:lts # It's recommended to use LTS (tag: "lts") version - image: jenkins/jenkins:2.319.1-lts-alpine + image: jenkins/jenkins:2.319.3-lts # env contains jenkins container environment variables env: [] @@ -72,20 +72,20 @@ jenkins: # Example: # # basePlugins: - # - name: kubernetes - # version: 1.30.11 - # - name: workflow-job - # version: "1145.v7f2433caa07f" - # - name: workflow-aggregator - # version: "2.6" + # - name: configuration-as-code + # version: "1346.ve8cfa_3473c94" # - name: git - # version: 4.10.0 + # version: 4.10.3 # - name: job-dsl # version: "1.78.1" - # - name: configuration-as-code - # version: "1.55" + # - name: kubernetes + # version: 1.31.3 # - name: kubernetes-credentials-provider # version: 0.20 + # - name: workflow-aggregator + # version: "2.6" + # - name: workflow-job + # version: "1145.v7f2433caa07f" basePlugins: [] # plugins are plugins required by the user @@ -118,7 +118,7 @@ jenkins: cpu: 1000m memory: 3Gi requests: - cpu: 1 + cpu: 250m memory: 500Mi # volumes used by Jenkins diff --git a/config/crd/bases/jenkins.io_jenkins.yaml b/config/crd/bases/jenkins.io_jenkins.yaml index cad76ae5..33b373fc 100644 --- a/config/crd/bases/jenkins.io_jenkins.yaml +++ b/config/crd/bases/jenkins.io_jenkins.yaml @@ -157,10 +157,10 @@ spec: type: object basePlugins: description: 'BasePlugins contains plugins required by operator - Defaults to : - name: kubernetes version: "1.30.11" - name: + Defaults to : - name: kubernetes version: "1.31.3" - name: workflow-job version: "1145.v7f2433caa07f" - name: workflow-aggregator version: - "2.6" - name: git version: "4.10.0" - name: job-dsl version: - "1.78.1" - name: configuration-as-code version: "1.55" - name: + "2.6" - name: git version: "4.10.3" - name: job-dsl version: + "1.78.1" - name: configuration-as-code version: "1346.ve8cfa_3473c94" - name: kubernetes-credentials-provider version: "0.20"' items: description: Plugin defines Jenkins plugin. diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index a4387e2c..b2d795d8 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -8,7 +8,7 @@ const ( // SeedJobSuffix is a suffix added for all seed jobs SeedJobSuffix = "job-dsl-seed" // DefaultJenkinsMasterImage is the default Jenkins master docker image - DefaultJenkinsMasterImage = "jenkins/jenkins:2.303.2-lts-alpine" + DefaultJenkinsMasterImage = "jenkins/jenkins:2.319.3-lts" // DefaultHTTPPortInt32 is the default Jenkins HTTP port DefaultHTTPPortInt32 = int32(8080) // DefaultSlavePortInt32 is the default Jenkins port for slaves diff --git a/pkg/plugins/base_plugins.go b/pkg/plugins/base_plugins.go index dd690837..66d719f4 100644 --- a/pkg/plugins/base_plugins.go +++ b/pkg/plugins/base_plugins.go @@ -1,24 +1,24 @@ package plugins const ( - configurationAsCodePlugin = "configuration-as-code:1.55" - gitPlugin = "git:4.10.0" + configurationAsCodePlugin = "configuration-as-code:1346.ve8cfa_3473c94" + gitPlugin = "git:4.10.3" jobDslPlugin = "job-dsl:1.78.1" + kubernetesPlugin = "kubernetes:1.31.3" kubernetesCredentialsProviderPlugin = "kubernetes-credentials-provider:0.20" - kubernetesPlugin = "kubernetes:1.30.11" workflowAggregatorPlugin = "workflow-aggregator:2.6" workflowJobPlugin = "workflow-job:1145.v7f2433caa07f" ) // basePluginsList contains plugins to install by operator. var basePluginsList = []Plugin{ - Must(New(kubernetesPlugin)), - Must(New(workflowJobPlugin)), - Must(New(workflowAggregatorPlugin)), + Must(New(configurationAsCodePlugin)), Must(New(gitPlugin)), Must(New(jobDslPlugin)), - Must(New(configurationAsCodePlugin)), + Must(New(kubernetesPlugin)), Must(New(kubernetesCredentialsProviderPlugin)), + Must(New(workflowJobPlugin)), + Must(New(workflowAggregatorPlugin)), } // BasePlugins returns list of plugins to install by operator. diff --git a/test/e2e/configuration_test.go b/test/e2e/configuration_test.go index 509a2ca0..daed1ebb 100644 --- a/test/e2e/configuration_test.go +++ b/test/e2e/configuration_test.go @@ -23,6 +23,16 @@ import ( const e2e = "e2e" +var expectedBasePluginsList = []plugins.Plugin{ + plugins.Must(plugins.New("configuration-as-code:1346.ve8cfa_3473c94")), + plugins.Must(plugins.New("git:4.10.3")), + plugins.Must(plugins.New("kubernetes:1.31.3")), + plugins.Must(plugins.New("kubernetes-credentials-provider:0.20")), + plugins.Must(plugins.New("job-dsl:1.78.1")), + plugins.Must(plugins.New("workflow-aggregator:2.6")), + plugins.Must(plugins.New("workflow-job:1145.v7f2433caa07f")), +} + func createUserConfigurationSecret(namespace string, stringData map[string]string) { By("creating user configuration secret") @@ -179,7 +189,7 @@ func verifyPlugins(jenkinsClient jenkinsclient.Jenkins, jenkins *v1alpha2.Jenkin installedPlugins, err := jenkinsClient.GetPlugins(1) Expect(err).NotTo(HaveOccurred()) - for _, basePlugin := range plugins.BasePlugins() { + for _, basePlugin := range expectedBasePluginsList { if found, ok := isPluginValid(installedPlugins, basePlugin); !ok { Fail(fmt.Sprintf("Invalid plugin '%s', actual '%+v'", basePlugin, found)) } diff --git a/test/e2e/jenkins_test.go b/test/e2e/jenkins_test.go index 972e0c9b..4d461b56 100644 --- a/test/e2e/jenkins_test.go +++ b/test/e2e/jenkins_test.go @@ -104,7 +104,7 @@ func createJenkinsCRSafeRestart(name, namespace string, seedJob *[]v1alpha2.Seed }, Resources: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceCPU: resource.MustParse("250m"), corev1.ResourceMemory: resource.MustParse("500Mi"), }, Limits: corev1.ResourceList{ diff --git a/test/e2e/restorebackup_test.go b/test/e2e/restorebackup_test.go index 9d710ace..515d591b 100644 --- a/test/e2e/restorebackup_test.go +++ b/test/e2e/restorebackup_test.go @@ -146,7 +146,7 @@ func createJenkinsWithBackupAndRestoreConfigured(name, namespace string) *v1alph }, Resources: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceCPU: resource.MustParse("250m"), corev1.ResourceMemory: resource.MustParse("500Mi"), }, Limits: corev1.ResourceList{ diff --git a/test/e2e/test_utility.go b/test/e2e/test_utility.go index 949da22b..846a25f9 100644 --- a/test/e2e/test_utility.go +++ b/test/e2e/test_utility.go @@ -21,7 +21,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/envtest" ) -const JenkinsTestImage = "jenkins/jenkins:2.319.1-lts" +const JenkinsTestImage = "jenkins/jenkins:2.319.3-lts" var ( Cfg *rest.Config @@ -126,7 +126,7 @@ func RenderJenkinsCR(name, namespace string, seedJob *[]v1alpha2.SeedJob, groovy }, Resources: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceCPU: resource.MustParse("250m"), corev1.ResourceMemory: resource.MustParse("500Mi"), }, Limits: corev1.ResourceList{ diff --git a/test/helm/helm_test.go b/test/helm/helm_test.go index bfc983d0..e6d455b0 100644 --- a/test/helm/helm_test.go +++ b/test/helm/helm_test.go @@ -47,7 +47,7 @@ var _ = Describe("Jenkins Controller", func() { cmd := exec.Command("../../bin/helm", "upgrade", "jenkins", "../../chart/jenkins-operator", "--namespace", namespace.Name, "--debug", "--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace.Name), - "--set-string", fmt.Sprintf("jenkins.image=%s", "jenkins/jenkins:2.303.2-lts"), + "--set-string", fmt.Sprintf("jenkins.image=%s", "jenkins/jenkins:2.319.3-lts"), "--set-string", fmt.Sprintf("operator.image=%s", *imageName), "--install") output, err := cmd.CombinedOutput() Expect(err).NotTo(HaveOccurred(), string(output))