Migrate Helm Chart to OSDK v1.3.0 (#551)

Migrate Helm Chart to OSDK v1.3.0
This commit is contained in:
SylwiaBrant 2021-04-29 13:50:06 +02:00 committed by GitHub
parent 223119b62d
commit c74606a2ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 4338 additions and 488 deletions

View File

@ -46,7 +46,10 @@ jobs:
make minikube-start MINIKUBE_DRIVER='docker' CPUS_NUMBER=2 make minikube-start MINIKUBE_DRIVER='docker' CPUS_NUMBER=2
- name: Jenkins Operator - e2e - name: Jenkins Operator - e2e
run: | run: make e2e E2E_TEST_ARGS='-ginkgo.v'
make e2e E2E_TEST_ARGS='-ginkgo.v'
#TODO Helm e2e test - name: Jenkins Operator - Helm Chart tests
run: |
make helm-lint
eval $(bin/minikube docker-env)
make helm-e2e E2E_TEST_ARGS='-ginkgo.v'

View File

@ -89,11 +89,17 @@ test: ## Runs the go tests
@RUNNING_TESTS=1 go test -tags "$(BUILDTAGS) cgo" $(PACKAGES_FOR_UNIT_TESTS) @RUNNING_TESTS=1 go test -tags "$(BUILDTAGS) cgo" $(PACKAGES_FOR_UNIT_TESTS)
.PHONY: e2e .PHONY: e2e
e2e: deepcopy-gen ## Runs e2e tests, you can use EXTRA_ARGS e2e: deepcopy-gen manifests ## Runs e2e tests, you can use EXTRA_ARGS
@echo "+ $@" @echo "+ $@"
RUNNING_TESTS=1 go test -parallel=1 "./test/e2e/" -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" \ RUNNING_TESTS=1 go test -parallel=1 "./test/e2e/" -ginkgo.v -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" \
-jenkins-api-hostname=$(JENKINS_API_HOSTNAME) -jenkins-api-port=$(JENKINS_API_PORT) -jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) $(E2E_TEST_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)
helm-e2e: helm container-runtime-build ## 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)
.PHONY: vet .PHONY: vet
vet: ## Verifies `go vet` passes vet: ## Verifies `go vet` passes
@echo "+ $@" @echo "+ $@"
@ -136,7 +142,7 @@ install: ## Installs the executable
.PHONY: run .PHONY: run
run: export WATCH_NAMESPACE = $(NAMESPACE) run: export WATCH_NAMESPACE = $(NAMESPACE)
run: export OPERATOR_NAME = $(NAME) run: export OPERATOR_NAME = $(NAME)
run: fmt vet manifests install-crds build ## Run the executable, you can use EXTRA_ARGS run: fmt vet install-crds build ## Run the executable, you can use EXTRA_ARGS
@echo "+ $@" @echo "+ $@"
ifeq ($(KUBERNETES_PROVIDER),minikube) ifeq ($(KUBERNETES_PROVIDER),minikube)
kubectl config use-context $(KUBECTL_CONTEXT) kubectl config use-context $(KUBECTL_CONTEXT)
@ -301,6 +307,18 @@ ifneq ($(KUBERNETES_PROVIDER),crc)
$(error KUBERNETES_PROVIDER not set to 'crc') $(error KUBERNETES_PROVIDER not set to 'crc')
endif endif
.PHONY: helm
HAS_HELM := $(shell which $(PROJECT_DIR)/bin/helm)
helm: ## Download helm if it's not present
@echo "+ $@"
ifndef HAS_HELM
mkdir -p $(PROJECT_DIR)/bin
curl -Lo bin/helm.tar.gz https://get.helm.sh/helm-v$(HELM_VERSION)-$(PLATFORM)-amd64.tar.gz && tar xzfv bin/helm.tar.gz -C $(PROJECT_DIR)/bin
mv $(PROJECT_DIR)/bin/$(PLATFORM)-amd64/helm $(PROJECT_DIR)/bin/helm
rm -rf $(PROJECT_DIR)/bin/$(PLATFORM)-amd64
rm -rf $(PROJECT_DIR)/bin/helm.tar.gz
endif
.PHONY: minikube .PHONY: minikube
HAS_MINIKUBE := $(shell which $(PROJECT_DIR)/bin/minikube) HAS_MINIKUBE := $(shell which $(PROJECT_DIR)/bin/minikube)
minikube: ## Download minikube if it's not present minikube: ## Download minikube if it's not present
@ -342,11 +360,13 @@ bump-version: sembump ## Bump the version in the version file. Set BUMP to [ pat
sed -i s/$(VERSION)/$(NEW_VERSION)/g README.md sed -i s/$(VERSION)/$(NEW_VERSION)/g README.md
sed -i s/$(VERSION)/$(NEW_VERSION)/g deploy/operator.yaml sed -i s/$(VERSION)/$(NEW_VERSION)/g deploy/operator.yaml
sed -i s/$(VERSION)/$(NEW_VERSION)/g deploy/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml sed -i s/$(VERSION)/$(NEW_VERSION)/g deploy/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml
cp deploy/service_account.yaml deploy/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml cp config/service_account.yaml deploy/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml
cat deploy/role.yaml >> deploy/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml cat config/rbac/leader_election_role.yaml >> config/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml
cat deploy/role_binding.yaml >> deploy/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml cat config/rbac/leader_election_role_binding.yaml >> config/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)=$(API_VERSION).yaml
cat deploy/operator.yaml >> deploy/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml cat config/rbac/role.yaml >> config/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)=$(API_VERSION).yaml
git add VERSION.txt README.md deploy/operator.yaml deploy/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml cat config/rbac/role_binding.yaml >> config/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml
cat config/manager/manager.yaml >> config/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml
git add VERSION.txt README.md config/manager/manager.yaml config/$(ALL_IN_ONE_DEPLOY_FILE_PREFIX)-$(API_VERSION).yaml
git commit -vaem "Bump version to $(NEW_VERSION)" git commit -vaem "Bump version to $(NEW_VERSION)"
@echo "Run make tag to create and push the tag for new version $(NEW_VERSION)" @echo "Run make tag to create and push the tag for new version $(NEW_VERSION)"
@ -379,19 +399,24 @@ endif
go mod vendor -v go mod vendor -v
@echo @echo
.PHONY: helm-lint
helm-lint: helm
@echo "+ $@"
bin/helm lint chart/jenkins-operator
.PHONY: helm-package .PHONY: helm-package
helm-package: helm-package: helm
@echo "+ $@" @echo "+ $@"
mkdir -p /tmp/jenkins-operator-charts mkdir -p /tmp/jenkins-operator-charts
mv chart/jenkins-operator/*.tgz /tmp/jenkins-operator-charts mv chart/jenkins-operator/*.tgz /tmp/jenkins-operator-charts
cd chart && helm package jenkins-operator cd chart && bin/helm package jenkins-operator
mv /tmp/jenkins-operator-charts/*.tgz chart/jenkins-operator/ mv /tmp/jenkins-operator-charts/*.tgz chart/jenkins-operator/
rm -rf /tmp/jenkins-operator-charts/ rm -rf /tmp/jenkins-operator-charts/
.PHONY: helm-deploy .PHONY: helm-deploy
helm-deploy: helm-package helm-deploy: helm-package
@echo "+ $@" @echo "+ $@"
helm repo index chart/ --url https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/ bin/helm repo index chart/ --url https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/
cd chart/ && mv jenkins-operator-*.tgz jenkins-operator cd chart/ && mv jenkins-operator-*.tgz jenkins-operator
# Download and build hugo extended locally if necessary # Download and build hugo extended locally if necessary
@ -418,6 +443,7 @@ FILENAME := config/all_in_one_$(API_VERSION).yaml
all-in-one-build: ## Re-generate all-in-one yaml all-in-one-build: ## Re-generate all-in-one yaml
@echo "+ $@" @echo "+ $@"
> $(FILENAME) > $(FILENAME)
cat config/service_account.yaml >> $(FILENAME)
cat config/rbac/leader_election_role.yaml >> $(FILENAME) cat config/rbac/leader_election_role.yaml >> $(FILENAME)
cat config/rbac/leader_election_role_binding.yaml >> $(FILENAME) cat config/rbac/leader_election_role_binding.yaml >> $(FILENAME)
cat config/rbac/role.yaml >> $(FILENAME) cat config/rbac/role.yaml >> $(FILENAME)

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +0,0 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: jenkinsimages.jenkins.io
spec:
group: jenkins.io
names:
kind: JenkinsImage
listKind: JenkinsImageList
plural: jenkinsimages
singular: jenkinsimage
scope: Namespaced
versions:
- name : v1alpha2
served: true
storage: true
- name : v1alpha1
served: true
storage: false

View File

@ -7,54 +7,80 @@ metadata:
name: jenkins-operator name: jenkins-operator
namespace: {{ $namespace }} namespace: {{ $namespace }}
rules: rules:
- apiGroups:
- ""
resources:
- services
- configmaps
- secrets
verbs:
- get
- create
- update
- list
- watch
- apiGroups: - apiGroups:
- apps - apps
resources: resources:
- deployments
- daemonsets - daemonsets
- deployments
- replicasets - replicasets
- statefulsets - statefulsets
verbs: verbs:
- '*' - '*'
- apiGroups: - apiGroups:
- "" - apps
- jenkins-operator
resources: resources:
- serviceaccounts - deployments/finalizers
verbs: verbs:
- get
- create
- update - update
- list
- watch
- apiGroups: - apiGroups:
- rbac.authorization.k8s.io - build.openshift.io
resources: resources:
- roles - buildconfigs
- rolebindings - builds
verbs: verbs:
- get - get
- create
- update
- list - list
- watch - watch
- apiGroups: - apiGroups:
- "" - ""
resources: resources:
- pods/portforward - configmaps
- secrets
- services
verbs: verbs:
- create - create
- get
- list
- update
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- get
- list
- patch
- watch
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- pods
- pods/exec
verbs:
- '*'
- apiGroups: - apiGroups:
- "" - ""
resources: resources:
@ -66,28 +92,41 @@ rules:
- apiGroups: - apiGroups:
- "" - ""
resources: resources:
- pods - pods/portforward
- pods/exec
verbs: verbs:
- "*" - create
- apiGroups: - apiGroups:
- "" - ""
resources: resources:
- events - serviceaccounts
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- image.openshift.io
resources:
- imagestreams
verbs: verbs:
- get - get
- watch
- list - list
- create - watch
- patch
- apiGroups: - apiGroups:
- apps - jenkins.io
resourceNames:
- jenkins-operator
resources: resources:
- deployments/finalizers - jenkins/finalizers
verbs: verbs:
- update - update
- apiGroups:
- jenkins.io
resources:
- jenkins/status
verbs:
- get
- patch
- update
- apiGroups: - apiGroups:
- jenkins.io - jenkins.io
resources: resources:
@ -95,23 +134,26 @@ rules:
verbs: verbs:
- '*' - '*'
- apiGroups: - apiGroups:
- "" - rbac.authorization.k8s.io
resources: resources:
- persistentvolumeclaims - rolebindings
- roles
verbs: verbs:
- create
- get - get
- list - list
- update
- watch - watch
- apiGroups: - apiGroups:
- "route.openshift.io" - "route.openshift.io"
resources: resources:
- routes - routes
verbs: verbs:
- create
- get - get
- list - list
- watch
- create
- update - update
- watch
- apiGroups: - apiGroups:
- "image.openshift.io" - "image.openshift.io"
resources: resources:

View File

@ -9,31 +9,41 @@ metadata:
{{- end }} {{- end }}
spec: spec:
configurationAsCode: configurationAsCode:
configurations:
{{- range .Values.jenkins.configuration.configurationAsCode }}
- name: {{ .configMapName }}
{{- end }}
{{- if .Values.jenkins.configuration.configurationAsCode }} {{- if .Values.jenkins.configuration.configurationAsCode }}
configurations:
{{ range .Values.jenkins.configuration.configurationAsCode }}
- name: {{ .configMapName }}
{{- end }}
secret: secret:
{{- if .Values.jenkins.configuration.secretRefName }} {{- if .Values.jenkins.configuration.secretRefName }}
name: {{ .Values.jenkins.configuration.secretRefName }} name: {{ .Values.jenkins.configuration.secretRefName }}
{{- else if .Values.jenkins.configuration.secretData }} {{- else if .Values.jenkins.configuration.secretData }}
name: jenkins-{{ .Values.jenkins.name }} name: jenkins-{{ .Values.jenkins.name }}
{{- end }} {{- end }}
{{- else }}
configurations: []
secret:
name: ""
{{- end }} {{- end }}
groovyScripts: groovyScripts:
configurations:
{{- range .Values.jenkins.configuration.groovyScripts }}
- name: {{ .configMapName }}
{{- end }}
{{- if .Values.jenkins.configuration.groovyScripts }} {{- if .Values.jenkins.configuration.groovyScripts }}
configurations:
{{- range .Values.jenkins.configuration.groovyScripts }}
- name: {{ .configMapName }}
{{- end }}
secret: secret:
{{- if .Values.jenkins.configuration.secretRefName }} {{- if .Values.jenkins.configuration.secretRefName }}
name: {{ .Values.jenkins.configuration.secretRefName }} name: {{ .Values.jenkins.configuration.secretRefName }}
{{- else if .Values.jenkins.configuration.secretData }} {{- else if .Values.jenkins.configuration.secretData }}
name: jenkins-{{ .Values.jenkins.name }} name: jenkins-{{ .Values.jenkins.name }}
{{- end }} {{- end }}
{{- else }}
configurations: []
secret:
name: ""
{{- end }} {{- end }}
jenkinsAPISettings:
authorizationStrategy: {{ .Values.jenkins.authorizationStrategy }}
{{- if .Values.jenkins.backup.enabled }} {{- if .Values.jenkins.backup.enabled }}
backup: backup:
containerName: {{ .Values.jenkins.backup.containerName }} containerName: {{ .Values.jenkins.backup.containerName }}
@ -84,7 +94,11 @@ spec:
{{- with .Values.jenkins.plugins }} {{- with .Values.jenkins.plugins }}
plugins: {{ toYaml . | nindent 4 }} plugins: {{ toYaml . | nindent 4 }}
{{- end }} {{- end }}
priorityClassName: {{ .Values.jenkins.priorityClassName }} {{- if .Values.jenkins.priorityClassName }}
priorityClassName: {{- .Values.jenkins.priorityClassName }}
{{- else }}
priorityClassName: ""
{{- end }}
disableCSRFProtection: {{ .Values.jenkins.disableCSRFProtection }} disableCSRFProtection: {{ .Values.jenkins.disableCSRFProtection }}
containers: containers:
- name: jenkins-master - name: jenkins-master
@ -112,6 +126,9 @@ spec:
- name: {{ .Values.jenkins.backup.containerName }} - name: {{ .Values.jenkins.backup.containerName }}
image: {{ .Values.jenkins.backup.image }} image: {{ .Values.jenkins.backup.image }}
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
{{- with .Values.jenkins.backup.resources }}
resources: {{ toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.jenkins.backup.env }} {{- with .Values.jenkins.backup.env }}
env: {{- toYaml . | nindent 8 }} env: {{- toYaml . | nindent 8 }}
{{- end }} {{- end }}

View File

@ -0,0 +1,28 @@
---
# permissions to do leader election.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: leader-election-role
rules:
- apiGroups:
- ""
- coordination.k8s.io
resources:
- configmaps
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch

View File

@ -0,0 +1,12 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: leader-election-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: leader-election-role
subjects:
- kind: ServiceAccount
name: jenkins-operator

View File

@ -30,7 +30,7 @@ spec:
containerPort: 80 containerPort: 80
protocol: TCP protocol: TCP
command: command:
- jenkins-operator - /manager
args: [] args: []
env: env:
- name: WATCH_NAMESPACE - name: WATCH_NAMESPACE

View File

@ -63,7 +63,7 @@ jenkins:
# #
# basePlugins: # basePlugins:
# - name: kubernetes # - name: kubernetes
# version: 1.28.6 # version: 1.29.2
# - name: workflow-job # - name: workflow-job
# version: "2.40" # version: "2.40"
# - name: workflow-aggregator # - name: workflow-aggregator
@ -136,6 +136,9 @@ jenkins:
# volumeMounts are mounts for Jenkins pod # volumeMounts are mounts for Jenkins pod
volumeMounts: [] volumeMounts: []
# defines authorization strategy of the operator for the Jenkins API
authorizationStrategy: createUser
# securityContext for pod # securityContext for pod
securityContext: securityContext:
runAsUser: 1000 runAsUser: 1000
@ -216,6 +219,15 @@ jenkins:
# See https://kubernetes.io/docs/concepts/storage/persistent-volumes/#class-1 for more details # See https://kubernetes.io/docs/concepts/storage/persistent-volumes/#class-1 for more details
className: "" className: ""
# resources used by backup container
resources:
limits:
cpu: 1500m
memory: 1Gi
requests:
cpu: 100m
memory: 256Mi
# env contains container environment variables # env contains container environment variables
# PVC backup provider handles these variables: # PVC backup provider handles these variables:
# BACKUP_DIR - path for storing backup files (default: "/backup") # BACKUP_DIR - path for storing backup files (default: "/backup")

View File

@ -1,4 +1,9 @@
--- ---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-operator
---
# permissions to do leader election. # permissions to do leader election.
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: Role kind: Role
@ -37,45 +42,95 @@ roleRef:
name: leader-election-role name: leader-election-role
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: default name: jenkins-operator
namespace: default
--- ---
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole kind: Role
metadata: metadata:
creationTimestamp: null creationTimestamp: null
name: manager-role name: jenkins-operator
rules: rules:
- apiGroups:
- ""
resources:
- services
- configmaps
- secrets
- serviceaccounts
verbs:
- get
- create
- update
- list
- watch
- apiGroups: - apiGroups:
- apps - apps
resources: resources:
- deployments
- daemonsets - daemonsets
- deployments
- replicasets - replicasets
- statefulsets - statefulsets
verbs: verbs:
- '*' - '*'
- apiGroups: - apiGroups:
- rbac.authorization.k8s.io - apps
- jenkins-operator
resources: resources:
- roles - deployments/finalizers
- rolebindings verbs:
- update
- apiGroups:
- build.openshift.io
resources:
- buildconfigs
- builds
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- secrets
- services
verbs: verbs:
- create - create
- get
- list
- update - update
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- get
- list
- patch
- watch
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- pods
- pods/exec
verbs:
- '*'
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- list - list
- watch - watch
- apiGroups: - apiGroups:
@ -83,100 +138,100 @@ rules:
resources: resources:
- pods/portforward - pods/portforward
verbs: verbs:
- create - create
- apiGroups: - apiGroups:
- "" - ""
resources: resources:
- pods/log - serviceaccounts
verbs: verbs:
- get - create
- list - get
- watch - list
- update
- watch
- apiGroups: - apiGroups:
- "" - image.openshift.io
resources: resources:
- pods - imagestreams
- pods/exec
verbs: verbs:
- "*" - get
- list
- watch
- apiGroups: - apiGroups:
- "" - jenkins.io
resources: resources:
- events - jenkins/finalizers
verbs: verbs:
- get - update
- watch
- list
- create
- patch
- apiGroups: - apiGroups:
- apps - jenkins.io
resourceNames:
- jenkins-operator
resources: resources:
- deployments/finalizers - jenkins/status
verbs: verbs:
- update - get
- patch
- update
- apiGroups: - apiGroups:
- jenkins.io - jenkins.io
resources: resources:
- '*' - '*'
verbs: verbs:
- '*' - '*'
- apiGroups: - apiGroups:
- "" - rbac.authorization.k8s.io
resources: resources:
- persistentvolumeclaims - rolebindings
- roles
verbs: verbs:
- get - create
- list - get
- watch - list
- update
- watch
- apiGroups: - apiGroups:
- "route.openshift.io" - "route.openshift.io"
resources: resources:
- routes - routes
verbs: verbs:
- get - create
- list - get
- watch - list
- create - update
- update - watch
- apiGroups: - apiGroups:
- "image.openshift.io" - "image.openshift.io"
resources: resources:
- imagestreams - imagestreams
verbs: verbs:
- get - get
- list - list
- watch - watch
- apiGroups: - apiGroups:
- "build.openshift.io" - "build.openshift.io"
resources: resources:
- builds - builds
- buildconfigs - buildconfigs
verbs: verbs:
- get - get
- list - list
- watch - watch
--- ---
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding kind: RoleBinding
metadata: metadata:
name: manager-rolebinding name: jenkins-operator
roleRef: roleRef:
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io
kind: ClusterRole kind: Role
name: manager-role name: jenkins-operator
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: default name: jenkins-operator
namespace: default
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: jenkins-operator name: jenkins-operator
namespace: default
labels: labels:
control-plane: controller-manager control-plane: controller-manager
spec: spec:
@ -189,6 +244,7 @@ spec:
labels: labels:
control-plane: controller-manager control-plane: controller-manager
spec: spec:
serviceAccountName: jenkins-operator
securityContext: securityContext:
runAsUser: 65532 runAsUser: 65532
containers: containers:

View File

@ -16,6 +16,7 @@ spec:
labels: labels:
control-plane: controller-manager control-plane: controller-manager
spec: spec:
serviceAccountName: jenkins-operator
securityContext: securityContext:
runAsUser: 65532 runAsUser: 65532
containers: containers:

View File

@ -1,119 +1,172 @@
--- ---
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole kind: Role
metadata: metadata:
creationTimestamp: null creationTimestamp: null
name: manager-role name: jenkins-operator
rules: rules:
- apiGroups: - apiGroups:
- "" - apps
resources: resources:
- services - daemonsets
- configmaps - deployments
- secrets - replicasets
- serviceaccounts - statefulsets
verbs: verbs:
- get - '*'
- create - apiGroups:
- update - apps
- list - jenkins-operator
- watch resources:
- apiGroups: - deployments/finalizers
- apps verbs:
resources: - update
- deployments - apiGroups:
- daemonsets - build.openshift.io
- replicasets resources:
- statefulsets - buildconfigs
verbs: - builds
- '*' verbs:
- apiGroups: - get
- rbac.authorization.k8s.io - list
resources: - watch
- roles - apiGroups:
- rolebindings - ""
verbs: resources:
- create - configmaps
- update - secrets
- list - services
- watch verbs:
- apiGroups: - create
- "" - get
resources: - list
- pods/portforward - update
verbs: - watch
- create - apiGroups:
- apiGroups: - ""
- "" resources:
resources: - events
- pods/log verbs:
verbs: - create
- get - get
- list - list
- watch - patch
- apiGroups: - watch
- "" - apiGroups:
resources: - ""
- pods resources:
- pods/exec - persistentvolumeclaims
verbs: verbs:
- "*" - get
- apiGroups: - list
- "" - watch
resources: - apiGroups:
- events - ""
verbs: resources:
- get - pods
- watch verbs:
- list - create
- create - delete
- patch - get
- apiGroups: - list
- apps - patch
resourceNames: - update
- jenkins-operator - watch
resources: - apiGroups:
- deployments/finalizers - ""
verbs: resources:
- update - pods
- apiGroups: - pods/exec
- jenkins.io verbs:
resources: - '*'
- '*' - apiGroups:
verbs: - ""
- '*' resources:
- apiGroups: - pods/log
- "" verbs:
resources: - get
- persistentvolumeclaims - list
verbs: - watch
- get - apiGroups:
- list - ""
- watch resources:
- apiGroups: - pods/portforward
- "route.openshift.io" verbs:
resources: - create
- routes - apiGroups:
verbs: - ""
- get resources:
- list - serviceaccounts
- watch verbs:
- create - create
- update - get
- apiGroups: - list
- "image.openshift.io" - update
resources: - watch
- imagestreams - apiGroups:
verbs: - image.openshift.io
- get resources:
- list - imagestreams
- watch verbs:
- apiGroups: - get
- "build.openshift.io" - list
resources: - watch
- builds - apiGroups:
- buildconfigs - jenkins.io
verbs: resources:
- get - jenkins/finalizers
- list verbs:
- watch - update
- apiGroups:
- jenkins.io
resources:
- jenkins/status
verbs:
- get
- patch
- update
- apiGroups:
- jenkins.io
resources:
- '*'
verbs:
- '*'
- apiGroups:
- rbac.authorization.k8s.io
resources:
- rolebindings
- roles
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- "route.openshift.io"
resources:
- routes
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- "image.openshift.io"
resources:
- imagestreams
verbs:
- get
- list
- watch
- apiGroups:
- "build.openshift.io"
resources:
- builds
- buildconfigs
verbs:
- get
- list
- watch

View File

@ -1,13 +1,12 @@
--- ---
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding kind: RoleBinding
metadata: metadata:
name: manager-rolebinding name: manager-rolebinding
roleRef: roleRef:
apiGroup: rbac.authorization.k8s.io apiGroup: rbac.authorization.k8s.io
kind: ClusterRole kind: Role
name: manager-role name: jenkins-operator
subjects: subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: default name: jenkins-operator
namespace: default

View File

@ -0,0 +1,6 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-operator
namespace: default

View File

@ -111,8 +111,20 @@ func (r *JenkinsReconciler) newJenkinsReconcilier(jenkins *v1alpha2.Jenkins) con
// +kubebuilder:rbac:groups=jenkins.io,resources=jenkins/status,verbs=get;update;patch // +kubebuilder:rbac:groups=jenkins.io,resources=jenkins/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=jenkins.io,resources=jenkins/finalizers,verbs=update // +kubebuilder:rbac:groups=jenkins.io,resources=jenkins/finalizers,verbs=update
// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch // +kubebuilder:rbac:groups=core,resources=services;configmaps;secrets,verbs=get;list;watch;create;update
// +kubebuilder:rbac:groups=v1,resources=secrets,verbs=get;list;watch // +kubebuilder:rbac:groups=apps,resources=deployments;daemonsets;replicasets;statefulsets,verbs=*
// +kubebuilder:rbac:groups=core,resources=serviceaccounts,verbs=get;list;watch;create;update
// +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=roles;rolebindings,verbs=get;list;watch;create;update
// +kubebuilder:rbac:groups=core,resources=pods/portforward,verbs=create
// +kubebuilder:rbac:groups=core,resources=pods/log,verbs=get;list;watch
// +kubebuilder:rbac:groups=core,resources=pods;pods/exec,verbs=*
// +kubebuilder:rbac:groups=core,resources=events,verbs=get;watch;list;create;patch
// +kubebuilder:rbac:groups=apps;jenkins-operator,resources=deployments/finalizers,verbs=update
// +kubebuilder:rbac:groups=jenkins.io,resources=*,verbs=*
// +kubebuilder:rbac:groups=core,resources=persistentvolumeclaims,verbs=get;list;watch
// +kubebuilder:rbac:groups=route.openshift.io,resources=routes,verbs=get;list;watch;create;update
// +kubebuilder:rbac:groups=image.openshift.io,resources=imagestreams,verbs=get;list;watch
// +kubebuilder:rbac:groups=build.openshift.io,resources=builds;buildconfigs,verbs=get;list;watch
// For more details, check Reconcile and its Result here: // For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.7.0/pkg/reconcile // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.7.0/pkg/reconcile

View File

@ -122,6 +122,7 @@ func main() {
HealthProbeBindAddress: probeAddr, HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection, LeaderElection: enableLeaderElection,
LeaderElectionID: "c674355f.jenkins.io", LeaderElectionID: "c674355f.jenkins.io",
Namespace: namespace,
}) })
if err != nil { if err != nil {
fatal(errors.Wrap(err, "unable to start manager"), *debug) fatal(errors.Wrap(err, "unable to start manager"), *debug)

View File

@ -35,7 +35,7 @@ func createUserConfigurationSecret(namespace string, stringData map[string]strin
} }
_, _ = fmt.Fprintf(GinkgoWriter, "User configuration secret %+v\n", *userConfiguration) _, _ = fmt.Fprintf(GinkgoWriter, "User configuration secret %+v\n", *userConfiguration)
Expect(k8sClient.Create(context.TODO(), userConfiguration)).Should(Succeed()) Expect(K8sClient.Create(context.TODO(), userConfiguration)).Should(Succeed())
} }
func createUserConfigurationConfigMap(namespace string, numberOfExecutorsSecretKeyName string, systemMessage string) { func createUserConfigurationConfigMap(namespace string, numberOfExecutorsSecretKeyName string, systemMessage string) {
@ -63,7 +63,7 @@ unclassified:
} }
_, _ = fmt.Fprintf(GinkgoWriter, "User configuration %+v\n", *userConfiguration) _, _ = fmt.Fprintf(GinkgoWriter, "User configuration %+v\n", *userConfiguration)
Expect(k8sClient.Create(context.TODO(), userConfiguration)).Should(Succeed()) Expect(K8sClient.Create(context.TODO(), userConfiguration)).Should(Succeed())
} }
func createDefaultLimitsForContainersInNamespace(namespace string) { func createDefaultLimitsForContainersInNamespace(namespace string) {
@ -92,7 +92,7 @@ func createDefaultLimitsForContainersInNamespace(namespace string) {
} }
_, _ = fmt.Fprintf(GinkgoWriter, "LimitRange %+v\n", *limitRange) _, _ = fmt.Fprintf(GinkgoWriter, "LimitRange %+v\n", *limitRange)
Expect(k8sClient.Create(context.TODO(), limitRange)).Should(Succeed()) Expect(K8sClient.Create(context.TODO(), limitRange)).Should(Succeed())
} }
func verifyJenkinsMasterPodAttributes(jenkins *v1alpha2.Jenkins) { func verifyJenkinsMasterPodAttributes(jenkins *v1alpha2.Jenkins) {

View File

@ -1,71 +0,0 @@
// +build Helm
package e2e
// TODO
/*
import (
"fmt"
"os/exec"
"testing"
"github.com/jenkinsci/kubernetes-operator/pkg/apis"
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
framework "github.com/operator-framework/operator-sdk/pkg/test"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestLintHelmChart(t *testing.T) {
t.Parallel()
cmd := exec.Command("helm", "lint", "./chart/jenkins-operator")
output, err := cmd.CombinedOutput()
require.NoError(t, err, string(output))
}
func TestDeployHelmChart(t *testing.T) {
// Given
t.Parallel()
ctx := framework.NewContext(t)
defer ctx.Cleanup()
namespace, err := ctx.GetNamespace()
require.NoError(t, err)
jenkinsServiceList := &v1alpha2.JenkinsList{
TypeMeta: metav1.TypeMeta{
Kind: v1alpha2.Kind,
APIVersion: v1alpha2.SchemeGroupVersion.String(),
},
}
err = framework.AddToFrameworkScheme(apis.AddToScheme, jenkinsServiceList)
require.NoError(t, err)
jenkins := &v1alpha2.Jenkins{
TypeMeta: v1alpha2.JenkinsTypeMeta(),
ObjectMeta: metav1.ObjectMeta{
Name: "jenkins",
Namespace: namespace,
},
}
cmd := exec.Command("helm", "upgrade", "jenkins", "./chart/jenkins-operator", "--namespace", namespace, "--debug",
"--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace), "--install")
output, err := cmd.CombinedOutput()
require.NoError(t, err, string(output))
waitForJenkinsBaseConfigurationToComplete(t, jenkins)
waitForJenkinsUserConfigurationToComplete(t, jenkins)
cmd = exec.Command("helm", "upgrade", "jenkins", "./chart/jenkins-operator", "--namespace", namespace, "--debug",
"--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace), "--install")
output, err = cmd.CombinedOutput()
require.NoError(t, err, string(output))
// Then
waitForJenkinsBaseConfigurationToComplete(t, jenkins)
waitForJenkinsUserConfigurationToComplete(t, jenkins)
}
*/

