diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c726b0b5d..31270ced1 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ { "name": "Kubernetes - Minikube-in-Docker", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/base:bullseye", + "image": "mcr.microsoft.com/devcontainers/base:bookworm", "features": { "ghcr.io/devcontainers/features/docker-in-docker:2": { diff --git a/.github/workflows/release-backup.yaml b/.github/workflows/release-backup.yaml index 9e2a7ba40..337c263d6 100644 --- a/.github/workflows/release-backup.yaml +++ b/.github/workflows/release-backup.yaml @@ -56,6 +56,5 @@ jobs: if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' run: | git reset --hard - rm bin/sembump make -C backup/pvc docker-build make -C backup/pvc docker-release diff --git a/Makefile b/Makefile index 744d10c0a..4d6c66480 100644 --- a/Makefile +++ b/Makefile @@ -146,6 +146,7 @@ update-lts-version: ## Update the latest lts version sed -i 's|jenkins/jenkins:[0-9]\+.[0-9]\+.[0-9]\+|jenkins/jenkins:$(LATEST_LTS_VERSION)|g' chart/jenkins-operator/values.yaml sed -i 's|jenkins/jenkins:[0-9]\+.[0-9]\+.[0-9]\+|jenkins/jenkins:$(LATEST_LTS_VERSION)|g' test/e2e/test_utility.go sed -i 's|jenkins/jenkins:[0-9]\+.[0-9]\+.[0-9]\+|jenkins/jenkins:$(LATEST_LTS_VERSION)|g' test/helm/helm_test.go + sed -i 's|jenkins/jenkins:[0-9]\+.[0-9]\+.[0-9]\+|jenkins/jenkins:$(LATEST_LTS_VERSION)|g' pkg/constants/constants.go .PHONY: run run: export WATCH_NAMESPACE = $(NAMESPACE) diff --git a/api/v1alpha2/jenkins_types.go b/api/v1alpha2/jenkins_types.go index 3e380c994..6064dccfd 100644 --- a/api/v1alpha2/jenkins_types.go +++ b/api/v1alpha2/jenkins_types.go @@ -373,7 +373,8 @@ type JenkinsMaster struct { // Allow to override jenkins-plugin-cli default behavior // while downloading the plugin and dependencies // see: https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options - LatestPlugins bool `json:"latestPlugins"` + // +optional + LatestPlugins *bool `json:"latestPlugins,omitempty"` // DisableCSRFProtection allows you to toggle CSRF Protection on Jenkins DisableCSRFProtection bool `json:"disableCSRFProtection"` diff --git a/api/v1alpha2/zz_generated.deepcopy.go b/api/v1alpha2/zz_generated.deepcopy.go index cfd1b3059..35547563f 100644 --- a/api/v1alpha2/zz_generated.deepcopy.go +++ b/api/v1alpha2/zz_generated.deepcopy.go @@ -23,7 +23,7 @@ package v1alpha2 import ( corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -400,7 +400,7 @@ func (in *JenkinsSpec) DeepCopyInto(out *JenkinsSpec) { in.ConfigurationAsCode.DeepCopyInto(&out.ConfigurationAsCode) if in.Roles != nil { in, out := &in.Roles, &out.Roles - *out = make([]rbacv1.RoleRef, len(*in)) + *out = make([]v1.RoleRef, len(*in)) copy(*out, *in) } in.ServiceAccount.DeepCopyInto(&out.ServiceAccount) diff --git a/chart/jenkins-operator/crds/jenkins-crd.yaml b/chart/jenkins-operator/crds/jenkins-crd.yaml index b00bb4f47..87d407049 100644 --- a/chart/jenkins-operator/crds/jenkins-crd.yaml +++ b/chart/jenkins-operator/crds/jenkins-crd.yaml @@ -157,11 +157,11 @@ spec: type: object basePlugins: description: 'BasePlugins contains plugins required by operator - Defaults to : - name: kubernetes version: "1.31.3" - name: - workflow-job version: "1145.v7f2433caa07f" - name: workflow-aggregator version: - "2.6" - name: git version: "4.11.3" - name: job-dsl version: - "1.78.1" - name: configuration-as-code version: "1346.ve8cfa_3473c94" - name: - kubernetes-credentials-provider version: "0.20"' + Defaults to : - name: configuration-as-code version: "1625.v27444588cc3d" + - name: git version: "5.0.0" - name: job-dsl version: "1.83" + - name: kubernetes version: "3909.v1f2c633e8590" - name: kubernetes-credentials-provider + version: "1.211.vc236a_f5a_2f3c" - name: workflow-aggregator + version: "596.v8c21c963d92d" - name: workflow-job version: "1289.vd1c337fd5354"' items: description: Plugin defines Jenkins plugin. properties: @@ -1100,11 +1100,6 @@ spec: - resources type: object type: array - latestPlugins: - description: 'Allow to override jenkins-plugin-cli default behavior - while downloading the plugin and dependencies, see: - https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options' - type: boolean disableCSRFProtection: description: DisableCSRFProtection allows you to toggle CSRF Protection on Jenkins @@ -1150,6 +1145,10 @@ spec: selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' type: object + latestPlugins: + description: 'Allow to override jenkins-plugin-cli default behavior + while downloading the plugin and dependencies see: https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options' + type: boolean nodeSelector: additionalProperties: type: string @@ -3124,8 +3123,10 @@ spec: type: object type: array seedJobAgentImage: + description: SeedJobAgentImage defines the image that will be used + by the seed job agent. If not defined jenkins/inbound-agent:4.9-1 + will be used. type: string - description: 'SeedJobAgentImage defines the image that will be used by the seed job agent. If not defined jenkins/inbound-agent:4.10-3 will be used.' seedJobs: description: 'SeedJobs defines list of Jenkins Seed Job configurations More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuration#configure-seed-jobs-and-pipelines' diff --git a/config/crd/bases/jenkins.io_jenkins.yaml b/config/crd/bases/jenkins.io_jenkins.yaml index b00bb4f47..87d407049 100644 --- a/config/crd/bases/jenkins.io_jenkins.yaml +++ b/config/crd/bases/jenkins.io_jenkins.yaml @@ -157,11 +157,11 @@ spec: type: object basePlugins: description: 'BasePlugins contains plugins required by operator - Defaults to : - name: kubernetes version: "1.31.3" - name: - workflow-job version: "1145.v7f2433caa07f" - name: workflow-aggregator version: - "2.6" - name: git version: "4.11.3" - name: job-dsl version: - "1.78.1" - name: configuration-as-code version: "1346.ve8cfa_3473c94" - name: - kubernetes-credentials-provider version: "0.20"' + Defaults to : - name: configuration-as-code version: "1625.v27444588cc3d" + - name: git version: "5.0.0" - name: job-dsl version: "1.83" + - name: kubernetes version: "3909.v1f2c633e8590" - name: kubernetes-credentials-provider + version: "1.211.vc236a_f5a_2f3c" - name: workflow-aggregator + version: "596.v8c21c963d92d" - name: workflow-job version: "1289.vd1c337fd5354"' items: description: Plugin defines Jenkins plugin. properties: @@ -1100,11 +1100,6 @@ spec: - resources type: object type: array - latestPlugins: - description: 'Allow to override jenkins-plugin-cli default behavior - while downloading the plugin and dependencies, see: - https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options' - type: boolean disableCSRFProtection: description: DisableCSRFProtection allows you to toggle CSRF Protection on Jenkins @@ -1150,6 +1145,10 @@ spec: selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' type: object + latestPlugins: + description: 'Allow to override jenkins-plugin-cli default behavior + while downloading the plugin and dependencies see: https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options' + type: boolean nodeSelector: additionalProperties: type: string @@ -3124,8 +3123,10 @@ spec: type: object type: array seedJobAgentImage: + description: SeedJobAgentImage defines the image that will be used + by the seed job agent. If not defined jenkins/inbound-agent:4.9-1 + will be used. type: string - description: 'SeedJobAgentImage defines the image that will be used by the seed job agent. If not defined jenkins/inbound-agent:4.10-3 will be used.' seedJobs: description: 'SeedJobs defines list of Jenkins Seed Job configurations More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuration#configure-seed-jobs-and-pipelines' diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index dd2efda58..789349e93 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -1,9 +1,10 @@ --- apiVersion: rbac.authorization.k8s.io/v1 -kind: Role +kind: ClusterRole metadata: - name: jenkins-operator + creationTimestamp: null + name: manager-role rules: - apiGroups: - apps diff --git a/pkg/configuration/base/resources/scripts_configmap.go b/pkg/configuration/base/resources/scripts_configmap.go index 732d656e5..b60aa50b4 100644 --- a/pkg/configuration/base/resources/scripts_configmap.go +++ b/pkg/configuration/base/resources/scripts_configmap.go @@ -68,13 +68,11 @@ func buildConfigMapTypeMeta() metav1.TypeMeta { } func buildInitBashScript(jenkins *v1alpha2.Jenkins) (*string, error) { - defaultlatestPlugin := true - latestP := jenkins.Spec.Master.LatestPlugins - if !latestP { - latestP = defaultlatestPlugin + if latestP == nil { + latestP = new(bool) + *latestP = true } - data := struct { JenkinsHomePath string InitConfigurationPath string @@ -90,7 +88,7 @@ func buildInitBashScript(jenkins *v1alpha2.Jenkins) (*string, error) { UserPlugins: jenkins.Spec.Master.Plugins, InstallPluginsCommand: installPluginsCommand, JenkinsScriptsVolumePath: JenkinsScriptsVolumePath, - LatestPlugins: latestP, + LatestPlugins: *latestP, } output, err := render.Render(initBashTemplate, data) diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index b2d795d83..49c23ac4a 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.319.3-lts" + DefaultJenkinsMasterImage = "jenkins/jenkins:2.401.1-lts" // DefaultHTTPPortInt32 is the default Jenkins HTTP port DefaultHTTPPortInt32 = int32(8080) // DefaultSlavePortInt32 is the default Jenkins port for slaves diff --git a/test/bats/1-deploy.bats b/test/bats/1-deploy.bats index 911d323e6..2392293fb 100644 --- a/test/bats/1-deploy.bats +++ b/test/bats/1-deploy.bats @@ -23,6 +23,8 @@ diag() { --set jenkins.namespace=${DETIK_CLIENT_NAMESPACE} \ --set namespace=${DETIK_CLIENT_NAMESPACE} \ --set operator.image=${OPERATOR_IMAGE} \ + --set jenkins.latestPlugins=true \ + --set jenkins.backup.makeBackupBeforePodDeletion=false \ chart/jenkins-operator assert_success assert ${HELM} status default @@ -98,6 +100,19 @@ diag() { assert_success } +#bats test_tags=phase:helm +@test "1.9 Helm: check Jenkins crd" { + [[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly" + run verify "there is 1 crd named 'jenkins.jenkins.io'" + assert_success +} + @test "1.9 Helm: Clean" { + run ${HELM} uninstall default + assert_success + # Wait for the complete removal + sleep 30 + run verify "there is 0 pvc named 'jenkins backup'" + assert_success rm "chart/jenkins-operator/deploy.tmp" } diff --git a/test/bats/2-deploy-with-more-options.bats b/test/bats/2-deploy-with-more-options.bats new file mode 100644 index 000000000..a39c9ea0d --- /dev/null +++ b/test/bats/2-deploy-with-more-options.bats @@ -0,0 +1,88 @@ +setup() { + load 'test_helper' + _common_setup +} + +#bats test_tags=phase:helm +@test "2.1 Install helm chart with options" { + run ${HELM} dependency update chart/jenkins-operator + assert_success + run ${KUBECTL} label node jenkins-control-plane batstest=yep + ${HELM} status options && skip "Helm release 'options' already exists" + run ${HELM} install options \ + --set jenkins.namespace=${DETIK_CLIENT_NAMESPACE} \ + --set namespace=${DETIK_CLIENT_NAMESPACE} \ + --set operator.image=${OPERATOR_IMAGE} \ + --set jenkins.latestPlugins=true \ + --set jenkins.nodeSelector.batstest=yep \ + --set jenkins.backup.makeBackupBeforePodDeletion=false \ + chart/jenkins-operator + assert_success + assert ${HELM} status options + touch "chart/jenkins-operator/deploy.tmp" +} + +#bats test_tags=phase:helm +@test "2.2 Helm: check Jenkins operator pods status" { + [[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly" + + run verify "there is 1 deployment named 'options-jenkins-operator'" + assert_success + + run verify "there is 1 pod named 'options-jenkins-operator-'" + assert_success + + run try "at most 20 times every 10s to get pods named 'options-jenkins-operator-' and verify that '.status.containerStatuses[?(@.name==\"jenkins-operator\")].ready' is 'true'" + assert_success +} + +#bats test_tags=phase:helm +@test "2.3 Helm: check Jenkins Pod status" { + [[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly" + + run try "at most 20 times every 10s to get pods named 'jenkins-jenkins' and verify that '.status.containerStatuses[?(@.name==\"jenkins-master\")].ready' is 'true'" + assert_success + + run try "at most 20 times every 5s to get pods named 'jenkins-jenkins' and verify that '.status.containerStatuses[?(@.name==\"jenkins-master\")].ready' is 'true'" + assert_success +} + +@test "2.4 check node selector" { + [[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly" + + NODENAME=$(${KUBECTL} get pod jenkins-jenkins -o jsonpath={.spec.nodeName}) + + run ${KUBECTL} get node -l batstest=yep -o name + assert_success + assert_output "node/$NODENAME" +} + +@test "2.5 check jenkins-plugin-cli command" { + [[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly" + + run ${KUBECTL} logs -c jenkins-master jenkins-jenkins + assert_success + assert_output --partial 'jenkins-plugin-cli --verbose --latest true -f /var/lib/jenkins/base-plugins.txt' + assert_output --partial 'jenkins-plugin-cli --verbose --latest true -f /var/lib/jenkins/user-plugins.txt' +} + + +@test "2.7 check backup" { + [[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly" + sleep 120 + run ${KUBECTL} logs -l app.kubernetes.io/name=jenkins-operator --tail 10000 + assert_success + assert_output --partial "Performing backup '1'" + assert_output --partial "Backup completed '1', updating status" +} + + +@test "2. Helm: Clean" { + skip + [[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly" + + run ${HELM} uninstall options + assert_success + + rm "chart/jenkins-operator/deploy.tmp" +} diff --git a/test/helm/helm_test.go b/test/helm/helm_test.go index 58d2dfc9f..98c76b945 100644 --- a/test/helm/helm_test.go +++ b/test/helm/helm_test.go @@ -127,6 +127,7 @@ var _ = Describe("Jenkins Controller with security validator", func() { "--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace.Name), "--set-string", fmt.Sprintf("operator.image=%s", *imageName), "--set", fmt.Sprintf("webhook.enabled=%t", true), + "--set", fmt.Sprintf("jenkins.latestPlugins=%t", true), "--set", fmt.Sprintf("jenkins.enabled=%t", false), "--install") output, err := cmd.CombinedOutput() Expect(err).NotTo(HaveOccurred(), string(output))