diff --git a/.pipeline-config-ci.yaml b/.pipeline-config-ci.yaml new file mode 100644 index 00000000..a0b01664 --- /dev/null +++ b/.pipeline-config-ci.yaml @@ -0,0 +1,56 @@ +version: '2' + +# CI Pipeline: code-checks, code-build, deploy-checks, deploy-release +tasks: + code-checks: + # code-checks includes five configurable steps: setup, detect-secrets, compliance-checks, peer-review, static-scan + include: + - dind + steps: + - name: checks-setup + when: 'false' + - name: detect-secrets + when: 'false' + include: + - docker-socket + - name: compliance-checks + when: 'false' + - name: peer-review + when: 'false' + - name: static-scan + when: 'false' + + code-build: + include: + - dind + # code-build includes five configurable steps: setup, unit-test, build-artifact, sign-artifact, scan-artifact + steps: + - name: setup + when: 'false' + - name: unit-test + include: + - docker-socket + - dind + image: icr.io/continuous-delivery/base-images/base:v1.21.0 + displayName: Build cert-manager operator image + script: | + #!/usr/bin/env bash + if [[ "$PIPELINE_DEBUG" == 1 ]]; then + trap env EXIT + env + set -x + fi + cd "$WORKSPACE/$(load_repo app-repo path)" + export DOCKER_REGISTRY="$(get_env DOCKER_REGISTRY)" + export DOCKER_USER="$(get_env DOCKER_USER)" + export DOCKER_PASS="$(get_env DOCKER_PASS)" + export BUILD_LOCALLY="$(get_env BUILD_LOCALLY)" + echo "Installing Go dependencies" + yum install -y -q golang + make images + - name: build-artifact + when: 'false' + - name: sign-artifact + when: 'false' + - name: scan-artifact + when: 'false' diff --git a/.pipeline-config-pr.yaml b/.pipeline-config-pr.yaml new file mode 100644 index 00000000..d4a1717c --- /dev/null +++ b/.pipeline-config-pr.yaml @@ -0,0 +1,137 @@ + +version: '2' + +# PR Pipeline: pr-code-checks, code-pr-finish +tasks: + pr-code-checks: + runtimeClassName: x86-xlarge + include: + - dind + steps: + - name: checks-setup + when: 'false' + - name: detect-secrets + when: 'false' + include: + - docker-socket + - name: unit-test + include: + - docker-socket + - dind + image: icr.io/continuous-delivery/base-images/base:v1.21.0 + displayName: Lint Check for cert-manager operator + script: | + #!/usr/bin/env bash + if [[ "$PIPELINE_DEBUG" == 1 ]]; then + trap env EXIT + env + set -x + fi + cd "$WORKSPACE/$(load_repo app-repo path)" + echo "Installing Go dependencies" + yum install -y -q golang + make check + - name: compliance-checks + when: 'false' + + pr-code-checks-test: + from: pr-code-checks + runtimeClassName: x86-xlarge + include: + - dind + steps: + - name: checks-setup + when: 'false' + - name: detect-secrets + when: 'false' + include: + - docker-socket + - name: unit-test + include: + - docker-socket + - dind + image: icr.io/continuous-delivery/base-images/base:v1.21.0 + displayName: Unit test for cert-manager operator + script: | + #!/usr/bin/env bash + if [[ "$PIPELINE_DEBUG" == 1 ]]; then + trap env EXIT + env + set -x + fi + cd "$WORKSPACE/$(load_repo app-repo path)" + echo "Installing Go dependencies" + yum install -y -q golang + make test + - name: compliance-checks + when: 'false' + + pr-pr-code-checks-binary-build: + from: pr-code-checks + runtimeClassName: x86-xlarge + include: + - dind + steps: + - name: checks-setup + when: 'false' + - name: detect-secrets + when: 'false' + include: + - docker-socket + - name: unit-test + include: + - docker-socket + - dind + image: icr.io/continuous-delivery/base-images/base:v1.21.0 + displayName: Build Binary for cert-manager operator + script: | + #!/usr/bin/env bash + if [[ "$PIPELINE_DEBUG" == 1 ]]; then + trap env EXIT + env + set -x + fi + cd "$WORKSPACE/$(load_repo app-repo path)" + echo "Installing Go dependencies" + yum install -y -q golang + make build + - name: compliance-checks + when: 'false' + + pr-code-checks-image-build: + from: pr-code-checks + runtimeClassName: x86-xlarge + include: + - dind + steps: + - name: checks-setup + when: 'false' + - name: detect-secrets + when: 'false' + include: + - docker-socket + - name: unit-test + include: + - docker-socket + - dind + image: icr.io/continuous-delivery/base-images/base:v1.21.0 + displayName: Build cert-manager operator image + script: | + #!/usr/bin/env bash + if [[ "$PIPELINE_DEBUG" == 1 ]]; then + trap env EXIT + env + set -x + fi + cd "$WORKSPACE/$(load_repo app-repo path)" + export DOCKER_REGISTRY="$(get_env DOCKER_REGISTRY)" + export DOCKER_USER="$(get_env DOCKER_USER)" + export DOCKER_PASS="$(get_env DOCKER_PASS)" + export GIT_COMMIT="$(get_env git-commit)" + export BUILD_VERSION="${GIT_COMMIT:0:7}" + export BUILD_LOCALLY="$(get_env BUILD_LOCALLY)" + echo "Installing Go dependencies" + yum install -y -q golang + make images + - name: compliance-checks + when: 'false' diff --git a/Makefile b/Makefile index 4333c483..dddf7138 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,10 @@ BUILD_LOCALLY ?= 1 ifeq ($(BUILD_LOCALLY),0) export CONFIG_DOCKER_TARGET = config-docker - REGISTRY ?= "hyc-cloud-private-integration-docker-local.artifactory.swg-devops.com/ibmcom" +endif + +ifdef DOCKER_REGISTRY + REGISTRY ?= $(DOCKER_REGISTRY) else REGISTRY ?= "hyc-cloud-private-scratch-docker-local.artifactory.swg-devops.com/ibmcom" endif @@ -32,7 +35,11 @@ PREV_VERSION ?= 3.18.0 # To re-generate a bundle for another specific version without changing the standard setup, you can: # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) -VERSION ?= 3.18.1 +ifdef BUILD_VERSION + VERSION ?= $(BUILD_VERSION) +else + VERSION ?= 4.2.19 +endif # CHANNELS define the bundle channels used in the bundle. # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") @@ -67,7 +74,7 @@ BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) # Image URL to use all building/pushing image targets IMG ?= ibm-cert-manager-operator # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.22 +ENVTEST_K8S_VERSION ?= 1.28 # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) # ifeq (,$(shell go env GOBIN)) @@ -76,10 +83,21 @@ ENVTEST_K8S_VERSION = 1.22 # GOBIN=$(shell go env GOBIN) # endif +PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) + +GOTOOLCHAIN ?= auto +export GOTOOLCHAIN + # Setting SHELL to bash allows bash commands to be executed by recipes. # This is a requirement for 'setup-envtest.sh' in the test target. # Options are set to exit when a recipe line exits non-zero or a piped command fails. SHELL = /usr/bin/env bash -o pipefail +HADOLINT_BIN ?= $(shell command -v hadolint 2>/dev/null) +ifeq ($(HADOLINT_BIN),) +HADOLINT_BIN := $(PROJECT_DIR)/bin/hadolint +endif +HADOLINT_VERSION ?= v2.12.0 + .SHELLFLAGS = -ec all: build @@ -97,6 +115,48 @@ all: build # More info on the awk command: # http://linuxcommand.org/lc3_adv_awk.php +SHELLCHECK_BIN ?= $(shell command -v shellcheck 2>/dev/null) +ifeq ($(SHELLCHECK_BIN),) +SHELLCHECK_BIN := $(PROJECT_DIR)/bin/shellcheck +endif +SHELLCHECK_VERSION ?= v0.10.0 + +.PHONY: shellcheck +shellcheck: ## Download shellcheck locally if necessary. + @if [ ! -x "$(SHELLCHECK_BIN)" ]; then \ + OS=$$(uname -s); \ + ARCH=$$(uname -m); \ + if [ "$$OS" = "Linux" ] && [ "$$ARCH" = "x86_64" ]; then \ + echo "Downloading shellcheck $(SHELLCHECK_VERSION) ..."; \ + mkdir -p $(PROJECT_DIR)/bin; \ + TMP_DIR=$$(mktemp -d); \ + ARCHIVE=$$TMP_DIR/shellcheck.tar.xz; \ + curl -sSL https://github.com/koalaman/shellcheck/releases/download/$(SHELLCHECK_VERSION)/shellcheck-$(SHELLCHECK_VERSION).linux.x86_64.tar.xz -o $$ARCHIVE; \ + if command -v xz >/dev/null 2>&1; then \ + tar -xf $$ARCHIVE -C $$TMP_DIR; \ + elif command -v python3 >/dev/null 2>&1; then \ + ARCHIVE_PATH="$$ARCHIVE" TMP_DIR_PATH="$$TMP_DIR" python3 -c "import io, os, tarfile, lzma, pathlib; archive=pathlib.Path(os.environ['ARCHIVE_PATH']); out=pathlib.Path(os.environ['TMP_DIR_PATH']); data=lzma.open(archive, 'rb').read(); tarfile.open(fileobj=io.BytesIO(data)).extractall(path=out)" || { rm -rf $$TMP_DIR; echo "Failed to extract shellcheck archive"; exit 1; }; \ + else \ + echo "shellcheck install requires 'xz' or Python 3 with lzma support"; \ + rm -rf $$TMP_DIR; \ + exit 1; \ + fi; \ + SC_BIN=$$(find $$TMP_DIR -type f -name shellcheck -perm -u+x | head -n 1); \ + if [ -z "$$SC_BIN" ]; then \ + echo "Unable to locate shellcheck binary in archive"; \ + rm -rf $$TMP_DIR; \ + exit 1; \ + fi; \ + mv "$$SC_BIN" $(PROJECT_DIR)/bin/shellcheck; \ + chmod +x $(PROJECT_DIR)/bin/shellcheck; \ + rm -rf $$TMP_DIR; \ + else \ + echo "shellcheck not found and automatic install unsupported for $$OS/$$ARCH"; \ + echo "Please install shellcheck manually and re-run make."; \ + exit 1; \ + fi; \ + fi + help: ## Display this help. @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) @@ -197,7 +257,7 @@ undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/confi CONTROLLER_GEN = $(shell pwd)/bin/controller-gen controller-gen: ## Download controller-gen locally if necessary. - $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.7.0) + $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.19.0) KUSTOMIZE = $(shell pwd)/bin/kustomize kustomize: ## Download kustomize locally if necessary. @@ -208,11 +268,11 @@ yq: ## Download kustomize locally if necessary. $(call go-get-tool,$(YQ),github.com/mikefarah/yq/v4@v4.17.2) ENVTEST = $(shell pwd)/bin/setup-envtest +ENVTEST_VERSION ?= latest envtest: ## Download envtest-setup locally if necessary. - $(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest) + $(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@$(ENVTEST_VERSION)) # go-get-tool will 'go get' any package $2 and install it to $1. -PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) define go-get-tool @[ -f $(1) ] || { \ set -e ;\ @@ -221,11 +281,41 @@ cd $$TMP_DIR ;\ go mod init tmp ;\ echo "Downloading $(2)" ;\ export GOSUMDB=sum.golang.org ;\ -GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\ +GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\ rm -rf $$TMP_DIR ;\ } endef +GOIMPORTS_VERSION ?= v0.36.0 +GOIMPORTS_BIN ?= $(PROJECT_DIR)/bin/goimports + +.PHONY: goimports +goimports: ## Download goimports locally if necessary. + $(call go-get-tool,$(GOIMPORTS_BIN),golang.org/x/tools/cmd/goimports@$(GOIMPORTS_VERSION)) + +HADOLINT_BIN ?= $(shell command -v hadolint 2>/dev/null) +ifeq ($(HADOLINT_BIN),) +HADOLINT_BIN := $(PROJECT_DIR)/bin/hadolint +endif +HADOLINT_VERSION ?= v2.12.0 + +.PHONY: hadolint +hadolint: ## Download hadolint locally if necessary. + @if [ ! -x "$(HADOLINT_BIN)" ]; then \ + OS=$$(uname -s); \ + ARCH=$$(uname -m); \ + if [ "$$OS" = "Linux" ] && [ "$$ARCH" = "x86_64" ]; then \ + echo "Downloading hadolint $(HADOLINT_VERSION) ..."; \ + mkdir -p $(PROJECT_DIR)/bin; \ + curl -sSL https://github.com/hadolint/hadolint/releases/download/$(HADOLINT_VERSION)/hadolint-$$OS-$$ARCH -o "$(PROJECT_DIR)/bin/hadolint"; \ + chmod +x "$(PROJECT_DIR)/bin/hadolint"; \ + else \ + echo "hadolint not found and automatic install unsupported for $$OS/$$ARCH"; \ + echo "Please install hadolint manually and re-run make."; \ + exit 1; \ + fi; \ + fi + .PHONY: bundle bundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files. common/scripts/patch-csv.sh v$(PREV_VERSION) $(VERSION) diff --git a/apis/acme.cert-manager/v1/groupversion_info.go b/apis/acme.cert-manager/v1/groupversion_info.go index 5c13a878..1fc1c80e 100644 --- a/apis/acme.cert-manager/v1/groupversion_info.go +++ b/apis/acme.cert-manager/v1/groupversion_info.go @@ -15,8 +15,8 @@ limitations under the License. */ // Package v1 contains API Schema definitions for the acme.cert-manager v1 API group -//+kubebuilder:object:generate=true -//+groupName=acme.cert-manager.io +// +kubebuilder:object:generate=true +// +groupName=acme.cert-manager.io package v1 import ( diff --git a/apis/cert-manager/v1/groupversion_info.go b/apis/cert-manager/v1/groupversion_info.go index c4710647..cc535f27 100644 --- a/apis/cert-manager/v1/groupversion_info.go +++ b/apis/cert-manager/v1/groupversion_info.go @@ -15,8 +15,8 @@ limitations under the License. */ // Package v1 contains API Schema definitions for the cert-manager v1 API group -//+kubebuilder:object:generate=true -//+groupName=cert-manager.io +// +kubebuilder:object:generate=true +// +groupName=cert-manager.io package v1 import ( diff --git a/apis/meta.cert-manager/v1/groupversion_info.go b/apis/meta.cert-manager/v1/groupversion_info.go index 9eb7e1bc..c3a219c8 100644 --- a/apis/meta.cert-manager/v1/groupversion_info.go +++ b/apis/meta.cert-manager/v1/groupversion_info.go @@ -15,8 +15,8 @@ limitations under the License. */ // Package v1 contains API Schema definitions for the meta.cert-manager v1 API group -//+kubebuilder:object:generate=true -//+groupName=meta.cert-manager.io +// +kubebuilder:object:generate=true +// +groupName=meta.cert-manager.io package v1 import ( diff --git a/apis/meta.cert-manager/v1/zz_generated.deepcopy.go b/apis/meta.cert-manager/v1/zz_generated.deepcopy.go index 9e402a65..63c9b01f 100644 --- a/apis/meta.cert-manager/v1/zz_generated.deepcopy.go +++ b/apis/meta.cert-manager/v1/zz_generated.deepcopy.go @@ -21,8 +21,6 @@ limitations under the License. package v1 -import () - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalObjectReference) DeepCopyInto(out *LocalObjectReference) { *out = *in diff --git a/apis/operator/v1alpha1/groupversion_info.go b/apis/operator/v1alpha1/groupversion_info.go index 94e9ee11..0efb19e5 100644 --- a/apis/operator/v1alpha1/groupversion_info.go +++ b/apis/operator/v1alpha1/groupversion_info.go @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package v1alpha1 contains API Schema definitions for the operator v1alpha1 API group -//+kubebuilder:object:generate=true -//+groupName=operator.ibm.com -package v1alpha1 +// Package v1 contains API Schema definitions for the operator v1 API group +// +kubebuilder:object:generate=true +// +groupName=operator.ibm.com +package v1 import ( "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/common/Makefile.common.mk b/common/Makefile.common.mk index ae68ed7b..07997266 100644 --- a/common/Makefile.common.mk +++ b/common/Makefile.common.mk @@ -27,8 +27,13 @@ endif get-cluster-credentials: activate-serviceaccount @gcloud container clusters get-credentials "$(CLUSTER)" --project="$(PROJECT)" --zone="$(ZONE)" -config-docker: get-cluster-credentials - @common/scripts/config_docker.sh +config-docker: + @echo "Configuring docker for building images" + @if [ -z "$(DOCKER_USER)" ] || [ -z "$(DOCKER_PASS)" ]; then \ + echo "Error: DOCKER_USER and DOCKER_PASS must be defined"; \ + exit 1; \ + fi + docker login -u $(DOCKER_USER) -p $(DOCKER_PASS) $(DOCKER_REGISTRY); \ ############################################################ # lint section @@ -49,17 +54,45 @@ FINDFILES=find . \( -path ./.git -o -path ./.github \) -prune -o -type f XARGS = xargs -0 ${XARGS_FLAGS} CLEANXARGS = xargs ${XARGS_FLAGS} -lint-dockerfiles: - @${FINDFILES} -name 'Dockerfile*' -print0 | ${XARGS} hadolint -c ./common/config/.hadolint.yml +GOIMPORTS_BIN ?= goimports +HADOLINT_BIN ?= hadolint +SHELLCHECK_BIN ?= shellcheck +YAMLLINT_BIN ?= $(shell command -v yamllint 2>/dev/null) +HELM_BIN ?= $(shell command -v helm 2>/dev/null) +MDL_BIN ?= $(shell command -v mdl 2>/dev/null) +AWESOME_BOT_BIN ?= $(shell command -v awesome_bot 2>/dev/null) +SASS_LINT_BIN ?= $(shell command -v sass-lint 2>/dev/null) +TSLINT_BIN ?= $(shell command -v tslint 2>/dev/null) +PROTOTOOL_BIN ?= $(shell command -v prototool 2>/dev/null) + +lint-dockerfiles: | hadolint + @if [ -z "$(HADOLINT_BIN)" ]; then \ + echo "Skipping lint-dockerfiles: hadolint not available."; \ + else \ + ${FINDFILES} -name 'Dockerfile*' -print0 | ${XARGS} $(HADOLINT_BIN) --config ./common/config/.hadolint.yml --failure-threshold error; \ + fi lint-scripts: - @${FINDFILES} -name '*.sh' -print0 | ${XARGS} shellcheck +lint-scripts: | shellcheck + @if [ -z "$(SHELLCHECK_BIN)" ]; then \ + echo "Skipping lint-scripts: shellcheck not available."; \ + else \ + ${FINDFILES} -name '*.sh' -print0 | ${XARGS} $(SHELLCHECK_BIN); \ + fi lint-yaml: - @${FINDFILES} \( -name '*.yml' -o -name '*.yaml' \) -print0 | { ${XARGS} grep -L -e "{{" || true; } | ${CLEANXARGS} yamllint -c ./common/config/.yamllint.yml + @if [ -z "$(YAMLLINT_BIN)" ]; then \ + echo "Skipping lint-yaml: yamllint not available."; \ + else \ + ${FINDFILES} \( -name '*.yml' -o -name '*.yaml' \) -print0 | { ${XARGS} grep -L -e "{{" || true; } | ${CLEANXARGS} $(YAMLLINT_BIN) -c ./common/config/.yamllint.yml; \ + fi lint-helm: - @${FINDFILES} -name 'Chart.yaml' -print0 | ${XARGS} -L 1 dirname | ${CLEANXARGS} helm lint + @if [ -z "$(HELM_BIN)" ]; then \ + echo "Skipping lint-helm: helm not available."; \ + else \ + ${FINDFILES} -name 'Chart.yaml' -print0 | ${XARGS} -L 1 dirname | ${CLEANXARGS} $(HELM_BIN) lint; \ + fi lint-copyright-banner: @${FINDFILES} \( -name '*.go' -o -name '*.cc' -o -name '*.h' -o -name '*.proto' -o -name '*.py' -o -name '*.sh' \) \( ! \( -name '*.gen.go' -o -name '*.pb.go' -o -name '*_pb2.py' \) \) -print0 |\ @@ -72,26 +105,50 @@ lint-python: @${FINDFILES} -name '*.py' \( ! \( -name '*_pb2.py' \) \) -print0 | ${XARGS} autopep8 --max-line-length 160 --exit-code -d lint-markdown: - @${FINDFILES} -name '*.md' -print0 | ${XARGS} mdl --ignore-front-matter --style common/config/mdl.rb + @if [ -z "$(MDL_BIN)" ]; then \ + echo "Skipping lint-markdown: mdl not available."; \ + else \ + ${FINDFILES} -name '*.md' -print0 | ${XARGS} $(MDL_BIN) --ignore-front-matter --style common/config/mdl.rb; \ + fi ifdef MARKDOWN_LINT_WHITELIST - @${FINDFILES} -name '*.md' -print0 | ${XARGS} awesome_bot --skip-save-results --allow_ssl --allow-timeout --allow-dupe --allow-redirect --white-list ${MARKDOWN_LINT_WHITELIST} + @if [ -z "$(AWESOME_BOT_BIN)" ]; then \ + echo "Skipping awesome_bot markdown lint: awesome_bot not available."; \ + else \ + ${FINDFILES} -name '*.md' -print0 | ${XARGS} $(AWESOME_BOT_BIN) --skip-save-results --allow_ssl --allow-timeout --allow-dupe --allow-redirect --white-list ${MARKDOWN_LINT_WHITELIST}; \ + fi else - @${FINDFILES} -name '*.md' -print0 | ${XARGS} awesome_bot --skip-save-results --allow_ssl --allow-timeout --allow-dupe --allow-redirect + @if [ -z "$(AWESOME_BOT_BIN)" ]; then \ + echo "Skipping awesome_bot markdown lint: awesome_bot not available."; \ + else \ + ${FINDFILES} -name '*.md' -print0 | ${XARGS} $(AWESOME_BOT_BIN) --skip-save-results --allow_ssl --allow-timeout --allow-dupe --allow-redirect; \ + fi endif lint-sass: - @${FINDFILES} -name '*.scss' -print0 | ${XARGS} sass-lint -c common/config/sass-lint.yml --verbose + @if [ -z "$(SASS_LINT_BIN)" ]; then \ + echo "Skipping lint-sass: sass-lint not available."; \ + else \ + ${FINDFILES} -name '*.scss' -print0 | ${XARGS} $(SASS_LINT_BIN) -c common/config/sass-lint.yml --verbose; \ + fi lint-typescript: - @${FINDFILES} -name '*.ts' -print0 | ${XARGS} tslint -c common/config/tslint.json + @if [ -z "$(TSLINT_BIN)" ]; then \ + echo "Skipping lint-typescript: tslint not available."; \ + else \ + ${FINDFILES} -name '*.ts' -print0 | ${XARGS} $(TSLINT_BIN) -c common/config/tslint.json; \ + fi lint-protos: - @$(FINDFILES) -name '*.proto' -print0 | $(XARGS) -L 1 prototool lint --protoc-bin-path=/usr/bin/protoc + @if [ -z "$(PROTOTOOL_BIN)" ]; then \ + echo "Skipping lint-protos: prototool not available."; \ + else \ + $(FINDFILES) -name '*.proto' -print0 | $(XARGS) -L 1 $(PROTOTOOL_BIN) lint --protoc-bin-path=/usr/bin/protoc; \ + fi lint-all: lint-dockerfiles lint-scripts lint-yaml lint-helm lint-copyright-banner lint-go lint-python lint-markdown lint-sass lint-typescript lint-protos -format-go: - @${FINDFILES} -name '*.go' \( ! \( -name '*.gen.go' -o -name '*.pb.go' \) \) -print0 | ${XARGS} goimports -w -local "github.com/IBM" +format-go: | goimports + @${FINDFILES} -name '*.go' \( ! \( -name '*.gen.go' -o -name '*.pb.go' \) \) -print0 | ${XARGS} $(GOIMPORTS_BIN) -w -local "github.com/IBM" format-python: @${FINDFILES} -name '*.py' -print0 | ${XARGS} autopep8 --max-line-length 160 --aggressive --aggressive -i diff --git a/config/crd/bases/cert-manager.io_certificates.yaml b/config/crd/bases/cert-manager.io_certificates.yaml index 10b967cc..ad14349c 100644 --- a/config/crd/bases/cert-manager.io_certificates.yaml +++ b/config/crd/bases/cert-manager.io_certificates.yaml @@ -4,8 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.19.0 name: certificates.cert-manager.io spec: group: cert-manager.io @@ -49,13 +48,11 @@ spec: name: v1 schema: openAPIV3Schema: - description: "A Certificate resource should be created to ensure an up to - date and signed x509 certificate is stored in the Kubernetes Secret resource - named in `spec.secretName`. Documentation For additional details regarding - install parameters check: https://ibm.biz/icpfs39install. License By installing - this product you accept the license terms https://ibm.biz/icpfs39license. - \n The stored certificate will be renewed before it expires (as configured - by `spec.renewBefore`)." + description: |- + A Certificate resource should be created to ensure an up to date and signed + x509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. Documentation For additional details regarding install parameters check: https://ibm.biz/icpfs39install. License By installing this product you accept the license terms https://ibm.biz/icpfs39license. + + The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`). properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -72,11 +69,41 @@ spec: spec: description: Desired state of the Certificate resource. properties: + additionalOutputFormats: + description: |- + Defines extra output formats of the private key and signed certificate chain + to be written to this Certificate's target Secret. + + This is an Alpha Feature and is only enabled with the + `--feature-gates=AdditionalCertificateOutputFormats=true` option set on both + the controller and webhook components. + items: + description: |- + CertificateAdditionalOutputFormat defines an additional output format of a + Certificate resource. These contain supplementary data formats of the signed + certificate chain and paired private key. + properties: + type: + description: |- + Type is the name of the format type that should be written to the + Certificate's target Secret. + enum: + - DER + - CombinedPEM + type: string + required: + - type + type: object + type: array commonName: - description: 'CommonName is a common name to be used on the Certificate. - The CommonName should have a length of 64 characters or fewer to - avoid generating invalid CSRs. This value is ignored by TLS clients - when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4' + description: |- + Requested common name X509 certificate subject attribute. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + NOTE: TLS clients will ignore this value when any subject alternative name is + set (see https://tools.ietf.org/html/rfc6125#section-6.4.4). + + Should have a length of 64 characters or fewer to avoid generating invalid CSRs. + Cannot be set if the `literalSubject` field is set. type: string dnsNames: description: DNSNames is a list of DNS subjectAltNames to be set on @@ -85,12 +112,14 @@ spec: type: string type: array duration: - description: The requested 'duration' (i.e. lifetime) of the Certificate. - This option may be ignored/overridden by some issuer types. If unset - this defaults to 90 days. Certificate will be renewed either 2/3 - through its duration or `renewBefore` period before its expiry, - whichever is later. Minimum accepted duration is 1 hour. Value must - be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + description: |- + Requested 'duration' (i.e. lifetime) of the Certificate. Note that the + issuer may choose to ignore the requested duration, just like any other + requested attribute. + + If unset, this defaults to 90 days. + Minimum accepted duration is 1 hour. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. type: string emailAddresses: description: EmailAddresses is a list of email subjectAltNames to @@ -99,8 +128,11 @@ spec: type: string type: array encodeUsagesInRequest: - description: EncodeUsagesInRequest controls whether key usages should - be present in the CertificateRequest + description: |- + Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR. + + This option defaults to true, and should only be disabled if the target + issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions. type: boolean ipAddresses: description: IPAddresses is a list of IP address subjectAltNames to @@ -109,17 +141,23 @@ spec: type: string type: array isCA: - description: IsCA will mark this Certificate as valid for certificate - signing. This will automatically add the `cert sign` usage to the - list of `usages`. + description: |- + Requested basic constraints isCA value. + The isCA value is used to set the `isCA` field on the created CertificateRequest + resources. Note that the issuer may choose to ignore the requested isCA value, just + like any other requested attribute. + + If true, this will automatically add the `cert sign` usage to the list + of requested `usages`. type: boolean issuerRef: - description: IssuerRef is a reference to the issuer for this certificate. - If the `kind` field is not set, or set to `Issuer`, an Issuer resource - with the given name in the same namespace as the Certificate will - be used. If the `kind` field is set to `ClusterIssuer`, a ClusterIssuer - with the provided name will be used. The `name` field in this stanza - is required at all times. + description: |- + Reference to the issuer responsible for issuing the certificate. + If the issuer is namespace-scoped, it must be in the same namespace + as the Certificate. If the issuer is cluster-scoped, it can be used + from any namespace. + + The `name` field of the reference must always be specified. properties: group: description: Group of the resource being referred to. @@ -208,64 +246,106 @@ spec: - passwordSecretRef type: object type: object + literalSubject: + description: |- + Requested X.509 certificate subject, represented using the LDAP "String + Representation of a Distinguished Name" [1]. + Important: the LDAP string format also specifies the order of the attributes + in the subject, this is important when issuing certs for LDAP authentication. + Example: `CN=foo,DC=corp,DC=example,DC=com` + More info [1]: https://datatracker.ietf.org/doc/html/rfc4514 + More info: https://github.com/cert-manager/cert-manager/issues/3203 + More info: https://github.com/cert-manager/cert-manager/issues/4424 + + Cannot be set if the `subject` or `commonName` field is set. + This is an Alpha Feature and is only enabled with the + `--feature-gates=LiteralCertificateSubject=true` option set on both + the controller and webhook components. + type: string privateKey: description: Options to control private keys used for the Certificate. properties: algorithm: - description: Algorithm is the private key algorithm of the corresponding - private key for this certificate. If provided, allowed values - are either `RSA` or `ECDSA` If `algorithm` is specified and - `size` is not provided, key size of 256 will be used for `ECDSA` - key algorithm and key size of 2048 will be used for `RSA` key - algorithm. + description: |- + Algorithm is the private key algorithm of the corresponding private key + for this certificate. + + If provided, allowed values are either `RSA`, `ECDSA` or `Ed25519`. + If `algorithm` is specified and `size` is not provided, + key size of 2048 will be used for `RSA` key algorithm and + key size of 256 will be used for `ECDSA` key algorithm. + key size is ignored when using the `Ed25519` key algorithm. enum: - RSA - ECDSA type: string encoding: - description: The private key cryptography standards (PKCS) encoding - for this certificate's private key to be encoded in. If provided, - allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 and - PKCS#8, respectively. Defaults to `PKCS1` if not specified. + description: |- + The private key cryptography standards (PKCS) encoding for this + certificate's private key to be encoded in. + + If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 + and PKCS#8, respectively. + Defaults to `PKCS1` if not specified. enum: - PKCS1 - PKCS8 type: string rotationPolicy: - description: RotationPolicy controls how private keys should be - regenerated when a re-issuance is being processed. If set to - Never, a private key will only be generated if one does not - already exist in the target `spec.secretName`. If one does exists - but it does not have the correct algorithm or size, a warning - will be raised to await user intervention. If set to Always, - a private key matching the specified requirements will be generated - whenever a re-issuance occurs. Default is 'Never' for backward - compatibility. + description: |- + RotationPolicy controls how private keys should be regenerated when a + re-issuance is being processed. + + If set to `Never`, a private key will only be generated if one does not + already exist in the target `spec.secretName`. If one does exists but it + does not have the correct algorithm or size, a warning will be raised + to await user intervention. + If set to `Always`, a private key matching the specified requirements + will be generated whenever a re-issuance occurs. + Default is `Never` for backward compatibility. + enum: + - Never + - Always type: string size: - description: Size is the key bit size of the corresponding private - key for this certificate. If `algorithm` is set to `RSA`, valid - values are `2048`, `4096` or `8192`, and will default to `2048` - if not specified. If `algorithm` is set to `ECDSA`, valid values - are `256`, `384` or `521`, and will default to `256` if not - specified. No other values are allowed. + description: |- + Size is the key bit size of the corresponding private key for this certificate. + + If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, + and will default to `2048` if not specified. + If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, + and will default to `256` if not specified. + If `algorithm` is set to `Ed25519`, Size is ignored. + No other values are allowed. type: integer type: object renewBefore: - description: How long before the currently issued certificate's expiry - cert-manager should renew the certificate. The default is 2/3 of - the issued certificate's duration. Minimum accepted value is 5 minutes. - Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + description: |- + How long before the currently issued certificate's expiry cert-manager should + renew the certificate. For example, if a certificate is valid for 60 minutes, + and `renewBefore=10m`, cert-manager will begin to attempt to renew the certificate + 50 minutes after it was issued (i.e. when there are 10 minutes remaining until + the certificate is no longer valid). + + NOTE: The actual lifetime of the issued certificate is used to determine the + renewal time. If an issuer returns a certificate with a different lifetime than + the one requested, cert-manager will use the lifetime of the issued certificate. + + If unset, this defaults to 1/3 of the issued certificate's lifetime. + Minimum accepted value is 5 minutes. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. type: string revisionHistoryLimit: - description: revisionHistoryLimit is the maximum number of CertificateRequest - revisions that are maintained in the Certificate's history. Each - revision represents a single `CertificateRequest` created by this - Certificate, either when it was created, renewed, or Spec was changed. - Revisions will be removed by oldest first if the number of revisions - exceeds this number. If set, revisionHistoryLimit must be a value - of `1` or greater. If unset (`nil`), revisions will not be garbage - collected. Default value is `nil`. + description: |- + The maximum number of CertificateRequest revisions that are maintained in + the Certificate's history. Each revision represents a single `CertificateRequest` + created by this Certificate, either when it was created, renewed, or Spec + was changed. Revisions will be removed by oldest first if the number of + revisions exceeds this number. + + If set, revisionHistoryLimit must be a value of `1` or greater. + If unset (`nil`), revisions will not be garbage collected. + Default value is `nil`. format: int32 type: integer secretName: @@ -275,7 +355,12 @@ spec: by the denoted issuer. type: string subject: - description: Full X509 name specification (https://golang.org/pkg/crypto/x509/pkix/#Name). + description: |- + Requested set of X509 certificate subject attributes. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + + The common name attribute is specified separately in the `commonName` field. + Cannot be set if the `literalSubject` field is set. properties: countries: description: Countries to be used on the Certificate. @@ -323,19 +408,44 @@ spec: type: string type: array usages: - description: Usages is the set of x509 usages that are requested for - the certificate. Defaults to `digital signature` and `key encipherment` - if not specified. + description: |- + Requested key usages and extended key usages. + These usages are used to set the `usages` field on the created CertificateRequest + resources. If `encodeUsagesInRequest` is unset or set to `true`, the usages + will additionally be encoded in the `request` field which contains the CSR blob. + + If unset, defaults to `digital signature` and `key encipherment`. items: - description: 'KeyUsage specifies valid usage contexts for keys. - See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 - Valid KeyUsage values are as follows: "signing", "digital signature", - "content commitment", "key encipherment", "key agreement", "data - encipherment", "cert sign", "crl sign", "encipher only", "decipher - only", "any", "server auth", "client auth", "code signing", "email - protection", "s/mime", "ipsec end system", "ipsec tunnel", "ipsec - user", "timestamping", "ocsp signing", "microsoft sgc", "netscape - sgc"' + description: |- + KeyUsage specifies valid usage contexts for keys. + See: + https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + + Valid KeyUsage values are as follows: + "signing", + "digital signature", + "content commitment", + "key encipherment", + "key agreement", + "data encipherment", + "cert sign", + "crl sign", + "encipher only", + "decipher only", + "any", + "server auth", + "client auth", + "code signing", + "email protection", + "s/mime", + "ipsec end system", + "ipsec tunnel", + "ipsec user", + "timestamping", + "ocsp signing", + "microsoft sgc", + "netscape sgc" enum: - signing - digital signature @@ -444,16 +554,21 @@ spec: format: date-time type: string revision: - description: "The current 'revision' of the certificate as issued. - \n When a CertificateRequest resource is created, it will have the + description: |- + The current 'revision' of the certificate as issued. + + When a CertificateRequest resource is created, it will have the `cert-manager.io/certificate-revision` set to one greater than the - current value of this field. \n Upon issuance, this field will be - set to the value of the annotation on the CertificateRequest resource - used to issue the certificate. \n Persisting the value on the CertificateRequest - resource allows the certificates controller to know whether a request - is part of an old issuance or if it is part of the ongoing revision's - issuance by checking if the revision value in the annotation is - greater than this field." + current value of this field. + + Upon issuance, this field will be set to the value of the annotation + on the CertificateRequest resource used to issue the certificate. + + Persisting the value on the CertificateRequest resource allows the + certificates controller to know whether a request is part of an old + issuance or if it is part of the ongoing revision's issuance by + checking if the revision value in the annotation is greater than this + field. type: integer type: object required: diff --git a/config/crd/bases/cert-manager.io_issuers.yaml b/config/crd/bases/cert-manager.io_issuers.yaml index 34950d82..c1f20d8d 100644 --- a/config/crd/bases/cert-manager.io_issuers.yaml +++ b/config/crd/bases/cert-manager.io_issuers.yaml @@ -4,8 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.19.0 name: issuers.cert-manager.io spec: group: cert-manager.io @@ -570,6 +569,180 @@ spec: domain names (e.g. `*.example.com`) using the HTTP01 challenge mechanism. properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + properties: + labels: + additionalProperties: + type: string + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, experimental, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, experimental, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + + + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener Name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port Name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. Note that attaching Routes to Services as Parents + is part of experimental Mesh support and is not supported for any other + purpose. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + type: array + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + type: object ingress: description: The ingress based HTTP01 challenge solver will solve challenges by creating or modifying Ingress @@ -1977,6 +2150,21 @@ spec: type: array type: object type: object + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: array nodeSelector: additionalProperties: type: string diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index f2384918..313b98a3 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -31,16 +31,6 @@ rules: - "" resources: - secrets - verbs: - - create - - delete - - get - - list - - update - - watch - - apiGroups: - - "" - resources: - serviceaccounts verbs: - create @@ -87,17 +77,6 @@ rules: - admissionregistration.k8s.io resources: - mutatingwebhookconfigurations - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - admissionregistration.k8s.io - resources: - validatingwebhookconfigurations verbs: - create @@ -135,7 +114,6 @@ rules: - apps resources: - daemonsets - - deployments - statefulsets verbs: - create @@ -175,6 +153,8 @@ rules: - cert-manager.io resources: - certificaterequests + - certificates + - issuers verbs: - create - delete @@ -188,37 +168,17 @@ rules: - cert-manager.io resources: - certificaterequests/finalizers - verbs: - - update - - apiGroups: - - cert-manager.io - resources: - certificaterequests/status - verbs: - - update - - apiGroups: - - cert-manager.io - resources: - - certificates - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - cert-manager.io - resources: - certificates/finalizers + - clusterissuers/status + - issuers/finalizers verbs: - update - apiGroups: - cert-manager.io resources: - certificates/status + - issuers/status verbs: - get - patch @@ -232,39 +192,6 @@ rules: - list - update - watch - - apiGroups: - - cert-manager.io - resources: - - clusterissuers/status - verbs: - - update - - apiGroups: - - cert-manager.io - resources: - - issuers - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - cert-manager.io - resources: - - issuers/finalizers - verbs: - - update - - apiGroups: - - cert-manager.io - resources: - - issuers/status - verbs: - - get - - patch - - update - apiGroups: - cert-manager.io resources: diff --git a/controllers/resources/util.go b/controllers/resources/util.go index a7688856..985265b6 100644 --- a/controllers/resources/util.go +++ b/controllers/resources/util.go @@ -25,7 +25,7 @@ import ( var log = logf.Log.WithName("resource_utils") -//GetImageID constructs image IDs for operands: either : or @ +// GetImageID constructs image IDs for operands: either : or @ func GetImageID(imageRegistry, imageName, defaultImageVersion, imagePostfix, envVarName string) string { //Check if the env var exists, if yes, check whether it's a SHA or tag and use accordingly; if no, use the default image version