View File

@ -73,7 +73,7 @@ var _ = Describe("Jenkins controller configuration", func() {
) )
BeforeEach(func() { BeforeEach(func() {
namespace = createNamespace() namespace = CreateNamespace()
createUserConfigurationSecret(namespace.Name, userConfigurationSecretData) createUserConfigurationSecret(namespace.Name, userConfigurationSecretData)
createUserConfigurationConfigMap(namespace.Name, numberOfExecutorsEnvName, fmt.Sprintf("${%s}", systemMessageEnvName)) createUserConfigurationConfigMap(namespace.Name, numberOfExecutorsEnvName, fmt.Sprintf("${%s}", systemMessageEnvName))
@ -83,18 +83,18 @@ var _ = Describe("Jenkins controller configuration", func() {
}) })
AfterEach(func() { AfterEach(func() {
destroyNamespace(namespace) DestroyNamespace(namespace)
}) })
Context("when deploying CR to cluster", func() { Context("when deploying CR to cluster", func() {
It("creates Jenkins instance and configures it", func() { It("creates Jenkins instance and configures it", func() {
waitForJenkinsBaseConfigurationToComplete(jenkins) WaitForJenkinsBaseConfigurationToComplete(jenkins)
verifyJenkinsMasterPodAttributes(jenkins) verifyJenkinsMasterPodAttributes(jenkins)
verifyServices(jenkins) verifyServices(jenkins)
jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name) jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name)
defer cleanUpFunc() defer cleanUpFunc()
verifyPlugins(jenkinsClient, jenkins) verifyPlugins(jenkinsClient, jenkins)
waitForJenkinsUserConfigurationToComplete(jenkins) WaitForJenkinsUserConfigurationToComplete(jenkins)
verifyUserConfiguration(jenkinsClient, numberOfExecutors, systemMessage) verifyUserConfiguration(jenkinsClient, numberOfExecutors, systemMessage)
verifyJenkinsSeedJobs(jenkinsClient, []seedJobConfig{mySeedJob}) verifyJenkinsSeedJobs(jenkinsClient, []seedJobConfig{mySeedJob})
}) })
@ -124,17 +124,17 @@ var _ = Describe("Jenkins controller priority class", func() {
) )
BeforeEach(func() { BeforeEach(func() {
namespace = createNamespace() namespace = CreateNamespace()
jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName) jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName)
}) })
AfterEach(func() { AfterEach(func() {
destroyNamespace(namespace) DestroyNamespace(namespace)
}) })
Context("when deploying CR with priority class to cluster", func() { Context("when deploying CR with priority class to cluster", func() {
It("creates Jenkins instance and configures it", func() { It("creates Jenkins instance and configures it", func() {
waitForJenkinsBaseConfigurationToComplete(jenkins) WaitForJenkinsBaseConfigurationToComplete(jenkins)
verifyJenkinsMasterPodAttributes(jenkins) verifyJenkinsMasterPodAttributes(jenkins)
}) })
}) })
@ -175,17 +175,17 @@ var _ = Describe("Jenkins controller plugins test", func() {
) )
BeforeEach(func() { BeforeEach(func() {
namespace = createNamespace() namespace = CreateNamespace()
jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, &[]v1alpha2.SeedJob{mySeedJob.SeedJob}, groovyScripts, casc, priorityClassName) jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, &[]v1alpha2.SeedJob{mySeedJob.SeedJob}, groovyScripts, casc, priorityClassName)
}) })
AfterEach(func() { AfterEach(func() {
destroyNamespace(namespace) DestroyNamespace(namespace)
}) })
Context("when deploying CR with a SeedJob to cluster", func() { Context("when deploying CR with a SeedJob to cluster", func() {
It("runs kubernetes plugin job successfully", func() { It("runs kubernetes plugin job successfully", func() {
waitForJenkinsUserConfigurationToComplete(jenkins) WaitForJenkinsUserConfigurationToComplete(jenkins)
jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name) jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name)
defer cleanUpFunc() defer cleanUpFunc()
waitForJobCreation(jenkinsClient, jobID) waitForJobCreation(jenkinsClient, jobID)

View File

@ -32,23 +32,23 @@ var _ = Describe("Jenkins controller", func() {
) )
BeforeEach(func() { BeforeEach(func() {
namespace = createNamespace() namespace = CreateNamespace()
configureAuthorizationToUnSecure(namespace.Name, userConfigurationConfigMapName) configureAuthorizationToUnSecure(namespace.Name, userConfigurationConfigMapName)
jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName) jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName)
}) })
AfterEach(func() { AfterEach(func() {
destroyNamespace(namespace) DestroyNamespace(namespace)
}) })
Context("when restarting Jenkins master pod", func() { Context("when restarting Jenkins master pod", func() {
It("new Jenkins Master pod should be created", func() { It("new Jenkins Master pod should be created", func() {
waitForJenkinsBaseConfigurationToComplete(jenkins) WaitForJenkinsBaseConfigurationToComplete(jenkins)
restartJenkinsMasterPod(jenkins) restartJenkinsMasterPod(jenkins)
waitForRecreateJenkinsMasterPod(jenkins) waitForRecreateJenkinsMasterPod(jenkins)
checkBaseConfigurationCompleteTimeIsNotSet(jenkins) checkBaseConfigurationCompleteTimeIsNotSet(jenkins)
waitForJenkinsBaseConfigurationToComplete(jenkins) WaitForJenkinsBaseConfigurationToComplete(jenkins)
}) })
}) })
}) })
@ -80,20 +80,20 @@ var _ = Describe("Jenkins controller", func() {
) )
BeforeEach(func() { BeforeEach(func() {
namespace = createNamespace() namespace = CreateNamespace()
configureAuthorizationToUnSecure(namespace.Name, userConfigurationConfigMapName) configureAuthorizationToUnSecure(namespace.Name, userConfigurationConfigMapName)
jenkins = createJenkinsCRSafeRestart(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName) jenkins = createJenkinsCRSafeRestart(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName)
}) })
AfterEach(func() { AfterEach(func() {
destroyNamespace(namespace) DestroyNamespace(namespace)
}) })
Context("when running Jenkins safe restart", func() { Context("when running Jenkins safe restart", func() {
It("authorization strategy is not overwritten", func() { It("authorization strategy is not overwritten", func() {
waitForJenkinsBaseConfigurationToComplete(jenkins) WaitForJenkinsBaseConfigurationToComplete(jenkins)
waitForJenkinsUserConfigurationToComplete(jenkins) WaitForJenkinsUserConfigurationToComplete(jenkins)
jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name) jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name)
defer cleanUpFunc() defer cleanUpFunc()
checkIfAuthorizationStrategyUnsecuredIsSet(jenkinsClient) checkIfAuthorizationStrategyUnsecuredIsSet(jenkinsClient)

View File

@ -21,19 +21,19 @@ var _ = Describe("Jenkins controller backup and restore", func() {
) )
BeforeEach(func() { BeforeEach(func() {
namespace = createNamespace() namespace = CreateNamespace()
createPVC(namespace.Name) createPVC(namespace.Name)
jenkins = createJenkinsWithBackupAndRestoreConfigured(jenkinsCRName, namespace.Name) jenkins = createJenkinsWithBackupAndRestoreConfigured(jenkinsCRName, namespace.Name)
}) })
AfterEach(func() { AfterEach(func() {
destroyNamespace(namespace) DestroyNamespace(namespace)
}) })
Context("when deploying CR with backup enabled to cluster", func() { Context("when deploying CR with backup enabled to cluster", func() {
It("performs backups before pod deletion and restores them even Jenkins status is restarted", func() { It("performs backups before pod deletion and restores them even Jenkins status is restarted", func() {
waitForJenkinsUserConfigurationToComplete(jenkins) WaitForJenkinsUserConfigurationToComplete(jenkins)
jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name) jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name)
defer cleanUpFunc() defer cleanUpFunc()
waitForJobCreation(jenkinsClient, jobID) waitForJobCreation(jenkinsClient, jobID)
@ -42,7 +42,7 @@ var _ = Describe("Jenkins controller backup and restore", func() {
jenkins = getJenkins(jenkins.Namespace, jenkins.Name) jenkins = getJenkins(jenkins.Namespace, jenkins.Name)
restartJenkinsMasterPod(jenkins) restartJenkinsMasterPod(jenkins)
waitForRecreateJenkinsMasterPod(jenkins) waitForRecreateJenkinsMasterPod(jenkins)
waitForJenkinsUserConfigurationToComplete(jenkins) WaitForJenkinsUserConfigurationToComplete(jenkins)
jenkinsClient2, cleanUpFunc2 := verifyJenkinsAPIConnection(jenkins, namespace.Name) jenkinsClient2, cleanUpFunc2 := verifyJenkinsAPIConnection(jenkins, namespace.Name)
defer cleanUpFunc2() defer cleanUpFunc2()
waitForJobCreation(jenkinsClient2, jobID) waitForJobCreation(jenkinsClient2, jobID)
@ -51,7 +51,7 @@ var _ = Describe("Jenkins controller backup and restore", func() {
resetJenkinsStatus(jenkins) resetJenkinsStatus(jenkins)
jenkins = getJenkins(jenkins.Namespace, jenkins.Name) jenkins = getJenkins(jenkins.Namespace, jenkins.Name)
checkBaseConfigurationCompleteTimeIsNotSet(jenkins) checkBaseConfigurationCompleteTimeIsNotSet(jenkins)
waitForJenkinsUserConfigurationToComplete(jenkins) WaitForJenkinsUserConfigurationToComplete(jenkins)
jenkinsClient3, cleanUpFunc3 := verifyJenkinsAPIConnection(jenkins, namespace.Name) jenkinsClient3, cleanUpFunc3 := verifyJenkinsAPIConnection(jenkins, namespace.Name)
defer cleanUpFunc3() defer cleanUpFunc3()
waitForJobCreation(jenkinsClient3, jobID) waitForJobCreation(jenkinsClient3, jobID)

View File

@ -31,7 +31,7 @@ const (
func getJenkins(namespace, name string) *v1alpha2.Jenkins { func getJenkins(namespace, name string) *v1alpha2.Jenkins {
jenkins := &v1alpha2.Jenkins{} jenkins := &v1alpha2.Jenkins{}
namespaceName := types.NamespacedName{Namespace: namespace, Name: name} namespaceName := types.NamespacedName{Namespace: namespace, Name: name}
Expect(k8sClient.Get(context.TODO(), namespaceName, jenkins)).Should(Succeed()) Expect(K8sClient.Get(context.TODO(), namespaceName, jenkins)).Should(Succeed())
return jenkins return jenkins
} }
@ -41,7 +41,7 @@ func getJenkinsMasterPod(jenkins *v1alpha2.Jenkins) *corev1.Pod {
Namespace: jenkins.Namespace, Namespace: jenkins.Namespace,
} }
pods := &corev1.PodList{} pods := &corev1.PodList{}
Expect(k8sClient.List(context.TODO(), pods, lo)).Should(Succeed()) Expect(K8sClient.List(context.TODO(), pods, lo)).Should(Succeed())
Expect(pods.Items).Should(HaveLen(1), fmt.Sprintf("Jenkins pod not found, pod list: %+v", pods.Items)) Expect(pods.Items).Should(HaveLen(1), fmt.Sprintf("Jenkins pod not found, pod list: %+v", pods.Items))
return &pods.Items[0] return &pods.Items[0]
} }
@ -147,7 +147,7 @@ func createJenkinsCR(name, namespace string, seedJob *[]v1alpha2.SeedJob, groovy
_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins CR %+v\n", *jenkins) _, _ = fmt.Fprintf(GinkgoWriter, "Jenkins CR %+v\n", *jenkins)
Expect(k8sClient.Create(context.TODO(), jenkins)).Should(Succeed()) Expect(K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
return jenkins return jenkins
} }
@ -253,7 +253,7 @@ func createJenkinsCRSafeRestart(name, namespace string, seedJob *[]v1alpha2.Seed
_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins CR %+v\n", *jenkins) _, _ = fmt.Fprintf(GinkgoWriter, "Jenkins CR %+v\n", *jenkins)
Expect(k8sClient.Create(context.TODO(), jenkins)).Should(Succeed()) Expect(K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
return jenkins return jenkins
} }
@ -261,11 +261,11 @@ func createJenkinsCRSafeRestart(name, namespace string, seedJob *[]v1alpha2.Seed
func createJenkinsAPIClientFromServiceAccount(jenkins *v1alpha2.Jenkins, jenkinsAPIURL string) (jenkinsclient.Jenkins, error) { func createJenkinsAPIClientFromServiceAccount(jenkins *v1alpha2.Jenkins, jenkinsAPIURL string) (jenkinsclient.Jenkins, error) {
podName := resources.GetJenkinsMasterPodName(jenkins) podName := resources.GetJenkinsMasterPodName(jenkins)
clientSet, err := kubernetes.NewForConfig(cfg) clientSet, err := kubernetes.NewForConfig(Cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
config := configuration.Configuration{Jenkins: jenkins, ClientSet: *clientSet, Config: cfg} config := configuration.Configuration{Jenkins: jenkins, ClientSet: *clientSet, Config: Cfg}
r := base.New(config, jenkinsclient.JenkinsAPIConnectionSettings{}) r := base.New(config, jenkinsclient.JenkinsAPIConnectionSettings{})
token, _, err := r.Configuration.Exec(podName, resources.JenkinsMasterContainerName, []string{"cat", "/var/run/secrets/kubernetes.io/serviceaccount/token"}) token, _, err := r.Configuration.Exec(podName, resources.JenkinsMasterContainerName, []string{"cat", "/var/run/secrets/kubernetes.io/serviceaccount/token"})
@ -281,7 +281,7 @@ func createJenkinsAPIClientFromSecret(jenkins *v1alpha2.Jenkins, jenkinsAPIURL s
adminSecret := &corev1.Secret{} adminSecret := &corev1.Secret{}
namespaceName := types.NamespacedName{Namespace: jenkins.Namespace, Name: resources.GetOperatorCredentialsSecretName(jenkins)} namespaceName := types.NamespacedName{Namespace: jenkins.Namespace, Name: resources.GetOperatorCredentialsSecretName(jenkins)}
if err := k8sClient.Get(context.TODO(), namespaceName, adminSecret); err != nil { if err := K8sClient.Get(context.TODO(), namespaceName, adminSecret); err != nil {
return nil, err return nil, err
} }
@ -296,7 +296,7 @@ func verifyJenkinsAPIConnection(jenkins *v1alpha2.Jenkins, namespace string) (je
By("establishing Jenkins API connection") By("establishing Jenkins API connection")
var service corev1.Service var service corev1.Service
err := k8sClient.Get(context.TODO(), types.NamespacedName{ err := K8sClient.Get(context.TODO(), types.NamespacedName{
Namespace: jenkins.Namespace, Namespace: jenkins.Namespace,
Name: resources.GetJenkinsHTTPServiceName(jenkins), Name: resources.GetJenkinsHTTPServiceName(jenkins),
}, &service) }, &service)
@ -333,7 +333,7 @@ func verifyJenkinsAPIConnection(jenkins *v1alpha2.Jenkins, namespace string) (je
func restartJenkinsMasterPod(jenkins *v1alpha2.Jenkins) { func restartJenkinsMasterPod(jenkins *v1alpha2.Jenkins) {
_, _ = fmt.Fprintf(GinkgoWriter, "Restarting Jenkins master pod\n") _, _ = fmt.Fprintf(GinkgoWriter, "Restarting Jenkins master pod\n")
jenkinsPod := getJenkinsMasterPod(jenkins) jenkinsPod := getJenkinsMasterPod(jenkins)
Expect(k8sClient.Delete(context.TODO(), jenkinsPod)).Should(Succeed()) Expect(K8sClient.Delete(context.TODO(), jenkinsPod)).Should(Succeed())
Eventually(func() (bool, error) { Eventually(func() (bool, error) {
jenkinsPod = getJenkinsMasterPod(jenkins) jenkinsPod = getJenkinsMasterPod(jenkins)
@ -346,7 +346,7 @@ func restartJenkinsMasterPod(jenkins *v1alpha2.Jenkins) {
func getJenkinsService(jenkins *v1alpha2.Jenkins, serviceKind string) *corev1.Service { func getJenkinsService(jenkins *v1alpha2.Jenkins, serviceKind string) *corev1.Service {
service := &corev1.Service{} service := &corev1.Service{}
serviceName := constants.OperatorName + "-" + serviceKind + "-" + jenkins.ObjectMeta.Name serviceName := constants.OperatorName + "-" + serviceKind + "-" + jenkins.ObjectMeta.Name
Expect(k8sClient.Get(context.TODO(), client.ObjectKey{Name: serviceName, Namespace: jenkins.Namespace}, service)).Should(Succeed()) Expect(K8sClient.Get(context.TODO(), client.ObjectKey{Name: serviceName, Namespace: jenkins.Namespace}, service)).Should(Succeed())
return service return service
} }

View File

@ -66,7 +66,7 @@ func setupPortForwardToPod(namespace, podName string, podPort int) (port int, cl
readyCh := make(chan struct{}) readyCh := make(chan struct{})
req := portForwardToPodRequest{ req := portForwardToPodRequest{
config: cfg, config: Cfg,
pod: v1.Pod{ pod: v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: podName, Name: podName,

View File

@ -33,7 +33,7 @@ jenkins.save()
}, },
} }
Expect(k8sClient.Create(context.TODO(), limitRange)).Should(Succeed()) Expect(K8sClient.Create(context.TODO(), limitRange)).Should(Succeed())
} }
func checkIfAuthorizationStrategyUnsecuredIsSet(jenkinsClient jenkinsclient.Jenkins) { func checkIfAuthorizationStrategyUnsecuredIsSet(jenkinsClient jenkinsclient.Jenkins) {
@ -56,7 +56,7 @@ func checkBaseConfigurationCompleteTimeIsNotSet(jenkins *v1alpha2.Jenkins) {
Eventually(func() (bool, error) { Eventually(func() (bool, error) {
actualJenkins := &v1alpha2.Jenkins{} actualJenkins := &v1alpha2.Jenkins{}
err := k8sClient.Get(context.TODO(), types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, actualJenkins) err := K8sClient.Get(context.TODO(), types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, actualJenkins)
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -61,7 +61,7 @@ func createPVC(namespace string) {
}, },
} }
Expect(k8sClient.Create(context.TODO(), pvc)).Should(Succeed()) Expect(K8sClient.Create(context.TODO(), pvc)).Should(Succeed())
} }
func createJenkinsWithBackupAndRestoreConfigured(name, namespace string) *v1alpha2.Jenkins { func createJenkinsWithBackupAndRestoreConfigured(name, namespace string) *v1alpha2.Jenkins {
@ -180,7 +180,7 @@ func createJenkinsWithBackupAndRestoreConfigured(name, namespace string) *v1alph
_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins CR %+v\n", *jenkins) _, _ = fmt.Fprintf(GinkgoWriter, "Jenkins CR %+v\n", *jenkins)
Expect(k8sClient.Create(context.TODO(), jenkins)).Should(Succeed()) Expect(K8sClient.Create(context.TODO(), jenkins)).Should(Succeed())
return jenkins return jenkins
} }
@ -190,5 +190,5 @@ func resetJenkinsStatus(jenkins *v1alpha2.Jenkins) {
jenkins = getJenkins(jenkins.Namespace, jenkins.Name) jenkins = getJenkins(jenkins.Namespace, jenkins.Name)
jenkins.Status = v1alpha2.JenkinsStatus{} jenkins.Status = v1alpha2.JenkinsStatus{}
Expect(k8sClient.Status().Update(context.TODO(), jenkins)).Should(Succeed()) Expect(K8sClient.Status().Update(context.TODO(), jenkins)).Should(Succeed())
} }

View File

@ -104,7 +104,7 @@ func createKubernetesCredentialsProviderSecret(namespace string, config seedJobC
}, },
} }
Expect(k8sClient.Create(context.TODO(), secret)).Should(Succeed()) Expect(K8sClient.Create(context.TODO(), secret)).Should(Succeed())
} }
func verifyJenkinsSeedJobs(jenkinsClient jenkinsclient.Jenkins, seedJobs []seedJobConfig) { func verifyJenkinsSeedJobs(jenkinsClient jenkinsclient.Jenkins, seedJobs []seedJobConfig) {

View File

@ -1,12 +1,9 @@
package e2e package e2e
import ( import (
"context"
"flag" "flag"
"fmt"
"path/filepath" "path/filepath"
"testing" "testing"
"time"
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2" "github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
"github.com/jenkinsci/kubernetes-operator/controllers" "github.com/jenkinsci/kubernetes-operator/controllers"
@ -18,13 +15,9 @@ import (
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime" ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/envtest"
"sigs.k8s.io/controller-runtime/pkg/envtest/printer" "sigs.k8s.io/controller-runtime/pkg/envtest/printer"
logf "sigs.k8s.io/controller-runtime/pkg/log" logf "sigs.k8s.io/controller-runtime/pkg/log"
@ -32,16 +25,6 @@ import (
// +kubebuilder:scaffold:imports // +kubebuilder:scaffold:imports
) )
var (
cfg *rest.Config
k8sClient client.Client
testEnv *envtest.Environment
hostname *string
port *int
useNodePort *bool
)
func init() { func init() {
hostname = flag.String("jenkins-api-hostname", "", "Hostname or IP of Jenkins API. It can be service name, node IP or localhost.") hostname = flag.String("jenkins-api-hostname", "", "Hostname or IP of Jenkins API. It can be service name, node IP or localhost.")
port = flag.Int("jenkins-api-port", 0, "The port on which Jenkins API is running. Note: If you want to use nodePort don't set this setting and --jenkins-api-use-nodeport must be true.") port = flag.Int("jenkins-api-port", 0, "The port on which Jenkins API is running. Note: If you want to use nodePort don't set this setting and --jenkins-api-use-nodeport must be true.")
@ -68,9 +51,9 @@ var _ = BeforeSuite(func(done Done) {
} }
var err error var err error
cfg, err = testEnv.Start() Cfg, err = testEnv.Start()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil()) Expect(Cfg).NotTo(BeNil())
err = v1alpha2.AddToScheme(scheme.Scheme) err = v1alpha2.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -78,20 +61,20 @@ var _ = BeforeSuite(func(done Done) {
// +kubebuilder:scaffold:scheme // +kubebuilder:scaffold:scheme
// setup manager // setup manager
k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ k8sManager, err := ctrl.NewManager(Cfg, ctrl.Options{
Scheme: scheme.Scheme, Scheme: scheme.Scheme,
}) })
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
// setup controller // setup controller
clientSet, err := kubernetes.NewForConfig(cfg) clientSet, err := kubernetes.NewForConfig(Cfg)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
// setup events // setup events
events, err := event.New(cfg, constants.OperatorName) events, err := event.New(Cfg, constants.OperatorName)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
notificationEvents := make(chan e.Event) notificationEvents := make(chan e.Event)
go notifications.Listen(notificationEvents, events, k8sClient) go notifications.Listen(notificationEvents, events, K8sClient)
jenkinsAPIConnectionSettings := jenkinsClient.JenkinsAPIConnectionSettings{ jenkinsAPIConnectionSettings := jenkinsClient.JenkinsAPIConnectionSettings{
Hostname: *hostname, Hostname: *hostname,
@ -104,7 +87,7 @@ var _ = BeforeSuite(func(done Done) {
Scheme: k8sManager.GetScheme(), Scheme: k8sManager.GetScheme(),
JenkinsAPIConnectionSettings: jenkinsAPIConnectionSettings, JenkinsAPIConnectionSettings: jenkinsAPIConnectionSettings,
ClientSet: *clientSet, ClientSet: *clientSet,
Config: *cfg, Config: *Cfg,
NotificationEvents: &notificationEvents, NotificationEvents: &notificationEvents,
KubernetesClusterDomain: "cluster.local", KubernetesClusterDomain: "cluster.local",
}).SetupWithManager(k8sManager) }).SetupWithManager(k8sManager)
@ -115,8 +98,8 @@ var _ = BeforeSuite(func(done Done) {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
}() }()
k8sClient = k8sManager.GetClient() K8sClient = k8sManager.GetClient()
Expect(k8sClient).NotTo(BeNil()) Expect(K8sClient).NotTo(BeNil())
close(done) close(done)
}, 60) }, 60)
@ -125,39 +108,3 @@ var _ = AfterSuite(func() {
err := testEnv.Stop() err := testEnv.Stop()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
}) })
func createNamespace() *corev1.Namespace {
By("creating temporary namespace")
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%d", time.Now().Unix()),
},
}
Expect(k8sClient.Create(context.TODO(), namespace)).Should(Succeed())
return namespace
}
func destroyNamespace(namespace *corev1.Namespace) {
By("deleting temporary namespace")
Expect(k8sClient.Delete(context.TODO(), namespace)).Should(Succeed())
Eventually(func() (bool, error) {
namespaces := &corev1.NamespaceList{}
err := k8sClient.List(context.TODO(), namespaces)
if err != nil {
return false, err
}
exists := false
for _, namespaceItem := range namespaces.Items {
if namespaceItem.Name == namespace.Name {
exists = true
break
}
}
return !exists, nil
}, time.Second*120, time.Second).Should(BeTrue())
}

61
test/e2e/test_utility.go Normal file
View File

@ -0,0 +1,61 @@
package e2e
import (
"context"
"fmt"
"time"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
)
var (
Cfg *rest.Config
K8sClient client.Client
testEnv *envtest.Environment
hostname *string
port *int
useNodePort *bool
)
func CreateNamespace() *corev1.Namespace {
ginkgo.By("creating temporary namespace")
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("ns%d", time.Now().Unix()),
},
}
gomega.Expect(K8sClient.Create(context.TODO(), namespace)).Should(gomega.Succeed())
return namespace
}
func DestroyNamespace(namespace *corev1.Namespace) {
ginkgo.By("deleting temporary namespace")
gomega.Expect(K8sClient.Delete(context.TODO(), namespace)).Should(gomega.Succeed())
gomega.Eventually(func() (bool, error) {
namespaces := &corev1.NamespaceList{}
err := K8sClient.List(context.TODO(), namespaces)
if err != nil {
return false, err
}
exists := false
for _, namespaceItem := range namespaces.Items {
if namespaceItem.Name == namespace.Name {
exists = true
break
}
}
return !exists, nil
}, time.Second*120, time.Second).Should(gomega.BeTrue())
}

View File

@ -10,8 +10,8 @@ import (
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client" jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources" "github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
. "github.com/onsi/ginkgo" "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
@ -23,36 +23,36 @@ var (
retryInterval = time.Second * 5 retryInterval = time.Second * 5
) )
func waitForJenkinsBaseConfigurationToComplete(jenkins *v1alpha2.Jenkins) { func WaitForJenkinsBaseConfigurationToComplete(jenkins *v1alpha2.Jenkins) {
By("waiting for Jenkins base configuration phase to complete") ginkgo.By("waiting for Jenkins base configuration phase to complete")
Eventually(func() (*metav1.Time, error) { gomega.Eventually(func() (*metav1.Time, error) {
actualJenkins := &v1alpha2.Jenkins{} actualJenkins := &v1alpha2.Jenkins{}
err := k8sClient.Get(context.TODO(), types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, actualJenkins) err := K8sClient.Get(context.TODO(), types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, actualJenkins)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return actualJenkins.Status.BaseConfigurationCompletedTime, nil return actualJenkins.Status.BaseConfigurationCompletedTime, nil
}, time.Duration(170)*retryInterval, retryInterval).Should(Not(BeNil())) }, time.Duration(170)*retryInterval, retryInterval).Should(gomega.Not(gomega.BeNil()))
_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins pod is running\n") _, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Jenkins pod is running\n")
// update jenkins CR because Operator sets default values // update jenkins CR because Operator sets default values
namespacedName := types.NamespacedName{Namespace: jenkins.Namespace, Name: jenkins.Name} namespacedName := types.NamespacedName{Namespace: jenkins.Namespace, Name: jenkins.Name}
Expect(k8sClient.Get(context.TODO(), namespacedName, jenkins)).Should(Succeed()) gomega.Expect(K8sClient.Get(context.TODO(), namespacedName, jenkins)).Should(gomega.Succeed())
} }
func waitForRecreateJenkinsMasterPod(jenkins *v1alpha2.Jenkins) { func waitForRecreateJenkinsMasterPod(jenkins *v1alpha2.Jenkins) {
By("waiting for Jenkins Master Pod recreation") ginkgo.By("waiting for Jenkins Master Pod recreation")
Eventually(func() (bool, error) { gomega.Eventually(func() (bool, error) {
lo := &client.ListOptions{ lo := &client.ListOptions{
LabelSelector: labels.SelectorFromSet(resources.GetJenkinsMasterPodLabels(*jenkins)), LabelSelector: labels.SelectorFromSet(resources.GetJenkinsMasterPodLabels(*jenkins)),
Namespace: jenkins.Namespace, Namespace: jenkins.Namespace,
} }
pods := &corev1.PodList{} pods := &corev1.PodList{}
err := k8sClient.List(context.TODO(), pods, lo) err := K8sClient.List(context.TODO(), pods, lo)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -61,31 +61,31 @@ func waitForRecreateJenkinsMasterPod(jenkins *v1alpha2.Jenkins) {
} }
return pods.Items[0].DeletionTimestamp == nil, nil return pods.Items[0].DeletionTimestamp == nil, nil
}, 30*retryInterval, retryInterval).Should(BeTrue()) }, 30*retryInterval, retryInterval).Should(gomega.BeTrue())
_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins pod has been recreated\n") _, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Jenkins pod has been recreated\n")
} }
func waitForJenkinsUserConfigurationToComplete(jenkins *v1alpha2.Jenkins) { func WaitForJenkinsUserConfigurationToComplete(jenkins *v1alpha2.Jenkins) {
By("waiting for Jenkins user configuration phase to complete") ginkgo.By("waiting for Jenkins user configuration phase to complete")
Eventually(func() (*metav1.Time, error) { gomega.Eventually(func() (*metav1.Time, error) {
actualJenkins := &v1alpha2.Jenkins{} actualJenkins := &v1alpha2.Jenkins{}
err := k8sClient.Get(context.TODO(), types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, actualJenkins) err := K8sClient.Get(context.TODO(), types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, actualJenkins)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return actualJenkins.Status.UserConfigurationCompletedTime, nil return actualJenkins.Status.UserConfigurationCompletedTime, nil
}, time.Duration(110)*retryInterval, retryInterval).Should(Not(BeNil())) }, time.Duration(110)*retryInterval, retryInterval).Should(gomega.Not(gomega.BeNil()))
_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins instance is up and ready\n") _, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Jenkins instance is up and ready\n")
} }
func waitForJenkinsSafeRestart(jenkinsClient jenkinsclient.Jenkins) { func waitForJenkinsSafeRestart(jenkinsClient jenkinsclient.Jenkins) {
By("waiting for Jenkins safe restart") ginkgo.By("waiting for Jenkins safe restart")
Eventually(func() (bool, error) { gomega.Eventually(func() (bool, error) {
status, err := jenkinsClient.Poll() status, err := jenkinsClient.Poll()
_, _ = fmt.Fprintf(GinkgoWriter, "Safe restart status: %+v, err: %s\n", status, err) _, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Safe restart status: %+v, err: %s\n", status, err)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -93,5 +93,5 @@ func waitForJenkinsSafeRestart(jenkinsClient jenkinsclient.Jenkins) {
return false, err return false, err
} }
return true, nil return true, nil
}, time.Second*200, time.Second*5).Should(BeTrue()) }, time.Second*200, time.Second*5).Should(gomega.BeTrue())
} }

60
test/helm/helm_test.go Normal file
View File

@ -0,0 +1,60 @@
package helm
import (
"fmt"
"os/exec"
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
"github.com/jenkinsci/kubernetes-operator/test/e2e"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
// +kubebuilder:scaffold:imports
)
var _ = Describe("Jenkins controller", func() {
var (
namespace *corev1.Namespace
)
BeforeEach(func() {
namespace = e2e.CreateNamespace()
})
AfterEach(func() {
showLogsIfTestHasFailed(CurrentGinkgoTestDescription().Failed, namespace.Name)
e2e.DestroyNamespace(namespace)
})
Context("when deploying Helm Chart to cluster", func() {
It("creates Jenkins instance and configures it", func() {
jenkins := &v1alpha2.Jenkins{
TypeMeta: v1alpha2.JenkinsTypeMeta(),
ObjectMeta: metav1.ObjectMeta{
Name: "jenkins",
Namespace: namespace.Name,
},
}
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("operator.image=%s", *imageName), "--install")
output, err := cmd.CombinedOutput()
Expect(err).NotTo(HaveOccurred(), string(output))
e2e.WaitForJenkinsBaseConfigurationToComplete(jenkins)
e2e.WaitForJenkinsUserConfigurationToComplete(jenkins)
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("operator.image=%s", *imageName), "--install")
output, err = cmd.CombinedOutput()
Expect(err).NotTo(HaveOccurred(), string(output))
e2e.WaitForJenkinsBaseConfigurationToComplete(jenkins)
e2e.WaitForJenkinsUserConfigurationToComplete(jenkins)
})
})
})

135
test/helm/logging_test.go Normal file
View File

@ -0,0 +1,135 @@
package helm
import (
"bytes"
"context"
"fmt"
"io"
"sort"
"github.com/jenkinsci/kubernetes-operator/test/e2e"
"github.com/onsi/ginkgo"
corev1 "k8s.io/api/core/v1"
"k8s.io/api/events/v1beta1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client"
)
var (
podLogTailLimit int64 = 15
kubernetesEventsLimit int64 = 15
// MUST match the labels in the deployment manifest: deploy/operator.yaml
operatorPodLabels = map[string]string{
"name": "jenkins-operator",
}
)
func getOperatorPod(namespace string) (*corev1.Pod, error) {
lo := &client.ListOptions{
LabelSelector: labels.SelectorFromSet(operatorPodLabels),
Namespace: namespace,
}
pods := &corev1.PodList{}
err := e2e.K8sClient.List(context.TODO(), pods, lo)
if err != nil {
return nil, err
}
return &pods.Items[0], nil
}
func getOperatorLogs(namespace string) (string, error) {
pod, err := getOperatorPod(namespace)
if err != nil {
return "Operator pod doesn't exist", err
}
logOptions := corev1.PodLogOptions{TailLines: &podLogTailLimit}
// creates the clientset
clientset, err := kubernetes.NewForConfig(e2e.Cfg)
if err != nil {
return "", err
}
req := clientset.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &logOptions)
podLogs, err := req.Stream(context.TODO())
if err != nil {
return "", err
}
defer func() {
if podLogs != nil {
_ = podLogs.Close()
}
}()
buf := new(bytes.Buffer)
_, err = io.Copy(buf, podLogs)
if err != nil {
return "", err
}
logs := buf.String()
return logs, nil
}
func printOperatorLogs(namespace string) {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Operator logs in '%s' namespace:\n", namespace)
logs, err := getOperatorLogs(namespace)
if err != nil {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Couldn't get the operator pod logs: %s", err)
} else {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Last %d lines of log from operator:\n %s", podLogTailLimit, logs)
}
}
func getKubernetesEvents(namespace string) ([]v1beta1.Event, error) {
listOptions := &client.ListOptions{
Limit: kubernetesEventsLimit,
Namespace: namespace,
}
events := &v1beta1.EventList{}
err := e2e.K8sClient.List(context.TODO(), events, listOptions)
if err != nil {
return nil, err
}
sort.SliceStable(events.Items, func(i, j int) bool {
return events.Items[i].CreationTimestamp.Unix() < events.Items[j].CreationTimestamp.Unix()
})
return events.Items, nil
}
func printKubernetesEvents(namespace string) {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Kubernetes events in '%s' namespace:\n", namespace)
events, err := getKubernetesEvents(namespace)
if err != nil {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Couldn't get kubernetes events: %s", err)
} else {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Last %d events from kubernetes:\n", kubernetesEventsLimit)
for _, event := range events {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "%+v\n\n", event)
}
}
}
func printKubernetesPods(namespace string) {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "All pods in '%s' namespace:\n", namespace)
pod, err := getOperatorPod(namespace)
if err == nil {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "%+v\n\n", pod)
}
}
func showLogsIfTestHasFailed(failed bool, namespace string) {
if failed {
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Test failed. Bellow here you can check logs:")
printKubernetesEvents(namespace)
printKubernetesPods(namespace)
printOperatorLogs(namespace)
}
}

76
test/helm/suite_test.go Normal file
View File

@ -0,0 +1,76 @@
package helm
import (
"flag"
"testing"
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
"github.com/jenkinsci/kubernetes-operator/test/e2e"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/envtest"
"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
// +kubebuilder:scaffold:imports
)
var (
testEnv *envtest.Environment
imageName *string
)
func init() {
imageName = flag.String("image-name", "", "Name of the locally built for testing Jenkins Operator Image.")
}
func TestHelm(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecsWithDefaultAndCustomReporters(t,
"Controller Suite",
[]Reporter{printer.NewlineReporter{}})
}
var _ = BeforeSuite(func(done Done) {
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(false)))
By("bootstrapping test environment")
useExistingCluster := true
testEnv = &envtest.Environment{
UseExistingCluster: &useExistingCluster,
}
cfg, err := testEnv.Start()
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())
err = v1alpha2.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())
// +kubebuilder:scaffold:scheme
// setup manager
k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
Scheme: scheme.Scheme,
})
Expect(err).NotTo(HaveOccurred())
go func() {
err = k8sManager.Start(ctrl.SetupSignalHandler())
Expect(err).NotTo(HaveOccurred())
}()
e2e.K8sClient = k8sManager.GetClient()
Expect(e2e.K8sClient).NotTo(BeNil())
close(done)
}, 60)
var _ = AfterSuite(func() {
By("tearing down the test environment")
err := testEnv.Stop()
Expect(err).NotTo(HaveOccurred())
})

View File

@ -59,7 +59,7 @@ GO_LDFLAGS_STATIC=-ldflags "-w $(CTIMEVAR) -extldflags -static"
GOOSARCHES = linux/amd64 GOOSARCHES = linux/amd64
PACKAGES = $(shell go list -f '{{.ImportPath}}/' ./... | grep -v vendor) PACKAGES = $(shell go list -f '{{.ImportPath}}/' ./... | grep -v vendor)
PACKAGES_FOR_UNIT_TESTS = $(shell go list -f '{{.ImportPath}}/' ./... | grep -v vendor | grep -v e2e | grep -v controllers) PACKAGES_FOR_UNIT_TESTS = $(shell go list -f '{{.ImportPath}}/' ./... | grep -v vendor | grep -v e2e | grep -v helm)
# Run all the e2e tests by default # Run all the e2e tests by default
E2E_TEST_SELECTOR ?= .* E2E_TEST_SELECTOR ?= .*