diff --git a/.gitignore b/.gitignore index d1278242..76ff2649 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ bundle bundle/** bundle.Dockerfile charts/ +charts-unittest/ bundle*/ .vscode diff --git a/Makefile b/Makefile index c15e2cca..3e608280 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,18 @@ BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) # Image URL to use all building/pushing image targets IMG ?= controller:latest + +# Parse image components from IMG (e.g., quay.io/org/repo:tag) +# IMG_NO_TAG removes the tag portion +IMG_NO_TAG = $(firstword $(subst :, ,${IMG})) +# Count slashes to determine if registry is present +IMG_PARTS = $(subst /, ,$(IMG_NO_TAG)) +IMG_PARTS_COUNT = $(words $(IMG_PARTS)) +# If 3+ parts (registry/org/repo), first part is registry; otherwise empty +IMAGE_REGISTRY = $(if $(filter 3,$(IMG_PARTS_COUNT))$(filter 4,$(IMG_PARTS_COUNT))$(filter 5,$(IMG_PARTS_COUNT)),$(firstword $(IMG_PARTS)),) +# Repository is everything after registry (or full path if no registry) +IMAGE_REPO = $(if $(IMAGE_REGISTRY),$(subst $(IMAGE_REGISTRY)/,,$(IMG_NO_TAG)),$(IMG_NO_TAG)) + # Produce CRDs that work back to Kubernetes 1.11 (no version conversion) CRD_OPTIONS ?= "crd:trivialVersions=true,preserveUnknownFields=false" @@ -359,7 +371,7 @@ helmchart: helmchart-clean kustomize helm mv ./charts/${OPERATOR_NAME}/templates/apiextensions.k8s.io_v1_customresourcedefinition* ./charts/${OPERATOR_NAME}/crds cp ./config/helmchart/templates/* ./charts/${OPERATOR_NAME}/templates version=${VERSION} envsubst < ./config/helmchart/Chart.yaml.tpl > ./charts/${OPERATOR_NAME}/Chart.yaml - version=${VERSION} image_repo=$${IMG%:*} envsubst < ./config/helmchart/values.yaml.tpl > ./charts/${OPERATOR_NAME}/values.yaml + version=${VERSION} image_registry=${IMAGE_REGISTRY} image_repo=${IMAGE_REPO} envsubst < ./config/helmchart/values.yaml.tpl > ./charts/${OPERATOR_NAME}/values.yaml sed -i '1s/^/{{- if .Values.enableMonitoring }}\n/' ./charts/${OPERATOR_NAME}/templates/monitoring.coreos.com_v1_servicemonitor_${OPERATOR_NAME}-controller-manager-metrics-monitor.yaml echo {{- end }} >> ./charts/${OPERATOR_NAME}/templates/monitoring.coreos.com_v1_servicemonitor_${OPERATOR_NAME}-controller-manager-metrics-monitor.yaml sed -i 's/name: vault-config-operator-certs/{{- if .Values.enableCertManager }}\n name: vault-config-operator-metrics-service-cert\n {{- else }}\n name: vault-config-operator-certs\n {{- end }}/' ./charts/${OPERATOR_NAME}/templates/monitoring.coreos.com_v1_servicemonitor_${OPERATOR_NAME}-controller-manager-metrics-monitor.yaml @@ -384,7 +396,7 @@ HELM_TEST_IMG_TAG ?= helmchart-test # Deploy the helmchart to a kind cluster to test deployment. # If the test-metrics sidecar in the prometheus pod is ready, the metrics work and the test is successful. .PHONY: helmchart-test -helmchart-test: kind-setup deploy-vault helmchart +helmchart-test: kind-setup deploy-vault helmchart helmchart-unittest $(MAKE) IMG=${HELM_TEST_IMG_NAME}:${HELM_TEST_IMG_TAG} docker-build docker tag ${HELM_TEST_IMG_NAME}:${HELM_TEST_IMG_TAG} docker.io/library/${HELM_TEST_IMG_NAME}:${HELM_TEST_IMG_TAG} $(KIND) load docker-image ${HELM_TEST_IMG_NAME}:${HELM_TEST_IMG_TAG} docker.io/library/${HELM_TEST_IMG_NAME}:${HELM_TEST_IMG_TAG} @@ -403,6 +415,14 @@ helmchart-test: kind-setup deploy-vault helmchart $(KUBECTL) wait --namespace default --for=condition=ready pod prometheus-kube-prometheus-stack-prometheus-0 --timeout=180s $(KUBECTL) exec prometheus-kube-prometheus-stack-prometheus-0 -n default -c test-metrics -- /bin/sh -c "echo 'Example metrics...' && cat /tmp/ready" +.PHONY: helmchart-unittest +helmchart-unittest: helmchart helm-unittest + mkdir -p ./charts-unittest/ + rm -rf ./charts-unittest/${OPERATOR_NAME} + cp -r ./charts/${OPERATOR_NAME} ./charts-unittest/${OPERATOR_NAME} + cp -r ./config/helmchart/tests ./charts-unittest/${OPERATOR_NAME}/tests + $(HELM) unittest ./charts-unittest/${OPERATOR_NAME}/ + .PHONY: helmchart-clean helmchart-clean: rm -rf ./charts @@ -451,6 +471,10 @@ ifeq (,$(wildcard $(HELM))) mv ./bin/$${OS}-$${ARCH}/helm ${HELM} endif +.PHONY: helm-unittest +helm-unittest: helm ## Download helm unittest plugin locally. + ${HELM} plugin list | grep -q unittest || ${HELM} plugin install https://github.com/helm-unittest/helm-unittest.git + .PHONY: operator-sdk OPERATOR_SDK ?= $(LOCALBIN)/operator-sdk operator-sdk: ## Download operator-sdk locally if necessary. diff --git a/config/helmchart/.helmignore b/config/helmchart/.helmignore index 9433d34f..b0909c71 100644 --- a/config/helmchart/.helmignore +++ b/config/helmchart/.helmignore @@ -22,3 +22,5 @@ *.tmproj .vscode/ local-development/ +# helm unittest +tests \ No newline at end of file diff --git a/config/helmchart/templates/_helpers.tpl b/config/helmchart/templates/_helpers.tpl index 10c134f5..4c9c645a 100644 --- a/config/helmchart/templates/_helpers.tpl +++ b/config/helmchart/templates/_helpers.tpl @@ -50,3 +50,29 @@ Selector labels app.kubernetes.io/name: {{ include "vault-config-operator.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} + +{{/* +Return the proper image name +{{ include "vault-config-operator.image" ( dict "imageRoot" .Values.image "global" .Values.global "Chart" .Chart "context" $ ) }} +*/}} +{{- define "vault-config-operator.image" -}} +{{- $registryName := "" -}} +{{- $repositoryName := "" -}} +{{- $tag := .imageRoot.tag | default .Chart.AppVersion | toString -}} +{{- if .imageRoot.registry }} + {{- $registryName = tpl .imageRoot.registry .context -}} +{{- end -}} +{{- if .imageRoot.repository }} + {{- $repositoryName = tpl .imageRoot.repository .context -}} +{{- end -}} +{{- if .global }} + {{- if .global.imageRegistry }} + {{- $registryName = tpl .global.imageRegistry .context -}} + {{- end -}} +{{- end -}} +{{- if $registryName }} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- else }} + {{- printf "%s:%s" $repositoryName $tag -}} +{{- end -}} +{{- end -}} diff --git a/config/helmchart/templates/manager.yaml b/config/helmchart/templates/manager.yaml index e533a240..edae75b3 100644 --- a/config/helmchart/templates/manager.yaml +++ b/config/helmchart/templates/manager.yaml @@ -36,7 +36,7 @@ spec: - --tls-cert-file=/etc/certs/tls/tls.crt - --tls-private-key-file=/etc/certs/tls/tls.key - --v=0 - image: "{{ .Values.kube_rbac_proxy.image.repository }}:{{ .Values.kube_rbac_proxy.image.tag }}" + image: {{ include "vault-config-operator.image" ( dict "imageRoot" .Values.kube_rbac_proxy.image "global" .Values.global "Chart" .Chart "context" $ ) }} name: kube-rbac-proxy securityContext: {{- toYaml .Values.kube_rbac_proxy.securityContext | nindent 10 }} @@ -57,7 +57,7 @@ spec: {{- with .Values.args }} {{- toYaml . | nindent 8 }} {{- end }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + image: {{ include "vault-config-operator.image" ( dict "imageRoot" .Values.image "global" .Values.global "Chart" .Chart "context" $ ) }} imagePullPolicy: {{ .Values.image.pullPolicy }} volumeMounts: - name: webhook-service-cert diff --git a/config/helmchart/tests/image_test.yaml b/config/helmchart/tests/image_test.yaml new file mode 100644 index 00000000..ae97ec6c --- /dev/null +++ b/config/helmchart/tests/image_test.yaml @@ -0,0 +1,95 @@ +suite: Image repository and tag tests +templates: + - manager.yaml +tests: + - it: default values + asserts: + - isKind: + of: Deployment + - matchRegex: + path: spec.template.spec.containers[0].image + pattern: ^quay\.io/redhat-cop/kube-rbac-proxy:v\d+\.\d+\.\d+$ + - equal: + path: spec.template.spec.containers[1].image + value: controller:0.0.1 + - it: latest tag for operator + set: + image.tag: latest + asserts: + - isKind: + of: Deployment + - equal: + path: spec.template.spec.containers[1].image + value: controller:latest + - it: image repository and tag for operator + set: + image.repository: quay.io/redhat-cop/vault-config-operator + image.tag: 1.0.0 + asserts: + - isKind: + of: Deployment + - equal: + path: spec.template.spec.containers[1].image + value: quay.io/redhat-cop/vault-config-operator:1.0.0 + - it: image registry + set: + image.registry: quay.io + image.repository: redhat-cop/vault-config-operator + image.tag: 1.0.1 + asserts: + - isKind: + of: Deployment + - equal: + path: spec.template.spec.containers[1].image + value: quay.io/redhat-cop/vault-config-operator:1.0.1 + - it: global image registry + set: + global.imageRegistry: quay.io + asserts: + - isKind: + of: Deployment + - matchRegex: + path: spec.template.spec.containers[0].image + pattern: ^quay\.io/redhat-cop/kube-rbac-proxy:v\d+\.\d+\.\d+$ + - equal: + path: spec.template.spec.containers[1].image + value: quay.io/controller:0.0.1 + - it: image registry template + set: + global.containerImageRegistry: registry.example.com + image.registry: "{{.Values.global.containerImageRegistry}}" + image.repository: redhat-cop/vault-config-operator + image.tag: 1.0.1 + asserts: + - isKind: + of: Deployment + - equal: + path: spec.template.spec.containers[1].image + value: registry.example.com/redhat-cop/vault-config-operator:1.0.1 + - it: image repository template + set: + global.containerImageRegistry: registry.example.com + image.repository: "{{.Values.global.containerImageRegistry}}/redhat-cop/vault-config-operator" + image.tag: 1.0.1 + asserts: + - isKind: + of: Deployment + - matchRegex: + path: spec.template.spec.containers[0].image + pattern: ^quay\.io/redhat-cop/kube-rbac-proxy:v\d+\.\d+\.\d+$ + - equal: + path: spec.template.spec.containers[1].image + value: registry.example.com/redhat-cop/vault-config-operator:1.0.1 + - it: global image registry template + set: + global.containerImageRegistry: registry.example.com + global.imageRegistry: "{{.Values.global.containerImageRegistry}}" + asserts: + - isKind: + of: Deployment + - matchRegex: + path: spec.template.spec.containers[0].image + pattern: ^registry\.example\.com/redhat-cop/kube-rbac-proxy:v\d+\.\d+\.\d+$ + - equal: + path: spec.template.spec.containers[1].image + value: registry.example.com/controller:0.0.1 \ No newline at end of file diff --git a/config/helmchart/values.yaml.tpl b/config/helmchart/values.yaml.tpl index 8204ecf8..ac31c78f 100644 --- a/config/helmchart/values.yaml.tpl +++ b/config/helmchart/values.yaml.tpl @@ -2,9 +2,19 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. +# Global parameters +# Global Docker image registry +global: + imageRegistry: "" + imagePullSecrets: [] + # imagePullSecrets: + # - myRegistryKeySecretName + replicaCount: 1 image: + # image.registry -- Image registry (overridden by global.imageRegistry if set) + registry: ${image_registry} repository: ${image_repo} pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. @@ -41,7 +51,9 @@ affinity: {} kube_rbac_proxy: image: - repository: quay.io/redhat-cop/kube-rbac-proxy + # kube_rbac_proxy.image.registry -- Image registry (overridden by global.imageRegistry if set) + registry: quay.io + repository: redhat-cop/kube-rbac-proxy pullPolicy: IfNotPresent tag: v0.11.0 resources: