From 95353e8be6d283a20b57073036777dc3a351c7ac Mon Sep 17 00:00:00 2001 From: paulwilljones Date: Thu, 29 Aug 2024 11:30:56 +0100 Subject: [PATCH 1/7] Use basic auth when token endpoint is not found --- pkg/client/selfhosted/selfhosted.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/client/selfhosted/selfhosted.go b/pkg/client/selfhosted/selfhosted.go index 47982684..bc019164 100644 --- a/pkg/client/selfhosted/selfhosted.go +++ b/pkg/client/selfhosted/selfhosted.go @@ -34,6 +34,7 @@ const ( // HTTP headers to request API version dockerAPIv1Header = "application/vnd.docker.distribution.manifest.v1+json" + ociV1Header = "application/vnd.oci.image.manifest.v1+json" dockerAPIv2Header = "application/vnd.docker.distribution.manifest.v2+json" ) @@ -237,6 +238,7 @@ func (c *Client) doRequest(ctx context.Context, url, header string, obj interfac if len(header) > 0 { req.Header.Set("Accept", header) + req.Header.Set("Accept", ociV1Header) } resp, err := c.Do(req) From e44ccea21cae80172eb9f0fc910145f722032df2 Mon Sep 17 00:00:00 2001 From: paulwilljones Date: Thu, 29 Aug 2024 11:34:28 +0100 Subject: [PATCH 2/7] Add e2e test --- Makefile | 125 +++- .../version-checker/templates/deployment.yaml | 1 - make/00_mod.mk | 58 ++ make/02_mod.mk | 21 + make/_shared/helm/01_mod.mk | 16 + make/_shared/helm/deploy.mk | 54 ++ make/_shared/helm/helm.mk | 126 ++++ make/_shared/help/01_mod.mk | 22 + make/_shared/help/help.sh | 115 ++++ make/_shared/kind/00_kind_image_versions.mk | 34 + make/_shared/kind/00_mod.mk | 21 + make/_shared/kind/01_mod.mk | 16 + make/_shared/kind/kind-image-preload.mk | 61 ++ make/_shared/kind/kind.mk | 86 +++ make/_shared/oci-build/00_mod.mk | 125 ++++ make/_shared/oci-build/01_mod.mk | 90 +++ .../oci-build/image_tool/append_layers.go | 220 ++++++ .../image_tool/convert_to_docker_tar.go | 97 +++ make/_shared/oci-build/image_tool/go.mod | 19 + make/_shared/oci-build/image_tool/go.sum | 58 ++ .../oci-build/image_tool/list_digests.go | 46 ++ make/_shared/oci-build/image_tool/main.go | 46 ++ make/_shared/oci-publish/00_mod.mk | 58 ++ make/_shared/oci-publish/01_mod.mk | 127 ++++ make/_shared/oci-publish/image-exists.sh | 70 ++ make/_shared/tools/00_mod.mk | 627 ++++++++++++++++++ make/_shared/tools/util/checkhash.sh | 58 ++ make/_shared/tools/util/hash.sh | 27 + make/_shared/tools/util/lock.sh | 70 ++ make/config/kaniko/context.tar.gz | Bin 0 -> 174 bytes make/config/kaniko/context/dockerfile | 1 + make/config/kind/cluster.yaml | 32 + .../registry/docker-registry-values.yaml | 24 + make/config/version-checker-values.yaml | 7 + make/test-e2e.mk | 90 +++ make/test-unit.mk | 29 + test/e2e/manifests/docker-credentials.yaml | 7 + test/e2e/manifests/image-from-reg.yaml | 13 + test/e2e/manifests/pod-gcs.yaml | 65 ++ test/e2e/manifests/pod.yaml | 27 + test/e2e/manifests/volume.yaml | 27 + 41 files changed, 2797 insertions(+), 19 deletions(-) create mode 100644 make/00_mod.mk create mode 100644 make/02_mod.mk create mode 100644 make/_shared/helm/01_mod.mk create mode 100644 make/_shared/helm/deploy.mk create mode 100644 make/_shared/helm/helm.mk create mode 100644 make/_shared/help/01_mod.mk create mode 100755 make/_shared/help/help.sh create mode 100755 make/_shared/kind/00_kind_image_versions.mk create mode 100644 make/_shared/kind/00_mod.mk create mode 100644 make/_shared/kind/01_mod.mk create mode 100644 make/_shared/kind/kind-image-preload.mk create mode 100644 make/_shared/kind/kind.mk create mode 100644 make/_shared/oci-build/00_mod.mk create mode 100644 make/_shared/oci-build/01_mod.mk create mode 100644 make/_shared/oci-build/image_tool/append_layers.go create mode 100644 make/_shared/oci-build/image_tool/convert_to_docker_tar.go create mode 100644 make/_shared/oci-build/image_tool/go.mod create mode 100644 make/_shared/oci-build/image_tool/go.sum create mode 100644 make/_shared/oci-build/image_tool/list_digests.go create mode 100644 make/_shared/oci-build/image_tool/main.go create mode 100644 make/_shared/oci-publish/00_mod.mk create mode 100644 make/_shared/oci-publish/01_mod.mk create mode 100755 make/_shared/oci-publish/image-exists.sh create mode 100644 make/_shared/tools/00_mod.mk create mode 100755 make/_shared/tools/util/checkhash.sh create mode 100755 make/_shared/tools/util/hash.sh create mode 100755 make/_shared/tools/util/lock.sh create mode 100644 make/config/kaniko/context.tar.gz create mode 100644 make/config/kaniko/context/dockerfile create mode 100644 make/config/kind/cluster.yaml create mode 100644 make/config/registry/docker-registry-values.yaml create mode 100644 make/config/version-checker-values.yaml create mode 100644 make/test-e2e.mk create mode 100644 make/test-unit.mk create mode 100644 test/e2e/manifests/docker-credentials.yaml create mode 100644 test/e2e/manifests/image-from-reg.yaml create mode 100644 test/e2e/manifests/pod-gcs.yaml create mode 100644 test/e2e/manifests/pod.yaml create mode 100644 test/e2e/manifests/volume.yaml diff --git a/Makefile b/Makefile index 4aa48283..0d32b939 100644 --- a/Makefile +++ b/Makefile @@ -1,31 +1,120 @@ -BINDIR ?= $(CURDIR)/bin -ARCH ?= amd64 +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. -help: ## display this help - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n\nTargets:\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/Makefile instead. -.PHONY: help build image all clean +# NOTE FOR DEVELOPERS: "How do the Makefiles work and how can I extend them?" +# +# Shared Makefile logic lives in the make/_shared/ directory. The source of truth for these files +# lies outside of this repository, eg. in the cert-manager/makefile-modules repository. +# +# Logic specific to this repository must be defined in the make/00_mod.mk and make/02_mod.mk files: +# - The make/00_mod.mk file is included first and contains variable definitions needed by +# the shared Makefile logic. +# - The make/02_mod.mk file is included later, it can make use of most of the shared targets +# defined in the make/_shared/ directory (all targets defined in 00_mod.mk and 01_mod.mk). +# This file should be used to define targets specific to this repository. -deps: ## Download all Dependencies - go mod download +################################## -test: deps ## test version-checker - go test ./... -coverprofile=coverage.out +# Some modules build their dependencies from variables, we want these to be +# evalutated at the last possible moment. For this we use second expansion to +# re-evaluate the generate and verify targets a second time. +# +# See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html +.SECONDEXPANSION: -$(BINDIR): - mkdir -p $(BINDIR) +# For details on some of these "prelude" settings, see: +# https://clarkgrubb.com/makefile-style-guide +MAKEFLAGS += --warn-undefined-variables --no-builtin-rules +SHELL := /usr/bin/env bash +.SHELLFLAGS := -uo pipefail -c +.DEFAULT_GOAL := help +.DELETE_ON_ERROR: +.SUFFIXES: +FORCE: -build: deps $(BINDIR) ## build version-checker - CGO_ENABLED=0 go build -o ./bin/version-checker ./cmd/. +noop: # do nothing -verify: test build ## tests and builds version-checker +# Set empty value for MAKECMDGOALS to prevent the "warning: undefined variable 'MAKECMDGOALS'" +# warning from happening when running make without arguments +MAKECMDGOALS ?= image: ## build docker image GOARCH=$(ARCH) GOOS=linux CGO_ENABLED=0 go build -o ./bin/version-checker-linux ./cmd/. docker build -t quay.io/jetstack/version-checker:v0.9.0 . -clean: ## clean up created files - rm -rf \ - $(BINDIR) +################################## +# Host OS and architecture setup # +################################## -all: test build image ## runs test, build and image +# The reason we don't use "go env GOOS" or "go env GOARCH" is that the "go" +# binary may not be available in the PATH yet when the Makefiles are +# evaluated. HOST_OS and HOST_ARCH only support Linux, *BSD and macOS (M1 +# and Intel). +host_os := $(shell uname -s | tr A-Z a-z) +host_arch := $(shell uname -m) +HOST_OS ?= $(host_os) +HOST_ARCH ?= $(host_arch) + +ifeq (x86_64, $(HOST_ARCH)) + HOST_ARCH = amd64 +else ifeq (aarch64, $(HOST_ARCH)) + # linux reports the arm64 arch as aarch64 + HOST_ARCH = arm64 +endif + +################################## +# Git and versioning information # +################################## + +git_version := $(shell git describe --tags --always --match='v*' --abbrev=14 --dirty) +VERSION ?= $(git_version) +IS_PRERELEASE := $(shell git describe --tags --always --match='v*' --abbrev=0 | grep -q '-' && echo true || echo false) +GITCOMMIT := $(shell git rev-parse HEAD) +GITEPOCH := $(shell git show -s --format=%ct HEAD) + +################################## +# Global variables and dirs # +################################## + +bin_dir := _bin + +# The ARTIFACTS environment variable is set by the CI system to a directory +# where artifacts should be placed. These artifacts are then uploaded to a +# storage bucket by the CI system (https://docs.prow.k8s.io/docs/components/pod-utilities/). +# An example of such an artifact is a jUnit XML file containing test results. +# If the ARTIFACTS environment variable is not set, we default to a local +# directory in the _bin directory. +ARTIFACTS ?= $(bin_dir)/artifacts + +$(bin_dir) $(ARTIFACTS) $(bin_dir)/scratch: + mkdir -p $@ + +.PHONY: clean +## Clean all temporary files +## @category [shared] Tools +clean: + rm -rf $(bin_dir) + +################################## +# Include all the Makefiles # +################################## + +-include make/00_mod.mk +-include make/_shared/*/00_mod.mk +-include make/_shared/*/01_mod.mk +-include make/02_mod.mk +-include make/_shared/*/02_mod.mk diff --git a/deploy/charts/version-checker/templates/deployment.yaml b/deploy/charts/version-checker/templates/deployment.yaml index f483a0f8..6509335e 100644 --- a/deploy/charts/version-checker/templates/deployment.yaml +++ b/deploy/charts/version-checker/templates/deployment.yaml @@ -42,7 +42,6 @@ spec: ports: - name: metrics containerPort: 8080 - command: ["version-checker"] args: {{- include "version-checker.pod.args" . | nindent 8 }} resources: diff --git a/make/00_mod.mk b/make/00_mod.mk new file mode 100644 index 00000000..55cb460c --- /dev/null +++ b/make/00_mod.mk @@ -0,0 +1,58 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +repo_name := github.com/jetstack/version-checker + +kind_cluster_name := version-checker +kind_cluster_config := $(bin_dir)/scratch/kind_cluster.yaml + +build_names := manager + +go_manager_main_dir := ./cmd +go_manager_mod_dir := . +go_manager_ldflags := -X $(repo_name)/internal/version.AppVersion=$(VERSION) -X $(repo_name)/internal/version.GitCommit=$(GITCOMMIT) +oci_manager_base_image_flavor := static +oci_manager_image_name := quay.io/jetstack/version-checker +oci_manager_image_tag := $(VERSION) +oci_manager_image_name_development := version-checker.local/version-checker +oci_platforms := linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x + +deploy_name := version-checker +deploy_namespace := version-checker + +helm_chart_source_dir := deploy/charts/version-checker +helm_chart_name := version-checker +helm_chart_version := $(VERSION) +helm_labels_template_name := version-checker.labels +helm_docs_use_helm_tool := 1 +helm_generate_schema := 1 +helm_verify_values := 1 + +golangci_lint_config := .golangci.yaml + +define helm_values_mutation_function +$(YQ) \ + '( .image.repository = "$(oci_manager_image_name)" ) | \ + ( .image.tag = "$(oci_manager_image_tag)" )' \ + $1 --inplace +endef + +images_amd64 ?= +images_arm64 ?= + +images_amd64 += docker.io/kong/httpbin:0.1.0@sha256:9d65a5b1955d2466762f53ea50eebae76be9dc7e277217cd8fb9a24b004154f4 +images_arm64 += docker.io/kong/httpbin:0.1.0@sha256:c546c8b06c542b615f053b577707cb72ddc875a0731d56d0ffaf840f767322ad + +images_amd64 += quay.io/curl/curl:8.5.0@sha256:e40a76dcfa9405678336774130411ca35beba85db426d5755b3cdd7b99d09a7a +images_arm64 += quay.io/curl/curl:8.5.0@sha256:038b0290c9e4a371aed4f9d6993e3548fcfa32b96e9a170bfc73f5da4ec2354d diff --git a/make/02_mod.mk b/make/02_mod.mk new file mode 100644 index 00000000..f23d0984 --- /dev/null +++ b/make/02_mod.mk @@ -0,0 +1,21 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +$(kind_cluster_config): make/config/kind/cluster.yaml | $(bin_dir)/scratch + cat $< | \ + sed -e 's|{{KIND_IMAGES}}|$(CURDIR)/$(images_tar_dir)|g' \ + > $@ + +include make/test-e2e.mk +include make/test-unit.mk diff --git a/make/_shared/helm/01_mod.mk b/make/_shared/helm/01_mod.mk new file mode 100644 index 00000000..001c98af --- /dev/null +++ b/make/_shared/helm/01_mod.mk @@ -0,0 +1,16 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(dir $(lastword $(MAKEFILE_LIST)))/helm.mk +include $(dir $(lastword $(MAKEFILE_LIST)))/deploy.mk diff --git a/make/_shared/helm/deploy.mk b/make/_shared/helm/deploy.mk new file mode 100644 index 00000000..8bc6ebb4 --- /dev/null +++ b/make/_shared/helm/deploy.mk @@ -0,0 +1,54 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifndef deploy_name +$(error deploy_name is not set) +endif + +ifndef deploy_namespace +$(error deploy_namespace is not set) +endif + +# Install options allows the user configuration of extra flags +INSTALL_OPTIONS ?= + +########################################## + +.PHONY: install +## Install controller helm chart on the current active K8S cluster. +## @category [shared] Deployment +install: $(helm_chart_archive) | $(NEEDS_HELM) + $(HELM) upgrade $(deploy_name) $(helm_chart_archive) \ + --wait \ + --install \ + --create-namespace \ + $(INSTALL_OPTIONS) \ + --namespace $(deploy_namespace) + +.PHONY: uninstall +## Uninstall controller helm chart from the current active K8S cluster. +## @category [shared] Deployment +uninstall: | $(NEEDS_HELM) + $(HELM) uninstall $(deploy_name) \ + --wait \ + --namespace $(deploy_namespace) + +.PHONY: template +## Template the helm chart. +## @category [shared] Deployment +template: $(helm_chart_archive) | $(NEEDS_HELM) + @$(HELM) template $(deploy_name) $(helm_chart_archive) \ + --create-namespace \ + $(INSTALL_OPTIONS) \ + --namespace $(deploy_namespace) diff --git a/make/_shared/helm/helm.mk b/make/_shared/helm/helm.mk new file mode 100644 index 00000000..7a0cc909 --- /dev/null +++ b/make/_shared/helm/helm.mk @@ -0,0 +1,126 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifndef bin_dir +$(error bin_dir is not set) +endif + +ifndef repo_name +$(error repo_name is not set) +endif + +ifndef helm_chart_source_dir +$(error helm_chart_source_dir is not set) +endif + +ifndef helm_chart_name +$(error helm_chart_name is not set) +endif + +ifndef helm_chart_version +$(error helm_chart_version is not set) +endif + +ifndef helm_values_mutation_function +$(error helm_values_mutation_function is not set) +endif + +########################################## + +helm_chart_sources := $(shell find $(helm_chart_source_dir) -maxdepth 1 -type f) $(shell find $(helm_chart_source_dir)/templates -type f) +helm_chart_archive := $(bin_dir)/scratch/image/$(helm_chart_name)-$(helm_chart_version).tgz + +$(helm_chart_archive): $(helm_chart_sources) | $(NEEDS_HELM) $(NEEDS_YQ) $(bin_dir)/scratch/image + $(eval helm_chart_source_dir_versioned := $@.tmp) + rm -rf $(helm_chart_source_dir_versioned) + mkdir -p $(dir $(helm_chart_source_dir_versioned)) + cp -a $(helm_chart_source_dir) $(helm_chart_source_dir_versioned) + + $(call helm_values_mutation_function,$(helm_chart_source_dir_versioned)/values.yaml) + + @if ! $(YQ) -oy '.name' $(helm_chart_source_dir_versioned)/Chart.yaml | grep -q '^$(helm_chart_name)$$'; then \ + echo "Chart name does not match the name in the helm_chart_name variable"; \ + exit 1; \ + fi + + $(YQ) '.annotations."artifacthub.io/prerelease" = "$(IS_PRERELEASE)"' \ + --inplace $(helm_chart_source_dir_versioned)/Chart.yaml + + mkdir -p $(dir $@) + $(HELM) package $(helm_chart_source_dir_versioned) \ + --app-version $(helm_chart_version) \ + --version $(helm_chart_version) \ + --destination $(dir $@) + +.PHONY: helm-chart +## Create a helm chart +## @category [shared] Helm Chart +helm-chart: $(helm_chart_archive) + +ifdef helm_docs_use_helm_tool + +helm_tool_header_search ?= ^ +helm_tool_footer_search ?= ^ + +.PHONY: generate-helm-docs +## Generate Helm chart documentation. +## @category [shared] Generate/ Verify +generate-helm-docs: | $(NEEDS_HELM-TOOL) + $(HELM-TOOL) inject -i $(helm_chart_source_dir)/values.yaml -o $(helm_chart_source_dir)/README.md --header-search "$(helm_tool_header_search)" --footer-search "$(helm_tool_footer_search)" +else +.PHONY: generate-helm-docs +## Generate Helm chart documentation. +## @category [shared] Generate/ Verify +generate-helm-docs: | $(NEEDS_HELM-DOCS) + $(HELM-DOCS) $(helm_chart_source_dir)/ +endif + +shared_generate_targets += generate-helm-docs + +ifdef helm_generate_schema +.PHONY: generate-helm-schema +## Generate Helm chart schema. +## @category [shared] Generate/ Verify +generate-helm-schema: | $(NEEDS_HELM-TOOL) $(NEEDS_GOJQ) + $(HELM-TOOL) schema -i $(helm_chart_source_dir)/values.yaml | $(GOJQ) > $(helm_chart_source_dir)/values.schema.json + +shared_generate_targets += generate-helm-schema +endif + +ifdef helm_verify_values +.PHONY: verify-helm-values +## Verify Helm chart values using helm-tool. +## @category [shared] Generate/ Verify +verify-helm-values: | $(NEEDS_HELM-TOOL) $(NEEDS_GOJQ) + $(HELM-TOOL) lint -i $(helm_chart_source_dir)/values.yaml -d $(helm_chart_source_dir)/templates -e $(helm_chart_source_dir)/values.linter.exceptions + +shared_verify_targets += verify-helm-values +endif + +.PHONY: verify-pod-security-standards +## Verify that the Helm chart complies with the pod security standards. +## @category [shared] Generate/ Verify +verify-pod-security-standards: $(helm_chart_archive) | $(NEEDS_KYVERNO) $(NEEDS_KUSTOMIZE) $(NEEDS_HELM) + $(KYVERNO) apply <($(KUSTOMIZE) build https://github.com/kyverno/policies/pod-security/enforce) \ + --resource <($(HELM) template $(helm_chart_archive)) 2>/dev/null + +shared_verify_targets_dirty += verify-pod-security-standards + +.PHONY: verify-helm-lint +## Verify that the Helm chart is linted. +## @category [shared] Generate/ Verify +verify-helm-lint: $(helm_chart_archive) | $(NEEDS_HELM) + $(HELM) lint $(helm_chart_archive) + +shared_verify_targets_dirty += verify-helm-lint diff --git a/make/_shared/help/01_mod.mk b/make/_shared/help/01_mod.mk new file mode 100644 index 00000000..1a6a3b48 --- /dev/null +++ b/make/_shared/help/01_mod.mk @@ -0,0 +1,22 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +help_sh := $(dir $(lastword $(MAKEFILE_LIST)))/help.sh + +.PHONY: help +help: + @MAKEFILE_LIST="$(MAKEFILE_LIST)" \ + MAKE="$(MAKE)" \ + $(help_sh) diff --git a/make/_shared/help/help.sh b/make/_shared/help/help.sh new file mode 100755 index 00000000..400aab3d --- /dev/null +++ b/make/_shared/help/help.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash + +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +## 1. Build set of extracted line items + +EMPTYLINE_REGEX="^[[:space:]]*$" +DOCBLOCK_REGEX="^##[[:space:]]*(.*)$" +CATEGORY_REGEX="^##[[:space:]]*@category[[:space:]]*(.*)$" +TARGET_REGEX="^(([a-zA-Z0-9\_\/\%\$\(\)]|-)+):.*$" + +EMPTY_ITEM="" + +# shellcheck disable=SC2086 +raw_lines=$(cat ${MAKEFILE_LIST} | tr '\t' ' ' | grep -E "($TARGET_REGEX|$DOCBLOCK_REGEX|$EMPTYLINE_REGEX)") +extracted_lines="" +extracted_current="$EMPTY_ITEM" +max_target_length=0 + +## Extract all the commented targets from the Makefile +while read -r line; do + if [[ $line =~ $EMPTYLINE_REGEX ]]; then + # Reset current item. + extracted_current="$EMPTY_ITEM" + elif [[ $line =~ $CATEGORY_REGEX ]]; then + extracted_current=${extracted_current///${BASH_REMATCH[1]}} + elif [[ $line =~ $TARGET_REGEX ]]; then + # only keep the target if there is a comment + if [[ $extracted_current != *""* ]]; then + max_target_length=$(( ${#BASH_REMATCH[1]} > max_target_length ? ${#BASH_REMATCH[1]} : max_target_length )) + extracted_current=${extracted_current///${BASH_REMATCH[1]}} + extracted_lines="$extracted_lines\n$extracted_current" + fi + + extracted_current="$EMPTY_ITEM" + elif [[ $line =~ $DOCBLOCK_REGEX ]]; then + extracted_current=${extracted_current///${BASH_REMATCH[1]}} + fi +done <<< "$raw_lines" + +## 2. Build mapping for expanding targets + +ASSIGNMENT_REGEX="^(([a-zA-Z0-9\_\/\%\$\(\)]|-)+)[[:space:]]*:=[[:space:]]*(.*)$" + +raw_expansions=$(${MAKE} --dry-run --print-data-base noop | tr '\t' ' ' | grep -E "$ASSIGNMENT_REGEX") +extracted_expansions="" + +while read -r line; do + if [[ $line =~ $ASSIGNMENT_REGEX ]]; then + target=${BASH_REMATCH[1]} + expansion=${BASH_REMATCH[3]// /, } + extracted_expansions="$extracted_expansions\n$target$expansion" + fi +done <<< "$raw_expansions" + +## 3. Sort and print the extracted line items + +RULE_COLOR="$(TERM=xterm tput setaf 6)" +CATEGORY_COLOR="$(TERM=xterm tput setaf 3)" +CLEAR_STYLE="$(TERM=xterm tput sgr0)" +PURPLE=$(TERM=xterm tput setaf 125) + +extracted_lines=$(echo -e "$extracted_lines" | LC_ALL=C sort -r) +current_category="" + +## Print the help +echo "Usage: make [target1] [target2] ..." + +IFS=$'\n'; for line in $extracted_lines; do + category=$([[ $line =~ \(.*)\ ]] && echo "${BASH_REMATCH[1]}") + target=$([[ $line =~ \(.*)\ ]] && echo "${BASH_REMATCH[1]}") + comment=$([[ $line =~ \(.*)\ ]] && echo -e "${BASH_REMATCH[1]///\\n}") + + # Print the category header if it's changed + if [[ "$current_category" != "$category" ]]; then + current_category=$category + echo -e "\n${CATEGORY_COLOR}${current_category}${CLEAR_STYLE}" + fi + + # replace any $(...) with the actual value + if [[ $target =~ \$\((.*)\) ]]; then + new_target=$(echo -e "$extracted_expansions" | grep "${BASH_REMATCH[1]}" || true) + if [[ -n "$new_target" ]]; then + target=$([[ $new_target =~ \(.*)\ ]] && echo -e "${BASH_REMATCH[1]}") + fi + fi + + # Print the target and its multiline comment + is_first_line=true + while read -r comment_line; do + if [[ "$is_first_line" == true ]]; then + is_first_line=false + padding=$(( max_target_length - ${#target} )) + printf " %s%${padding}s ${PURPLE}>${CLEAR_STYLE} %s\n" "${RULE_COLOR}${target}${CLEAR_STYLE}" "" "${comment_line}" + else + printf " %${max_target_length}s %s\n" "" "${comment_line}" + fi + done <<< "$comment" +done diff --git a/make/_shared/kind/00_kind_image_versions.mk b/make/_shared/kind/00_kind_image_versions.mk new file mode 100755 index 00000000..aa9db20b --- /dev/null +++ b/make/_shared/kind/00_kind_image_versions.mk @@ -0,0 +1,34 @@ +# Copyright 2024 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is auto-generated by the learn_kind_images.sh script in the makefile-modules repo. +# Do not edit manually. + +kind_image_kindversion := v0.23.0 + +kind_image_kube_1.25_amd64 := docker.io/kindest/node:v1.25.16@sha256:06bd8a1c3af74cf360a524aa0c4a59922e023a1fb3526ee748609d4823f560f3 +kind_image_kube_1.25_arm64 := docker.io/kindest/node:v1.25.16@sha256:3b2127454d2e55a96e594debf450b80e87fe3273f0c7f74aa0c6be9972b8467e +kind_image_kube_1.26_amd64 := docker.io/kindest/node:v1.26.15@sha256:ad06ec62683fe300927150377e43df432da2228261bedf8eb2442fe5956d5e58 +kind_image_kube_1.26_arm64 := docker.io/kindest/node:v1.26.15@sha256:73f30c6f49b97aa178d14483dfb3ad47a1e014a53589ec02191c3fcd1df7cb71 +kind_image_kube_1.27_amd64 := docker.io/kindest/node:v1.27.13@sha256:30c5d91cab1f2915ad61f38b6279254397c433fc745b74533daa3c1e16617326 +kind_image_kube_1.27_arm64 := docker.io/kindest/node:v1.27.13@sha256:f72a6686e25f80052f37b177215a0a353ed23718d8ee2739cc17cfdb4b8feffb +kind_image_kube_1.28_amd64 := docker.io/kindest/node:v1.28.9@sha256:9ba4d311e7861d27b210e5960e5ce921a7c53d3c67e0545fd8a1cb9a76dfa2cb +kind_image_kube_1.28_arm64 := docker.io/kindest/node:v1.28.9@sha256:2bbf55860a6d38e25e5db113a1035f2286c87fb4f7b1594cfc3643a17b59351f +kind_image_kube_1.29_amd64 := docker.io/kindest/node:v1.29.4@sha256:ea40a6bd365a17f71fd3883a1d34a0791d7d6b0eb75832c6d85b6f2326827f1e +kind_image_kube_1.29_arm64 := docker.io/kindest/node:v1.29.4@sha256:e63a7f74e80b746328fbaa70be406639d0c31c8c8cf0a3d57efdd23c64fe4bba +kind_image_kube_1.30_amd64 := docker.io/kindest/node:v1.30.0@sha256:2af5d1b382926abcd6336312d652cd045b7cc47475844a608669c71b1fefcfbc +kind_image_kube_1.30_arm64 := docker.io/kindest/node:v1.30.0@sha256:5e4ce6f9033bdb9ce81a7fd699c8e67cfcacfab57076058e3e6f33c32036b42b + +kind_image_latest_amd64 := $(kind_image_kube_1.30_amd64) +kind_image_latest_arm64 := $(kind_image_kube_1.30_arm64) diff --git a/make/_shared/kind/00_mod.mk b/make/_shared/kind/00_mod.mk new file mode 100644 index 00000000..a4489159 --- /dev/null +++ b/make/_shared/kind/00_mod.mk @@ -0,0 +1,21 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(dir $(lastword $(MAKEFILE_LIST)))/00_kind_image_versions.mk + +images_amd64 ?= +images_arm64 ?= + +images_amd64 += $(kind_image_latest_amd64) +images_arm64 += $(kind_image_latest_arm64) diff --git a/make/_shared/kind/01_mod.mk b/make/_shared/kind/01_mod.mk new file mode 100644 index 00000000..a7eb1b2b --- /dev/null +++ b/make/_shared/kind/01_mod.mk @@ -0,0 +1,16 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(dir $(lastword $(MAKEFILE_LIST)))/kind.mk +include $(dir $(lastword $(MAKEFILE_LIST)))/kind-image-preload.mk diff --git a/make/_shared/kind/kind-image-preload.mk b/make/_shared/kind/kind-image-preload.mk new file mode 100644 index 00000000..e95c9ee4 --- /dev/null +++ b/make/_shared/kind/kind-image-preload.mk @@ -0,0 +1,61 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifndef bin_dir +$(error bin_dir is not set) +endif + +ifndef images_amd64 +$(error images_amd64 is not set) +endif + +ifndef images_arm64 +$(error images_arm64 is not set) +endif + +########################################## + +images := $(images_$(HOST_ARCH)) +images_files := $(foreach image,$(images),$(subst :,+,$(image))) + +images_tar_dir := $(bin_dir)/downloaded/containers/$(HOST_ARCH) +images_tars := $(images_files:%=$(images_tar_dir)/%.tar) + +# Download the images as tarballs. We must use the tag because the digest +# will change after we docker import the image. The tag is the only way to +# reference the image after it has been imported. Before downloading the +# image, we check that the provided digest matches the digest of the image +# that we are about to pull. +$(images_tars): $(images_tar_dir)/%.tar: | $(NEEDS_CRANE) + @$(eval image=$(subst +,:,$*)) + @$(eval image_without_digest=$(shell cut -d@ -f1 <<<"$(image)")) + @$(eval digest=$(subst $(image_without_digest)@,,$(image))) + @mkdir -p $(dir $@) + diff <(echo "$(digest) -" | cut -d: -f2) <($(CRANE) manifest --platform=linux/$(HOST_ARCH) $(image_without_digest) | sha256sum) + $(CRANE) pull $(image_without_digest) $@ --platform=linux/$(HOST_ARCH) + +images_tar_envs := $(images_files:%=env-%) + +.PHONY: $(images_tar_envs) +$(images_tar_envs): env-%: $(images_tar_dir)/%.tar | $(NEEDS_GOJQ) + @$(eval image_without_tag=$(shell cut -d+ -f1 <<<"$*")) + @$(eval $(image_without_tag).TAR="$(images_tar_dir)/$*.tar") + @$(eval $(image_without_tag).REPO=$(shell tar xfO "$(images_tar_dir)/$*.tar" manifest.json | $(GOJQ) '.[0].RepoTags[0]' -r | cut -d: -f1)) + @$(eval $(image_without_tag).TAG=$(shell tar xfO "$(images_tar_dir)/$*.tar" manifest.json | $(GOJQ) '.[0].RepoTags[0]' -r | cut -d: -f2)) + @$(eval $(image_without_tag).FULL=$($(image_without_tag).REPO):$($(image_without_tag).TAG)) + +.PHONY: images-preload +## Preload images. +## @category [shared] Kind cluster +images-preload: | $(images_tar_envs) diff --git a/make/_shared/kind/kind.mk b/make/_shared/kind/kind.mk new file mode 100644 index 00000000..c768c8d1 --- /dev/null +++ b/make/_shared/kind/kind.mk @@ -0,0 +1,86 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifndef bin_dir +$(error bin_dir is not set) +endif + +ifndef kind_cluster_name +$(error kind_cluster_name is not set) +endif + +ifndef kind_cluster_config +$(error kind_cluster_config is not set) +endif + +########################################## + +kind_kubeconfig := $(bin_dir)/scratch/kube.config +absolute_kubeconfig := $(CURDIR)/$(kind_kubeconfig) + +$(bin_dir)/scratch/cluster-check: FORCE | $(NEEDS_KIND) $(bin_dir)/scratch + @if ! $(KIND) get clusters -q | grep -q "^$(kind_cluster_name)\$$"; then \ + echo "❌ cluster $(kind_cluster_name) not found. Starting ..."; \ + echo "trigger" > $@; \ + else \ + echo "✅ existing cluster $(kind_cluster_name) found"; \ + fi + $(eval export KUBECONFIG=$(absolute_kubeconfig)) + +kind_post_create_hook ?= +$(kind_kubeconfig): $(kind_cluster_config) $(bin_dir)/scratch/cluster-check | images-preload $(bin_dir)/scratch $(NEEDS_KIND) $(NEEDS_KUBECTL) $(NEEDS_CTR) + @[ -f "$(bin_dir)/scratch/cluster-check" ] && ( \ + $(KIND) delete cluster --name $(kind_cluster_name); \ + $(CTR) load -i $(docker.io/kindest/node.TAR); \ + $(KIND) create cluster \ + --image $(docker.io/kindest/node.FULL) \ + --name $(kind_cluster_name) \ + --config "$<"; \ + $(CTR) exec $(kind_cluster_name)-control-plane find /mounted_images/ -name "*.tar" -exec echo {} \; -exec ctr --namespace=k8s.io images import --all-platforms --no-unpack --digests {} \; ; \ + $(MAKE) --no-print-directory noop $(kind_post_create_hook); \ + $(KUBECTL) config use-context kind-$(kind_cluster_name); \ + ) || true + + $(KIND) get kubeconfig --name $(kind_cluster_name) > $@ + +.PHONY: kind-cluster +kind-cluster: $(kind_kubeconfig) + +.PHONY: kind-cluster-load +## Create Kind cluster and wait for nodes to be ready +## Load the kubeconfig into the default location so that +## it can be easily queried by kubectl. This target is +## meant to be used directly, NOT as a dependency. +## Use `kind-cluster` as a dependency instead. +## @category [shared] Kind cluster +kind-cluster-load: kind-cluster | $(NEEDS_KUBECTL) + mkdir -p ~/.kube + KUBECONFIG=~/.kube/config:$(kind_kubeconfig) $(KUBECTL) config view --flatten > ~/.kube/config + $(KUBECTL) config use-context kind-$(kind_cluster_name) + +.PHONY: kind-cluster-clean +## Delete the Kind cluster +## @category [shared] Kind cluster +kind-cluster-clean: $(NEEDS_KIND) + $(KIND) delete cluster --name $(kind_cluster_name) + rm -rf $(kind_kubeconfig) + $(MAKE) --no-print-directory noop $(kind_post_create_hook) + +.PHONY: kind-logs +## Get the Kind cluster +## @category [shared] Kind cluster +kind-logs: | kind-cluster $(NEEDS_KIND) $(bin_dir)/artifacts + rm -rf $(bin_dir)/artifacts/e2e-logs + mkdir -p $(bin_dir)/artifacts/e2e-logs + $(KIND) export logs $(bin_dir)/artifacts/e2e-logs --name=$(kind_cluster_name) diff --git a/make/_shared/oci-build/00_mod.mk b/make/_shared/oci-build/00_mod.mk new file mode 100644 index 00000000..b7e2b0b4 --- /dev/null +++ b/make/_shared/oci-build/00_mod.mk @@ -0,0 +1,125 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +oci_platforms ?= linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le + +# Use distroless as minimal base image to package the manager binary +# To get latest SHA run "crane digest quay.io/jetstack/base-static:latest" +base_image_static := quay.io/jetstack/base-static@sha256:262e3020adb3b09ddbf9cd8fe672330451a556c8e7024142fa205c8876c3fd75 + +# Use custom apko-built image as minimal base image to package the manager binary +# To get latest SHA run "crane digest quay.io/jetstack/base-static-csi:latest" +base_image_csi-static := quay.io/jetstack/base-static-csi@sha256:f776795838d73f9836b134f688b4c827fcd7ed22f46d3cefcb9f57d668388fef + +# Utility functions +fatal_if_undefined = $(if $(findstring undefined,$(origin $1)),$(error $1 is not set)) + +# Validate globals that are required +$(call fatal_if_undefined,bin_dir) +$(call fatal_if_undefined,build_names) + +# Set default config values +CGO_ENABLED ?= 0 +GOEXPERIMENT ?= # empty by default + +# Default variables per build_names entry +# +# $1 - build_name +define default_per_build_variables +cgo_enabled_$1 ?= $(CGO_ENABLED) +goexperiment_$1 ?= $(GOEXPERIMENT) +oci_additional_layers_$1 ?= +endef + +$(foreach build_name,$(build_names),$(eval $(call default_per_build_variables,$(build_name)))) + +# Validate variables per build_names entry +# +# $1 - build_name +define check_per_build_variables +# Validate required config exists +$(call fatal_if_undefined,go_$1_ldflags) +$(call fatal_if_undefined,go_$1_main_dir) +$(call fatal_if_undefined,go_$1_mod_dir) +$(call fatal_if_undefined,oci_$1_base_image_flavor) +$(call fatal_if_undefined,oci_$1_image_name_development) + +# Validate we have valid base image config +ifeq ($(oci_$1_base_image_flavor),static) + oci_$1_base_image := $(base_image_static) +else ifeq ($(oci_$1_base_image_flavor),csi-static) + oci_$1_base_image := $(base_image_csi-static) +else ifeq ($(oci_$1_base_image_flavor),custom) + $$(call fatal_if_undefined,oci_$1_base_image) +else + $$(error oci_$1_base_image_flavor has unknown value "$(oci_$1_base_image_flavor)") +endif + +# Validate the config required to build the golang based images +ifneq ($(go_$1_main_dir:.%=.),.) +$$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES start with ".") +endif +ifeq ($(go_$1_main_dir:%/=/),/) +$$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES NOT end with "/") +endif +ifeq ($(go_$1_main_dir:%.go=.go),.go) +$$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES NOT end with ".go") +endif +ifneq ($(go_$1_mod_dir:.%=.),.) +$$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES start with ".") +endif +ifeq ($(go_$1_mod_dir:%/=/),/) +$$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES NOT end with "/") +endif +ifeq ($(go_$1_mod_dir:%.go=.go),.go) +$$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES NOT end with ".go") +endif +ifeq ($(wildcard $(go_$1_mod_dir)/go.mod),) +$$(error go_$1_mod_dir "$(go_$1_mod_dir)" does not contain a go.mod file) +endif +ifeq ($(wildcard $(go_$1_mod_dir)/$(go_$1_main_dir)/main.go),) +$$(error go_$1_main_dir "$(go_$1_mod_dir)" does not contain a main.go file) +endif + +# Validate the config required to build OCI images +ifneq ($(words $(oci_$1_image_name_development)),1) +$$(error oci_$1_image_name_development "$(oci_$1_image_name_development)" should be a single image name) +endif + +endef + +$(foreach build_name,$(build_names),$(eval $(call check_per_build_variables,$(build_name)))) + +# Create variables holding targets +# +# We create the following targets for each $(build_names) +# - oci-build-$(build_name) = build the oci directory +# - oci-load-$(build_name) = load the image into docker using the oci_$(build_name)_image_name_development variable +# - docker-tarball-$(build_name) = build a "docker load" compatible tarball of the image +# - ko-config-$(build_name) = generate "ko" config for a given build +oci_build_targets := $(build_names:%=oci-build-%) +oci_load_targets := $(build_names:%=oci-load-%) +docker_tarball_targets := $(build_names:%=docker-tarball-%) +ko_config_targets := $(build_names:%=ko-config-%) + +# Derive config based on user config +# +# - oci_layout_path_$(build_name) = path that the OCI image will be saved in OCI layout directory format +# - oci_digest_path_$(build_name) = path to the file that will contain the digests +# - ko_config_path_$(build_name) = path to the ko config file +# - docker_tarball_path_$(build_name) = path that the docker tarball that the docker-tarball-$(build_name) will produce +$(foreach build_name,$(build_names),$(eval oci_layout_path_$(build_name) := $(bin_dir)/scratch/image/oci-layout-$(build_name).$(oci_$(build_name)_image_tag))) +$(foreach build_name,$(build_names),$(eval oci_digest_path_$(build_name) := $(CURDIR)/$(oci_layout_path_$(build_name)).digests)) +$(foreach build_name,$(build_names),$(eval ko_config_path_$(build_name) := $(CURDIR)/$(oci_layout_path_$(build_name)).ko_config.yaml)) +$(foreach build_name,$(build_names),$(eval docker_tarball_path_$(build_name) := $(CURDIR)/$(oci_layout_path_$(build_name)).docker.tar)) diff --git a/make/_shared/oci-build/01_mod.mk b/make/_shared/oci-build/01_mod.mk new file mode 100644 index 00000000..ca6fc926 --- /dev/null +++ b/make/_shared/oci-build/01_mod.mk @@ -0,0 +1,90 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Utility variables +current_makefile = $(lastword $(MAKEFILE_LIST)) +current_makefile_directory = $(dir $(current_makefile)) + +# Build the image tool +image_tool_dir := $(current_makefile_directory:/=)/image_tool +IMAGE_TOOL := $(CURDIR)/$(bin_dir)/tools/image_tool +NEEDS_IMAGE_TOOL := $(bin_dir)/tools/image_tool +$(NEEDS_IMAGE_TOOL): $(wildcard $(image_tool_dir)/*.go) | $(NEEDS_GO) + cd $(image_tool_dir) && GOWORK=off GOBIN=$(CURDIR)/$(dir $@) $(GO) install . + +define ko_config_target +.PHONY: $(ko_config_path_$1:$(CURDIR)/%=%) +$(ko_config_path_$1:$(CURDIR)/%=%): | $(NEEDS_YQ) $(bin_dir)/scratch/image + echo '{}' | \ + $(YQ) '.defaultBaseImage = "$(oci_$1_base_image)"' | \ + $(YQ) '.builds[0].id = "$1"' | \ + $(YQ) '.builds[0].dir = "$(go_$1_mod_dir)"' | \ + $(YQ) '.builds[0].main = "$(go_$1_main_dir)"' | \ + $(YQ) '.builds[0].env[0] = "CGO_ENABLED=$(cgo_enabled_$1)"' | \ + $(YQ) '.builds[0].env[1] = "GOEXPERIMENT=$(goexperiment_$1)"' | \ + $(YQ) '.builds[0].ldflags[0] = "-s"' | \ + $(YQ) '.builds[0].ldflags[1] = "-w"' | \ + $(YQ) '.builds[0].ldflags[2] = "{{.Env.LDFLAGS}}"' \ + > $(CURDIR)/$(oci_layout_path_$1).ko_config.yaml + +ko-config-$1: $(ko_config_path_$1:$(CURDIR)/%=%) +endef + +.PHONY: $(ko_config_targets) +$(foreach build_name,$(build_names),$(eval $(call ko_config_target,$(build_name)))) + +.PHONY: $(oci_build_targets) +## Build the OCI image. +## @category [shared] Build +$(oci_build_targets): oci-build-%: ko-config-% | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS_YQ) $(NEEDS_IMAGE_TOOL) $(bin_dir)/scratch/image + rm -rf $(CURDIR)/$(oci_layout_path_$*) + GOWORK=off \ + KO_DOCKER_REPO=$(oci_$*_image_name_development) \ + KOCACHE=$(CURDIR)/$(bin_dir)/scratch/image/ko_cache \ + KO_CONFIG_PATH=$(ko_config_path_$*) \ + SOURCE_DATE_EPOCH=$(GITEPOCH) \ + KO_GO_PATH=$(GO) \ + LDFLAGS="$(go_$*_ldflags)" \ + $(KO) build $(go_$*_mod_dir)/$(go_$*_main_dir) \ + --platform=$(oci_platforms) \ + --oci-layout-path=$(oci_layout_path_$*) \ + --sbom-dir=$(CURDIR)/$(oci_layout_path_$*).sbom \ + --sbom=spdx \ + --push=false \ + --bare + + $(IMAGE_TOOL) append-layers \ + $(CURDIR)/$(oci_layout_path_$*) \ + $(oci_additional_layers_$*) + + $(IMAGE_TOOL) list-digests \ + $(CURDIR)/$(oci_layout_path_$*) \ + > $(oci_digest_path_$*) + +# Only include the oci-load target if kind is provided by the kind makefile-module +ifdef kind_cluster_name +.PHONY: $(oci_load_targets) +## Build OCI image for the local architecture and load +## it into the $(kind_cluster_name) kind cluster. +## @category [shared] Build +$(oci_load_targets): oci-load-%: docker-tarball-% | kind-cluster $(NEEDS_KIND) + $(KIND) load image-archive --name $(kind_cluster_name) $(docker_tarball_path_$*) +endif + +## Build Docker tarball image for the local architecture +## @category [shared] Build +.PHONY: $(docker_tarball_targets) +$(docker_tarball_targets): oci_platforms := "linux/$(HOST_ARCH)" +$(docker_tarball_targets): docker-tarball-%: oci-build-% | $(NEEDS_GO) $(NEEDS_IMAGE_TOOL) + $(IMAGE_TOOL) convert-to-docker-tar $(CURDIR)/$(oci_layout_path_$*) $(docker_tarball_path_$*) $(oci_$*_image_name_development):$(oci_$*_image_tag) \ No newline at end of file diff --git a/make/_shared/oci-build/image_tool/append_layers.go b/make/_shared/oci-build/image_tool/append_layers.go new file mode 100644 index 00000000..6af65e85 --- /dev/null +++ b/make/_shared/oci-build/image_tool/append_layers.go @@ -0,0 +1,220 @@ +/* +Copyright 2023 The cert-manager Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "archive/tar" + "bytes" + "io" + "io/fs" + "log/slog" + "os" + "path/filepath" + + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/layout" + "github.com/google/go-containerregistry/pkg/v1/match" + "github.com/google/go-containerregistry/pkg/v1/mutate" + "github.com/google/go-containerregistry/pkg/v1/tarball" + "github.com/google/go-containerregistry/pkg/v1/types" + "github.com/spf13/cobra" +) + +var CommandAppendLayers = cobra.Command{ + Use: "append-layers oci-path [path-to-tarball...]", + Short: "Appends a tarball or directory to every image in an OCI index.", + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + oci := args[0] + extra := args[1:] + + if len(extra) == 0 { + return + } + + path, err := layout.FromPath(oci) + must("could not load oci directory", err) + + index, err := path.ImageIndex() + must("could not load oci image index", err) + + layers := []untypedLayer{} + for _, path := range extra { + layers = append(layers, newUntypedLayerFromPath(path)) + } + + index = mutateImage(index, func(img v1.Image) v1.Image { + imgMediaType, err := img.MediaType() + must("could not get image media type", err) + + layerType := types.DockerLayer + if imgMediaType == types.OCIManifestSchema1 { + layerType = types.OCILayer + } + + for _, untypedLayer := range layers { + layer, err := untypedLayer.ToLayer(layerType) + must("could not load image layer", err) + + img, err = mutate.AppendLayers(img, layer) + must("could not append layer", err) + } + + return img + }) + + _, err = layout.Write(oci, index) + must("could not write image", err) + }, +} + +type untypedLayer struct { + tarball tarball.Opener +} + +func newUntypedLayer(tarball tarball.Opener) untypedLayer { + return untypedLayer{tarball: tarball} +} + +func newUntypedLayerFromPath(path string) untypedLayer { + stat, err := os.Stat(path) + must("could not open directory or tarball", err) + + var layer untypedLayer + if stat.IsDir() { + var buf bytes.Buffer + + tw := tar.NewWriter(&buf) + + filepath.Walk(path, func(target string, info fs.FileInfo, err error) error { + must("walk error", err) + + header, err := tar.FileInfoHeader(info, info.Name()) + must("could not create tar header", err) + + name, err := filepath.Rel(path, target) + must("could not build relative path", err) + + // Write simplified header, this removes all fields that would cause + // the build to be non-reproducible (like modtime for example) + err = tw.WriteHeader(&tar.Header{ + Typeflag: header.Typeflag, + Name: name, + Mode: header.Mode, + Linkname: header.Linkname, + Size: header.Size, + }) + + must("could not write tar header", err) + + if !info.IsDir() { + file, err := os.Open(target) + must("could not write tar contents", err) + + defer file.Close() + + _, err = io.Copy(tw, file) + must("could not write tar contents", err) + } + + return nil + }) + + tw.Close() + + byts := buf.Bytes() + + layer = newUntypedLayer( + func() (io.ReadCloser, error) { + return io.NopCloser(bytes.NewReader(byts)), nil + }, + ) + } else { + layer = newUntypedLayer( + func() (io.ReadCloser, error) { + return os.Open(path) + }, + ) + } + + return layer +} + +func (ul untypedLayer) ToLayer(mediaType types.MediaType) (v1.Layer, error) { + return tarball.LayerFromOpener(ul.tarball, tarball.WithMediaType(mediaType)) +} + +type imageMutateFn func(index v1.Image) v1.Image + +func mutateImage(index v1.ImageIndex, fn imageMutateFn) v1.ImageIndex { + manifest, err := index.IndexManifest() + must("could not load oci image manifest", err) + + for _, descriptor := range manifest.Manifests { + switch { + case descriptor.MediaType.IsImage(): + slog.Info("found image", "digest", descriptor.Digest, "platform", descriptor.Platform) + + img, err := index.Image(descriptor.Digest) + must("could not load oci image with digest", err) + + img = fn(img) + + digest, err := img.Digest() + must("could not get image digest", err) + + size, err := img.Size() + must("could not get image size", err) + + slog.Info("appended layers to image", "old_digest", descriptor.Digest, "digest", digest, "platform", descriptor.Platform) + + index = mutate.RemoveManifests(index, match.Digests(descriptor.Digest)) + + descriptor.Digest = digest + descriptor.Size = size + index = mutate.AppendManifests(index, mutate.IndexAddendum{ + Add: img, + Descriptor: descriptor, + }) + + case descriptor.MediaType.IsIndex(): + slog.Info("found image index", "digest", descriptor.Digest) + + child, err := index.ImageIndex(descriptor.Digest) + must("could not load oci index manifest", err) + + child = mutateImage(child, fn) + + digest, err := child.Digest() + must("could not get index digest", err) + + size, err := child.Size() + must("could not get index size", err) + + index = mutate.RemoveManifests(index, match.Digests(descriptor.Digest)) + + descriptor.Digest = digest + descriptor.Size = size + index = mutate.AppendManifests(index, mutate.IndexAddendum{ + Add: child, + Descriptor: descriptor, + }) + } + } + + return index +} diff --git a/make/_shared/oci-build/image_tool/convert_to_docker_tar.go b/make/_shared/oci-build/image_tool/convert_to_docker_tar.go new file mode 100644 index 00000000..c6e1e269 --- /dev/null +++ b/make/_shared/oci-build/image_tool/convert_to_docker_tar.go @@ -0,0 +1,97 @@ +/* +Copyright 2023 The cert-manager Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "runtime" + + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/layout" + "github.com/google/go-containerregistry/pkg/v1/match" + "github.com/google/go-containerregistry/pkg/v1/tarball" + "github.com/spf13/cobra" +) + +var CommandConvertToDockerTar = cobra.Command{ + Use: "convert-to-docker-tar oci-path output image-name", + Short: "Reads the OCI directory and outputs a tarball that is compatible with \"docker load\"", + Args: cobra.ExactArgs(3), + Run: func(cmd *cobra.Command, args []string) { + path := args[0] + output := args[1] + imageName := args[2] + + ociLayout, err := layout.FromPath(path) + must("could not load oci directory", err) + + index, err := ociLayout.ImageIndex() + must("could not load oci image index", err) + + images := getImagesFromIndex(index, func(desc v1.Descriptor) bool { + return desc.Platform != nil && desc.Platform.Architecture == runtime.GOARCH + }) + + switch { + case len(images) == 0: + fail("no matching images found") + case len(images) > 1: + fail("multiple matching images found") + } + + ref, err := name.ParseReference(imageName) + must("invalid image name", err) + + err = tarball.WriteToFile(output, ref, images[0]) + must("could not write tarball", err) + }, +} + +func getImagesFromIndex(index v1.ImageIndex, matcher match.Matcher) (images []v1.Image) { + manifest, err := index.IndexManifest() + must("could not load oci index manifest", err) + + for _, descriptor := range manifest.Manifests { + switch { + case descriptor.MediaType.IsImage(): + // If the platform is not part of the index manifest, attempt to + // load it from the image config + if descriptor.Platform == nil { + img, err := index.Image(descriptor.Digest) + must("could not load image", err) + + cfg, err := img.ConfigFile() + must("could not load image config", err) + + descriptor.Platform = cfg.Platform() + } + + if matcher(descriptor) { + img, err := index.Image(descriptor.Digest) + must("could not load image", err) + images = append(images, img) + } + + case descriptor.MediaType.IsIndex(): + idx, err := index.ImageIndex(descriptor.Digest) + must("could not load image index", err) + images = append(images, getImagesFromIndex(idx, matcher)...) + } + } + + return +} diff --git a/make/_shared/oci-build/image_tool/go.mod b/make/_shared/oci-build/image_tool/go.mod new file mode 100644 index 00000000..51f647bf --- /dev/null +++ b/make/_shared/oci-build/image_tool/go.mod @@ -0,0 +1,19 @@ +module image_tool + +go 1.21 + +require ( + github.com/google/go-containerregistry v0.20.2 + github.com/spf13/cobra v1.8.1 +) + +require ( + github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/klauspost/compress v1.16.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc3 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/vbatts/tar-split v0.11.3 // indirect + golang.org/x/sync v0.2.0 // indirect +) diff --git a/make/_shared/oci-build/image_tool/go.sum b/make/_shared/oci-build/image_tool/go.sum new file mode 100644 index 00000000..56873bb9 --- /dev/null +++ b/make/_shared/oci-build/image_tool/go.sum @@ -0,0 +1,58 @@ +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= +github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= +github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= +github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= +github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= +github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.1 h1:Ou41VVR3nMWWmTiEUnj0OlsgOSCUFgsPAOl6jRIcVtQ= +github.com/sirupsen/logrus v1.9.1/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= +github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= +github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/make/_shared/oci-build/image_tool/list_digests.go b/make/_shared/oci-build/image_tool/list_digests.go new file mode 100644 index 00000000..e08d9489 --- /dev/null +++ b/make/_shared/oci-build/image_tool/list_digests.go @@ -0,0 +1,46 @@ +/* +Copyright 2023 The cert-manager Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + + "github.com/google/go-containerregistry/pkg/v1/layout" + "github.com/spf13/cobra" +) + +var CommandListDigests = cobra.Command{ + Use: "list-digests oci-path", + Short: "Outputs the digests for images found inside the tarball", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + path := args[0] + + ociLayout, err := layout.FromPath(path) + must("could not load oci directory", err) + + imageIndex, err := ociLayout.ImageIndex() + must("could not load oci image index", err) + + indexManifest, err := imageIndex.IndexManifest() + must("could not load oci index manifest", err) + + for _, man := range indexManifest.Manifests { + fmt.Println(man.Digest) + } + }, +} diff --git a/make/_shared/oci-build/image_tool/main.go b/make/_shared/oci-build/image_tool/main.go new file mode 100644 index 00000000..507281e7 --- /dev/null +++ b/make/_shared/oci-build/image_tool/main.go @@ -0,0 +1,46 @@ +/* +Copyright 2023 The cert-manager Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var CommandRoot = cobra.Command{ + Use: "image-tool", +} + +func main() { + CommandRoot.AddCommand(&CommandAppendLayers) + CommandRoot.AddCommand(&CommandConvertToDockerTar) + CommandRoot.AddCommand(&CommandListDigests) + must("error running command", CommandRoot.Execute()) +} + +func must(msg string, err error) { + if err != nil { + fail(msg+": %w", err) + } +} + +func fail(msg string, a ...any) { + fmt.Fprintf(os.Stderr, msg+"\n", a...) + os.Exit(1) +} diff --git a/make/_shared/oci-publish/00_mod.mk b/make/_shared/oci-publish/00_mod.mk new file mode 100644 index 00000000..f27062ad --- /dev/null +++ b/make/_shared/oci-publish/00_mod.mk @@ -0,0 +1,58 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Push names is equivilent to build_names, additional names can be added for +# pushing images that are not build with the oci-build module +push_names ?= +push_names += $(build_names) + +# Sometimes we need to push to one registry, but pull from another. This allows +# that. +# +# The lines should be in the format a=b +# +# The value on the left is the domain you include in your oci__image_name +# variable, the one on the right is the domain that is actually pushed to. +# +# For example, if we set up a vanity domain for the current quay: +# +# oci_controller_image_name = registry.cert-manager.io/cert-manager-controller` +# image_registry_rewrite += registry.cert-manager.io=quay.io/jetstack +# +# This would push to quay.io/jetstack/cert-manager-controller. +# +# The general idea is oci__image_name contains the final image name, after replication, after vanity domains etc. + +image_registry_rewrite ?= + +# Utilities for extracting the key and value from a foo=bar style line +kv_key = $(word 1,$(subst =, ,$1)) +kv_value = $(word 2,$(subst =, ,$1)) + +# Apply the image_registry_rewrite rules, if no rules match an image then the +# image name is not changed. Any rules that match will be applied. +# +# For example, if there was a rule vanity-domain.com=real-registry.com/foo +# then any references to vanity-domain.com/image would be rewritten to +# real-registry.com/foo/image +image_registry_rewrite_rules_for_image = $(strip $(sort $(foreach rule,$(image_registry_rewrite),$(if $(findstring $(call kv_key,$(rule)),$1),$(rule))))) +apply_image_registry_rewrite_rules_to_image = $(if $(call image_registry_rewrite_rules_for_image,$1),\ + $(foreach rule,$(call image_registry_rewrite_rules_for_image,$1),$(subst $(call kv_key,$(rule)),$(call kv_value,$(rule)),$1)),\ + $1) +apply_image_registry_rewrite_rules = $(foreach image_name,$1,$(call apply_image_registry_rewrite_rules_to_image,$(image_name))) + +# This is a helper function to return the image names for a given build_name. +# It will apply all rewrite rules to the image names +oci_image_names_for = $(call apply_image_registry_rewrite_rules,$(oci_$1_image_name)) +oci_image_tag_for = $(oci_$1_image_tag) \ No newline at end of file diff --git a/make/_shared/oci-publish/01_mod.mk b/make/_shared/oci-publish/01_mod.mk new file mode 100644 index 00000000..348490c9 --- /dev/null +++ b/make/_shared/oci-publish/01_mod.mk @@ -0,0 +1,127 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Utility functions +fatal_if_undefined = $(if $(findstring undefined,$(origin $1)),$(error $1 is not set)) +oci_digest = $(shell head -1 $(oci_digest_path_$1) 2> /dev/null) +sanitize_target = $(subst :,-,$1) +registry_for = $(firstword $(subst /, ,$1)) + +# Utility variables +current_makefile_directory := $(dir $(lastword $(MAKEFILE_LIST))) +image_exists_script := $(current_makefile_directory)/image-exists.sh + +# Validate globals that are required +$(call fatal_if_undefined,bin_dir) +$(call fatal_if_undefined,push_names) + +# Set default config values +RELEASE_DRYRUN ?= false +CRANE_FLAGS ?= # empty by default +COSIGN_FLAGS ?= # empty by default +OCI_SIGN_ON_PUSH ?= true + +# Default variables per push_names entry +# +# $1 - build_name +define default_per_build_variables +release_dryrun_$1 ?= $(RELEASE_DRYRUN) +crane_flags_$1 ?= $(CRANE_FLAGS) +cosign_flags_$1 ?= $(COSIGN_FLAGS) +oci_sign_on_push_$1 ?= $(OCI_SIGN_ON_PUSH) +endef + +$(foreach build_name,$(push_names),$(eval $(call default_per_build_variables,$(build_name)))) + +# Validate variables per push_names entry +# +# $1 - build_name +define check_per_build_variables +$(call fatal_if_undefined,oci_digest_path_$1) +$(call fatal_if_undefined,oci_layout_path_$1) +$(call fatal_if_undefined,oci_$1_image_name) +$(call fatal_if_undefined,oci_$1_image_tag) +endef + +$(foreach build_name,$(push_names),$(eval $(call check_per_build_variables,$(build_name)))) + +# Create variables holding targets +# +# We create the following targets for each $(push_names) +# - oci-build-$(build_name) = build the oci directory +# - oci-load-$(build_name) = load the image into docker using the oci_$(build_name)_image_name_development variable +# - docker-tarball-$(build_name) = build a "docker load" compatible tarball of the image +# - ko-config-$(build_name) = generate "ko" config for a given build +oci_push_targets := $(push_names:%=oci-push-%) +oci_sign_targets := $(push_names:%=oci-sign-%) +oci_maybe_push_targets := $(push_names:%=oci-maybe-push-%) + +# Define push target +# $1 - build_name +# $2 - image_name +define oci_push_target +.PHONY: $(call sanitize_target,oci-push-$2) +$(call sanitize_target,oci-push-$2): oci-build-$1 | $(NEEDS_CRANE) + $$(CRANE) $(crane_flags_$1) push "$(oci_layout_path_$1)" "$2:$(call oci_image_tag_for,$1)" + $(if $(filter true,$(oci_sign_on_push_$1)),$(MAKE) $(call sanitize_target,oci-sign-$2)) + +.PHONY: $(call sanitize_target,oci-maybe-push-$2) +$(call sanitize_target,oci-maybe-push-$2): oci-build-$1 | $(NEEDS_CRANE) + CRANE="$$(CRANE) $(crane_flags_$1)" \ + source $(image_exists_script) $2:$(call oci_image_tag_for,$1); \ + $$(CRANE) $(crane_flags_$1) push "$(oci_layout_path_$1)" "$2:$(call oci_image_tag_for,$1)"; \ + $(if $(filter true,$(oci_sign_on_push_$1)),$(MAKE) $(call sanitize_target,oci-sign-$2)) + +oci-push-$1: $(call sanitize_target,oci-push-$2) +oci-maybe-push-$1: $(call sanitize_target,oci-maybe-push-$2) +endef + +oci_push_target_per_image = $(foreach image_name,$2,$(eval $(call oci_push_target,$1,$(image_name)))) +$(foreach build_name,$(push_names),$(eval $(call oci_push_target_per_image,$(build_name),$(call oci_image_names_for,$(build_name))))) + +.PHONY: $(oci_push_targets) +## Build and push OCI image. +## If the tag already exists, this target will overwrite it. +## If an identical image was already built before, we will add a new tag to it, but we will not sign it again. +## Expected pushed images: +## - :v1.2.3, @sha256:0000001 +## - :v1.2.3.sig, :sha256-0000001.sig +## @category [shared] Publish +$(oci_push_targets): + +.PHONY: $(oci_maybe_push_targets) +## Push image if tag does not already exist in registry. +## @category [shared] Publish +$(oci_maybe_push_targets): + +# Define sign target +# $1 - build_name +# $2 - image_name +define oci_sign_target +.PHONY: $(call sanitize_target,oci-sign-$2) +$(call sanitize_target,oci-sign-$2): $(oci_digest_path_$1) | $(NEEDS_CRANE) $(NEEDS_COSIGN) + $$(CRANE) $(crane_flags_$1) manifest $2:$$(subst :,-,$$(call oci_digest,$1)).sig > /dev/null 2>&1 || \ + $$(COSIGN) sign --yes=true $(cosign_flags_$1) "$2@$$(call oci_digest,$1)" + +oci-sign-$1: $(call sanitize_target,oci-sign-$2) +endef + +oci_sign_target_per_image = $(foreach image_name,$2,$(eval $(call oci_sign_target,$1,$(image_name)))) +$(foreach build_name,$(push_names),$(eval $(call oci_sign_target_per_image,$(build_name),$(call oci_image_names_for,$(build_name))))) + +.PHONY: $(oci_sign_targets) +## Sign an OCI image. +## If a signature already exists, this will not overwrite it. +## @category [shared] Publish +$(oci_sign_targets): \ No newline at end of file diff --git a/make/_shared/oci-publish/image-exists.sh b/make/_shared/oci-publish/image-exists.sh new file mode 100755 index 00000000..9ecbb61a --- /dev/null +++ b/make/_shared/oci-publish/image-exists.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +# Copyright 2022 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +# This script checks if a given image exists in the upstream registry, and if it +# does, whether it contains all the expected architectures. + +crane=${CRANE:-} + +FULL_IMAGE=${1:-} + +function print_usage() { + echo "usage: $0 [commands...]" +} + +if [[ -z $FULL_IMAGE ]]; then + print_usage + echo "Missing full-image" + exit 1 +fi + +if [[ -z $crane ]]; then + echo "CRANE environment variable must be set to the path of the crane binary" + exit 1 +fi + +shift 1 + +manifest=$(mktemp) +trap 'rm -f "$manifest"' EXIT SIGINT + +manifest_error=$(mktemp) +trap 'rm -f "$manifest_error"' EXIT SIGINT + +echo "+++ searching for $FULL_IMAGE in upstream registry" + +set +o errexit +$crane manifest "$FULL_IMAGE" > "$manifest" 2> "$manifest_error" +exit_code=$? +set -o errexit + +manifest_error_data=$(cat "$manifest_error") +if [[ $exit_code -eq 0 ]]; then + echo "+++ upstream registry appears to contain $FULL_IMAGE, exiting" + exit 0 + +elif [[ "$manifest_error_data" == *"MANIFEST_UNKNOWN"* ]]; then + echo "+++ upstream registry does not contain $FULL_IMAGE, will build and push" + # fall through to run the commands passed to this script + +else + echo "FATAL: upstream registry returned an unexpected error: $manifest_error_data, exiting" + exit 1 +fi diff --git a/make/_shared/tools/00_mod.mk b/make/_shared/tools/00_mod.mk new file mode 100644 index 00000000..234c005a --- /dev/null +++ b/make/_shared/tools/00_mod.mk @@ -0,0 +1,627 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifndef bin_dir +$(error bin_dir is not set) +endif + +########################################## + +export DOWNLOAD_DIR ?= $(CURDIR)/$(bin_dir)/downloaded +export GOVENDOR_DIR ?= $(CURDIR)/$(bin_dir)/go_vendor + +$(bin_dir)/scratch/image $(bin_dir)/tools $(DOWNLOAD_DIR)/tools: + @mkdir -p $@ + +checkhash_script := $(dir $(lastword $(MAKEFILE_LIST)))/util/checkhash.sh +lock_script := $(dir $(lastword $(MAKEFILE_LIST)))/util/lock.sh + +# $outfile is a variable in the lock script +outfile := $$outfile + +for_each_kv = $(foreach item,$2,$(eval $(call $1,$(word 1,$(subst =, ,$(item))),$(word 2,$(subst =, ,$(item)))))) + +# To make sure we use the right version of each tool, we put symlink in +# $(bin_dir)/tools, and the actual binaries are in $(bin_dir)/downloaded. When bumping +# the version of the tools, this symlink gets updated. + +# Let's have $(bin_dir)/tools in front of the PATH so that we don't inavertedly +# pick up the wrong binary somewhere. Watch out, $(shell echo $$PATH) will +# still print the original PATH, since GNU make does not honor exported +# variables: https://stackoverflow.com/questions/54726457 +export PATH := $(CURDIR)/$(bin_dir)/tools:$(PATH) + +CTR ?= docker +.PHONY: __require-ctr +ifneq ($(shell command -v $(CTR) >/dev/null || echo notfound),) +__require-ctr: + @:$(error "$(CTR) (or set CTR to a docker-compatible tool)") +endif +NEEDS_CTR = __require-ctr + +tools := +# https://github.com/helm/helm/releases +tools += helm=v3.14.4 +# https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl +tools += kubectl=v1.30.0 +# https://github.com/kubernetes-sigs/kind/releases +tools += kind=v0.23.0 +# https://www.vaultproject.io/downloads +tools += vault=1.16.2 +# https://github.com/Azure/azure-workload-identity/releases +tools += azwi=v1.2.2 +# https://github.com/kyverno/kyverno/releases +tools += kyverno=v1.12.1 +# https://github.com/mikefarah/yq/releases +tools += yq=v4.43.1 +# https://github.com/ko-build/ko/releases +tools += ko=0.15.2 +# https://github.com/protocolbuffers/protobuf/releases +tools += protoc=26.1 +# https://github.com/aquasecurity/trivy/releases +tools += trivy=v0.50.4 +# https://github.com/vmware-tanzu/carvel-ytt/releases +tools += ytt=v0.49.0 +# https://github.com/rclone/rclone/releases +tools += rclone=v1.66.0 + +### go packages +# https://pkg.go.dev/sigs.k8s.io/controller-tools/cmd/controller-gen?tab=versions +tools += controller-gen=v0.15.0 +# https://pkg.go.dev/golang.org/x/tools/cmd/goimports?tab=versions +tools += goimports=v0.20.0 +# https://pkg.go.dev/github.com/google/go-licenses/licenses?tab=versions +tools += go-licenses=706b9c60edd424a8b6d253fe10dfb7b8e942d4a5 +# https://pkg.go.dev/gotest.tools/gotestsum?tab=versions +tools += gotestsum=v1.11.0 +# https://pkg.go.dev/sigs.k8s.io/kustomize/kustomize/v4?tab=versions +tools += kustomize=v4.5.7 +# https://pkg.go.dev/github.com/itchyny/gojq?tab=versions +tools += gojq=v0.12.15 +# https://pkg.go.dev/github.com/google/go-containerregistry/pkg/crane?tab=versions +tools += crane=v0.19.1 +# https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go?tab=versions +tools += protoc-gen-go=v1.34.0 +# https://pkg.go.dev/github.com/norwoodj/helm-docs/cmd/helm-docs?tab=versions +tools += helm-docs=v1.13.1 +# https://pkg.go.dev/github.com/sigstore/cosign/v2/cmd/cosign?tab=versions +tools += cosign=v2.2.4 +# https://pkg.go.dev/github.com/cert-manager/boilersuite?tab=versions +tools += boilersuite=v0.1.0 +# https://pkg.go.dev/github.com/princjef/gomarkdoc/cmd/gomarkdoc?tab=versions +tools += gomarkdoc=v1.1.0 +# https://pkg.go.dev/oras.land/oras/cmd/oras?tab=versions +tools += oras=v1.1.0 +# https://pkg.go.dev/github.com/onsi/ginkgo/v2/ginkgo?tab=versions +# The gingko version should be kept in sync with the version used in code. +# If there is no go.mod file (which is only the case for the makefile-modules +# repo), then we default to a version that we know exists. We have to do this +# because otherwise the awk failure renders the whole makefile unusable. +detected_ginkgo_version := $(shell [[ -f go.mod ]] && awk '/ginkgo\/v2/ {print $$2}' go.mod || echo "v2.13.2") +tools += ginkgo=$(detected_ginkgo_version) +# https://pkg.go.dev/github.com/cert-manager/klone?tab=versions +tools += klone=v0.0.5 +# https://pkg.go.dev/github.com/goreleaser/goreleaser?tab=versions +tools += goreleaser=v1.25.1 +# https://pkg.go.dev/github.com/anchore/syft/cmd/syft?tab=versions +tools += syft=v0.100.0 +# https://github.com/cert-manager/helm-tool +tools += helm-tool=v0.5.1 +# https://github.com/cert-manager/cmctl +tools += cmctl=v2.0.0 +# https://pkg.go.dev/github.com/cert-manager/release/cmd/cmrel?tab=versions +tools += cmrel=e4c3a4dc07df5c7c0379d334c5bb00e172462551 +# https://github.com/golangci/golangci-lint/releases +tools += golangci-lint=v1.57.2 +# https://pkg.go.dev/golang.org/x/vuln?tab=versions +tools += govulncheck=v1.1.0 +# https://pkg.go.dev/github.com/operator-framework/operator-sdk/cmd/operator-sdk?tab=versions +tools += operator-sdk=v1.34.1 +# https://pkg.go.dev/github.com/cli/cli/v2?tab=versions +tools += gh=v2.49.0 +# https:///github.com/redhat-openshift-ecosystem/openshift-preflight/releases +tools += preflight=1.9.2 +# https://github.com/daixiang0/gci/releases +tools += gci=v0.13.4 +# https://github.com/google/yamlfmt/releases +tools += yamlfmt=v0.12.1 + +# https://pkg.go.dev/k8s.io/code-generator/cmd?tab=versions +K8S_CODEGEN_VERSION := v0.30.1 +tools += client-gen=$(K8S_CODEGEN_VERSION) +tools += deepcopy-gen=$(K8S_CODEGEN_VERSION) +tools += informer-gen=$(K8S_CODEGEN_VERSION) +tools += lister-gen=$(K8S_CODEGEN_VERSION) +tools += applyconfiguration-gen=$(K8S_CODEGEN_VERSION) +tools += defaulter-gen=$(K8S_CODEGEN_VERSION) +tools += conversion-gen=$(K8S_CODEGEN_VERSION) +# https://github.com/kubernetes/kube-openapi +tools += openapi-gen=f0e62f92d13f418e2732b21c952fd17cab771c75 + +# https://raw.githubusercontent.com/kubernetes-sigs/controller-tools/master/envtest-releases.yaml +KUBEBUILDER_ASSETS_VERSION := v1.30.0 +tools += etcd=$(KUBEBUILDER_ASSETS_VERSION) +tools += kube-apiserver=$(KUBEBUILDER_ASSETS_VERSION) + +# Additional tools can be defined to reuse the tooling in this file +ADDITIONAL_TOOLS ?= +tools += $(ADDITIONAL_TOOLS) + +# https://go.dev/dl/ +VENDORED_GO_VERSION := 1.22.6 + +# Print the go version which can be used in GH actions +.PHONY: print-go-version +print-go-version: + @echo result=$(VENDORED_GO_VERSION) + +# When switching branches which use different versions of the tools, we +# need a way to re-trigger the symlinking from $(bin_dir)/downloaded to $(bin_dir)/tools. +$(bin_dir)/scratch/%_VERSION: FORCE | $(bin_dir)/scratch + @test "$($*_VERSION)" == "$(shell cat $@ 2>/dev/null)" || echo $($*_VERSION) > $@ + +# --silent = don't print output like progress meters +# --show-error = but do print errors when they happen +# --fail = exit with a nonzero error code without the response from the server when there's an HTTP error +# --location = follow redirects from the server +# --retry = the number of times to retry a failed attempt to connect +# --retry-connrefused = retry even if the initial connection was refused +CURL := curl --silent --show-error --fail --location --retry 10 --retry-connrefused + +# LN is expected to be an atomic action, meaning that two Make processes +# can run the "link $(DOWNLOAD_DIR)/tools/xxx@$(XXX_VERSION)_$(HOST_OS)_$(HOST_ARCH) +# to $(bin_dir)/tools/xxx" operation simulatiously without issues (both +# will perform the action and the second time the link will be overwritten). +LN := ln -fs + +upper_map := a:A b:B c:C d:D e:E f:F g:G h:H i:I j:J k:K l:L m:M n:N o:O p:P q:Q r:R s:S t:T u:U v:V w:W x:X y:Y z:Z +uc = $(strip \ + $(eval __upper := $1) \ + $(foreach p,$(upper_map), \ + $(eval __upper := $(subst $(word 1,$(subst :, ,$p)),$(word 2,$(subst :, ,$p)),$(__upper))) \ + ) \ + )$(__upper) + +tool_names := + +# for each item `xxx` in the tools variable: +# - a $(XXX_VERSION) variable is generated +# -> this variable contains the version of the tool +# - a $(NEEDS_XXX) variable is generated +# -> this variable contains the target name for the tool, +# which is the relative path of the binary, this target +# should be used when adding the tool as a dependency to +# your target, you can't use $(XXX) as a dependency because +# make does not support an absolute path as a dependency +# - a $(XXX) variable is generated +# -> this variable contains the absolute path of the binary, +# the absolute path should be used when executing the binary +# in targets or in scripts, because it is agnostic to the +# working directory +# - an unversioned target $(bin_dir)/tools/xxx is generated that +# creates a link to the corresponding versioned target: +# $(DOWNLOAD_DIR)/tools/xxx@$(XXX_VERSION)_$(HOST_OS)_$(HOST_ARCH) +define tool_defs +tool_names += $1 + +$(call uc,$1)_VERSION ?= $2 +NEEDS_$(call uc,$1) := $$(bin_dir)/tools/$1 +$(call uc,$1) := $$(CURDIR)/$$(bin_dir)/tools/$1 + +$$(bin_dir)/tools/$1: $$(bin_dir)/scratch/$(call uc,$1)_VERSION | $$(DOWNLOAD_DIR)/tools/$1@$$($(call uc,$1)_VERSION)_$$(HOST_OS)_$$(HOST_ARCH) $$(bin_dir)/tools + @cd $$(dir $$@) && $$(LN) $$(patsubst $$(bin_dir)/%,../%,$$(word 1,$$|)) $$(notdir $$@) + @touch $$@ # making sure the target of the symlink is newer than *_VERSION +endef + +$(foreach tool,$(tools),$(eval $(call tool_defs,$(word 1,$(subst =, ,$(tool))),$(word 2,$(subst =, ,$(tool)))))) + +tools_paths := $(tool_names:%=$(bin_dir)/tools/%) + +###### +# Go # +###### + +# $(NEEDS_GO) is a target that is set as an order-only prerequisite in +# any target that calls $(GO), e.g.: +# +# $(bin_dir)/tools/crane: $(NEEDS_GO) +# $(GO) build -o $(bin_dir)/tools/crane +# +# $(NEEDS_GO) is empty most of the time, except when running "make vendor-go" +# or when "make vendor-go" was previously run, in which case $(NEEDS_GO) is set +# to $(bin_dir)/tools/go, since $(bin_dir)/tools/go is a prerequisite of +# any target depending on Go when "make vendor-go" was run. + +detected_vendoring := $(findstring vendor-go,$(MAKECMDGOALS))$(shell [ -f $(bin_dir)/tools/go ] && echo yes) +export VENDOR_GO ?= $(detected_vendoring) + +ifeq ($(VENDOR_GO),) +.PHONY: __require-go +ifneq ($(shell command -v go >/dev/null || echo notfound),) +__require-go: + @:$(error "$(GO) (or run 'make vendor-go')") +endif +GO := go +NEEDS_GO = __require-go +else +export GOROOT := $(CURDIR)/$(bin_dir)/tools/goroot +export PATH := $(CURDIR)/$(bin_dir)/tools/goroot/bin:$(PATH) +GO := $(CURDIR)/$(bin_dir)/tools/go +NEEDS_GO := $(bin_dir)/tools/go +MAKE := $(MAKE) vendor-go +endif + +.PHONY: vendor-go +## By default, this Makefile uses the system's Go. You can use a "vendored" +## version of Go that will get downloaded by running this command once. To +## disable vendoring, run "make unvendor-go". When vendoring is enabled, +## you will want to set the following: +## +## export PATH="$PWD/$(bin_dir)/tools:$PATH" +## export GOROOT="$PWD/$(bin_dir)/tools/goroot" +## @category [shared] Tools +vendor-go: $(bin_dir)/tools/go + +.PHONY: unvendor-go +unvendor-go: $(bin_dir)/tools/go + rm -rf $(bin_dir)/tools/go $(bin_dir)/tools/goroot + +.PHONY: which-go +## Print the version and path of go which will be used for building and +## testing in Makefile commands. Vendored go will have a path in ./bin +## @category [shared] Tools +which-go: | $(NEEDS_GO) + @$(GO) version + @echo "go binary used for above version information: $(GO)" + +$(bin_dir)/tools/go: $(bin_dir)/scratch/VENDORED_GO_VERSION | $(bin_dir)/tools/goroot $(bin_dir)/tools + @cd $(dir $@) && $(LN) ./goroot/bin/go $(notdir $@) + @touch $@ # making sure the target of the symlink is newer than *_VERSION + +# The "_" in "_bin" prevents "go mod tidy" from trying to tidy the vendored goroot. +$(bin_dir)/tools/goroot: $(bin_dir)/scratch/VENDORED_GO_VERSION | $(GOVENDOR_DIR)/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH)/goroot $(bin_dir)/tools + @cd $(dir $@) && $(LN) $(patsubst $(bin_dir)/%,../%,$(word 1,$|)) $(notdir $@) + @touch $@ # making sure the target of the symlink is newer than *_VERSION + +# Extract the tar to the $(GOVENDOR_DIR) directory, this directory is not cached across CI runs. +$(GOVENDOR_DIR)/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH)/goroot: | $(DOWNLOAD_DIR)/tools/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz + @source $(lock_script) $@; \ + mkdir -p $(outfile).dir; \ + tar xzf $| -C $(outfile).dir; \ + mv $(outfile).dir/go $(outfile); \ + rm -rf $(outfile).dir + +################### +# go dependencies # +################### + +go_dependencies := +go_dependencies += ginkgo=github.com/onsi/ginkgo/v2/ginkgo +go_dependencies += controller-gen=sigs.k8s.io/controller-tools/cmd/controller-gen +go_dependencies += goimports=golang.org/x/tools/cmd/goimports +go_dependencies += go-licenses=github.com/google/go-licenses +go_dependencies += gotestsum=gotest.tools/gotestsum +go_dependencies += kustomize=sigs.k8s.io/kustomize/kustomize/v4 +go_dependencies += gojq=github.com/itchyny/gojq/cmd/gojq +go_dependencies += crane=github.com/google/go-containerregistry/cmd/crane +go_dependencies += protoc-gen-go=google.golang.org/protobuf/cmd/protoc-gen-go +go_dependencies += helm-docs=github.com/norwoodj/helm-docs/cmd/helm-docs +go_dependencies += cosign=github.com/sigstore/cosign/v2/cmd/cosign +go_dependencies += boilersuite=github.com/cert-manager/boilersuite +go_dependencies += gomarkdoc=github.com/princjef/gomarkdoc/cmd/gomarkdoc +go_dependencies += oras=oras.land/oras/cmd/oras +go_dependencies += klone=github.com/cert-manager/klone +go_dependencies += goreleaser=github.com/goreleaser/goreleaser +go_dependencies += syft=github.com/anchore/syft/cmd/syft +go_dependencies += client-gen=k8s.io/code-generator/cmd/client-gen +go_dependencies += deepcopy-gen=k8s.io/code-generator/cmd/deepcopy-gen +go_dependencies += informer-gen=k8s.io/code-generator/cmd/informer-gen +go_dependencies += lister-gen=k8s.io/code-generator/cmd/lister-gen +go_dependencies += applyconfiguration-gen=k8s.io/code-generator/cmd/applyconfiguration-gen +go_dependencies += defaulter-gen=k8s.io/code-generator/cmd/defaulter-gen +go_dependencies += conversion-gen=k8s.io/code-generator/cmd/conversion-gen +go_dependencies += openapi-gen=k8s.io/kube-openapi/cmd/openapi-gen +go_dependencies += helm-tool=github.com/cert-manager/helm-tool +go_dependencies += cmctl=github.com/cert-manager/cmctl/v2 +go_dependencies += cmrel=github.com/cert-manager/release/cmd/cmrel +go_dependencies += golangci-lint=github.com/golangci/golangci-lint/cmd/golangci-lint +go_dependencies += govulncheck=golang.org/x/vuln/cmd/govulncheck +go_dependencies += operator-sdk=github.com/operator-framework/operator-sdk/cmd/operator-sdk +go_dependencies += gh=github.com/cli/cli/v2/cmd/gh +go_dependencies += gci=github.com/daixiang0/gci +go_dependencies += yamlfmt=github.com/google/yamlfmt/cmd/yamlfmt + +################# +# go build tags # +################# + +go_tags := + +# Additional Go dependencies can be defined to re-use the tooling in this file +ADDITIONAL_GO_DEPENDENCIES ?= +ADDITIONAL_GO_TAGS ?= +go_dependencies += $(ADDITIONAL_GO_DEPENDENCIES) +go_tags += $(ADDITIONAL_GO_TAGS) + +go_tags_init = go_tags_$1 := +$(call for_each_kv,go_tags_init,$(go_dependencies)) + +go_tags_defs = go_tags_$1 += $2 +$(call for_each_kv,go_tags_defs,$(go_tags)) + +define go_dependency +$$(DOWNLOAD_DIR)/tools/$1@$($(call uc,$1)_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $$(NEEDS_GO) $$(DOWNLOAD_DIR)/tools + @source $$(lock_script) $$@; \ + mkdir -p $$(outfile).dir; \ + GOWORK=off GOBIN=$$(outfile).dir $$(GO) install --tags "$(strip $(go_tags_$1))" $2@$($(call uc,$1)_VERSION); \ + mv $$(outfile).dir/$1 $$(outfile); \ + rm -rf $$(outfile).dir +endef +$(call for_each_kv,go_dependency,$(go_dependencies)) + +################## +# File downloads # +################## + +go_linux_amd64_SHA256SUM=999805bed7d9039ec3da1a53bfbcafc13e367da52aa823cb60b68ba22d44c616 +go_linux_arm64_SHA256SUM=c15fa895341b8eaf7f219fada25c36a610eb042985dc1a912410c1c90098eaf2 +go_darwin_amd64_SHA256SUM=9c3c0124b01b5365f73a1489649f78f971ecf84844ad9ca58fde133096ddb61b +go_darwin_arm64_SHA256SUM=ebac39fd44fc22feed1bb519af431c84c55776e39b30f4fd62930da9c0cfd1e3 + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz +$(DOWNLOAD_DIR)/tools/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz: | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) https://go.dev/dl/go$(VENDORED_GO_VERSION).$(HOST_OS)-$(HOST_ARCH).tar.gz -o $(outfile); \ + $(checkhash_script) $(outfile) $(go_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM) + +helm_linux_amd64_SHA256SUM=a5844ef2c38ef6ddf3b5a8f7d91e7e0e8ebc39a38bb3fc8013d629c1ef29c259 +helm_linux_arm64_SHA256SUM=113ccc53b7c57c2aba0cd0aa560b5500841b18b5210d78641acfddc53dac8ab2 +helm_darwin_amd64_SHA256SUM=73434aeac36ad068ce2e5582b8851a286dc628eae16494a26e2ad0b24a7199f9 +helm_darwin_arm64_SHA256SUM=61e9c5455f06b2ad0a1280975bf65892e707adc19d766b0cf4e9006e3b7b4b6c + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/helm@$(HELM_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/helm@$(HELM_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) https://get.helm.sh/helm-$(HELM_VERSION)-$(HOST_OS)-$(HOST_ARCH).tar.gz -o $(outfile).tar.gz; \ + $(checkhash_script) $(outfile).tar.gz $(helm_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + tar xfO $(outfile).tar.gz $(HOST_OS)-$(HOST_ARCH)/helm > $(outfile); \ + chmod +x $(outfile); \ + rm -f $(outfile).tar.gz + +kubectl_linux_amd64_SHA256SUM=7c3807c0f5c1b30110a2ff1e55da1d112a6d0096201f1beb81b269f582b5d1c5 +kubectl_linux_arm64_SHA256SUM=669af0cf520757298ea60a8b6eb6b719ba443a9c7d35f36d3fb2fd7513e8c7d2 +kubectl_darwin_amd64_SHA256SUM=bcfa57d020b8d07d0ea77235ce8012c2c28fefdfd7cb9738f33674a7b16cef08 +kubectl_darwin_arm64_SHA256SUM=45cfa208151320153742062824398f22bb6bfb5a142bf6238476d55dacbd1bdd + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/kubectl@$(KUBECTL_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/kubectl@$(KUBECTL_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) https://dl.k8s.io/release/$(KUBECTL_VERSION)/bin/$(HOST_OS)/$(HOST_ARCH)/kubectl -o $(outfile); \ + $(checkhash_script) $(outfile) $(kubectl_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + chmod +x $(outfile) + +kind_linux_amd64_SHA256SUM=1d86e3069ffbe3da9f1a918618aecbc778e00c75f838882d0dfa2d363bc4a68c +kind_linux_arm64_SHA256SUM=a416d6c311882337f0e56910e4a2e1f8c106ec70c22cbf0ac1dd8f33c1e284fe +kind_darwin_amd64_SHA256SUM=81c77f104b4b668812f7930659dc01ad88fa4d1cfc56900863eacdfb2731c457 +kind_darwin_arm64_SHA256SUM=68ec87c1e1ea2a708df883f4b94091150d19552d7b344e80ca59f449b301c2a0 + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/kind@$(KIND_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/kind@$(KIND_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) https://github.com/kubernetes-sigs/kind/releases/download/$(KIND_VERSION)/kind-$(HOST_OS)-$(HOST_ARCH) -o $(outfile); \ + $(checkhash_script) $(outfile) $(kind_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + chmod +x $(outfile) + +vault_linux_amd64_SHA256SUM=688ce462b70cb674f84fddb731f75bb710db5ad9e4e5a17659e90e1283a8b4b7 +vault_linux_arm64_SHA256SUM=d5bd42227d295b1dcc4a5889c37e6a8ca945ece4795819718eaf54db87aa6d4f +vault_darwin_amd64_SHA256SUM=e4886d22273dedc579dc2382e114e7be29341049a48592f8f7be8a0020310731 +vault_darwin_arm64_SHA256SUM=ca59c85e7e3d67e25b6bfa505f7e7717b418452e8bfcd602a2a717bc06d5b1ee + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/vault@$(VAULT_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/vault@$(VAULT_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) https://releases.hashicorp.com/vault/$(VAULT_VERSION)/vault_$(VAULT_VERSION)_$(HOST_OS)_$(HOST_ARCH).zip -o $(outfile).zip; \ + $(checkhash_script) $(outfile).zip $(vault_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + unzip -qq -c $(outfile).zip > $(outfile); \ + chmod +x $(outfile); \ + rm -f $(outfile).zip + +azwi_linux_amd64_SHA256SUM=d33aaedbcbcc0ef61d845b3704ab336deaafc192c854e887896e163b99097871 +azwi_linux_arm64_SHA256SUM=7c4b55ef83e62f4b597885e66fbbdf0720cf0e2be3f1a16212f9b41d4b61b454 +azwi_darwin_amd64_SHA256SUM=47a9e99a7e02e531967d1c9a8abf12e73134f88ce3363007f411ba9b83497fd0 +azwi_darwin_arm64_SHA256SUM=19c5cf9fe4e1a7394bc01456d5e314fd898162d2d360c585fc72e46dae930659 + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/azwi@$(AZWI_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/azwi@$(AZWI_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) https://github.com/Azure/azure-workload-identity/releases/download/$(AZWI_VERSION)/azwi-$(AZWI_VERSION)-$(HOST_OS)-$(HOST_ARCH).tar.gz -o $(outfile).tar.gz; \ + $(checkhash_script) $(outfile).tar.gz $(azwi_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + tar xfO $(outfile).tar.gz azwi > $(outfile) && chmod 775 $(outfile); \ + rm -f $(outfile).tar.gz + +kubebuilder_tools_linux_amd64_SHA256SUM=2a9792cb5f1403f524543ce94c3115e3c4a4229f0e86af55fd26c078da448164 +kubebuilder_tools_linux_arm64_SHA256SUM=39cc7274a3075a650a20fcd24b9e2067375732bebaf5356088a8efb35155f068 +kubebuilder_tools_darwin_amd64_SHA256SUM=85890b864330baec88f53aabfc1d5d94a8ca8c17483f34f4823dec0fae7c6e3a +kubebuilder_tools_darwin_arm64_SHA256SUM=849362d26105b64193b4142982c710306d90248272731a81fb83efac27c5a750 + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz +$(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz: | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) https://github.com/kubernetes-sigs/controller-tools/releases/download/envtest-$(KUBEBUILDER_ASSETS_VERSION)/envtest-$(KUBEBUILDER_ASSETS_VERSION)-$(HOST_OS)-$(HOST_ARCH).tar.gz -o $(outfile); \ + $(checkhash_script) $(outfile) $(kubebuilder_tools_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM) + +$(DOWNLOAD_DIR)/tools/etcd@$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH): $(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + tar xfO $< controller-tools/envtest/etcd > $(outfile) && chmod 775 $(outfile) + +$(DOWNLOAD_DIR)/tools/kube-apiserver@$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH): $(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + tar xfO $< controller-tools/envtest/kube-apiserver > $(outfile) && chmod 775 $(outfile) + +kyverno_linux_amd64_SHA256SUM=a5f6e9070c17acc47168c8ce4db78e45258376551b8bf68ad2d5ed27454cf666 +kyverno_linux_arm64_SHA256SUM=007e828d622e73614365f5f7e8e107e36ae686e97e8982b1eeb53511fb2363c3 +kyverno_darwin_amd64_SHA256SUM=20786eebf45238e8b4a35f4146c3f8dfea35968cf8ef6ca6d6727559f5c0156e +kyverno_darwin_arm64_SHA256SUM=3a454fb0b2bfbca6225d46ff4cc0b702fd4a63e978718c50225472b9631a8015 + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/kyverno@$(KYVERNO_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/kyverno@$(KYVERNO_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + $(eval ARCH := $(subst amd64,x86_64,$(HOST_ARCH))) + + @source $(lock_script) $@; \ + $(CURL) https://github.com/kyverno/kyverno/releases/download/$(KYVERNO_VERSION)/kyverno-cli_$(KYVERNO_VERSION)_$(HOST_OS)_$(ARCH).tar.gz -o $(outfile).tar.gz; \ + $(checkhash_script) $(outfile).tar.gz $(kyverno_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + tar xfO $(outfile).tar.gz kyverno > $(outfile); \ + chmod +x $(outfile); \ + rm -f $(outfile).tar.gz + +yq_linux_amd64_SHA256SUM=cfbbb9ba72c9402ef4ab9d8f843439693dfb380927921740e51706d90869c7e1 +yq_linux_arm64_SHA256SUM=a8186efb079673293289f8c31ee252b0d533c7bb8b1ada6a778ddd5ec0f325b6 +yq_darwin_amd64_SHA256SUM=fdc42b132ac460037f4f0f48caea82138772c651d91cfbb735210075ddfdbaed +yq_darwin_arm64_SHA256SUM=9f1063d910698834cb9176593aa288471898031929138d226c2c2de9f262f8e5 + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/yq@$(YQ_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/yq@$(YQ_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) https://github.com/mikefarah/yq/releases/download/$(YQ_VERSION)/yq_$(HOST_OS)_$(HOST_ARCH) -o $(outfile); \ + $(checkhash_script) $(outfile) $(yq_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + chmod +x $(outfile) + +ko_linux_amd64_SHA256SUM=d11f03f23261d16f9e7802291e9d098e84f5daecc7931e8573bece9025b6a2c5 +ko_linux_arm64_SHA256SUM=8294849c0f12138006cd149dd02bb580c0eea41a6031473705cbf825e021a688 +ko_darwin_amd64_SHA256SUM=314c33154de941bfc4ede5e7283eb182028459bac36eb4223859e0b778254936 +ko_darwin_arm64_SHA256SUM=b6ecd62eb4f9238a0ed0512d7a34648b881aea0774c3830e3e5159370eb6834f + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/ko@$(KO_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/ko@$(KO_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + $(eval OS := $(subst linux,Linux,$(subst darwin,Darwin,$(HOST_OS)))) + $(eval ARCH := $(subst amd64,x86_64,$(HOST_ARCH))) + + @source $(lock_script) $@; \ + $(CURL) https://github.com/ko-build/ko/releases/download/v$(KO_VERSION)/ko_$(KO_VERSION)_$(OS)_$(ARCH).tar.gz -o $(outfile).tar.gz; \ + $(checkhash_script) $(outfile).tar.gz $(ko_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + tar xfO $(outfile).tar.gz ko > $(outfile); \ + chmod +x $(outfile); \ + rm -f $(outfile).tar.gz + +protoc_linux_amd64_SHA256SUM=a7be2928c0454f132c599e25b79b7ad1b57663f2337d7f7e468a1d59b98ec1b0 +protoc_linux_arm64_SHA256SUM=64a3b3b5f7dac0c8f9cf1cb85b2b1a237eb628644f6bcb0fb8f23db6e0d66181 +protoc_darwin_amd64_SHA256SUM=febd8821c3a2a23f72f4641471e0ab6486f4fb07b68111490a27a31681465b3c +protoc_darwin_arm64_SHA256SUM=26a29befa8891ecc48809958c909d284f2b9539a2eb47f22cadc631fe6abe8fd + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/protoc@$(PROTOC_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/protoc@$(PROTOC_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + $(eval OS := $(subst darwin,osx,$(HOST_OS))) + $(eval ARCH := $(subst arm64,aarch_64,$(subst amd64,x86_64,$(HOST_ARCH)))) + + @source $(lock_script) $@; \ + $(CURL) https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-$(OS)-$(ARCH).zip -o $(outfile).zip; \ + $(checkhash_script) $(outfile).zip $(protoc_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + unzip -qq -c $(outfile).zip bin/protoc > $(outfile); \ + chmod +x $(outfile); \ + rm -f $(outfile).zip + +trivy_linux_amd64_SHA256SUM=b0d135815867246baba52f608f4af84beca90cfeb17a9ce407a21acca760ace1 +trivy_linux_arm64_SHA256SUM=1be1dee3a5e013528374f25391d6ba84e2a10fda59f4e98431e30d9c4975762b +trivy_darwin_amd64_SHA256SUM=744f5e8c5c09c1e5ec6ec6a0570f779d89964c0a91ab60b4e59b284cdd3e1576 +trivy_darwin_arm64_SHA256SUM=e78a0db86f6364e756d5e058316c7815a747fc7fd8e8e984e3baf5830166ec63 + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/trivy@$(TRIVY_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/trivy@$(TRIVY_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + $(eval OS := $(subst linux,Linux,$(subst darwin,macOS,$(HOST_OS)))) + $(eval ARCH := $(subst amd64,64bit,$(subst arm64,ARM64,$(HOST_ARCH)))) + + @source $(lock_script) $@; \ + $(CURL) https://github.com/aquasecurity/trivy/releases/download/$(TRIVY_VERSION)/trivy_$(patsubst v%,%,$(TRIVY_VERSION))_$(OS)-$(ARCH).tar.gz -o $(outfile).tar.gz; \ + $(checkhash_script) $(outfile).tar.gz $(trivy_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + tar xfO $(outfile).tar.gz trivy > $(outfile); \ + chmod +x $(outfile); \ + rm $(outfile).tar.gz + +ytt_linux_amd64_SHA256SUM=357ec754446b1eda29dd529e088f617e85809726c686598ab03cfc1c79f43b56 +ytt_linux_arm64_SHA256SUM=a2d195b058884c0e36a918936076965b8efb426f7e00f6b7d7b99b82737c7299 +ytt_darwin_amd64_SHA256SUM=71b5ea38bfc7a9748c35ce0735fd6f806dce46bd5c9039d527050c7682e62a70 +ytt_darwin_arm64_SHA256SUM=0658db4af8263ca091ca31e4b599cb40c324b75934660a4c0ed98ad9b701f7e9 + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/ytt@$(YTT_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/ytt@$(YTT_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) -sSfL https://github.com/vmware-tanzu/carvel-ytt/releases/download/$(YTT_VERSION)/ytt-$(HOST_OS)-$(HOST_ARCH) -o $(outfile); \ + $(checkhash_script) $(outfile) $(ytt_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + chmod +x $(outfile) + +rclone_linux_amd64_SHA256SUM=b4d304b1dc76001b1d3bb820ae8d1ae60a072afbd3296be904a3ee00b3d4fab9 +rclone_linux_arm64_SHA256SUM=c50a3ab93082f21788f9244393b19f2426edeeb896eec2e3e05ffb2e8727e075 +rclone_darwin_amd64_SHA256SUM=5adb4c5fe0675627461000a63156001301ec7cade966c55c8c4ebcfaeb62c5ae +rclone_darwin_arm64_SHA256SUM=b5f4c4d06ff3d426aee99870ad437276c9ddaad55442f2df6a58b918115fe4cf + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/rclone@$(RCLONE_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/rclone@$(RCLONE_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + $(eval OS := $(subst darwin,osx,$(HOST_OS))) + + @source $(lock_script) $@; \ + $(CURL) https://github.com/rclone/rclone/releases/download/$(RCLONE_VERSION)/rclone-$(RCLONE_VERSION)-$(OS)-$(HOST_ARCH).zip -o $(outfile).zip; \ + $(checkhash_script) $(outfile).zip $(rclone_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + unzip -p $(outfile).zip rclone-$(RCLONE_VERSION)-$(OS)-$(HOST_ARCH)/rclone > $(outfile); \ + chmod +x $(outfile); \ + rm -f $(outfile).zip + +preflight_linux_amd64_SHA256SUM=20f31e4af2004e8e3407844afea4e973975069169d69794e0633f0cb91d45afd +preflight_linux_arm64_SHA256SUM=c42cf4132027d937da88da07760e8fd9b1a8836f9c7795a1b60513d99c6939fe + +# Currently there are no offical releases for darwin, you cannot submit results +# on non-official binaries, but we can still run tests. +# +# Once https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/942 is merged +# we can remove this darwin specific hack +.PRECIOUS: $(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_darwin_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_darwin_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + mkdir -p $(outfile).dir; \ + GOWORK=off GOBIN=$(outfile).dir $(GO) install github.com/redhat-openshift-ecosystem/openshift-preflight/cmd/preflight@$(PREFLIGHT_VERSION); \ + mv $(outfile).dir/preflight $(outfile); \ + rm -rf $(outfile).dir + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_linux_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_linux_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + @source $(lock_script) $@; \ + $(CURL) https://github.com/redhat-openshift-ecosystem/openshift-preflight/releases/download/$(PREFLIGHT_VERSION)/preflight-linux-$(HOST_ARCH) -o $(outfile); \ + $(checkhash_script) $(outfile) $(preflight_linux_$(HOST_ARCH)_SHA256SUM); \ + chmod +x $(outfile) + +################# +# Other Targets # +################# + +# Although we "vendor" most tools in $(bin_dir)/tools, we still require some binaries +# to be available on the system. The vendor-go MAKECMDGOALS trick prevents the +# check for the presence of Go when 'make vendor-go' is run. + +# Gotcha warning: MAKECMDGOALS only contains what the _top level_ make invocation used, and doesn't look at target dependencies +# i.e. if we have a target "abc: vendor-go test" and run "make abc", we'll get an error +# about go being missing even though abc itself depends on vendor-go! +# That means we need to pass vendor-go at the top level if go is not installed (i.e. "make vendor-go abc") + +missing=$(shell (command -v curl >/dev/null || echo curl) \ + && (command -v sha256sum >/dev/null || command -v shasum >/dev/null || echo sha256sum) \ + && (command -v git >/dev/null || echo git) \ + && (command -v rsync >/dev/null || echo rsync) \ + && (command -v bash >/dev/null || echo bash)) +ifneq ($(missing),) +$(error Missing required tools: $(missing)) +endif + +.PHONY: tools +## Download and setup all tools +## @category [shared] Tools +tools: $(tools_paths) diff --git a/make/_shared/tools/util/checkhash.sh b/make/_shared/tools/util/checkhash.sh new file mode 100755 index 00000000..62e5489b --- /dev/null +++ b/make/_shared/tools/util/checkhash.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# This script takes the hash of its first argument and verifies it against the +# hex hash given in its second argument + +function usage_and_exit() { + echo "usage: $0 " + echo "or: LEARN_FILE= $0 " + exit 1 +} + +HASH_TARGET=${1:-} +EXPECTED_HASH=${2:-} + +if [[ -z $HASH_TARGET ]]; then + usage_and_exit +fi + +if [[ -z $EXPECTED_HASH ]]; then + usage_and_exit +fi + +SHASUM=$("${SCRIPT_DIR}/hash.sh" "$HASH_TARGET") + +if [[ "$SHASUM" == "$EXPECTED_HASH" ]]; then + exit 0 +fi + +# When running 'make learn-sha-tools', we don't want this script to fail. +# Instead we log what sha values are wrong, so the make.mk file can be updated. + +if [ "${LEARN_FILE:-}" != "" ]; then + echo "s/$EXPECTED_HASH/$SHASUM/g" >> "${LEARN_FILE:-}" + exit 0 +fi + +echo "invalid checksum for \"$HASH_TARGET\": wanted \"$EXPECTED_HASH\" but got \"$SHASUM\"" +exit 1 diff --git a/make/_shared/tools/util/hash.sh b/make/_shared/tools/util/hash.sh new file mode 100755 index 00000000..21d006fc --- /dev/null +++ b/make/_shared/tools/util/hash.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +# This script is a wrapper for outputting purely the sha256 hash of the input file, +# ideally in a portable way. + +case "$(uname -s)" in + Darwin*) shasum -a 256 "$1";; + *) sha256sum "$1" +esac | cut -d" " -f1 \ No newline at end of file diff --git a/make/_shared/tools/util/lock.sh b/make/_shared/tools/util/lock.sh new file mode 100755 index 00000000..22564f7c --- /dev/null +++ b/make/_shared/tools/util/lock.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +# This script is used to lock a file while it is being downloaded. It prevents +# multiple processes from downloading the same file at the same time or from reading +# a half-downloaded file. +# We need this solution because we have recursive $(MAKE) calls in our makefile +# which each will try to download a set of tools. To prevent them from all downloading +# the same files, we re-use the same downloads folder for all $(MAKE) invocations and +# use this script to deduplicate the download processes. + +finalfile="$1" +lockfile="$finalfile.lock" + +# On OSX, flock is not installed, we just skip locking in that case, +# this means that running verify in parallel without downloading all +# tools first will not work. +flock_installed=$(command -v flock >/dev/null && echo "yes" || echo "no") + +if [[ "$flock_installed" == "yes" ]]; then + mkdir -p "$(dirname "$lockfile")" + touch "$lockfile" + exec {FD}<>"$lockfile" + + # wait for the file to be unlocked + if ! flock -x $FD; then + echo "Failed to obtain a lock for $lockfile" + exit 1 + fi +fi + +# now that we have the lock, check if file is already there +if [[ -e "$finalfile" ]]; then + exit 0 +fi + +# use a temporary file to prevent Make from thinking the file is ready +# while in reality is is only a partial download +# shellcheck disable=SC2034 +outfile="$finalfile.tmp" + +finish() { + rv=$? + if [[ $rv -eq 0 ]]; then + mv "$outfile" "$finalfile" + echo "[info]: downloaded $finalfile" + else + rm -rf "$outfile" || true + rm -rf "$finalfile" || true + fi + rm -rf "$lockfile" || true +} +trap finish EXIT SIGINT diff --git a/make/config/kaniko/context.tar.gz b/make/config/kaniko/context.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..693b797194ed4d404c751e760f166627648f9b57 GIT binary patch literal 174 zcmV;f08#%RiwFSy&&g&01MQJb3c@fDg|qe)IYB%5naK^@iQo;2CK3&)v=%+S!It7e zx{D&_+q}(V=FPmSX4wG%gUFvsqk`0@#q|yd8au7-qF^>78F*fwqrb|&S%@A%r zgi{-B|HhYW&MnND?wIvQsOm$zKikgvU~}zA{~)aw`WI^M-;hlGqY{d7$Q9_7Kkt9N c+irL~`gmV`J4&HYC=@=(1BWlOHvkF%072zd6#xJL literal 0 HcmV?d00001 diff --git a/make/config/kaniko/context/dockerfile b/make/config/kaniko/context/dockerfile new file mode 100644 index 00000000..8bd0a7f1 --- /dev/null +++ b/make/config/kaniko/context/dockerfile @@ -0,0 +1 @@ +FROM nginx diff --git a/make/config/kind/cluster.yaml b/make/config/kind/cluster.yaml new file mode 100644 index 00000000..4d1f7cf1 --- /dev/null +++ b/make/config/kind/cluster.yaml @@ -0,0 +1,32 @@ +apiVersion: kind.x-k8s.io/v1alpha4 +kind: Cluster +kubeadmConfigPatches: + - | + kind: ClusterConfiguration + metadata: + name: config + etcd: + local: + extraArgs: + unsafe-no-fsync: "true" + networking: + serviceSubnet: 10.0.0.0/16 +nodes: +- role: control-plane + + extraPortMappings: + - containerPort: 30443 + hostPort: 30443 + listenAddress: "0.0.0.0" + protocol: tcp + + extraMounts: + - hostPath: {{KIND_IMAGES}} + containerPath: /mounted_images + +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker-registry.registry.svc.cluster.local:5000"] + endpoint = ["http://localhost:30443"] + [plugins."io.containerd.grpc.v1.cri".registry.configs."docker-registry.registry.svc.cluster.local:5000".tls] + insecure_skip_verify = true diff --git a/make/config/registry/docker-registry-values.yaml b/make/config/registry/docker-registry-values.yaml new file mode 100644 index 00000000..e175502d --- /dev/null +++ b/make/config/registry/docker-registry-values.yaml @@ -0,0 +1,24 @@ +configData: + version: 0.1 + log: + fields: + service: registry + storage: + cache: + blobdescriptor: inmemory + http: + addr: :5000 + headers: + X-Content-Type-Options: [nosniff] + debug: + addr: :5001 + prometheus: + enabled: false + path: /metrics + health: + storagedriver: + enabled: true + interval: 10s + threshold: 3 + secrets: + htpasswd: "user:$2y$05$zDST8320bM1EcRhcj2nsheN7conl3kkOWxPXESn.HW/1lnThDmoBG" diff --git a/make/config/version-checker-values.yaml b/make/config/version-checker-values.yaml new file mode 100644 index 00000000..5f99bde6 --- /dev/null +++ b/make/config/version-checker-values.yaml @@ -0,0 +1,7 @@ +versionChecker: + testAllContainers: false +selfhosted: + - name: registry + host: http://docker-registry.registry.svc.cluster.local:5000 + username: user + password: password diff --git a/make/test-e2e.mk b/make/test-e2e.mk new file mode 100644 index 00000000..65392cde --- /dev/null +++ b/make/test-e2e.mk @@ -0,0 +1,90 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.PHONY: e2e-setup-docker-registry +e2e-setup-docker-registry: | kind-cluster $(NEEDS_HELM) $(NEEDS_KUBECTL) + $(HELM) repo add twuni https://helm.twun.io + $(HELM) upgrade \ + --install \ + --create-namespace \ + -n registry \ + --wait \ + --set service.type=NodePort \ + --set service.nodePort=30443 \ + -f ./make/config/registry/docker-registry-values.yaml \ + docker-registry twuni/docker-registry >/dev/null + +.PHONY: install-harbor +e2e-setup-harbor: | kind-cluster $(NEEDS_HELM) $(NEEDS_KUBECTL) + $(HELM) repo add harbor https://helm.goharbor.io + $(HELM) upgrade \ + --install \ + --create-namespace \ + -n harbor \ + --wait \ + --set expose.type=nodePort \ + --set expose.tls.enabled=false \ + --set trivy.enabled=false \ + --set registry.credentials.username="user" \ + --set registry.credentials.password="password" \ + --set expose.nodePort.ports.http.nodePort=30443 \ + harbor harbor/harbor >/dev/null + + +INSTALL_OPTIONS += --set image.repository=$(oci_manager_image_name_development) +INSTALL_OPTIONS += -f ./make/config/version-checker-values.yaml + +.PHONY: e2e-setup-deps +e2e-setup-deps: | kind-cluster $(NEEDS_KUBECTL) + $(KUBECTL) apply -f test/e2e/manifests/docker-credentials.yaml + $(KUBECTL) apply -f test/e2e/manifests/gsa-secret.yaml #TODO replace with local hostPath context + $(KUBECTL) apply -f test/e2e/manifests/pod-gcs.yaml + +is_e2e_test= + +# The "install" target can be run on its own with any currently active cluster, +# we can't use any other cluster then a target containing "test-e2e" is run. +# When a "test-e2e*" target is run, the currently active cluster must be the kind +# cluster created by the "kind-cluster" target. +ifeq ($(findstring test-e2e,$(MAKECMDGOALS)),test-e2e) +is_e2e_test = yes +endif + + +ifdef is_e2e_test +install: kind-cluster oci-load-manager +endif + +test-e2e-deps: e2e-setup-docker-registry +test-e2e-deps: e2e-setup-deps +test-e2e-deps: install + + + +.PHONY: test-e2e +## e2e end-to-end tests +## @category Testing +test-e2e: test-e2e-deps | kind-cluster #$(NEEDS_GINKGO) $(NEEDS_KUBECTL) +# $(GINKGO) \ +# --output-dir=$(ARTIFACTS) \ +# --focus="$(E2E_FOCUS)" \ +# --junit-report=junit-go-e2e.xml \ +# $(EXTRA_GINKGO_FLAGS) \ +# ./test/e2e/ \ +# -ldflags $(go_manager_ldflags) \ +# -- \ +# --istioctl-path $(CURDIR)/$(bin_dir)/scratch/istioctl-$(ISTIO_VERSION) \ +# --kubeconfig-path $(CURDIR)/$(kind_kubeconfig) \ +# --kubectl-path $(KUBECTL) \ +# --runtime-issuance-config-map-name=$(E2E_RUNTIME_CONFIG_MAP_NAME) diff --git a/make/test-unit.mk b/make/test-unit.mk new file mode 100644 index 00000000..61695fa2 --- /dev/null +++ b/make/test-unit.mk @@ -0,0 +1,29 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.PHONY: test-unit +## Unit tests +## @category Testing +test-unit: | $(NEEDS_GOTESTSUM) $(NEEDS_GO) $(NEEDS_ETCD) $(NEEDS_KUBE-APISERVER) $(NEEDS_KUBECTL) $(ARTIFACTS) + KUBEBUILDER_ASSETS=$(CURDIR)/$(bin_dir)/tools \ + $(GOTESTSUM) \ + --junitfile=$(ARTIFACTS)/junit-go-e2e.xml \ + -- \ + -coverprofile=$(ARTIFACTS)/filtered.cov \ + ./cmd/... ./pkg/... \ + -- \ + -ldflags $(go_manager_ldflags) \ + -test.timeout 2m \ + + $(GO) tool cover -html=$(ARTIFACTS)/filtered.cov -o=$(ARTIFACTS)/filtered.html diff --git a/test/e2e/manifests/docker-credentials.yaml b/test/e2e/manifests/docker-credentials.yaml new file mode 100644 index 00000000..835b79b6 --- /dev/null +++ b/test/e2e/manifests/docker-credentials.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: regcred +type: kubernetes.io/dockerconfigjson +data: + .dockerconfigjson: eyJhdXRocyI6eyJkb2NrZXItcmVnaXN0cnkucmVnaXN0cnkuc3ZjLmNsdXN0ZXIubG9jYWw6NTAwMCI6eyJ1c2VybmFtZSI6InVzZXIiLCJwYXNzd29yZCI6InBhc3N3b3JkIiwiYXV0aCI6ImRYTmxjanB3WVhOemQyOXlaQT09In19fQ== diff --git a/test/e2e/manifests/image-from-reg.yaml b/test/e2e/manifests/image-from-reg.yaml new file mode 100644 index 00000000..d3e95800 --- /dev/null +++ b/test/e2e/manifests/image-from-reg.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: image-from-reg + annotations: + enable.version-checker.io/test: "true" +spec: + containers: + - name: test + image: docker-registry.registry.svc.cluster.local:5000/my-app:0.0.1 + imagePullPolicy: Always + imagePullSecrets: + - name: regcred diff --git a/test/e2e/manifests/pod-gcs.yaml b/test/e2e/manifests/pod-gcs.yaml new file mode 100644 index 00000000..5ddd9371 --- /dev/null +++ b/test/e2e/manifests/pod-gcs.yaml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Pod +metadata: + name: kaniko-0 +spec: + containers: + - name: kaniko + image: gcr.io/kaniko-project/executor:latest + args: ["--dockerfile=dockerfile", + "--context=gs://jetstack-kaniko-contexts/context.tar.gz", + "--insecure=true", + "--destination=docker-registry.registry.svc.cluster.local:5000/my-app:0.0.1", + "--insecure-registry=docker-registry.registry.svc.cluster.local:5000"] + volumeMounts: + - name: docker-secret + mountPath: /kaniko/.docker + - name: kaniko-secret + mountPath: /secret + env: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: /secret/kaniko-secret.json + restartPolicy: Never + volumes: + - name: docker-secret + secret: + secretName: regcred + items: + - key: .dockerconfigjson + path: config.json + - name: kaniko-secret + secret: + secretName: kaniko-secret +--- +apiVersion: v1 +kind: Pod +metadata: + name: kaniko-1 +spec: + containers: + - name: kaniko + image: gcr.io/kaniko-project/executor:latest + args: ["--dockerfile=dockerfile", + "--context=gs://jetstack-kaniko-contexts/context.tar.gz", + "--insecure=true", + "--destination=docker-registry.registry.svc.cluster.local:5000/my-app:0.0.2", + "--insecure-registry=docker-registry.registry.svc.cluster.local:5000"] + volumeMounts: + - name: docker-secret + mountPath: /kaniko/.docker + - name: kaniko-secret + mountPath: /secret + env: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: /secret/kaniko-secret.json + restartPolicy: Never + volumes: + - name: docker-secret + secret: + secretName: regcred + items: + - key: .dockerconfigjson + path: config.json + - name: kaniko-secret + secret: + secretName: kaniko-secret diff --git a/test/e2e/manifests/pod.yaml b/test/e2e/manifests/pod.yaml new file mode 100644 index 00000000..e1e55570 --- /dev/null +++ b/test/e2e/manifests/pod.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Pod +metadata: + name: kaniko +spec: + containers: + - name: kaniko + image: gcr.io/kaniko-project/executor:latest + args: ["--dockerfile=/workspace/dockerfile", + "--context=dir://workspace", + "--destination=docker-registry.registry.svc.cluster.local/version-checker:0.0.1"] + volumeMounts: + - name: kaniko-secret + mountPath: /kaniko/.docker + - name: dockerfile-storage + mountPath: /workspace + restartPolicy: Never + volumes: + - name: kaniko-secret + secret: + secretName: regcred + items: + - key: .dockerconfigjson + path: config.json + - name: dockerfile-storage + persistentVolumeClaim: + claimName: dockerfile-claim diff --git a/test/e2e/manifests/volume.yaml b/test/e2e/manifests/volume.yaml new file mode 100644 index 00000000..998aad3d --- /dev/null +++ b/test/e2e/manifests/volume.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: dockerfile + labels: + type: local +spec: + capacity: + storage: 1Gi + accessModes: + - ReadWriteOnce + storageClassName: local-storage + hostPath: + path: "/Users/paulwilljones/repos/jetstack/version-checker/make/config/kaniko/" + type: Directory +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: dockerfile-claim +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-storage From d0a62c086c7e2668ee9ff334d6beb7d372a82949 Mon Sep 17 00:00:00 2001 From: paulwilljones Date: Fri, 6 Sep 2024 13:21:48 +0100 Subject: [PATCH 3/7] Add ginkgo e2e tests --- go.mod | 8 ++ go.sum | 4 + make/test-e2e.mk | 34 ++------ pkg/client/selfhosted/selfhosted.go | 6 +- test/e2e/e2e_test.go | 15 ++++ test/e2e/manifests/prom2json.yaml | 14 ++++ test/e2e/suite/version_checker.go | 117 ++++++++++++++++++++++++++++ 7 files changed, 168 insertions(+), 30 deletions(-) create mode 100644 test/e2e/e2e_test.go create mode 100644 test/e2e/manifests/prom2json.yaml create mode 100644 test/e2e/suite/version_checker.go diff --git a/go.mod b/go.mod index c9253b09..1ff1ad6c 100644 --- a/go.mod +++ b/go.mod @@ -43,8 +43,12 @@ require ( github.com/patrickmn/go-cache v2.1.0+incompatible github.com/stretchr/testify v1.10.0 sigs.k8s.io/controller-runtime v0.20.4 + github.com/onsi/ginkgo/v2 v2.19.0 + github.com/onsi/gomega v1.33.1 ) +require github.com/itchyny/timefmt-go v0.1.6 // indirect + require ( github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect @@ -79,6 +83,7 @@ require ( github.com/go-openapi/jsonpointer v0.21.1 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.1 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -86,10 +91,13 @@ require ( github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/itchyny/gojq v0.12.16 + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.0 // indirect diff --git a/go.sum b/go.sum index 985fee26..fe38ec6a 100644 --- a/go.sum +++ b/go.sum @@ -148,6 +148,10 @@ github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISH github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/itchyny/gojq v0.12.16 h1:yLfgLxhIr/6sJNVmYfQjTIv0jGctu6/DgDoivmxTr7g= +github.com/itchyny/gojq v0.12.16/go.mod h1:6abHbdC2uB9ogMS38XsErnfqJ94UlngIJGlRAIj4jTM= +github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= +github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg= github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww= github.com/jarcoal/httpmock v1.3.1/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= diff --git a/make/test-e2e.mk b/make/test-e2e.mk index 65392cde..2ddae902 100644 --- a/make/test-e2e.mk +++ b/make/test-e2e.mk @@ -25,22 +25,6 @@ e2e-setup-docker-registry: | kind-cluster $(NEEDS_HELM) $(NEEDS_KUBECTL) -f ./make/config/registry/docker-registry-values.yaml \ docker-registry twuni/docker-registry >/dev/null -.PHONY: install-harbor -e2e-setup-harbor: | kind-cluster $(NEEDS_HELM) $(NEEDS_KUBECTL) - $(HELM) repo add harbor https://helm.goharbor.io - $(HELM) upgrade \ - --install \ - --create-namespace \ - -n harbor \ - --wait \ - --set expose.type=nodePort \ - --set expose.tls.enabled=false \ - --set trivy.enabled=false \ - --set registry.credentials.username="user" \ - --set registry.credentials.password="password" \ - --set expose.nodePort.ports.http.nodePort=30443 \ - harbor harbor/harbor >/dev/null - INSTALL_OPTIONS += --set image.repository=$(oci_manager_image_name_development) INSTALL_OPTIONS += -f ./make/config/version-checker-values.yaml @@ -75,16 +59,8 @@ test-e2e-deps: install .PHONY: test-e2e ## e2e end-to-end tests ## @category Testing -test-e2e: test-e2e-deps | kind-cluster #$(NEEDS_GINKGO) $(NEEDS_KUBECTL) -# $(GINKGO) \ -# --output-dir=$(ARTIFACTS) \ -# --focus="$(E2E_FOCUS)" \ -# --junit-report=junit-go-e2e.xml \ -# $(EXTRA_GINKGO_FLAGS) \ -# ./test/e2e/ \ -# -ldflags $(go_manager_ldflags) \ -# -- \ -# --istioctl-path $(CURDIR)/$(bin_dir)/scratch/istioctl-$(ISTIO_VERSION) \ -# --kubeconfig-path $(CURDIR)/$(kind_kubeconfig) \ -# --kubectl-path $(KUBECTL) \ -# --runtime-issuance-config-map-name=$(E2E_RUNTIME_CONFIG_MAP_NAME) +test-e2e: test-e2e-deps | kind-cluster $(NEEDS_GINKGO) $(NEEDS_KUBECTL) + $(GINKGO) \ + -v \ + --no-color \ + ./test/e2e/ diff --git a/pkg/client/selfhosted/selfhosted.go b/pkg/client/selfhosted/selfhosted.go index bc019164..282f45fd 100644 --- a/pkg/client/selfhosted/selfhosted.go +++ b/pkg/client/selfhosted/selfhosted.go @@ -232,13 +232,17 @@ func (c *Client) doRequest(ctx context.Context, url, header string, obj interfac req = req.WithContext(ctx) if len(c.Bearer) > 0 { req.Header.Add("Authorization", "Bearer "+c.Bearer) +<<<<<<< HEAD } else if c.Username != "" && c.Password != "" { +======= + } else if len(c.Username) > 0 && len(c.Password) > 0 { +>>>>>>> 8e64777... Add ginkgo e2e tests req.SetBasicAuth(c.Username, c.Password) } if len(header) > 0 { req.Header.Set("Accept", header) - req.Header.Set("Accept", ociV1Header) + req.Header.Add("Accept", ociV1Header) } resp, err := c.Do(req) diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go new file mode 100644 index 00000000..5842c74c --- /dev/null +++ b/test/e2e/e2e_test.go @@ -0,0 +1,15 @@ +package e2e + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + _ "github.com/jetstack/version-checker/test/e2e/suite" +) + +func TestVersionChecker(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "VersionChecker Suite") +} diff --git a/test/e2e/manifests/prom2json.yaml b/test/e2e/manifests/prom2json.yaml new file mode 100644 index 00000000..51655107 --- /dev/null +++ b/test/e2e/manifests/prom2json.yaml @@ -0,0 +1,14 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: prom2json +spec: + template: + spec: + containers: + - command: + - prom2json + - http://version-checker.version-checker:8080/metrics + image: prom/prom2json + name: prom2json + restartPolicy: Never \ No newline at end of file diff --git a/test/e2e/suite/version_checker.go b/test/e2e/suite/version_checker.go new file mode 100644 index 00000000..e5bfab1f --- /dev/null +++ b/test/e2e/suite/version_checker.go @@ -0,0 +1,117 @@ +package suite + +import ( + "bytes" + "encoding/json" + "log" + "os/exec" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/itchyny/gojq" +) + +var _ = Describe("version-checker", func() { + BeforeEach(func() { + cmd := exec.Command("kubectl", "apply", "-f", "./manifests/prom2json.yaml") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + cmd = exec.Command("kubectl", "wait", "--for=condition=Complete", "job", "-ljob-name=prom2json") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + }) + AfterEach(func() { + cmd := exec.Command("kubectl", "delete", "-f", "./manifests/prom2json.yaml") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + }) + + When("a Pod is deployed", func() { + BeforeEach(func() { + cmd := exec.Command("kubectl", "apply", "-f", "./manifests/image-from-reg.yaml") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + }) + AfterEach(func() { + cmd := exec.Command("kubectl", "delete", "-f", "./manifests/image-from-reg.yaml") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + }) + }) + + It("it should get the current version", func() { + buf := new(bytes.Buffer) + cmd := exec.Command("kubectl", "logs", "-ljob-name=prom2json") + cmd.Stdout = buf + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.current_version' + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.latest_version' + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .value' + query, err := gojq.Parse(".[]|select(.name==\"version_checker_is_latest_version\")| .metrics[] | select(.labels.image==\"docker-registry.registry.svc.cluster.local:5000/my-app\") | .labels.current_version") + if err != nil { + log.Fatalln(err) + } + var result []interface{} + err = json.Unmarshal(buf.Bytes(), &result) + if err != nil { + log.Fatalln(err) + } + iter := query.Run(result) + for { + v, ok := iter.Next() + if !ok { + break + } + if err, ok := v.(error); ok { + if err, ok := err.(*gojq.HaltError); ok && err.Value() == nil { + break + } + log.Fatalln(err) + } + Expect(v).To(Equal("0.0.1")) + } + }) + + It("it should find a newer version", func() { + buf := new(bytes.Buffer) + cmd := exec.Command("kubectl", "logs", "-ljob-name=prom2json") + cmd.Stdout = buf + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.current_version' + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.latest_version' + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .value' + query, err := gojq.Parse(".[]|select(.name==\"version_checker_is_latest_version\")| .metrics[] | select(.labels.image==\"docker-registry.registry.svc.cluster.local:5000/my-app\") | .labels.latest_version") + if err != nil { + log.Fatalln(err) + } + var result []interface{} + err = json.Unmarshal(buf.Bytes(), &result) + if err != nil { + log.Fatalln(err) + } + iter := query.Run(result) + for { + v, ok := iter.Next() + if !ok { + break + } + if err, ok := v.(error); ok { + if err, ok := err.(*gojq.HaltError); ok && err.Value() == nil { + break + } + log.Fatalln(err) + } + Expect(v).To(Equal("0.0.2")) + } + }) +}) From fa5465e4773044d6a6fd2c2b4e732b24310aaf2a Mon Sep 17 00:00:00 2001 From: paulwilljones Date: Fri, 6 Sep 2024 15:22:32 +0100 Subject: [PATCH 4/7] Use local kaniko docker context --- make/02_mod.mk | 6 +- make/config/kaniko/context.tar.gz | Bin 174 -> 0 bytes make/config/kaniko/{context => }/dockerfile | 0 make/config/kind/cluster.yaml | 2 + make/test-e2e.mk | 3 +- .../manifests/{pod-gcs.yaml => kaniko.yaml} | 38 +++--- test/e2e/manifests/volume.yaml | 27 ---- test/e2e/suite/version_checker.go | 119 +++++++++--------- 8 files changed, 87 insertions(+), 108 deletions(-) delete mode 100644 make/config/kaniko/context.tar.gz rename make/config/kaniko/{context => }/dockerfile (100%) rename test/e2e/manifests/{pod-gcs.yaml => kaniko.yaml} (64%) delete mode 100644 test/e2e/manifests/volume.yaml diff --git a/make/02_mod.mk b/make/02_mod.mk index f23d0984..f13aa687 100644 --- a/make/02_mod.mk +++ b/make/02_mod.mk @@ -14,8 +14,12 @@ $(kind_cluster_config): make/config/kind/cluster.yaml | $(bin_dir)/scratch cat $< | \ - sed -e 's|{{KIND_IMAGES}}|$(CURDIR)/$(images_tar_dir)|g' \ + sed -e 's|{{KIND_IMAGES}}|$(CURDIR)/$(images_tar_dir)|g' -e 's|{{KANIKO_DIR}}|$(CURDIR)/make/config/kaniko|g' \ > $@ +# cat $< | \ +# sed -e 's|{{KANIKO_DIR}}|$(CURDIR)/make/config/kaniko|g' \ +# > $@ + include make/test-e2e.mk include make/test-unit.mk diff --git a/make/config/kaniko/context.tar.gz b/make/config/kaniko/context.tar.gz deleted file mode 100644 index 693b797194ed4d404c751e760f166627648f9b57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174 zcmV;f08#%RiwFSy&&g&01MQJb3c@fDg|qe)IYB%5naK^@iQo;2CK3&)v=%+S!It7e zx{D&_+q}(V=FPmSX4wG%gUFvsqk`0@#q|yd8au7-qF^>78F*fwqrb|&S%@A%r zgi{-B|HhYW&MnND?wIvQsOm$zKikgvU~}zA{~)aw`WI^M-;hlGqY{d7$Q9_7Kkt9N c+irL~`gmV`J4&HYC=@=(1BWlOHvkF%072zd6#xJL diff --git a/make/config/kaniko/context/dockerfile b/make/config/kaniko/dockerfile similarity index 100% rename from make/config/kaniko/context/dockerfile rename to make/config/kaniko/dockerfile diff --git a/make/config/kind/cluster.yaml b/make/config/kind/cluster.yaml index 4d1f7cf1..f2da42ce 100644 --- a/make/config/kind/cluster.yaml +++ b/make/config/kind/cluster.yaml @@ -23,6 +23,8 @@ nodes: extraMounts: - hostPath: {{KIND_IMAGES}} containerPath: /mounted_images + - hostPath: {{KANIKO_DIR}} + containerPath: /workspace containerdConfigPatches: - |- diff --git a/make/test-e2e.mk b/make/test-e2e.mk index 2ddae902..c74690ed 100644 --- a/make/test-e2e.mk +++ b/make/test-e2e.mk @@ -33,7 +33,8 @@ INSTALL_OPTIONS += -f ./make/config/version-checker-values.yaml e2e-setup-deps: | kind-cluster $(NEEDS_KUBECTL) $(KUBECTL) apply -f test/e2e/manifests/docker-credentials.yaml $(KUBECTL) apply -f test/e2e/manifests/gsa-secret.yaml #TODO replace with local hostPath context - $(KUBECTL) apply -f test/e2e/manifests/pod-gcs.yaml + $(KUBECTL) apply -f test/e2e/manifests/kaniko.yaml + $(KUBECTL) wait pod -lapp=e2e-kaniko --for=jsonpath='{.status.containerStatuses[*].state.terminated.reason}'=Completed is_e2e_test= diff --git a/test/e2e/manifests/pod-gcs.yaml b/test/e2e/manifests/kaniko.yaml similarity index 64% rename from test/e2e/manifests/pod-gcs.yaml rename to test/e2e/manifests/kaniko.yaml index 5ddd9371..445e7cf9 100644 --- a/test/e2e/manifests/pod-gcs.yaml +++ b/test/e2e/manifests/kaniko.yaml @@ -2,23 +2,22 @@ apiVersion: v1 kind: Pod metadata: name: kaniko-0 + labels: + app: e2e-kaniko spec: containers: - name: kaniko image: gcr.io/kaniko-project/executor:latest - args: ["--dockerfile=dockerfile", - "--context=gs://jetstack-kaniko-contexts/context.tar.gz", + args: ["--dockerfile=/workspace/dockerfile", + "--context=dir://workspace", "--insecure=true", "--destination=docker-registry.registry.svc.cluster.local:5000/my-app:0.0.1", "--insecure-registry=docker-registry.registry.svc.cluster.local:5000"] volumeMounts: - name: docker-secret mountPath: /kaniko/.docker - - name: kaniko-secret - mountPath: /secret - env: - - name: GOOGLE_APPLICATION_CREDENTIALS - value: /secret/kaniko-secret.json + - name: dockerfile-storage + mountPath: /workspace restartPolicy: Never volumes: - name: docker-secret @@ -27,31 +26,30 @@ spec: items: - key: .dockerconfigjson path: config.json - - name: kaniko-secret - secret: - secretName: kaniko-secret + - name: dockerfile-storage + hostPath: + path: /workspace --- apiVersion: v1 kind: Pod metadata: name: kaniko-1 + labels: + app: e2e-kaniko spec: containers: - name: kaniko image: gcr.io/kaniko-project/executor:latest - args: ["--dockerfile=dockerfile", - "--context=gs://jetstack-kaniko-contexts/context.tar.gz", + args: ["--dockerfile=/workspace/dockerfile", + "--context=dir://workspace", "--insecure=true", "--destination=docker-registry.registry.svc.cluster.local:5000/my-app:0.0.2", "--insecure-registry=docker-registry.registry.svc.cluster.local:5000"] volumeMounts: - name: docker-secret mountPath: /kaniko/.docker - - name: kaniko-secret - mountPath: /secret - env: - - name: GOOGLE_APPLICATION_CREDENTIALS - value: /secret/kaniko-secret.json + - name: dockerfile-storage + mountPath: /workspace restartPolicy: Never volumes: - name: docker-secret @@ -60,6 +58,6 @@ spec: items: - key: .dockerconfigjson path: config.json - - name: kaniko-secret - secret: - secretName: kaniko-secret + - name: dockerfile-storage + hostPath: + path: /workspace \ No newline at end of file diff --git a/test/e2e/manifests/volume.yaml b/test/e2e/manifests/volume.yaml deleted file mode 100644 index 998aad3d..00000000 --- a/test/e2e/manifests/volume.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: dockerfile - labels: - type: local -spec: - capacity: - storage: 1Gi - accessModes: - - ReadWriteOnce - storageClassName: local-storage - hostPath: - path: "/Users/paulwilljones/repos/jetstack/version-checker/make/config/kaniko/" - type: Directory ---- -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: dockerfile-claim -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - storageClassName: local-storage diff --git a/test/e2e/suite/version_checker.go b/test/e2e/suite/version_checker.go index e5bfab1f..afc62e34 100644 --- a/test/e2e/suite/version_checker.go +++ b/test/e2e/suite/version_checker.go @@ -13,7 +13,7 @@ import ( ) var _ = Describe("version-checker", func() { - BeforeEach(func() { + JustBeforeEach(func() { cmd := exec.Command("kubectl", "apply", "-f", "./manifests/prom2json.yaml") cmd.Stdout = GinkgoWriter cmd.Stderr = GinkgoWriter @@ -36,6 +36,7 @@ var _ = Describe("version-checker", func() { cmd.Stdout = GinkgoWriter cmd.Stderr = GinkgoWriter Expect(cmd.Run()).NotTo(HaveOccurred()) + }) AfterEach(func() { cmd := exec.Command("kubectl", "delete", "-f", "./manifests/image-from-reg.yaml") @@ -43,75 +44,75 @@ var _ = Describe("version-checker", func() { cmd.Stderr = GinkgoWriter Expect(cmd.Run()).NotTo(HaveOccurred()) }) - }) - It("it should get the current version", func() { - buf := new(bytes.Buffer) - cmd := exec.Command("kubectl", "logs", "-ljob-name=prom2json") - cmd.Stdout = buf - cmd.Stderr = GinkgoWriter - Expect(cmd.Run()).NotTo(HaveOccurred()) + It("it should get the current version", func() { + buf := new(bytes.Buffer) + cmd := exec.Command("kubectl", "logs", "-ljob-name=prom2json") + cmd.Stdout = buf + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) - //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.current_version' - //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.latest_version' - //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .value' - query, err := gojq.Parse(".[]|select(.name==\"version_checker_is_latest_version\")| .metrics[] | select(.labels.image==\"docker-registry.registry.svc.cluster.local:5000/my-app\") | .labels.current_version") - if err != nil { - log.Fatalln(err) - } - var result []interface{} - err = json.Unmarshal(buf.Bytes(), &result) - if err != nil { - log.Fatalln(err) - } - iter := query.Run(result) - for { - v, ok := iter.Next() - if !ok { - break + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.current_version' + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.latest_version' + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .value' + query, err := gojq.Parse(".[]|select(.name==\"version_checker_is_latest_version\")| .metrics[] | select(.labels.image==\"docker-registry.registry.svc.cluster.local:5000/my-app\") | .labels.current_version") + if err != nil { + log.Fatalln(err) + } + var result []interface{} + err = json.Unmarshal(buf.Bytes(), &result) + if err != nil { + log.Fatalln(err) } - if err, ok := v.(error); ok { - if err, ok := err.(*gojq.HaltError); ok && err.Value() == nil { + iter := query.Run(result) + for { + v, ok := iter.Next() + if !ok { break } - log.Fatalln(err) + if err, ok := v.(error); ok { + if err, ok := err.(*gojq.HaltError); ok && err.Value() == nil { + break + } + log.Fatalln(err) + } + Expect(v).To(Equal("0.0.1")) } - Expect(v).To(Equal("0.0.1")) - } - }) + }) - It("it should find a newer version", func() { - buf := new(bytes.Buffer) - cmd := exec.Command("kubectl", "logs", "-ljob-name=prom2json") - cmd.Stdout = buf - cmd.Stderr = GinkgoWriter - Expect(cmd.Run()).NotTo(HaveOccurred()) + It("it should find a newer version", func() { + buf := new(bytes.Buffer) + cmd := exec.Command("kubectl", "logs", "-ljob-name=prom2json") + cmd.Stdout = buf + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) - //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.current_version' - //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.latest_version' - //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .value' - query, err := gojq.Parse(".[]|select(.name==\"version_checker_is_latest_version\")| .metrics[] | select(.labels.image==\"docker-registry.registry.svc.cluster.local:5000/my-app\") | .labels.latest_version") - if err != nil { - log.Fatalln(err) - } - var result []interface{} - err = json.Unmarshal(buf.Bytes(), &result) - if err != nil { - log.Fatalln(err) - } - iter := query.Run(result) - for { - v, ok := iter.Next() - if !ok { - break + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.current_version' + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .labels.latest_version' + //k logs -ljob-name=prom2json | jq '.[]|select(.name=="version_checker_is_latest_version")| .metrics[] | select(.labels.image=="docker-registry.registry.svc.cluster.local:5000/my-app") | .value' + query, err := gojq.Parse(".[]|select(.name==\"version_checker_is_latest_version\")| .metrics[] | select(.labels.image==\"docker-registry.registry.svc.cluster.local:5000/my-app\") | .labels.latest_version") + if err != nil { + log.Fatalln(err) } - if err, ok := v.(error); ok { - if err, ok := err.(*gojq.HaltError); ok && err.Value() == nil { + var result []interface{} + err = json.Unmarshal(buf.Bytes(), &result) + if err != nil { + log.Fatalln(err) + } + iter := query.Run(result) + for { + v, ok := iter.Next() + if !ok { break } - log.Fatalln(err) + if err, ok := v.(error); ok { + if err, ok := err.(*gojq.HaltError); ok && err.Value() == nil { + break + } + log.Fatalln(err) + } + Expect(v).To(Equal("0.0.2")) } - Expect(v).To(Equal("0.0.2")) - } + }) }) }) From 42ec40d89a7bd7f8362d44093aca311b778067a4 Mon Sep 17 00:00:00 2001 From: paulwilljones Date: Fri, 6 Sep 2024 16:38:19 +0100 Subject: [PATCH 5/7] e2e: retry pushing to registry --- make/_shared/tools/00_mod.mk | 1 - make/test-e2e.mk | 3 +-- test/e2e/manifests/kaniko.yaml | 6 ++++-- test/e2e/suite/version_checker.go | 19 ++++++++++++++++++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/make/_shared/tools/00_mod.mk b/make/_shared/tools/00_mod.mk index 234c005a..6491a62c 100644 --- a/make/_shared/tools/00_mod.mk +++ b/make/_shared/tools/00_mod.mk @@ -615,7 +615,6 @@ $(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_linux_$(HOST_ARCH): | $(DOW missing=$(shell (command -v curl >/dev/null || echo curl) \ && (command -v sha256sum >/dev/null || command -v shasum >/dev/null || echo sha256sum) \ && (command -v git >/dev/null || echo git) \ - && (command -v rsync >/dev/null || echo rsync) \ && (command -v bash >/dev/null || echo bash)) ifneq ($(missing),) $(error Missing required tools: $(missing)) diff --git a/make/test-e2e.mk b/make/test-e2e.mk index c74690ed..d462f698 100644 --- a/make/test-e2e.mk +++ b/make/test-e2e.mk @@ -32,9 +32,8 @@ INSTALL_OPTIONS += -f ./make/config/version-checker-values.yaml .PHONY: e2e-setup-deps e2e-setup-deps: | kind-cluster $(NEEDS_KUBECTL) $(KUBECTL) apply -f test/e2e/manifests/docker-credentials.yaml - $(KUBECTL) apply -f test/e2e/manifests/gsa-secret.yaml #TODO replace with local hostPath context $(KUBECTL) apply -f test/e2e/manifests/kaniko.yaml - $(KUBECTL) wait pod -lapp=e2e-kaniko --for=jsonpath='{.status.containerStatuses[*].state.terminated.reason}'=Completed + $(KUBECTL) wait pod -lapp=e2e-kaniko --timeout=30s --for=jsonpath='{.status.containerStatuses[*].state.terminated.reason}'=Completed is_e2e_test= diff --git a/test/e2e/manifests/kaniko.yaml b/test/e2e/manifests/kaniko.yaml index 445e7cf9..29014893 100644 --- a/test/e2e/manifests/kaniko.yaml +++ b/test/e2e/manifests/kaniko.yaml @@ -12,7 +12,8 @@ spec: "--context=dir://workspace", "--insecure=true", "--destination=docker-registry.registry.svc.cluster.local:5000/my-app:0.0.1", - "--insecure-registry=docker-registry.registry.svc.cluster.local:5000"] + "--insecure-registry=docker-registry.registry.svc.cluster.local:5000", + "--push-retry=10"] volumeMounts: - name: docker-secret mountPath: /kaniko/.docker @@ -44,7 +45,8 @@ spec: "--context=dir://workspace", "--insecure=true", "--destination=docker-registry.registry.svc.cluster.local:5000/my-app:0.0.2", - "--insecure-registry=docker-registry.registry.svc.cluster.local:5000"] + "--insecure-registry=docker-registry.registry.svc.cluster.local:5000", + "--push-retry=10"] volumeMounts: - name: docker-secret mountPath: /kaniko/.docker diff --git a/test/e2e/suite/version_checker.go b/test/e2e/suite/version_checker.go index afc62e34..af242c26 100644 --- a/test/e2e/suite/version_checker.go +++ b/test/e2e/suite/version_checker.go @@ -13,12 +13,29 @@ import ( ) var _ = Describe("version-checker", func() { + // BeforeEach(func() { + // cmd := exec.Command("kubectl", "apply", "-f", "./manifests/kaniko.yaml") + // cmd.Stdout = GinkgoWriter + // cmd.Stderr = GinkgoWriter + // Expect(cmd.Run()).NotTo(HaveOccurred()) + // cmd = exec.Command("kubectl", "wait", "pod", "-lapp=e2e-kaniko", "--timeout=30s", "--for=jsonpath='{.status.containerStatuses[*].state.terminated.reason}'=Completed") + // cmd.Stdout = GinkgoWriter + // cmd.Stderr = GinkgoWriter + // Expect(cmd.Run()).NotTo(HaveOccurred()) + // }) + // AfterEach(func() { + // cmd := exec.Command("kubectl", "delete", "-f", "./manifests/kaniko.yaml") + // cmd.Stdout = GinkgoWriter + // cmd.Stderr = GinkgoWriter + // Expect(cmd.Run()).NotTo(HaveOccurred()) + // }) + JustBeforeEach(func() { cmd := exec.Command("kubectl", "apply", "-f", "./manifests/prom2json.yaml") cmd.Stdout = GinkgoWriter cmd.Stderr = GinkgoWriter Expect(cmd.Run()).NotTo(HaveOccurred()) - cmd = exec.Command("kubectl", "wait", "--for=condition=Complete", "job", "-ljob-name=prom2json") + cmd = exec.Command("kubectl", "wait", "--for=condition=Complete", "--timeout=30s", "job", "-ljob-name=prom2json") cmd.Stdout = GinkgoWriter cmd.Stderr = GinkgoWriter Expect(cmd.Run()).NotTo(HaveOccurred()) From 09f7d3fda41f0379eecd8d987fccd713f5508787 Mon Sep 17 00:00:00 2001 From: paulwilljones Date: Fri, 25 Apr 2025 13:36:36 +0100 Subject: [PATCH 6/7] Add makefile-modules --- .github/workflows/govulncheck.yaml | 35 +++ .gitignore | 2 + .golangci.yaml | 85 ++++++ Makefile | 6 +- .../version-checker/values.linter.exceptions | 0 go.mod | 12 +- klone.yaml | 59 ++++ make/00_mod.mk | 2 +- make/_shared/generate-verify/00_mod.mk | 18 ++ make/_shared/generate-verify/02_mod.mk | 39 +++ make/_shared/generate-verify/util/verify.sh | 73 +++++ make/_shared/go/.golangci.override.yaml | 80 ++++++ make/_shared/go/01_mod.mk | 150 ++++++++++ make/_shared/go/README.md | 3 + .../base/.github/workflows/govulncheck.yaml | 35 +++ make/_shared/helm/01_mod.mk | 4 + make/_shared/helm/crd.template.footer.yaml | 1 + make/_shared/helm/crd.template.header.yaml | 11 + make/_shared/helm/crds.mk | 74 +++++ make/_shared/helm/crds_dir.README.md | 8 + make/_shared/helm/helm.mk | 96 +++++-- make/_shared/kind/00_kind_image_versions.mk | 28 +- make/_shared/kind/kind-image-preload.mk | 32 ++- make/_shared/klone/01_mod.mk | 27 ++ make/_shared/oci-build/00_mod.mk | 19 +- make/_shared/oci-build/01_mod.mk | 33 +-- .../oci-build/image_tool/append_layers.go | 220 --------------- .../image_tool/convert_to_docker_tar.go | 97 ------- make/_shared/oci-build/image_tool/go.mod | 19 -- make/_shared/oci-build/image_tool/go.sum | 58 ---- .../oci-build/image_tool/list_digests.go | 46 --- make/_shared/oci-publish/00_mod.mk | 2 +- make/_shared/repository-base/01_mod.mk | 33 +++ .../base-dependabot/.github/dependabot.yaml | 20 ++ .../.github/workflows/make-self-upgrade.yaml | 105 +++++++ make/_shared/repository-base/base/LICENSE | 201 +++++++++++++ make/_shared/repository-base/base/Makefile | 116 ++++++++ .../repository-base/base/OWNERS_ALIASES | 14 + make/_shared/tools/00_mod.mk | 267 ++++++++++-------- make/_shared/tools/util/lock.sh | 2 +- make/config/kaniko/dockerfile | 2 +- make/test-e2e.mk | 19 +- pkg/client/selfhosted/selfhosted.go | 4 - .../e2e/manifests/docker-registry-values.yaml | 24 ++ .../main.go => test/e2e/suite/doc.go | 31 +- .../selfhosted.go} | 54 ++-- 46 files changed, 1568 insertions(+), 698 deletions(-) create mode 100644 .github/workflows/govulncheck.yaml create mode 100644 .golangci.yaml create mode 100644 deploy/charts/version-checker/values.linter.exceptions create mode 100644 klone.yaml create mode 100644 make/_shared/generate-verify/00_mod.mk create mode 100644 make/_shared/generate-verify/02_mod.mk create mode 100755 make/_shared/generate-verify/util/verify.sh create mode 100644 make/_shared/go/.golangci.override.yaml create mode 100644 make/_shared/go/01_mod.mk create mode 100644 make/_shared/go/README.md create mode 100644 make/_shared/go/base/.github/workflows/govulncheck.yaml create mode 100644 make/_shared/helm/crd.template.footer.yaml create mode 100644 make/_shared/helm/crd.template.header.yaml create mode 100644 make/_shared/helm/crds.mk create mode 100644 make/_shared/helm/crds_dir.README.md create mode 100644 make/_shared/klone/01_mod.mk delete mode 100644 make/_shared/oci-build/image_tool/append_layers.go delete mode 100644 make/_shared/oci-build/image_tool/convert_to_docker_tar.go delete mode 100644 make/_shared/oci-build/image_tool/go.mod delete mode 100644 make/_shared/oci-build/image_tool/go.sum delete mode 100644 make/_shared/oci-build/image_tool/list_digests.go create mode 100644 make/_shared/repository-base/01_mod.mk create mode 100644 make/_shared/repository-base/base-dependabot/.github/dependabot.yaml create mode 100644 make/_shared/repository-base/base/.github/workflows/make-self-upgrade.yaml create mode 100644 make/_shared/repository-base/base/LICENSE create mode 100644 make/_shared/repository-base/base/Makefile create mode 100644 make/_shared/repository-base/base/OWNERS_ALIASES create mode 100644 test/e2e/manifests/docker-registry-values.yaml rename make/_shared/oci-build/image_tool/main.go => test/e2e/suite/doc.go (50%) rename test/e2e/suite/{version_checker.go => selfhosted/selfhosted.go} (73%) diff --git a/.github/workflows/govulncheck.yaml b/.github/workflows/govulncheck.yaml new file mode 100644 index 00000000..882e6863 --- /dev/null +++ b/.github/workflows/govulncheck.yaml @@ -0,0 +1,35 @@ +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/go/base/.github/workflows/govulncheck.yaml instead. + +# Run govulncheck at midnight every night on the main branch, +# to alert us to recent vulnerabilities which affect the Go code in this +# project. +name: govulncheck +on: + workflow_dispatch: {} + schedule: + - cron: '0 0 * * *' + +permissions: + contents: read + +jobs: + govulncheck: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + # Adding `fetch-depth: 0` makes sure tags are also fetched. We need + # the tags so `git describe` returns a valid version. + # see https://github.com/actions/checkout/issues/701 for extra info about this option + with: { fetch-depth: 0 } + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - run: make verify-govulncheck diff --git a/.gitignore b/.gitignore index 5931a6c0..6de93b30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /bin coverage.out .debug +_bin +.vscode diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 00000000..39538626 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,85 @@ +version: "2" +linters: + default: none + exclusions: + generated: lax + presets: [comments, common-false-positives, legacy, std-error-handling] + rules: + - linters: + - gomoddirectives + - promlinter + text: .* + paths: [third_party$, builtin$, examples$] + warn-unused: true + settings: + staticcheck: + checks: ["all", "-ST1000", "-ST1001", "-ST1003", "-ST1005", "-ST1012", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-QF1001", "-QF1003", "-QF1008"] + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - canonicalheader + - contextcheck + - copyloopvar + - decorder + - dogsled + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - exhaustive + - exptostd + - forbidigo + - ginkgolinter + - gocheckcompilerdirectives + - gochecksumtype + - gocritic + - goheader + - goprintffuncname + - gosec + - gosmopolitan + - govet + - grouper + - importas + - ineffassign + - interfacebloat + - intrange + - loggercheck + - makezero + - mirror + - misspell + - musttag + - nakedret + - nilerr + - nilnil + - noctx + - nosprintfhostport + - predeclared + - promlinter + - protogetter + - reassign + - sloglint + - staticcheck + - tagalign + - testableexamples + - unconvert + - unparam + - unused + - usestdlibvars + - usetesting + - wastedassign +formatters: + enable: [gci, gofmt] + settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(github.com/jetstack/version-checker) # Custom section: groups all imports with the specified Prefix. + - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. + exclusions: + generated: lax + paths: [third_party$, builtin$, examples$] diff --git a/Makefile b/Makefile index 0d32b939..6a1652d4 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ ################################## # Some modules build their dependencies from variables, we want these to be -# evalutated at the last possible moment. For this we use second expansion to +# evaluated at the last possible moment. For this we use second expansion to # re-evaluate the generate and verify targets a second time. # # See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html @@ -52,10 +52,6 @@ noop: # do nothing # warning from happening when running make without arguments MAKECMDGOALS ?= -image: ## build docker image - GOARCH=$(ARCH) GOOS=linux CGO_ENABLED=0 go build -o ./bin/version-checker-linux ./cmd/. - docker build -t quay.io/jetstack/version-checker:v0.9.0 . - ################################## # Host OS and architecture setup # ################################## diff --git a/deploy/charts/version-checker/values.linter.exceptions b/deploy/charts/version-checker/values.linter.exceptions new file mode 100644 index 00000000..e69de29b diff --git a/go.mod b/go.mod index 1ff1ad6c..7afb8cee 100644 --- a/go.mod +++ b/go.mod @@ -40,14 +40,17 @@ require ( github.com/google/go-github/v70 v70.0.0 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/jarcoal/httpmock v1.3.1 + github.com/onsi/ginkgo/v2 v2.22.0 + github.com/onsi/gomega v1.36.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/stretchr/testify v1.10.0 sigs.k8s.io/controller-runtime v0.20.4 - github.com/onsi/ginkgo/v2 v2.19.0 - github.com/onsi/gomega v1.33.1 ) -require github.com/itchyny/timefmt-go v0.1.6 // indirect +require ( + github.com/itchyny/timefmt-go v0.1.6 // indirect + golang.org/x/tools v0.29.0 // indirect +) require ( github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect @@ -91,13 +94,12 @@ require ( github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect + github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/itchyny/gojq v0.12.16 - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.0 // indirect diff --git a/klone.yaml b/klone.yaml new file mode 100644 index 00000000..b3cacda9 --- /dev/null +++ b/klone.yaml @@ -0,0 +1,59 @@ +# This klone.yaml file describes the Makefile modules and versions that are +# cloned into the "make/_shared" folder. These modules are dynamically imported +# by the root Makefile. The "make upgrade-klone" target can be used to pull +# the latest version from the upstream repositories (using the repo_ref value). +# +# More info can be found here: https://github.com/cert-manager/makefile-modules + +targets: + make/_shared: + - folder_name: generate-verify + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/generate-verify + - folder_name: go + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/go + - folder_name: helm + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/helm + - folder_name: help + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/help + - folder_name: kind + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/kind + - folder_name: klone + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/klone + - folder_name: oci-build + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/oci-build + - folder_name: oci-publish + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/oci-publish + - folder_name: repository-base + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/repository-base + - folder_name: tools + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 9c9f116938e082201a6bae0aedc7c7cf525fd8bf + repo_path: modules/tools diff --git a/make/00_mod.mk b/make/00_mod.mk index 55cb460c..ce05887d 100644 --- a/make/00_mod.mk +++ b/make/00_mod.mk @@ -32,7 +32,7 @@ deploy_name := version-checker deploy_namespace := version-checker helm_chart_source_dir := deploy/charts/version-checker -helm_chart_name := version-checker +helm_chart_image_name := version-checker helm_chart_version := $(VERSION) helm_labels_template_name := version-checker.labels helm_docs_use_helm_tool := 1 diff --git a/make/_shared/generate-verify/00_mod.mk b/make/_shared/generate-verify/00_mod.mk new file mode 100644 index 00000000..43555138 --- /dev/null +++ b/make/_shared/generate-verify/00_mod.mk @@ -0,0 +1,18 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +shared_generate_targets ?= +shared_generate_targets_dirty ?= +shared_verify_targets ?= +shared_verify_targets_dirty ?= diff --git a/make/_shared/generate-verify/02_mod.mk b/make/_shared/generate-verify/02_mod.mk new file mode 100644 index 00000000..f0677298 --- /dev/null +++ b/make/_shared/generate-verify/02_mod.mk @@ -0,0 +1,39 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.PHONY: generate +## Generate all generate targets. +## @category [shared] Generate/ Verify +generate: $$(shared_generate_targets) + @echo "The following targets cannot be run simultaneously with each other or other generate scripts:" + $(foreach TARGET,$(shared_generate_targets_dirty), $(MAKE) $(TARGET)) + +verify_script := $(dir $(lastword $(MAKEFILE_LIST)))/util/verify.sh + +# Run the supplied make target argument in a temporary workspace and diff the results. +verify-%: FORCE + +$(verify_script) $(MAKE) $* + +verify_generated_targets = $(shared_generate_targets:%=verify-%) +verify_generated_targets_dirty = $(shared_generate_targets_dirty:%=verify-%) + +verify_targets = $(sort $(verify_generated_targets) $(shared_verify_targets)) +verify_targets_dirty = $(sort $(verify_generated_targets_dirty) $(shared_verify_targets_dirty)) + +.PHONY: verify +## Verify code and generate targets. +## @category [shared] Generate/ Verify +verify: $$(verify_targets) + @echo "The following targets create temporary files in the current directory, that is why they have to be run last:" + $(foreach TARGET,$(verify_targets_dirty), $(MAKE) $(TARGET)) diff --git a/make/_shared/generate-verify/util/verify.sh b/make/_shared/generate-verify/util/verify.sh new file mode 100755 index 00000000..feb53bfe --- /dev/null +++ b/make/_shared/generate-verify/util/verify.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash + +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Verify that the supplied command does not make any changes to the repository. +# +# This is called from the Makefile to verify that all code generation scripts +# have been run and that their changes have been committed to the repository. +# +# Runs any of the scripts or Make targets in this repository, after making a +# copy of the repository, then reports any changes to the files in the copy. + +# For example: +# +# make verify-helm-chart-update || \ +# make helm-chart-update +# +set -o errexit +set -o nounset +set -o pipefail + +projectdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../../../.." && pwd )" + +cd "${projectdir}" + +# Use short form arguments here to support BSD/macOS. `-d` instructs +# it to make a directory, `-t` provides a prefix to use for the directory name. +tmp="$(mktemp -d /tmp/verify.sh.XXXXXXXX)" + +cleanup() { + rm -rf "${tmp}" +} +trap "cleanup" EXIT SIGINT + +# Why not just "cp" to the tmp dir? +# A dumb "cp" will fail sometimes since _bin can get changed while it's being copied if targets are run in parallel, +# and cp doesn't have some universal "exclude" option to ignore "_bin" +# +# We previously used "rsync" here, but: +# 1. That's another tool we need to depend on +# 2. rsync on macOS 15.4 and newer is actually openrsync, which has different permissions and throws errors when copying git objects +# +# So, we use find to list all files except _bin, and then copy each in turn +find . -maxdepth 1 -not \( -path "./_bin" \) -not \( -path "." \) | xargs -I% cp -af "${projectdir}/%" "${tmp}/" + +pushd "${tmp}" >/dev/null + +"$@" + +popd >/dev/null + +if ! diff \ + --exclude=".git" \ + --exclude="_bin" \ + --new-file --unified --show-c-function --recursive "${projectdir}" "${tmp}" +then + echo + echo "Project '${projectdir}' is out of date." + echo "Please run '${*}' or apply the above diffs" + exit 1 +fi diff --git a/make/_shared/go/.golangci.override.yaml b/make/_shared/go/.golangci.override.yaml new file mode 100644 index 00000000..f787d6a4 --- /dev/null +++ b/make/_shared/go/.golangci.override.yaml @@ -0,0 +1,80 @@ +version: "2" +linters: + default: none + exclusions: + generated: lax + presets: [ comments, common-false-positives, legacy, std-error-handling ] + paths: [ third_party$, builtin$, examples$ ] + warn-unused: true + settings: + staticcheck: + checks: [ "all", "-ST1000", "-ST1001", "-ST1003", "-ST1005", "-ST1012", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-QF1001", "-QF1003", "-QF1008" ] + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - canonicalheader + - contextcheck + - copyloopvar + - decorder + - dogsled + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - exhaustive + - exptostd + - forbidigo + - ginkgolinter + - gocheckcompilerdirectives + - gochecksumtype + - gocritic + - goheader + - goprintffuncname + - gosec + - gosmopolitan + - govet + - grouper + - importas + - ineffassign + - interfacebloat + - intrange + - loggercheck + - makezero + - mirror + - misspell + - musttag + - nakedret + - nilerr + - nilnil + - noctx + - nosprintfhostport + - predeclared + - promlinter + - protogetter + - reassign + - sloglint + - staticcheck + - tagalign + - testableexamples + - unconvert + - unparam + - unused + - usestdlibvars + - usetesting + - wastedassign +formatters: + enable: [ gci, gofmt ] + settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix({{REPO-NAME}}) # Custom section: groups all imports with the specified Prefix. + - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. + exclusions: + generated: lax + paths: [ third_party$, builtin$, examples$ ] diff --git a/make/_shared/go/01_mod.mk b/make/_shared/go/01_mod.mk new file mode 100644 index 00000000..81681ddd --- /dev/null +++ b/make/_shared/go/01_mod.mk @@ -0,0 +1,150 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifndef bin_dir +$(error bin_dir is not set) +endif + +ifndef repo_name +$(error repo_name is not set) +endif + +golangci_lint_override := $(dir $(lastword $(MAKEFILE_LIST)))/.golangci.override.yaml + +.PHONY: go-workspace +go-workspace: export GOWORK?=$(abspath go.work) +## Create a go.work file in the repository root (or GOWORK) +## +## @category Development +go-workspace: | $(NEEDS_GO) + @rm -f $(GOWORK) + $(GO) work init + @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ + | while read d; do \ + target=$$(dirname $${d}); \ + $(GO) work use "$${target}"; \ + done + +.PHONY: go-tidy +## Alias for `make generate-go-mod-tidy` +## @category [shared] Generate/ Verify +go-tidy: generate-go-mod-tidy + +.PHONY: generate-go-mod-tidy +## Run `go mod tidy` on all Go modules +## @category [shared] Generate/ Verify +generate-go-mod-tidy: | $(NEEDS_GO) + @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ + | while read d; do \ + target=$$(dirname $${d}); \ + echo "Running 'go mod tidy' in directory '$${target}'"; \ + pushd "$${target}" >/dev/null; \ + $(GO) mod tidy || exit; \ + popd >/dev/null; \ + echo ""; \ + done + +shared_generate_targets += generate-go-mod-tidy + +default_govulncheck_generate_base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ +# The base directory used to copy the govulncheck GH action from. This can be +# overwritten with an action with extra authentication or with a totally different +# pipeline (eg. a GitLab pipeline). +govulncheck_generate_base_dir ?= $(default_govulncheck_generate_base_dir) + +.PHONY: generate-govulncheck +## Generate base files in the repository +## @category [shared] Generate/ Verify +generate-govulncheck: + cp -r $(govulncheck_generate_base_dir)/. ./ + +shared_generate_targets += generate-govulncheck + +.PHONY: verify-govulncheck +## Verify all Go modules for vulnerabilities using govulncheck +## @category [shared] Generate/ Verify +# +# Runs `govulncheck` on all Go modules related to the project. +# Ignores Go modules among the temporary build artifacts in _bin, to avoid +# scanning the code of the vendored Go, after running make vendor-go. +# Ignores Go modules in make/_shared, because those will be checked in centrally +# in the makefile_modules repository. +# +# `verify-govulncheck` not added to the `shared_verify_targets` variable and is +# not run by `make verify`, because `make verify` is run for each PR, and we do +# not want new vulnerabilities in existing code to block the merging of PRs. +# Instead `make verify-govulncheck` is intended to be run periodically by a CI job. +verify-govulncheck: | $(NEEDS_GOVULNCHECK) + @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ + | while read d; do \ + target=$$(dirname $${d}); \ + echo "Running 'GOTOOLCHAIN=go$(VENDORED_GO_VERSION) $(bin_dir)/tools/govulncheck ./...' in directory '$${target}'"; \ + pushd "$${target}" >/dev/null; \ + GOTOOLCHAIN=go$(VENDORED_GO_VERSION) $(GOVULNCHECK) ./... || exit; \ + popd >/dev/null; \ + echo ""; \ + done + +ifdef golangci_lint_config + +.PHONY: generate-golangci-lint-config +## Generate a golangci-lint configuration file +## @category [shared] Generate/ Verify +generate-golangci-lint-config: | $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(bin_dir)/scratch + if [ "$$($(YQ) eval 'has("version") | not' $(golangci_lint_config))" == "true" ]; then \ + $(GOLANGCI-LINT) migrate -c $(golangci_lint_config); \ + rm $(basename $(golangci_lint_config)).bck$(suffix $(golangci_lint_config)); \ + fi + + cp $(golangci_lint_config) $(bin_dir)/scratch/golangci-lint.yaml.tmp + $(YQ) -i 'del(.linters.enable)' $(bin_dir)/scratch/golangci-lint.yaml.tmp + $(YQ) eval-all -i '. as $$item ireduce ({}; . * $$item)' $(bin_dir)/scratch/golangci-lint.yaml.tmp $(golangci_lint_override) + $(YQ) -i '(.. | select(tag == "!!str")) |= sub("{{REPO-NAME}}", "$(repo_name)")' $(bin_dir)/scratch/golangci-lint.yaml.tmp + mv $(bin_dir)/scratch/golangci-lint.yaml.tmp $(golangci_lint_config) + +shared_generate_targets += generate-golangci-lint-config + +golangci_lint_timeout ?= 10m + +.PHONY: verify-golangci-lint +## Verify all Go modules using golangci-lint +## @category [shared] Generate/ Verify +verify-golangci-lint: | $(NEEDS_GO) $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(bin_dir)/scratch + @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ + | while read d; do \ + target=$$(dirname $${d}); \ + echo "Running 'GOVERSION=$(VENDORED_GO_VERSION) $(bin_dir)/tools/golangci-lint run -c $(CURDIR)/$(golangci_lint_config) --timeout $(golangci_lint_timeout)' in directory '$${target}'"; \ + pushd "$${target}" >/dev/null; \ + GOVERSION=$(VENDORED_GO_VERSION) $(GOLANGCI-LINT) run -c $(CURDIR)/$(golangci_lint_config) --timeout $(golangci_lint_timeout) || exit; \ + popd >/dev/null; \ + echo ""; \ + done + +shared_verify_targets_dirty += verify-golangci-lint + +.PHONY: fix-golangci-lint +## Fix all Go modules using golangci-lint +## @category [shared] Generate/ Verify +fix-golangci-lint: | $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(NEEDS_GCI) $(bin_dir)/scratch + @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ + | while read d; do \ + target=$$(dirname $${d}); \ + echo "Running 'GOVERSION=$(VENDORED_GO_VERSION) $(bin_dir)/tools/golangci-lint fmt -c $(CURDIR)/$(golangci_lint_config)' in directory '$${target}'"; \ + pushd "$${target}" >/dev/null; \ + GOVERSION=$(VENDORED_GO_VERSION) $(GOLANGCI-LINT) fmt -c $(CURDIR)/$(golangci_lint_config) || exit; \ + popd >/dev/null; \ + echo ""; \ + done + +endif diff --git a/make/_shared/go/README.md b/make/_shared/go/README.md new file mode 100644 index 00000000..ad1962ba --- /dev/null +++ b/make/_shared/go/README.md @@ -0,0 +1,3 @@ +# README + +A module for various Go static checks. diff --git a/make/_shared/go/base/.github/workflows/govulncheck.yaml b/make/_shared/go/base/.github/workflows/govulncheck.yaml new file mode 100644 index 00000000..882e6863 --- /dev/null +++ b/make/_shared/go/base/.github/workflows/govulncheck.yaml @@ -0,0 +1,35 @@ +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/go/base/.github/workflows/govulncheck.yaml instead. + +# Run govulncheck at midnight every night on the main branch, +# to alert us to recent vulnerabilities which affect the Go code in this +# project. +name: govulncheck +on: + workflow_dispatch: {} + schedule: + - cron: '0 0 * * *' + +permissions: + contents: read + +jobs: + govulncheck: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + # Adding `fetch-depth: 0` makes sure tags are also fetched. We need + # the tags so `git describe` returns a valid version. + # see https://github.com/actions/checkout/issues/701 for extra info about this option + with: { fetch-depth: 0 } + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - run: make verify-govulncheck diff --git a/make/_shared/helm/01_mod.mk b/make/_shared/helm/01_mod.mk index 001c98af..45ed301b 100644 --- a/make/_shared/helm/01_mod.mk +++ b/make/_shared/helm/01_mod.mk @@ -12,5 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +ifndef helm_dont_include_crds +include $(dir $(lastword $(MAKEFILE_LIST)))/crds.mk +endif + include $(dir $(lastword $(MAKEFILE_LIST)))/helm.mk include $(dir $(lastword $(MAKEFILE_LIST)))/deploy.mk diff --git a/make/_shared/helm/crd.template.footer.yaml b/make/_shared/helm/crd.template.footer.yaml new file mode 100644 index 00000000..0a67617f --- /dev/null +++ b/make/_shared/helm/crd.template.footer.yaml @@ -0,0 +1 @@ +{{- end }} \ No newline at end of file diff --git a/make/_shared/helm/crd.template.header.yaml b/make/_shared/helm/crd.template.header.yaml new file mode 100644 index 00000000..663d7126 --- /dev/null +++ b/make/_shared/helm/crd.template.header.yaml @@ -0,0 +1,11 @@ +{{- if .Values.crds.enabled }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: "REPLACE_CRD_NAME" + {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + {{- end }} + labels: + {{- include "REPLACE_LABELS_TEMPLATE" . | nindent 4 }} \ No newline at end of file diff --git a/make/_shared/helm/crds.mk b/make/_shared/helm/crds.mk new file mode 100644 index 00000000..247e3619 --- /dev/null +++ b/make/_shared/helm/crds.mk @@ -0,0 +1,74 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################ +# Check Inputs # +################ + +ifndef helm_chart_source_dir +$(error helm_chart_source_dir is not set) +endif + +ifndef helm_labels_template_name +$(error helm_labels_template_name is not set) +endif + +################ +# Add targets # +################ + +crd_template_header := $(dir $(lastword $(MAKEFILE_LIST)))/crd.template.header.yaml +crd_template_footer := $(dir $(lastword $(MAKEFILE_LIST)))/crd.template.footer.yaml + +# see https://stackoverflow.com/a/53408233 +sed_inplace := sed -i'' +ifeq ($(HOST_OS),darwin) + sed_inplace := sed -i '' +endif + +crds_dir ?= deploy/crds +crds_dir_readme := $(dir $(lastword $(MAKEFILE_LIST)))/crds_dir.README.md + +.PHONY: generate-crds +## Generate CRD manifests. +## @category [shared] Generate/ Verify +generate-crds: | $(NEEDS_CONTROLLER-GEN) $(NEEDS_YQ) + $(eval crds_gen_temp := $(bin_dir)/scratch/crds) + $(eval directories := $(shell ls -d */ | grep -v -e 'make' $(shell git check-ignore -- * | sed 's/^/-e /'))) + + rm -rf $(crds_gen_temp) + mkdir -p $(crds_gen_temp) + + $(CONTROLLER-GEN) crd \ + $(directories:%=paths=./%...) \ + output:crd:artifacts:config=$(crds_gen_temp) + + @echo "Updating CRDs with helm templating, writing to $(helm_chart_source_dir)/templates" + + @for i in $$(ls $(crds_gen_temp)); do \ + crd_name=$$($(YQ) eval '.metadata.name' $(crds_gen_temp)/$$i); \ + cat $(crd_template_header) > $(helm_chart_source_dir)/templates/crd-$$i; \ + echo "" >> $(helm_chart_source_dir)/templates/crd-$$i; \ + $(sed_inplace) "s/REPLACE_CRD_NAME/$$crd_name/g" $(helm_chart_source_dir)/templates/crd-$$i; \ + $(sed_inplace) "s/REPLACE_LABELS_TEMPLATE/$(helm_labels_template_name)/g" $(helm_chart_source_dir)/templates/crd-$$i; \ + $(YQ) -I2 '{"spec": .spec}' $(crds_gen_temp)/$$i >> $(helm_chart_source_dir)/templates/crd-$$i; \ + cat $(crd_template_footer) >> $(helm_chart_source_dir)/templates/crd-$$i; \ + done + + @if [ -n "$$(ls $(crds_gen_temp) 2>/dev/null)" ]; then \ + cp $(crds_gen_temp)/* $(crds_dir)/ ; \ + cp $(crds_dir_readme) $(crds_dir)/README.md ; \ + fi + +shared_generate_targets += generate-crds diff --git a/make/_shared/helm/crds_dir.README.md b/make/_shared/helm/crds_dir.README.md new file mode 100644 index 00000000..fba79fed --- /dev/null +++ b/make/_shared/helm/crds_dir.README.md @@ -0,0 +1,8 @@ +# CRDs source directory + +> **WARNING**: if you are an end-user, you probably should NOT need to use the +> files in this directory. These files are for **reference, development and testing purposes only**. + +This directory contains 'source code' used to build our CustomResourceDefinition +resources consumed by our officially supported deployment methods (e.g. the Helm chart). +The CRDs in this directory might be incomplete, and should **NOT** be used to provision the operator. \ No newline at end of file diff --git a/make/_shared/helm/helm.mk b/make/_shared/helm/helm.mk index 7a0cc909..1e9dd0a1 100644 --- a/make/_shared/helm/helm.mk +++ b/make/_shared/helm/helm.mk @@ -24,13 +24,16 @@ ifndef helm_chart_source_dir $(error helm_chart_source_dir is not set) endif -ifndef helm_chart_name -$(error helm_chart_name is not set) +ifndef helm_chart_image_name +$(error helm_chart_image_name is not set) endif ifndef helm_chart_version $(error helm_chart_version is not set) endif +ifneq ($(helm_chart_version:v%=v),v) +$(error helm_chart_version "$(helm_chart_version)" should start with a "v") +endif ifndef helm_values_mutation_function $(error helm_values_mutation_function is not set) @@ -38,10 +41,18 @@ endif ########################################## +helm_chart_name := $(notdir $(helm_chart_image_name)) +helm_chart_image_registry := $(dir $(helm_chart_image_name)) +helm_chart_image_tag := $(helm_chart_version) helm_chart_sources := $(shell find $(helm_chart_source_dir) -maxdepth 1 -type f) $(shell find $(helm_chart_source_dir)/templates -type f) -helm_chart_archive := $(bin_dir)/scratch/image/$(helm_chart_name)-$(helm_chart_version).tgz +helm_chart_archive := $(bin_dir)/scratch/helm/$(helm_chart_name)-$(helm_chart_version).tgz +helm_digest_path := $(bin_dir)/scratch/helm/$(helm_chart_name)-$(helm_chart_version).digests +helm_digest = $(shell head -1 $(helm_digest_path) 2> /dev/null) + +$(bin_dir)/scratch/helm: + @mkdir -p $@ -$(helm_chart_archive): $(helm_chart_sources) | $(NEEDS_HELM) $(NEEDS_YQ) $(bin_dir)/scratch/image +$(helm_chart_archive): $(helm_chart_sources) | $(NEEDS_HELM) $(NEEDS_YQ) $(bin_dir)/scratch/helm $(eval helm_chart_source_dir_versioned := $@.tmp) rm -rf $(helm_chart_source_dir_versioned) mkdir -p $(dir $(helm_chart_source_dir_versioned)) @@ -53,7 +64,7 @@ $(helm_chart_archive): $(helm_chart_sources) | $(NEEDS_HELM) $(NEEDS_YQ) $(bin_d echo "Chart name does not match the name in the helm_chart_name variable"; \ exit 1; \ fi - + $(YQ) '.annotations."artifacthub.io/prerelease" = "$(IS_PRERELEASE)"' \ --inplace $(helm_chart_source_dir_versioned)/Chart.yaml @@ -63,13 +74,24 @@ $(helm_chart_archive): $(helm_chart_sources) | $(NEEDS_HELM) $(NEEDS_YQ) $(bin_d --version $(helm_chart_version) \ --destination $(dir $@) +.PHONY: helm-chart-oci-push +## Create and push Helm chart to OCI registry. +## Will also create a non-v-prefixed tag for the OCI image. +## @category [shared] Publish +helm-chart-oci-push: $(helm_chart_archive) | $(NEEDS_HELM) $(NEEDS_CRANE) + $(HELM) push "$(helm_chart_archive)" "oci://$(helm_chart_image_registry)" 2>&1 \ + | tee >(grep -o "sha256:.\+" | tee $(helm_digest_path)) + + @# $(helm_chart_image_tag:v%=%) removes the v prefix from the value stored in helm_chart_image_tag. + @# See https://www.gnu.org/software/make/manual/html_node/Substitution-Refs.html for the manual on the syntax. + helm_digest=$$(cat $(helm_digest_path)) && \ + $(CRANE) copy "$(helm_chart_image_name)@$$helm_digest" "$(helm_chart_image_name):$(helm_chart_image_tag:v%=%)" + .PHONY: helm-chart ## Create a helm chart ## @category [shared] Helm Chart helm-chart: $(helm_chart_archive) -ifdef helm_docs_use_helm_tool - helm_tool_header_search ?= ^ helm_tool_footer_search ?= ^ @@ -78,17 +100,9 @@ helm_tool_footer_search ?= ^ ## @category [shared] Generate/ Verify generate-helm-docs: | $(NEEDS_HELM-TOOL) $(HELM-TOOL) inject -i $(helm_chart_source_dir)/values.yaml -o $(helm_chart_source_dir)/README.md --header-search "$(helm_tool_header_search)" --footer-search "$(helm_tool_footer_search)" -else -.PHONY: generate-helm-docs -## Generate Helm chart documentation. -## @category [shared] Generate/ Verify -generate-helm-docs: | $(NEEDS_HELM-DOCS) - $(HELM-DOCS) $(helm_chart_source_dir)/ -endif shared_generate_targets += generate-helm-docs -ifdef helm_generate_schema .PHONY: generate-helm-schema ## Generate Helm chart schema. ## @category [shared] Generate/ Verify @@ -96,9 +110,7 @@ generate-helm-schema: | $(NEEDS_HELM-TOOL) $(NEEDS_GOJQ) $(HELM-TOOL) schema -i $(helm_chart_source_dir)/values.yaml | $(GOJQ) > $(helm_chart_source_dir)/values.schema.json shared_generate_targets += generate-helm-schema -endif -ifdef helm_verify_values .PHONY: verify-helm-values ## Verify Helm chart values using helm-tool. ## @category [shared] Generate/ Verify @@ -106,14 +118,56 @@ verify-helm-values: | $(NEEDS_HELM-TOOL) $(NEEDS_GOJQ) $(HELM-TOOL) lint -i $(helm_chart_source_dir)/values.yaml -d $(helm_chart_source_dir)/templates -e $(helm_chart_source_dir)/values.linter.exceptions shared_verify_targets += verify-helm-values + +$(bin_dir)/scratch/kyverno: + @mkdir -p $@ + +$(bin_dir)/scratch/kyverno/pod-security-policy.yaml: | $(NEEDS_KUSTOMIZE) $(bin_dir)/scratch/kyverno + @$(KUSTOMIZE) build https://github.com/kyverno/policies/pod-security/enforce > $@ + +# Extra arguments for kyverno apply. +kyverno_apply_extra_args := +# Allows known policy violations to be skipped by supplying Kyverno policy +# exceptions as a Kyverno YAML resource, e.g.: +# apiVersion: kyverno.io/v2 +# kind: PolicyException +# metadata: +# name: pod-security-exceptions +# spec: +# exceptions: +# - policyName: disallow-privilege-escalation +# ruleNames: +# - autogen-privilege-escalation +# - policyName: restrict-seccomp-strict +# ruleNames: +# - autogen-check-seccomp-strict +# match: +# any: +# - resources: +# kinds: +# - Deployment +# namespaces: +# - mynamespace +# names: +# - my-deployment +ifneq ("$(wildcard make/verify-pod-security-standards-exceptions.yaml)","") + kyverno_apply_extra_args += --exceptions make/verify-pod-security-standards-exceptions.yaml endif .PHONY: verify-pod-security-standards ## Verify that the Helm chart complies with the pod security standards. +## +## You can add Kyverno policy exceptions to +## `make/verify-pod-security-standards-exceptions.yaml`, to skip some of the pod +## security policy rules. +## ## @category [shared] Generate/ Verify -verify-pod-security-standards: $(helm_chart_archive) | $(NEEDS_KYVERNO) $(NEEDS_KUSTOMIZE) $(NEEDS_HELM) - $(KYVERNO) apply <($(KUSTOMIZE) build https://github.com/kyverno/policies/pod-security/enforce) \ - --resource <($(HELM) template $(helm_chart_archive)) 2>/dev/null +verify-pod-security-standards: $(helm_chart_archive) $(bin_dir)/scratch/kyverno/pod-security-policy.yaml | $(NEEDS_KYVERNO) $(NEEDS_HELM) + $(HELM) template $(helm_chart_archive) $(INSTALL_OPTIONS) \ + | $(KYVERNO) apply $(bin_dir)/scratch/kyverno/pod-security-policy.yaml \ + $(kyverno_apply_extra_args) \ + --resource - \ + --table shared_verify_targets_dirty += verify-pod-security-standards @@ -123,4 +177,4 @@ shared_verify_targets_dirty += verify-pod-security-standards verify-helm-lint: $(helm_chart_archive) | $(NEEDS_HELM) $(HELM) lint $(helm_chart_archive) -shared_verify_targets_dirty += verify-helm-lint +shared_verify_targets_dirty += verify-helm-lint \ No newline at end of file diff --git a/make/_shared/kind/00_kind_image_versions.mk b/make/_shared/kind/00_kind_image_versions.mk index aa9db20b..987a4aa2 100755 --- a/make/_shared/kind/00_kind_image_versions.mk +++ b/make/_shared/kind/00_kind_image_versions.mk @@ -15,20 +15,18 @@ # This file is auto-generated by the learn_kind_images.sh script in the makefile-modules repo. # Do not edit manually. -kind_image_kindversion := v0.23.0 +kind_image_kindversion := v0.27.0 -kind_image_kube_1.25_amd64 := docker.io/kindest/node:v1.25.16@sha256:06bd8a1c3af74cf360a524aa0c4a59922e023a1fb3526ee748609d4823f560f3 -kind_image_kube_1.25_arm64 := docker.io/kindest/node:v1.25.16@sha256:3b2127454d2e55a96e594debf450b80e87fe3273f0c7f74aa0c6be9972b8467e -kind_image_kube_1.26_amd64 := docker.io/kindest/node:v1.26.15@sha256:ad06ec62683fe300927150377e43df432da2228261bedf8eb2442fe5956d5e58 -kind_image_kube_1.26_arm64 := docker.io/kindest/node:v1.26.15@sha256:73f30c6f49b97aa178d14483dfb3ad47a1e014a53589ec02191c3fcd1df7cb71 -kind_image_kube_1.27_amd64 := docker.io/kindest/node:v1.27.13@sha256:30c5d91cab1f2915ad61f38b6279254397c433fc745b74533daa3c1e16617326 -kind_image_kube_1.27_arm64 := docker.io/kindest/node:v1.27.13@sha256:f72a6686e25f80052f37b177215a0a353ed23718d8ee2739cc17cfdb4b8feffb -kind_image_kube_1.28_amd64 := docker.io/kindest/node:v1.28.9@sha256:9ba4d311e7861d27b210e5960e5ce921a7c53d3c67e0545fd8a1cb9a76dfa2cb -kind_image_kube_1.28_arm64 := docker.io/kindest/node:v1.28.9@sha256:2bbf55860a6d38e25e5db113a1035f2286c87fb4f7b1594cfc3643a17b59351f -kind_image_kube_1.29_amd64 := docker.io/kindest/node:v1.29.4@sha256:ea40a6bd365a17f71fd3883a1d34a0791d7d6b0eb75832c6d85b6f2326827f1e -kind_image_kube_1.29_arm64 := docker.io/kindest/node:v1.29.4@sha256:e63a7f74e80b746328fbaa70be406639d0c31c8c8cf0a3d57efdd23c64fe4bba -kind_image_kube_1.30_amd64 := docker.io/kindest/node:v1.30.0@sha256:2af5d1b382926abcd6336312d652cd045b7cc47475844a608669c71b1fefcfbc -kind_image_kube_1.30_arm64 := docker.io/kindest/node:v1.30.0@sha256:5e4ce6f9033bdb9ce81a7fd699c8e67cfcacfab57076058e3e6f33c32036b42b +kind_image_kube_1.29_amd64 := docker.io/kindest/node:v1.29.14@sha256:e7858e6394f5e834802ce573ab340a0584d8314f909cb0717e14b57f2dd97257 +kind_image_kube_1.29_arm64 := docker.io/kindest/node:v1.29.14@sha256:6eed9bfd0313cc3574c4613adeb7f53832cb8d9c0ca9ffa8b8221716fd96dc18 +kind_image_kube_1.30_amd64 := docker.io/kindest/node:v1.30.10@sha256:e382f9b891474f1c4b0b5cfcf27f8e471f1bdc1f285afe38adeec1bd5b856cfe +kind_image_kube_1.30_arm64 := docker.io/kindest/node:v1.30.10@sha256:ca8e16c04ee9ebaeb9a4dd85abbe188f3893fb39bd658d6d3e639d16cf46e3da +kind_image_kube_1.31_amd64 := docker.io/kindest/node:v1.31.6@sha256:37d52dc19f59394f9347b00547c3ed2d73eb301a60294b9b05fbe56fb6196517 +kind_image_kube_1.31_arm64 := docker.io/kindest/node:v1.31.6@sha256:4e6223faa19178922d30e7b62546c5464fdf9bc66a3df64073424a51ab44f2ab +kind_image_kube_1.32_amd64 := docker.io/kindest/node:v1.32.2@sha256:a37b679ad8c1cfa7c64aca1734cc4299dc833258d6c131ed0204c8cd2bd56ff7 +kind_image_kube_1.32_arm64 := docker.io/kindest/node:v1.32.2@sha256:4d0e1b60f1da0d1349996a9778f8bace905189af5e05e04618eae0a155dd9f9c +kind_image_kube_1.33_amd64 := docker.io/kindest/node:v1.33.0@sha256:c9ec7bf998c310c5a6c903d66c2e595fb3e2eb53fb626cd53d07a3a5499de412 +kind_image_kube_1.33_arm64 := docker.io/kindest/node:v1.33.0@sha256:96ae3b980f87769e0117c2a89ec74fc660b84eedb573432abd2a682af3eccc02 -kind_image_latest_amd64 := $(kind_image_kube_1.30_amd64) -kind_image_latest_arm64 := $(kind_image_kube_1.30_arm64) +kind_image_latest_amd64 := $(kind_image_kube_1.33_amd64) +kind_image_latest_arm64 := $(kind_image_kube_1.33_arm64) diff --git a/make/_shared/kind/kind-image-preload.mk b/make/_shared/kind/kind-image-preload.mk index e95c9ee4..88471e26 100644 --- a/make/_shared/kind/kind-image-preload.mk +++ b/make/_shared/kind/kind-image-preload.mk @@ -32,18 +32,28 @@ images_files := $(foreach image,$(images),$(subst :,+,$(image))) images_tar_dir := $(bin_dir)/downloaded/containers/$(HOST_ARCH) images_tars := $(images_files:%=$(images_tar_dir)/%.tar) -# Download the images as tarballs. We must use the tag because the digest -# will change after we docker import the image. The tag is the only way to -# reference the image after it has been imported. Before downloading the -# image, we check that the provided digest matches the digest of the image -# that we are about to pull. -$(images_tars): $(images_tar_dir)/%.tar: | $(NEEDS_CRANE) - @$(eval image=$(subst +,:,$*)) - @$(eval image_without_digest=$(shell cut -d@ -f1 <<<"$(image)")) - @$(eval digest=$(subst $(image_without_digest)@,,$(image))) +# Download the images as tarballs. After downloading the image using +# its digest, we untar the image and modify the .[0].RepoTags[0] value in +# the manifest.json file to have the correct tag (instead of "i-was-a-digest" +# which is set when the image is pulled using its digest). This tag is used +# to reference the image after it has been imported using docker or kind. Otherwise, +# the image would be imported with the tag "i-was-a-digest" which is not very useful. +# We would have to use digests to reference the image everywhere which might +# not always be possible and does not match the default behavior of eg. our helm charts. +# Untarring and modifying manifest.json is a hack and we hope that crane adds an option +# in the future that allows setting the tag on images that are pulled by digest. +# NOTE: the tag is fully determined based on the input, we fully allow the remote +# tag to point to a different digest. This prevents CI from breaking due to upstream +# changes. However, it also means that we can incorrectly combine digests with tags, +# hence caution is advised. +$(images_tars): $(images_tar_dir)/%.tar: | $(NEEDS_IMAGE-TOOL) $(NEEDS_CRANE) $(NEEDS_GOJQ) + @$(eval full_image=$(subst +,:,$*)) + @$(eval bare_image=$(word 1,$(subst :, ,$(full_image)))) + @$(eval digest=$(word 2,$(subst @, ,$(full_image)))) + @$(eval tag=$(word 2,$(subst :, ,$(word 1,$(subst @, ,$(full_image)))))) @mkdir -p $(dir $@) - diff <(echo "$(digest) -" | cut -d: -f2) <($(CRANE) manifest --platform=linux/$(HOST_ARCH) $(image_without_digest) | sha256sum) - $(CRANE) pull $(image_without_digest) $@ --platform=linux/$(HOST_ARCH) + $(CRANE) pull "$(bare_image)@$(digest)" $@ --platform=linux/$(HOST_ARCH) + $(IMAGE-TOOL) tag-docker-tar $@ "$(bare_image):$(tag)" images_tar_envs := $(images_files:%=env-%) diff --git a/make/_shared/klone/01_mod.mk b/make/_shared/klone/01_mod.mk new file mode 100644 index 00000000..a3d07dd2 --- /dev/null +++ b/make/_shared/klone/01_mod.mk @@ -0,0 +1,27 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.PHONY: generate-klone +## Generate klone shared Makefiles +## @category [shared] Generate/ Verify +generate-klone: | $(NEEDS_KLONE) + $(KLONE) sync + +shared_generate_targets += generate-klone + +.PHONY: upgrade-klone +## Upgrade klone Makefile modules to latest version +## @category [shared] Self-upgrade +upgrade-klone: | $(NEEDS_KLONE) + $(KLONE) upgrade diff --git a/make/_shared/oci-build/00_mod.mk b/make/_shared/oci-build/00_mod.mk index b7e2b0b4..c94c1f6a 100644 --- a/make/_shared/oci-build/00_mod.mk +++ b/make/_shared/oci-build/00_mod.mk @@ -16,14 +16,15 @@ oci_platforms ?= linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le # Use distroless as minimal base image to package the manager binary # To get latest SHA run "crane digest quay.io/jetstack/base-static:latest" -base_image_static := quay.io/jetstack/base-static@sha256:262e3020adb3b09ddbf9cd8fe672330451a556c8e7024142fa205c8876c3fd75 +base_image_static := quay.io/jetstack/base-static@sha256:16a5a64b918592f5c38fa73721a87f8585a3a501d261087e7b953f8b59279cd0 # Use custom apko-built image as minimal base image to package the manager binary # To get latest SHA run "crane digest quay.io/jetstack/base-static-csi:latest" -base_image_csi-static := quay.io/jetstack/base-static-csi@sha256:f776795838d73f9836b134f688b4c827fcd7ed22f46d3cefcb9f57d668388fef +base_image_csi-static := quay.io/jetstack/base-static-csi@sha256:fb97fc098aabdfb5b9b01475d3531b688a9c2219f4bbc143816d3e47a267be6d # Utility functions fatal_if_undefined = $(if $(findstring undefined,$(origin $1)),$(error $1 is not set)) +fatal_if_deprecated_defined = $(if $(findstring undefined,$(origin $1)),,$(error $1 is deprecated, use $2 instead)) # Validate globals that are required $(call fatal_if_undefined,bin_dir) @@ -37,9 +38,12 @@ GOEXPERIMENT ?= # empty by default # # $1 - build_name define default_per_build_variables -cgo_enabled_$1 ?= $(CGO_ENABLED) -goexperiment_$1 ?= $(GOEXPERIMENT) -oci_additional_layers_$1 ?= +go_$1_cgo_enabled ?= $(CGO_ENABLED) +go_$1_goexperiment ?= $(GOEXPERIMENT) +go_$1_flags ?= -tags= +oci_$1_additional_layers ?= +oci_$1_linux_capabilities ?= +oci_$1_build_args ?= endef $(foreach build_name,$(build_names),$(eval $(call default_per_build_variables,$(build_name)))) @@ -48,6 +52,11 @@ $(foreach build_name,$(build_names),$(eval $(call default_per_build_variables,$( # # $1 - build_name define check_per_build_variables +# Validate deprecated variables +$(call fatal_if_deprecated_defined,cgo_enabled_$1,go_$1_cgo_enabled) +$(call fatal_if_deprecated_defined,goexperiment_$1,go_$1_goexperiment) +$(call fatal_if_deprecated_defined,oci_additional_layers_$1,oci_$1_additional_layers) + # Validate required config exists $(call fatal_if_undefined,go_$1_ldflags) $(call fatal_if_undefined,go_$1_main_dir) diff --git a/make/_shared/oci-build/01_mod.mk b/make/_shared/oci-build/01_mod.mk index ca6fc926..726ad13c 100644 --- a/make/_shared/oci-build/01_mod.mk +++ b/make/_shared/oci-build/01_mod.mk @@ -12,17 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Utility variables -current_makefile = $(lastword $(MAKEFILE_LIST)) -current_makefile_directory = $(dir $(current_makefile)) +$(bin_dir)/scratch/image: + @mkdir -p $@ -# Build the image tool -image_tool_dir := $(current_makefile_directory:/=)/image_tool -IMAGE_TOOL := $(CURDIR)/$(bin_dir)/tools/image_tool -NEEDS_IMAGE_TOOL := $(bin_dir)/tools/image_tool -$(NEEDS_IMAGE_TOOL): $(wildcard $(image_tool_dir)/*.go) | $(NEEDS_GO) - cd $(image_tool_dir) && GOWORK=off GOBIN=$(CURDIR)/$(dir $@) $(GO) install . - define ko_config_target .PHONY: $(ko_config_path_$1:$(CURDIR)/%=%) $(ko_config_path_$1:$(CURDIR)/%=%): | $(NEEDS_YQ) $(bin_dir)/scratch/image @@ -31,11 +23,13 @@ $(ko_config_path_$1:$(CURDIR)/%=%): | $(NEEDS_YQ) $(bin_dir)/scratch/image $(YQ) '.builds[0].id = "$1"' | \ $(YQ) '.builds[0].dir = "$(go_$1_mod_dir)"' | \ $(YQ) '.builds[0].main = "$(go_$1_main_dir)"' | \ - $(YQ) '.builds[0].env[0] = "CGO_ENABLED=$(cgo_enabled_$1)"' | \ - $(YQ) '.builds[0].env[1] = "GOEXPERIMENT=$(goexperiment_$1)"' | \ + $(YQ) '.builds[0].env[0] = "CGO_ENABLED=$(go_$1_cgo_enabled)"' | \ + $(YQ) '.builds[0].env[1] = "GOEXPERIMENT=$(go_$1_goexperiment)"' | \ $(YQ) '.builds[0].ldflags[0] = "-s"' | \ $(YQ) '.builds[0].ldflags[1] = "-w"' | \ - $(YQ) '.builds[0].ldflags[2] = "{{.Env.LDFLAGS}}"' \ + $(YQ) '.builds[0].ldflags[2] = "{{.Env.LDFLAGS}}"' | \ + $(YQ) '.builds[0].flags[0] = "$(go_$1_flags)"' | \ + $(YQ) '.builds[0].linux_capabilities = "$(oci_$1_linux_capabilities)"' \ > $(CURDIR)/$(oci_layout_path_$1).ko_config.yaml ko-config-$1: $(ko_config_path_$1:$(CURDIR)/%=%) @@ -47,7 +41,7 @@ $(foreach build_name,$(build_names),$(eval $(call ko_config_target,$(build_name) .PHONY: $(oci_build_targets) ## Build the OCI image. ## @category [shared] Build -$(oci_build_targets): oci-build-%: ko-config-% | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS_YQ) $(NEEDS_IMAGE_TOOL) $(bin_dir)/scratch/image +$(oci_build_targets): oci-build-%: ko-config-% | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS_YQ) $(NEEDS_IMAGE-TOOL) $(bin_dir)/scratch/image rm -rf $(CURDIR)/$(oci_layout_path_$*) GOWORK=off \ KO_DOCKER_REPO=$(oci_$*_image_name_development) \ @@ -58,17 +52,18 @@ $(oci_build_targets): oci-build-%: ko-config-% | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS LDFLAGS="$(go_$*_ldflags)" \ $(KO) build $(go_$*_mod_dir)/$(go_$*_main_dir) \ --platform=$(oci_platforms) \ + $(oci_$*_build_args) \ --oci-layout-path=$(oci_layout_path_$*) \ --sbom-dir=$(CURDIR)/$(oci_layout_path_$*).sbom \ --sbom=spdx \ --push=false \ --bare - $(IMAGE_TOOL) append-layers \ + $(IMAGE-TOOL) append-layers \ $(CURDIR)/$(oci_layout_path_$*) \ - $(oci_additional_layers_$*) + $(oci_$*_additional_layers) - $(IMAGE_TOOL) list-digests \ + $(IMAGE-TOOL) list-digests \ $(CURDIR)/$(oci_layout_path_$*) \ > $(oci_digest_path_$*) @@ -86,5 +81,5 @@ endif ## @category [shared] Build .PHONY: $(docker_tarball_targets) $(docker_tarball_targets): oci_platforms := "linux/$(HOST_ARCH)" -$(docker_tarball_targets): docker-tarball-%: oci-build-% | $(NEEDS_GO) $(NEEDS_IMAGE_TOOL) - $(IMAGE_TOOL) convert-to-docker-tar $(CURDIR)/$(oci_layout_path_$*) $(docker_tarball_path_$*) $(oci_$*_image_name_development):$(oci_$*_image_tag) \ No newline at end of file +$(docker_tarball_targets): docker-tarball-%: oci-build-% | $(NEEDS_GO) $(NEEDS_IMAGE-TOOL) + $(IMAGE-TOOL) convert-to-docker-tar $(CURDIR)/$(oci_layout_path_$*) $(docker_tarball_path_$*) $(oci_$*_image_name_development):$(oci_$*_image_tag) diff --git a/make/_shared/oci-build/image_tool/append_layers.go b/make/_shared/oci-build/image_tool/append_layers.go deleted file mode 100644 index 6af65e85..00000000 --- a/make/_shared/oci-build/image_tool/append_layers.go +++ /dev/null @@ -1,220 +0,0 @@ -/* -Copyright 2023 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "archive/tar" - "bytes" - "io" - "io/fs" - "log/slog" - "os" - "path/filepath" - - v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/layout" - "github.com/google/go-containerregistry/pkg/v1/match" - "github.com/google/go-containerregistry/pkg/v1/mutate" - "github.com/google/go-containerregistry/pkg/v1/tarball" - "github.com/google/go-containerregistry/pkg/v1/types" - "github.com/spf13/cobra" -) - -var CommandAppendLayers = cobra.Command{ - Use: "append-layers oci-path [path-to-tarball...]", - Short: "Appends a tarball or directory to every image in an OCI index.", - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - oci := args[0] - extra := args[1:] - - if len(extra) == 0 { - return - } - - path, err := layout.FromPath(oci) - must("could not load oci directory", err) - - index, err := path.ImageIndex() - must("could not load oci image index", err) - - layers := []untypedLayer{} - for _, path := range extra { - layers = append(layers, newUntypedLayerFromPath(path)) - } - - index = mutateImage(index, func(img v1.Image) v1.Image { - imgMediaType, err := img.MediaType() - must("could not get image media type", err) - - layerType := types.DockerLayer - if imgMediaType == types.OCIManifestSchema1 { - layerType = types.OCILayer - } - - for _, untypedLayer := range layers { - layer, err := untypedLayer.ToLayer(layerType) - must("could not load image layer", err) - - img, err = mutate.AppendLayers(img, layer) - must("could not append layer", err) - } - - return img - }) - - _, err = layout.Write(oci, index) - must("could not write image", err) - }, -} - -type untypedLayer struct { - tarball tarball.Opener -} - -func newUntypedLayer(tarball tarball.Opener) untypedLayer { - return untypedLayer{tarball: tarball} -} - -func newUntypedLayerFromPath(path string) untypedLayer { - stat, err := os.Stat(path) - must("could not open directory or tarball", err) - - var layer untypedLayer - if stat.IsDir() { - var buf bytes.Buffer - - tw := tar.NewWriter(&buf) - - filepath.Walk(path, func(target string, info fs.FileInfo, err error) error { - must("walk error", err) - - header, err := tar.FileInfoHeader(info, info.Name()) - must("could not create tar header", err) - - name, err := filepath.Rel(path, target) - must("could not build relative path", err) - - // Write simplified header, this removes all fields that would cause - // the build to be non-reproducible (like modtime for example) - err = tw.WriteHeader(&tar.Header{ - Typeflag: header.Typeflag, - Name: name, - Mode: header.Mode, - Linkname: header.Linkname, - Size: header.Size, - }) - - must("could not write tar header", err) - - if !info.IsDir() { - file, err := os.Open(target) - must("could not write tar contents", err) - - defer file.Close() - - _, err = io.Copy(tw, file) - must("could not write tar contents", err) - } - - return nil - }) - - tw.Close() - - byts := buf.Bytes() - - layer = newUntypedLayer( - func() (io.ReadCloser, error) { - return io.NopCloser(bytes.NewReader(byts)), nil - }, - ) - } else { - layer = newUntypedLayer( - func() (io.ReadCloser, error) { - return os.Open(path) - }, - ) - } - - return layer -} - -func (ul untypedLayer) ToLayer(mediaType types.MediaType) (v1.Layer, error) { - return tarball.LayerFromOpener(ul.tarball, tarball.WithMediaType(mediaType)) -} - -type imageMutateFn func(index v1.Image) v1.Image - -func mutateImage(index v1.ImageIndex, fn imageMutateFn) v1.ImageIndex { - manifest, err := index.IndexManifest() - must("could not load oci image manifest", err) - - for _, descriptor := range manifest.Manifests { - switch { - case descriptor.MediaType.IsImage(): - slog.Info("found image", "digest", descriptor.Digest, "platform", descriptor.Platform) - - img, err := index.Image(descriptor.Digest) - must("could not load oci image with digest", err) - - img = fn(img) - - digest, err := img.Digest() - must("could not get image digest", err) - - size, err := img.Size() - must("could not get image size", err) - - slog.Info("appended layers to image", "old_digest", descriptor.Digest, "digest", digest, "platform", descriptor.Platform) - - index = mutate.RemoveManifests(index, match.Digests(descriptor.Digest)) - - descriptor.Digest = digest - descriptor.Size = size - index = mutate.AppendManifests(index, mutate.IndexAddendum{ - Add: img, - Descriptor: descriptor, - }) - - case descriptor.MediaType.IsIndex(): - slog.Info("found image index", "digest", descriptor.Digest) - - child, err := index.ImageIndex(descriptor.Digest) - must("could not load oci index manifest", err) - - child = mutateImage(child, fn) - - digest, err := child.Digest() - must("could not get index digest", err) - - size, err := child.Size() - must("could not get index size", err) - - index = mutate.RemoveManifests(index, match.Digests(descriptor.Digest)) - - descriptor.Digest = digest - descriptor.Size = size - index = mutate.AppendManifests(index, mutate.IndexAddendum{ - Add: child, - Descriptor: descriptor, - }) - } - } - - return index -} diff --git a/make/_shared/oci-build/image_tool/convert_to_docker_tar.go b/make/_shared/oci-build/image_tool/convert_to_docker_tar.go deleted file mode 100644 index c6e1e269..00000000 --- a/make/_shared/oci-build/image_tool/convert_to_docker_tar.go +++ /dev/null @@ -1,97 +0,0 @@ -/* -Copyright 2023 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "runtime" - - "github.com/google/go-containerregistry/pkg/name" - v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/layout" - "github.com/google/go-containerregistry/pkg/v1/match" - "github.com/google/go-containerregistry/pkg/v1/tarball" - "github.com/spf13/cobra" -) - -var CommandConvertToDockerTar = cobra.Command{ - Use: "convert-to-docker-tar oci-path output image-name", - Short: "Reads the OCI directory and outputs a tarball that is compatible with \"docker load\"", - Args: cobra.ExactArgs(3), - Run: func(cmd *cobra.Command, args []string) { - path := args[0] - output := args[1] - imageName := args[2] - - ociLayout, err := layout.FromPath(path) - must("could not load oci directory", err) - - index, err := ociLayout.ImageIndex() - must("could not load oci image index", err) - - images := getImagesFromIndex(index, func(desc v1.Descriptor) bool { - return desc.Platform != nil && desc.Platform.Architecture == runtime.GOARCH - }) - - switch { - case len(images) == 0: - fail("no matching images found") - case len(images) > 1: - fail("multiple matching images found") - } - - ref, err := name.ParseReference(imageName) - must("invalid image name", err) - - err = tarball.WriteToFile(output, ref, images[0]) - must("could not write tarball", err) - }, -} - -func getImagesFromIndex(index v1.ImageIndex, matcher match.Matcher) (images []v1.Image) { - manifest, err := index.IndexManifest() - must("could not load oci index manifest", err) - - for _, descriptor := range manifest.Manifests { - switch { - case descriptor.MediaType.IsImage(): - // If the platform is not part of the index manifest, attempt to - // load it from the image config - if descriptor.Platform == nil { - img, err := index.Image(descriptor.Digest) - must("could not load image", err) - - cfg, err := img.ConfigFile() - must("could not load image config", err) - - descriptor.Platform = cfg.Platform() - } - - if matcher(descriptor) { - img, err := index.Image(descriptor.Digest) - must("could not load image", err) - images = append(images, img) - } - - case descriptor.MediaType.IsIndex(): - idx, err := index.ImageIndex(descriptor.Digest) - must("could not load image index", err) - images = append(images, getImagesFromIndex(idx, matcher)...) - } - } - - return -} diff --git a/make/_shared/oci-build/image_tool/go.mod b/make/_shared/oci-build/image_tool/go.mod deleted file mode 100644 index 51f647bf..00000000 --- a/make/_shared/oci-build/image_tool/go.mod +++ /dev/null @@ -1,19 +0,0 @@ -module image_tool - -go 1.21 - -require ( - github.com/google/go-containerregistry v0.20.2 - github.com/spf13/cobra v1.8.1 -) - -require ( - github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.16.5 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc3 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/vbatts/tar-split v0.11.3 // indirect - golang.org/x/sync v0.2.0 // indirect -) diff --git a/make/_shared/oci-build/image_tool/go.sum b/make/_shared/oci-build/image_tool/go.sum deleted file mode 100644 index 56873bb9..00000000 --- a/make/_shared/oci-build/image_tool/go.sum +++ /dev/null @@ -1,58 +0,0 @@ -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= -github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= -github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= -github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= -github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= -github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= -github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sirupsen/logrus v1.9.1 h1:Ou41VVR3nMWWmTiEUnj0OlsgOSCUFgsPAOl6jRIcVtQ= -github.com/sirupsen/logrus v1.9.1/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= -github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= -github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/make/_shared/oci-build/image_tool/list_digests.go b/make/_shared/oci-build/image_tool/list_digests.go deleted file mode 100644 index e08d9489..00000000 --- a/make/_shared/oci-build/image_tool/list_digests.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2023 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "fmt" - - "github.com/google/go-containerregistry/pkg/v1/layout" - "github.com/spf13/cobra" -) - -var CommandListDigests = cobra.Command{ - Use: "list-digests oci-path", - Short: "Outputs the digests for images found inside the tarball", - Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { - path := args[0] - - ociLayout, err := layout.FromPath(path) - must("could not load oci directory", err) - - imageIndex, err := ociLayout.ImageIndex() - must("could not load oci image index", err) - - indexManifest, err := imageIndex.IndexManifest() - must("could not load oci index manifest", err) - - for _, man := range indexManifest.Manifests { - fmt.Println(man.Digest) - } - }, -} diff --git a/make/_shared/oci-publish/00_mod.mk b/make/_shared/oci-publish/00_mod.mk index f27062ad..099bff46 100644 --- a/make/_shared/oci-publish/00_mod.mk +++ b/make/_shared/oci-publish/00_mod.mk @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Push names is equivilent to build_names, additional names can be added for +# Push names is equivalent to build_names, additional names can be added for # pushing images that are not build with the oci-build module push_names ?= push_names += $(build_names) diff --git a/make/_shared/repository-base/01_mod.mk b/make/_shared/repository-base/01_mod.mk new file mode 100644 index 00000000..aa6b7ee2 --- /dev/null +++ b/make/_shared/repository-base/01_mod.mk @@ -0,0 +1,33 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ +base_dependabot_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base-dependabot/ + +ifdef repository_base_no_dependabot +.PHONY: generate-base +## Generate base files in the repository +## @category [shared] Generate/ Verify +generate-base: + cp -r $(base_dir)/. ./ +else +.PHONY: generate-base +## Generate base files in the repository +## @category [shared] Generate/ Verify +generate-base: + cp -r $(base_dir)/. ./ + cp -r $(base_dependabot_dir)/. ./ +endif + +shared_generate_targets += generate-base diff --git a/make/_shared/repository-base/base-dependabot/.github/dependabot.yaml b/make/_shared/repository-base/base-dependabot/.github/dependabot.yaml new file mode 100644 index 00000000..d950a83e --- /dev/null +++ b/make/_shared/repository-base/base-dependabot/.github/dependabot.yaml @@ -0,0 +1,20 @@ +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base-dependabot/.github/dependabot.yaml instead. + +# Update Go dependencies and GitHub Actions dependencies daily. +version: 2 +updates: +- package-ecosystem: gomod + directory: / + schedule: + interval: daily + groups: + all: + patterns: ["*"] +- package-ecosystem: github-actions + directory: / + schedule: + interval: daily + groups: + all: + patterns: ["*"] diff --git a/make/_shared/repository-base/base/.github/workflows/make-self-upgrade.yaml b/make/_shared/repository-base/base/.github/workflows/make-self-upgrade.yaml new file mode 100644 index 00000000..1097272e --- /dev/null +++ b/make/_shared/repository-base/base/.github/workflows/make-self-upgrade.yaml @@ -0,0 +1,105 @@ +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/.github/workflows/make-self-upgrade.yaml instead. + +name: make-self-upgrade +concurrency: make-self-upgrade +on: + workflow_dispatch: {} + schedule: + - cron: '0 0 * * *' + +permissions: + contents: read + +jobs: + self_upgrade: + runs-on: ubuntu-latest + + if: github.repository_owner == 'cert-manager' + + permissions: + contents: write + pull-requests: write + + env: + SOURCE_BRANCH: "${{ github.ref_name }}" + SELF_UPGRADE_BRANCH: "self-upgrade-${{ github.ref_name }}" + + steps: + - name: Fail if branch is not head of branch. + if: ${{ !startsWith(github.ref, 'refs/heads/') && env.SOURCE_BRANCH != '' && env.SELF_UPGRADE_BRANCH != '' }} + run: | + echo "This workflow should not be run on a non-branch-head." + exit 1 + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + # Adding `fetch-depth: 0` makes sure tags are also fetched. We need + # the tags so `git describe` returns a valid version. + # see https://github.com/actions/checkout/issues/701 for extra info about this option + with: { fetch-depth: 0 } + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - run: | + git checkout -B "$SELF_UPGRADE_BRANCH" + + - run: | + make -j upgrade-klone + make -j generate + + - id: is-up-to-date + shell: bash + run: | + git_status=$(git status -s) + is_up_to_date="true" + if [ -n "$git_status" ]; then + is_up_to_date="false" + echo "The following changes will be committed:" + echo "$git_status" + fi + echo "result=$is_up_to_date" >> "$GITHUB_OUTPUT" + + - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} + run: | + git config --global user.name "cert-manager-bot" + git config --global user.email "cert-manager-bot@users.noreply.github.com" + git add -A && git commit -m "BOT: run 'make upgrade-klone' and 'make generate'" --signoff + git push -f origin "$SELF_UPGRADE_BRANCH" + + - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const { repo, owner } = context.repo; + const pulls = await github.rest.pulls.list({ + owner: owner, + repo: repo, + head: owner + ':' + process.env.SELF_UPGRADE_BRANCH, + base: process.env.SOURCE_BRANCH, + state: 'open', + }); + + if (pulls.data.length < 1) { + const result = await github.rest.pulls.create({ + title: '[CI] Merge ' + process.env.SELF_UPGRADE_BRANCH + ' into ' + process.env.SOURCE_BRANCH, + owner: owner, + repo: repo, + head: process.env.SELF_UPGRADE_BRANCH, + base: process.env.SOURCE_BRANCH, + body: [ + 'This PR is auto-generated to bump the Makefile modules.', + ].join('\n'), + }); + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: result.data.number, + labels: ['skip-review'] + }); + } diff --git a/make/_shared/repository-base/base/LICENSE b/make/_shared/repository-base/base/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/make/_shared/repository-base/base/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/make/_shared/repository-base/base/Makefile b/make/_shared/repository-base/base/Makefile new file mode 100644 index 00000000..6a1652d4 --- /dev/null +++ b/make/_shared/repository-base/base/Makefile @@ -0,0 +1,116 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/Makefile instead. + +# NOTE FOR DEVELOPERS: "How do the Makefiles work and how can I extend them?" +# +# Shared Makefile logic lives in the make/_shared/ directory. The source of truth for these files +# lies outside of this repository, eg. in the cert-manager/makefile-modules repository. +# +# Logic specific to this repository must be defined in the make/00_mod.mk and make/02_mod.mk files: +# - The make/00_mod.mk file is included first and contains variable definitions needed by +# the shared Makefile logic. +# - The make/02_mod.mk file is included later, it can make use of most of the shared targets +# defined in the make/_shared/ directory (all targets defined in 00_mod.mk and 01_mod.mk). +# This file should be used to define targets specific to this repository. + +################################## + +# Some modules build their dependencies from variables, we want these to be +# evaluated at the last possible moment. For this we use second expansion to +# re-evaluate the generate and verify targets a second time. +# +# See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html +.SECONDEXPANSION: + +# For details on some of these "prelude" settings, see: +# https://clarkgrubb.com/makefile-style-guide +MAKEFLAGS += --warn-undefined-variables --no-builtin-rules +SHELL := /usr/bin/env bash +.SHELLFLAGS := -uo pipefail -c +.DEFAULT_GOAL := help +.DELETE_ON_ERROR: +.SUFFIXES: +FORCE: + +noop: # do nothing + +# Set empty value for MAKECMDGOALS to prevent the "warning: undefined variable 'MAKECMDGOALS'" +# warning from happening when running make without arguments +MAKECMDGOALS ?= + +################################## +# Host OS and architecture setup # +################################## + +# The reason we don't use "go env GOOS" or "go env GOARCH" is that the "go" +# binary may not be available in the PATH yet when the Makefiles are +# evaluated. HOST_OS and HOST_ARCH only support Linux, *BSD and macOS (M1 +# and Intel). +host_os := $(shell uname -s | tr A-Z a-z) +host_arch := $(shell uname -m) +HOST_OS ?= $(host_os) +HOST_ARCH ?= $(host_arch) + +ifeq (x86_64, $(HOST_ARCH)) + HOST_ARCH = amd64 +else ifeq (aarch64, $(HOST_ARCH)) + # linux reports the arm64 arch as aarch64 + HOST_ARCH = arm64 +endif + +################################## +# Git and versioning information # +################################## + +git_version := $(shell git describe --tags --always --match='v*' --abbrev=14 --dirty) +VERSION ?= $(git_version) +IS_PRERELEASE := $(shell git describe --tags --always --match='v*' --abbrev=0 | grep -q '-' && echo true || echo false) +GITCOMMIT := $(shell git rev-parse HEAD) +GITEPOCH := $(shell git show -s --format=%ct HEAD) + +################################## +# Global variables and dirs # +################################## + +bin_dir := _bin + +# The ARTIFACTS environment variable is set by the CI system to a directory +# where artifacts should be placed. These artifacts are then uploaded to a +# storage bucket by the CI system (https://docs.prow.k8s.io/docs/components/pod-utilities/). +# An example of such an artifact is a jUnit XML file containing test results. +# If the ARTIFACTS environment variable is not set, we default to a local +# directory in the _bin directory. +ARTIFACTS ?= $(bin_dir)/artifacts + +$(bin_dir) $(ARTIFACTS) $(bin_dir)/scratch: + mkdir -p $@ + +.PHONY: clean +## Clean all temporary files +## @category [shared] Tools +clean: + rm -rf $(bin_dir) + +################################## +# Include all the Makefiles # +################################## + +-include make/00_mod.mk +-include make/_shared/*/00_mod.mk +-include make/_shared/*/01_mod.mk +-include make/02_mod.mk +-include make/_shared/*/02_mod.mk diff --git a/make/_shared/repository-base/base/OWNERS_ALIASES b/make/_shared/repository-base/base/OWNERS_ALIASES new file mode 100644 index 00000000..672704c9 --- /dev/null +++ b/make/_shared/repository-base/base/OWNERS_ALIASES @@ -0,0 +1,14 @@ +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/OWNERS_ALIASES instead. + +aliases: + cm-maintainers: + - munnerz + - joshvanl + - wallrj + - jakexks + - maelvls + - sgtcodfish + - inteon + - thatsmrtalbot + - erikgb diff --git a/make/_shared/tools/00_mod.mk b/make/_shared/tools/00_mod.mk index 6491a62c..56a6ee7a 100644 --- a/make/_shared/tools/00_mod.mk +++ b/make/_shared/tools/00_mod.mk @@ -21,7 +21,7 @@ endif export DOWNLOAD_DIR ?= $(CURDIR)/$(bin_dir)/downloaded export GOVENDOR_DIR ?= $(CURDIR)/$(bin_dir)/go_vendor -$(bin_dir)/scratch/image $(bin_dir)/tools $(DOWNLOAD_DIR)/tools: +$(bin_dir)/tools $(DOWNLOAD_DIR)/tools: @mkdir -p $@ checkhash_script := $(dir $(lastword $(MAKEFILE_LIST)))/util/checkhash.sh @@ -36,7 +36,7 @@ for_each_kv = $(foreach item,$2,$(eval $(call $1,$(word 1,$(subst =, ,$(item))), # $(bin_dir)/tools, and the actual binaries are in $(bin_dir)/downloaded. When bumping # the version of the tools, this symlink gets updated. -# Let's have $(bin_dir)/tools in front of the PATH so that we don't inavertedly +# Let's have $(bin_dir)/tools in front of the PATH so that we don't inadvertently # pick up the wrong binary somewhere. Watch out, $(shell echo $$PATH) will # still print the original PATH, since GNU make does not honor exported # variables: https://stackoverflow.com/questions/54726457 @@ -52,57 +52,57 @@ NEEDS_CTR = __require-ctr tools := # https://github.com/helm/helm/releases -tools += helm=v3.14.4 +tools += helm=v3.17.2 # https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl -tools += kubectl=v1.30.0 +tools += kubectl=v1.32.3 # https://github.com/kubernetes-sigs/kind/releases -tools += kind=v0.23.0 +tools += kind=v0.27.0 # https://www.vaultproject.io/downloads -tools += vault=1.16.2 +tools += vault=1.19.1 # https://github.com/Azure/azure-workload-identity/releases -tools += azwi=v1.2.2 +tools += azwi=v1.4.1 # https://github.com/kyverno/kyverno/releases -tools += kyverno=v1.12.1 +tools += kyverno=v1.13.4 # https://github.com/mikefarah/yq/releases -tools += yq=v4.43.1 +tools += yq=v4.45.1 # https://github.com/ko-build/ko/releases -tools += ko=0.15.2 +tools += ko=0.17.1 # https://github.com/protocolbuffers/protobuf/releases -tools += protoc=26.1 +tools += protoc=30.2 # https://github.com/aquasecurity/trivy/releases -tools += trivy=v0.50.4 +tools += trivy=v0.61.0 # https://github.com/vmware-tanzu/carvel-ytt/releases -tools += ytt=v0.49.0 +tools += ytt=v0.51.2 # https://github.com/rclone/rclone/releases -tools += rclone=v1.66.0 +tools += rclone=v1.69.1 +# https://github.com/istio/istio/releases +tools += istioctl=1.25.1 ### go packages # https://pkg.go.dev/sigs.k8s.io/controller-tools/cmd/controller-gen?tab=versions -tools += controller-gen=v0.15.0 +tools += controller-gen=v0.17.3 # https://pkg.go.dev/golang.org/x/tools/cmd/goimports?tab=versions -tools += goimports=v0.20.0 -# https://pkg.go.dev/github.com/google/go-licenses/licenses?tab=versions -tools += go-licenses=706b9c60edd424a8b6d253fe10dfb7b8e942d4a5 +tools += goimports=v0.31.0 +# https://pkg.go.dev/github.com/google/go-licenses/v2?tab=versions +tools += go-licenses=v2.0.0-alpha.1 # https://pkg.go.dev/gotest.tools/gotestsum?tab=versions -tools += gotestsum=v1.11.0 +tools += gotestsum=v1.12.1 # https://pkg.go.dev/sigs.k8s.io/kustomize/kustomize/v4?tab=versions tools += kustomize=v4.5.7 # https://pkg.go.dev/github.com/itchyny/gojq?tab=versions -tools += gojq=v0.12.15 +tools += gojq=v0.12.17 # https://pkg.go.dev/github.com/google/go-containerregistry/pkg/crane?tab=versions -tools += crane=v0.19.1 +tools += crane=v0.20.3 # https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go?tab=versions -tools += protoc-gen-go=v1.34.0 -# https://pkg.go.dev/github.com/norwoodj/helm-docs/cmd/helm-docs?tab=versions -tools += helm-docs=v1.13.1 +tools += protoc-gen-go=v1.36.6 # https://pkg.go.dev/github.com/sigstore/cosign/v2/cmd/cosign?tab=versions -tools += cosign=v2.2.4 +tools += cosign=v2.4.3 # https://pkg.go.dev/github.com/cert-manager/boilersuite?tab=versions tools += boilersuite=v0.1.0 # https://pkg.go.dev/github.com/princjef/gomarkdoc/cmd/gomarkdoc?tab=versions tools += gomarkdoc=v1.1.0 # https://pkg.go.dev/oras.land/oras/cmd/oras?tab=versions -tools += oras=v1.1.0 +tools += oras=v1.2.2 # https://pkg.go.dev/github.com/onsi/ginkgo/v2/ginkgo?tab=versions # The gingko version should be kept in sync with the version used in code. # If there is no go.mod file (which is only the case for the makefile-modules @@ -111,34 +111,36 @@ tools += oras=v1.1.0 detected_ginkgo_version := $(shell [[ -f go.mod ]] && awk '/ginkgo\/v2/ {print $$2}' go.mod || echo "v2.13.2") tools += ginkgo=$(detected_ginkgo_version) # https://pkg.go.dev/github.com/cert-manager/klone?tab=versions -tools += klone=v0.0.5 +tools += klone=v0.2.0 # https://pkg.go.dev/github.com/goreleaser/goreleaser?tab=versions -tools += goreleaser=v1.25.1 +tools += goreleaser=v1.26.2 # https://pkg.go.dev/github.com/anchore/syft/cmd/syft?tab=versions -tools += syft=v0.100.0 -# https://github.com/cert-manager/helm-tool -tools += helm-tool=v0.5.1 -# https://github.com/cert-manager/cmctl -tools += cmctl=v2.0.0 +tools += syft=v1.22.0 +# https://github.com/cert-manager/helm-tool/releases +tools += helm-tool=v0.5.3 +# https://github.com/cert-manager/image-tool/releases +tools += image-tool=v0.0.2 +# https://github.com/cert-manager/cmctl/releases +tools += cmctl=v2.1.1 # https://pkg.go.dev/github.com/cert-manager/release/cmd/cmrel?tab=versions -tools += cmrel=e4c3a4dc07df5c7c0379d334c5bb00e172462551 -# https://github.com/golangci/golangci-lint/releases -tools += golangci-lint=v1.57.2 +tools += cmrel=e3cbe5171488deda000145003e22567bdce622ea +# https://pkg.go.dev/github.com/golangci/golangci-lint/v2/cmd/golangci-lint?tab=versions +tools += golangci-lint=v2.1.2 # https://pkg.go.dev/golang.org/x/vuln?tab=versions -tools += govulncheck=v1.1.0 +tools += govulncheck=v1.1.4 # https://pkg.go.dev/github.com/operator-framework/operator-sdk/cmd/operator-sdk?tab=versions -tools += operator-sdk=v1.34.1 +tools += operator-sdk=v1.39.2 # https://pkg.go.dev/github.com/cli/cli/v2?tab=versions -tools += gh=v2.49.0 -# https:///github.com/redhat-openshift-ecosystem/openshift-preflight/releases -tools += preflight=1.9.2 +tools += gh=v2.69.0 +# https://github.com/redhat-openshift-ecosystem/openshift-preflight/releases +tools += preflight=1.12.1 # https://github.com/daixiang0/gci/releases -tools += gci=v0.13.4 +tools += gci=v0.13.6 # https://github.com/google/yamlfmt/releases -tools += yamlfmt=v0.12.1 +tools += yamlfmt=v0.16.0 # https://pkg.go.dev/k8s.io/code-generator/cmd?tab=versions -K8S_CODEGEN_VERSION := v0.30.1 +K8S_CODEGEN_VERSION := v0.32.3 tools += client-gen=$(K8S_CODEGEN_VERSION) tools += deepcopy-gen=$(K8S_CODEGEN_VERSION) tools += informer-gen=$(K8S_CODEGEN_VERSION) @@ -147,10 +149,10 @@ tools += applyconfiguration-gen=$(K8S_CODEGEN_VERSION) tools += defaulter-gen=$(K8S_CODEGEN_VERSION) tools += conversion-gen=$(K8S_CODEGEN_VERSION) # https://github.com/kubernetes/kube-openapi -tools += openapi-gen=f0e62f92d13f418e2732b21c952fd17cab771c75 +tools += openapi-gen=c8a335a9a2ffc5aff16dfef74896a1ee34eb235d # https://raw.githubusercontent.com/kubernetes-sigs/controller-tools/master/envtest-releases.yaml -KUBEBUILDER_ASSETS_VERSION := v1.30.0 +KUBEBUILDER_ASSETS_VERSION := v1.32.0 tools += etcd=$(KUBEBUILDER_ASSETS_VERSION) tools += kube-apiserver=$(KUBEBUILDER_ASSETS_VERSION) @@ -159,7 +161,7 @@ ADDITIONAL_TOOLS ?= tools += $(ADDITIONAL_TOOLS) # https://go.dev/dl/ -VENDORED_GO_VERSION := 1.22.6 +VENDORED_GO_VERSION := 1.24.2 # Print the go version which can be used in GH actions .PHONY: print-go-version @@ -181,9 +183,13 @@ CURL := curl --silent --show-error --fail --location --retry 10 --retry-connrefu # LN is expected to be an atomic action, meaning that two Make processes # can run the "link $(DOWNLOAD_DIR)/tools/xxx@$(XXX_VERSION)_$(HOST_OS)_$(HOST_ARCH) -# to $(bin_dir)/tools/xxx" operation simulatiously without issues (both +# to $(bin_dir)/tools/xxx" operation simultaneously without issues (both # will perform the action and the second time the link will be overwritten). -LN := ln -fs +# +# -s = Create a symbolic link +# -f = Force the creation of the link (replace existing links) +# -n = If destination already exists, replace it, don't use it as a directory to create a new link inside +LN := ln -fsn upper_map := a:A b:B c:C d:D e:E f:F g:G h:H i:I j:J k:K l:L m:M n:N o:O p:P q:Q r:R s:S t:T u:U v:V w:W x:X y:Y z:Z uc = $(strip \ @@ -226,8 +232,6 @@ endef $(foreach tool,$(tools),$(eval $(call tool_defs,$(word 1,$(subst =, ,$(tool))),$(word 2,$(subst =, ,$(tool)))))) -tools_paths := $(tool_names:%=$(bin_dir)/tools/%) - ###### # Go # ###### @@ -310,13 +314,12 @@ go_dependencies := go_dependencies += ginkgo=github.com/onsi/ginkgo/v2/ginkgo go_dependencies += controller-gen=sigs.k8s.io/controller-tools/cmd/controller-gen go_dependencies += goimports=golang.org/x/tools/cmd/goimports -go_dependencies += go-licenses=github.com/google/go-licenses +go_dependencies += go-licenses=github.com/google/go-licenses/v2 go_dependencies += gotestsum=gotest.tools/gotestsum go_dependencies += kustomize=sigs.k8s.io/kustomize/kustomize/v4 go_dependencies += gojq=github.com/itchyny/gojq/cmd/gojq go_dependencies += crane=github.com/google/go-containerregistry/cmd/crane go_dependencies += protoc-gen-go=google.golang.org/protobuf/cmd/protoc-gen-go -go_dependencies += helm-docs=github.com/norwoodj/helm-docs/cmd/helm-docs go_dependencies += cosign=github.com/sigstore/cosign/v2/cmd/cosign go_dependencies += boilersuite=github.com/cert-manager/boilersuite go_dependencies += gomarkdoc=github.com/princjef/gomarkdoc/cmd/gomarkdoc @@ -333,9 +336,10 @@ go_dependencies += defaulter-gen=k8s.io/code-generator/cmd/defaulter-gen go_dependencies += conversion-gen=k8s.io/code-generator/cmd/conversion-gen go_dependencies += openapi-gen=k8s.io/kube-openapi/cmd/openapi-gen go_dependencies += helm-tool=github.com/cert-manager/helm-tool +go_dependencies += image-tool=github.com/cert-manager/image-tool go_dependencies += cmctl=github.com/cert-manager/cmctl/v2 go_dependencies += cmrel=github.com/cert-manager/release/cmd/cmrel -go_dependencies += golangci-lint=github.com/golangci/golangci-lint/cmd/golangci-lint +go_dependencies += golangci-lint=github.com/golangci/golangci-lint/v2/cmd/golangci-lint go_dependencies += govulncheck=golang.org/x/vuln/cmd/govulncheck go_dependencies += operator-sdk=github.com/operator-framework/operator-sdk/cmd/operator-sdk go_dependencies += gh=github.com/cli/cli/v2/cmd/gh @@ -360,7 +364,10 @@ $(call for_each_kv,go_tags_init,$(go_dependencies)) go_tags_defs = go_tags_$1 += $2 $(call for_each_kv,go_tags_defs,$(go_tags)) +go_tool_names := + define go_dependency +go_tool_names += $1 $$(DOWNLOAD_DIR)/tools/$1@$($(call uc,$1)_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $$(NEEDS_GO) $$(DOWNLOAD_DIR)/tools @source $$(lock_script) $$@; \ mkdir -p $$(outfile).dir; \ @@ -374,10 +381,10 @@ $(call for_each_kv,go_dependency,$(go_dependencies)) # File downloads # ################## -go_linux_amd64_SHA256SUM=999805bed7d9039ec3da1a53bfbcafc13e367da52aa823cb60b68ba22d44c616 -go_linux_arm64_SHA256SUM=c15fa895341b8eaf7f219fada25c36a610eb042985dc1a912410c1c90098eaf2 -go_darwin_amd64_SHA256SUM=9c3c0124b01b5365f73a1489649f78f971ecf84844ad9ca58fde133096ddb61b -go_darwin_arm64_SHA256SUM=ebac39fd44fc22feed1bb519af431c84c55776e39b30f4fd62930da9c0cfd1e3 +go_linux_amd64_SHA256SUM=68097bd680839cbc9d464a0edce4f7c333975e27a90246890e9f1078c7e702ad +go_linux_arm64_SHA256SUM=756274ea4b68fa5535eb9fe2559889287d725a8da63c6aae4d5f23778c229f4b +go_darwin_amd64_SHA256SUM=238d9c065d09ff6af229d2e3b8b5e85e688318d69f4006fb85a96e41c216ea83 +go_darwin_arm64_SHA256SUM=b70f8b3c5b4ccb0ad4ffa5ee91cd38075df20fdbd953a1daedd47f50fbcff47a .PRECIOUS: $(DOWNLOAD_DIR)/tools/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz $(DOWNLOAD_DIR)/tools/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz: | $(DOWNLOAD_DIR)/tools @@ -385,10 +392,10 @@ $(DOWNLOAD_DIR)/tools/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz: $(CURL) https://go.dev/dl/go$(VENDORED_GO_VERSION).$(HOST_OS)-$(HOST_ARCH).tar.gz -o $(outfile); \ $(checkhash_script) $(outfile) $(go_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM) -helm_linux_amd64_SHA256SUM=a5844ef2c38ef6ddf3b5a8f7d91e7e0e8ebc39a38bb3fc8013d629c1ef29c259 -helm_linux_arm64_SHA256SUM=113ccc53b7c57c2aba0cd0aa560b5500841b18b5210d78641acfddc53dac8ab2 -helm_darwin_amd64_SHA256SUM=73434aeac36ad068ce2e5582b8851a286dc628eae16494a26e2ad0b24a7199f9 -helm_darwin_arm64_SHA256SUM=61e9c5455f06b2ad0a1280975bf65892e707adc19d766b0cf4e9006e3b7b4b6c +helm_linux_amd64_SHA256SUM=90c28792a1eb5fb0b50028e39ebf826531ebfcf73f599050dbd79bab2f277241 +helm_linux_arm64_SHA256SUM=d78d76ec7625a94991e887ac049d93f44bd70e4876200b945f813c9e1ed1df7c +helm_darwin_amd64_SHA256SUM=3e240238c7a3a10efd37b8e16615b28e94ba5db5957247bb42009ba6d52f76e9 +helm_darwin_arm64_SHA256SUM=b843cebcbebc9eccb1e43aba9cca7693d32e9f2c4a35344990e3b7b381933948 .PRECIOUS: $(DOWNLOAD_DIR)/tools/helm@$(HELM_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/helm@$(HELM_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -399,10 +406,10 @@ $(DOWNLOAD_DIR)/tools/helm@$(HELM_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD chmod +x $(outfile); \ rm -f $(outfile).tar.gz -kubectl_linux_amd64_SHA256SUM=7c3807c0f5c1b30110a2ff1e55da1d112a6d0096201f1beb81b269f582b5d1c5 -kubectl_linux_arm64_SHA256SUM=669af0cf520757298ea60a8b6eb6b719ba443a9c7d35f36d3fb2fd7513e8c7d2 -kubectl_darwin_amd64_SHA256SUM=bcfa57d020b8d07d0ea77235ce8012c2c28fefdfd7cb9738f33674a7b16cef08 -kubectl_darwin_arm64_SHA256SUM=45cfa208151320153742062824398f22bb6bfb5a142bf6238476d55dacbd1bdd +kubectl_linux_amd64_SHA256SUM=ab209d0c5134b61486a0486585604a616a5bb2fc07df46d304b3c95817b2d79f +kubectl_linux_arm64_SHA256SUM=6c2c91e760efbf3fa111a5f0b99ba8975fb1c58bb3974eca88b6134bcf3717e2 +kubectl_darwin_amd64_SHA256SUM=b814c523071cd09e27c88d8c87c0e9b054ca0cf5c2b93baf3127750a4f194d5b +kubectl_darwin_arm64_SHA256SUM=a110af64fc31e2360dd0f18e4110430e6eedda1a64f96e9d89059740a7685bbd .PRECIOUS: $(DOWNLOAD_DIR)/tools/kubectl@$(KUBECTL_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/kubectl@$(KUBECTL_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -411,10 +418,10 @@ $(DOWNLOAD_DIR)/tools/kubectl@$(KUBECTL_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DO $(checkhash_script) $(outfile) $(kubectl_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ chmod +x $(outfile) -kind_linux_amd64_SHA256SUM=1d86e3069ffbe3da9f1a918618aecbc778e00c75f838882d0dfa2d363bc4a68c -kind_linux_arm64_SHA256SUM=a416d6c311882337f0e56910e4a2e1f8c106ec70c22cbf0ac1dd8f33c1e284fe -kind_darwin_amd64_SHA256SUM=81c77f104b4b668812f7930659dc01ad88fa4d1cfc56900863eacdfb2731c457 -kind_darwin_arm64_SHA256SUM=68ec87c1e1ea2a708df883f4b94091150d19552d7b344e80ca59f449b301c2a0 +kind_linux_amd64_SHA256SUM=a6875aaea358acf0ac07786b1a6755d08fd640f4c79b7a2e46681cc13f49a04b +kind_linux_arm64_SHA256SUM=5e4507a41c69679562610b1be82ba4f80693a7826f4e9c6e39236169a3e4f9d0 +kind_darwin_amd64_SHA256SUM=3435134325b6b9406ccfec417b13bb46a808fc74e9a2ebb0ca31b379c8293863 +kind_darwin_arm64_SHA256SUM=5240ca1acb587e1d0386532dd8c3373d81f5173b5af322919fc56f0cdd646596 .PRECIOUS: $(DOWNLOAD_DIR)/tools/kind@$(KIND_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/kind@$(KIND_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -423,10 +430,10 @@ $(DOWNLOAD_DIR)/tools/kind@$(KIND_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD $(checkhash_script) $(outfile) $(kind_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ chmod +x $(outfile) -vault_linux_amd64_SHA256SUM=688ce462b70cb674f84fddb731f75bb710db5ad9e4e5a17659e90e1283a8b4b7 -vault_linux_arm64_SHA256SUM=d5bd42227d295b1dcc4a5889c37e6a8ca945ece4795819718eaf54db87aa6d4f -vault_darwin_amd64_SHA256SUM=e4886d22273dedc579dc2382e114e7be29341049a48592f8f7be8a0020310731 -vault_darwin_arm64_SHA256SUM=ca59c85e7e3d67e25b6bfa505f7e7717b418452e8bfcd602a2a717bc06d5b1ee +vault_linux_amd64_SHA256SUM=a673933f5b02236b5e241e153c0d2fed15b47b48ad640ae886f8b3b567087a05 +vault_linux_arm64_SHA256SUM=27561edfbc3a59936c9a892d6a130ada5a224c91862523c1aa596bfd30cd45e3 +vault_darwin_amd64_SHA256SUM=3cb0eddebbe82622a20f5256890d71fcc1a4b0ff56561f9d68b29bb0e8b99ab6 +vault_darwin_arm64_SHA256SUM=392df64ce576fcc61508755b842160058e79fe438b30ac4b7fb64dd71f2ca781 .PRECIOUS: $(DOWNLOAD_DIR)/tools/vault@$(VAULT_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/vault@$(VAULT_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -437,10 +444,10 @@ $(DOWNLOAD_DIR)/tools/vault@$(VAULT_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLO chmod +x $(outfile); \ rm -f $(outfile).zip -azwi_linux_amd64_SHA256SUM=d33aaedbcbcc0ef61d845b3704ab336deaafc192c854e887896e163b99097871 -azwi_linux_arm64_SHA256SUM=7c4b55ef83e62f4b597885e66fbbdf0720cf0e2be3f1a16212f9b41d4b61b454 -azwi_darwin_amd64_SHA256SUM=47a9e99a7e02e531967d1c9a8abf12e73134f88ce3363007f411ba9b83497fd0 -azwi_darwin_arm64_SHA256SUM=19c5cf9fe4e1a7394bc01456d5e314fd898162d2d360c585fc72e46dae930659 +azwi_linux_amd64_SHA256SUM=1824d5c0ff700e6aff38f99812670f0dbf828407da0e977cd6c2342e40a32ee6 +azwi_linux_arm64_SHA256SUM=80a5028c27168cea36c34baf893ba6431cc5bcfc5023c1bc8790bf6d8f984f3d +azwi_darwin_amd64_SHA256SUM=18b459c1d82cc92142485720ab797e98706cfaa7280c0308a5cd2d8220f9798b +azwi_darwin_arm64_SHA256SUM=09e8eb961e020ed0e9bfb93ddc30f06d2e3f99203e01f863be131528722d687c .PRECIOUS: $(DOWNLOAD_DIR)/tools/azwi@$(AZWI_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/azwi@$(AZWI_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -450,10 +457,10 @@ $(DOWNLOAD_DIR)/tools/azwi@$(AZWI_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD tar xfO $(outfile).tar.gz azwi > $(outfile) && chmod 775 $(outfile); \ rm -f $(outfile).tar.gz -kubebuilder_tools_linux_amd64_SHA256SUM=2a9792cb5f1403f524543ce94c3115e3c4a4229f0e86af55fd26c078da448164 -kubebuilder_tools_linux_arm64_SHA256SUM=39cc7274a3075a650a20fcd24b9e2067375732bebaf5356088a8efb35155f068 -kubebuilder_tools_darwin_amd64_SHA256SUM=85890b864330baec88f53aabfc1d5d94a8ca8c17483f34f4823dec0fae7c6e3a -kubebuilder_tools_darwin_arm64_SHA256SUM=849362d26105b64193b4142982c710306d90248272731a81fb83efac27c5a750 +kubebuilder_tools_linux_amd64_SHA256SUM=2f8252f327e53f6a3ecb92280cc7eb373ca18fd9305a151a1a2d8f769b30feba +kubebuilder_tools_linux_arm64_SHA256SUM=b817a5e7c2a25d84c4c979b37a4797f93c4d316d9059c064f991e5f2fe869164 +kubebuilder_tools_darwin_amd64_SHA256SUM=a6c9005d55ef51d1266f74cf10333892b7c9514231b9a489efc4efb23ac76f9e +kubebuilder_tools_darwin_arm64_SHA256SUM=9108ab4e970aff81fd5ad8272a841e472a772f0ec347318a69f1925f1e8a7a54 .PRECIOUS: $(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz $(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz: | $(DOWNLOAD_DIR)/tools @@ -469,10 +476,10 @@ $(DOWNLOAD_DIR)/tools/kube-apiserver@$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$( @source $(lock_script) $@; \ tar xfO $< controller-tools/envtest/kube-apiserver > $(outfile) && chmod 775 $(outfile) -kyverno_linux_amd64_SHA256SUM=a5f6e9070c17acc47168c8ce4db78e45258376551b8bf68ad2d5ed27454cf666 -kyverno_linux_arm64_SHA256SUM=007e828d622e73614365f5f7e8e107e36ae686e97e8982b1eeb53511fb2363c3 -kyverno_darwin_amd64_SHA256SUM=20786eebf45238e8b4a35f4146c3f8dfea35968cf8ef6ca6d6727559f5c0156e -kyverno_darwin_arm64_SHA256SUM=3a454fb0b2bfbca6225d46ff4cc0b702fd4a63e978718c50225472b9631a8015 +kyverno_linux_amd64_SHA256SUM=abd318dbb971ab6de2bbe3b7226f4a03230d5c9c651df8a29b6b5e085a55aeeb +kyverno_linux_arm64_SHA256SUM=33ccb628b939f075bb8b7f35f5c6ce672cb6733d5748f4df196fa0ce1c67b4d2 +kyverno_darwin_amd64_SHA256SUM=ade0f72c5e93a906396b82f2007226b507d2ff1e06e6b548756ec62a86efc941 +kyverno_darwin_arm64_SHA256SUM=af61da03d44c4e213e05c11981e80b511725c65911a09dc12f0371e06d190766 .PRECIOUS: $(DOWNLOAD_DIR)/tools/kyverno@$(KYVERNO_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/kyverno@$(KYVERNO_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -485,10 +492,10 @@ $(DOWNLOAD_DIR)/tools/kyverno@$(KYVERNO_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DO chmod +x $(outfile); \ rm -f $(outfile).tar.gz -yq_linux_amd64_SHA256SUM=cfbbb9ba72c9402ef4ab9d8f843439693dfb380927921740e51706d90869c7e1 -yq_linux_arm64_SHA256SUM=a8186efb079673293289f8c31ee252b0d533c7bb8b1ada6a778ddd5ec0f325b6 -yq_darwin_amd64_SHA256SUM=fdc42b132ac460037f4f0f48caea82138772c651d91cfbb735210075ddfdbaed -yq_darwin_arm64_SHA256SUM=9f1063d910698834cb9176593aa288471898031929138d226c2c2de9f262f8e5 +yq_linux_amd64_SHA256SUM=654d2943ca1d3be2024089eb4f270f4070f491a0610481d128509b2834870049 +yq_linux_arm64_SHA256SUM=ceea73d4c86f2e5c91926ee0639157121f5360da42beeb8357783d79c2cc6a1d +yq_darwin_amd64_SHA256SUM=cee787479550f0c94662e45251e7bb80f70e7071840bd19ce24542e9bcb4157a +yq_darwin_arm64_SHA256SUM=83edb55e254993f9043d01a1515205b54ffc2c7ce815a780573da64afaf2c71b .PRECIOUS: $(DOWNLOAD_DIR)/tools/yq@$(YQ_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/yq@$(YQ_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -497,10 +504,10 @@ $(DOWNLOAD_DIR)/tools/yq@$(YQ_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR $(checkhash_script) $(outfile) $(yq_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ chmod +x $(outfile) -ko_linux_amd64_SHA256SUM=d11f03f23261d16f9e7802291e9d098e84f5daecc7931e8573bece9025b6a2c5 -ko_linux_arm64_SHA256SUM=8294849c0f12138006cd149dd02bb580c0eea41a6031473705cbf825e021a688 -ko_darwin_amd64_SHA256SUM=314c33154de941bfc4ede5e7283eb182028459bac36eb4223859e0b778254936 -ko_darwin_arm64_SHA256SUM=b6ecd62eb4f9238a0ed0512d7a34648b881aea0774c3830e3e5159370eb6834f +ko_linux_amd64_SHA256SUM=4f0b979b59880b3232f47d79c940f2279165aaad15a11d7614e8a2c9e5c78c29 +ko_linux_arm64_SHA256SUM=9421ebe2a611bac846844bd34fed5c75fba7b36c8cb1d113ad8680c48f6106df +ko_darwin_amd64_SHA256SUM=888656c3f0028d4211654a9df57b003fe26f874b092776c83acace7aca8a73a4 +ko_darwin_arm64_SHA256SUM=d0b6bcc4f86c8d775688d1c21d416985ee557a85ad557c4a7d0e2d82b7cdbd92 .PRECIOUS: $(DOWNLOAD_DIR)/tools/ko@$(KO_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/ko@$(KO_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -514,10 +521,10 @@ $(DOWNLOAD_DIR)/tools/ko@$(KO_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR chmod +x $(outfile); \ rm -f $(outfile).tar.gz -protoc_linux_amd64_SHA256SUM=a7be2928c0454f132c599e25b79b7ad1b57663f2337d7f7e468a1d59b98ec1b0 -protoc_linux_arm64_SHA256SUM=64a3b3b5f7dac0c8f9cf1cb85b2b1a237eb628644f6bcb0fb8f23db6e0d66181 -protoc_darwin_amd64_SHA256SUM=febd8821c3a2a23f72f4641471e0ab6486f4fb07b68111490a27a31681465b3c -protoc_darwin_arm64_SHA256SUM=26a29befa8891ecc48809958c909d284f2b9539a2eb47f22cadc631fe6abe8fd +protoc_linux_amd64_SHA256SUM=327e9397c6fb3ea2a542513a3221334c6f76f7aa524a7d2561142b67b312a01f +protoc_linux_arm64_SHA256SUM=a3173ea338ef91b1605b88c4f8120d6c8ccf36f744d9081991d595d0d4352996 +protoc_darwin_amd64_SHA256SUM=65675c3bb874a2d5f0c941e61bce6175090be25fe466f0ec2d4a6f5978333624 +protoc_darwin_arm64_SHA256SUM=92728c650f6cf2b6c37891ae04ef5bc2d4b5f32c5fbbd101eda623f90bb95f63 .PRECIOUS: $(DOWNLOAD_DIR)/tools/protoc@$(PROTOC_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/protoc@$(PROTOC_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -531,10 +538,10 @@ $(DOWNLOAD_DIR)/tools/protoc@$(PROTOC_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWN chmod +x $(outfile); \ rm -f $(outfile).zip -trivy_linux_amd64_SHA256SUM=b0d135815867246baba52f608f4af84beca90cfeb17a9ce407a21acca760ace1 -trivy_linux_arm64_SHA256SUM=1be1dee3a5e013528374f25391d6ba84e2a10fda59f4e98431e30d9c4975762b -trivy_darwin_amd64_SHA256SUM=744f5e8c5c09c1e5ec6ec6a0570f779d89964c0a91ab60b4e59b284cdd3e1576 -trivy_darwin_arm64_SHA256SUM=e78a0db86f6364e756d5e058316c7815a747fc7fd8e8e984e3baf5830166ec63 +trivy_linux_amd64_SHA256SUM=31af7049380abcdc422094638cc33364593f0ccc89c955dd69d27aca288ae79c +trivy_linux_arm64_SHA256SUM=e3ff876fd6fa95919de02c38258acdb26b8f71be1b89c5cb7831f6ec29719ca5 +trivy_darwin_amd64_SHA256SUM=7454cd0d31dec55498baa2fbec9c4034c23ab52df45bb256c29297f2099129f8 +trivy_darwin_arm64_SHA256SUM=9ad04f68b7823109b93d3c6b4e069d932348bf2847e4ccd197787f87f346138e .PRECIOUS: $(DOWNLOAD_DIR)/tools/trivy@$(TRIVY_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/trivy@$(TRIVY_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -548,10 +555,10 @@ $(DOWNLOAD_DIR)/tools/trivy@$(TRIVY_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLO chmod +x $(outfile); \ rm $(outfile).tar.gz -ytt_linux_amd64_SHA256SUM=357ec754446b1eda29dd529e088f617e85809726c686598ab03cfc1c79f43b56 -ytt_linux_arm64_SHA256SUM=a2d195b058884c0e36a918936076965b8efb426f7e00f6b7d7b99b82737c7299 -ytt_darwin_amd64_SHA256SUM=71b5ea38bfc7a9748c35ce0735fd6f806dce46bd5c9039d527050c7682e62a70 -ytt_darwin_arm64_SHA256SUM=0658db4af8263ca091ca31e4b599cb40c324b75934660a4c0ed98ad9b701f7e9 +ytt_linux_amd64_SHA256SUM=61ad01f1df9cc8344c786e93acb1f5707ded9e4b52e4ec55a0f6637f2af53bae +ytt_linux_arm64_SHA256SUM=ae0bdc3aca64e71276f59679ea9253be5f88fc6880937ae1de3dd42a00492a8c +ytt_darwin_amd64_SHA256SUM=a25dd1c8b74f276a6ef2b4c2d0b493f8aaf87839e90762aa3c444e0b7eec95c8 +ytt_darwin_arm64_SHA256SUM=4fa87a81af4634099c3a1c7396d4d0f0b6fee9f4854b37a6a547d55bfca897c5 .PRECIOUS: $(DOWNLOAD_DIR)/tools/ytt@$(YTT_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/ytt@$(YTT_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -560,10 +567,10 @@ $(DOWNLOAD_DIR)/tools/ytt@$(YTT_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_D $(checkhash_script) $(outfile) $(ytt_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ chmod +x $(outfile) -rclone_linux_amd64_SHA256SUM=b4d304b1dc76001b1d3bb820ae8d1ae60a072afbd3296be904a3ee00b3d4fab9 -rclone_linux_arm64_SHA256SUM=c50a3ab93082f21788f9244393b19f2426edeeb896eec2e3e05ffb2e8727e075 -rclone_darwin_amd64_SHA256SUM=5adb4c5fe0675627461000a63156001301ec7cade966c55c8c4ebcfaeb62c5ae -rclone_darwin_arm64_SHA256SUM=b5f4c4d06ff3d426aee99870ad437276c9ddaad55442f2df6a58b918115fe4cf +rclone_linux_amd64_SHA256SUM=231841f8d8029ae6cfca932b601b3b50d0e2c3c2cb9da3166293f1c3eae7d79c +rclone_linux_arm64_SHA256SUM=a03de8f700fcda7a1aef6b568f88d44218b698fb4e1637596c024d341bb24124 +rclone_darwin_amd64_SHA256SUM=ebe1d5e13b0255605becfafbfa7c1809bc985272bcea0b342675c7e29c57629b +rclone_darwin_arm64_SHA256SUM=09b42295c30ba6b41a0d9c6741e4b5769de9ddecf5069f93c33f01bb46caa228 .PRECIOUS: $(DOWNLOAD_DIR)/tools/rclone@$(RCLONE_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/rclone@$(RCLONE_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @@ -576,10 +583,26 @@ $(DOWNLOAD_DIR)/tools/rclone@$(RCLONE_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWN chmod +x $(outfile); \ rm -f $(outfile).zip -preflight_linux_amd64_SHA256SUM=20f31e4af2004e8e3407844afea4e973975069169d69794e0633f0cb91d45afd -preflight_linux_arm64_SHA256SUM=c42cf4132027d937da88da07760e8fd9b1a8836f9c7795a1b60513d99c6939fe +istioctl_linux_amd64_SHA256SUM=dcdd18d94e398b49221c33d723a2d0bf2d022e795655dd7ce22b8b98a8982a8c +istioctl_linux_arm64_SHA256SUM=aec291d524239822779abc1ec53f141740d693b5a125599e8d6a92c0d443559f +istioctl_darwin_amd64_SHA256SUM=fc2424008654bc2172ebe7646d5af68fd511b0a049f92216b1859d8a0b62d36d +istioctl_darwin_arm64_SHA256SUM=503e3af5d9d713b464dd33ca3308f52843e835804e55a2da8b30f1959b5bb45c + +.PRECIOUS: $(DOWNLOAD_DIR)/tools/istioctl@$(ISTIOCTL_VERSION)_$(HOST_OS)_$(HOST_ARCH) +$(DOWNLOAD_DIR)/tools/istioctl@$(ISTIOCTL_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools + $(eval OS := $(subst darwin,osx,$(HOST_OS))) -# Currently there are no offical releases for darwin, you cannot submit results + @source $(lock_script) $@; \ + $(CURL) https://github.com/istio/istio/releases/download/$(ISTIOCTL_VERSION)/istio-$(ISTIOCTL_VERSION)-$(OS)-$(HOST_ARCH).tar.gz -o $(outfile).tar.gz; \ + $(checkhash_script) $(outfile).tar.gz $(istioctl_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ + tar xfO $(outfile).tar.gz istio-$(ISTIOCTL_VERSION)/bin/istioctl > $(outfile); \ + chmod +x $(outfile); \ + rm $(outfile).tar.gz + +preflight_linux_amd64_SHA256SUM=ee92573f38929be67c7bda91dad614ac1b7d1dd81fa8bd15dfe01e385a540856 +preflight_linux_arm64_SHA256SUM=1f4d199386e5152e59b36acb42fb870ffe7a70b4fe70b49b19f8f73c0f6382ce + +# Currently there are no official releases for darwin, you cannot submit results # on non-official binaries, but we can still run tests. # # Once https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/942 is merged @@ -615,12 +638,28 @@ $(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_linux_$(HOST_ARCH): | $(DOW missing=$(shell (command -v curl >/dev/null || echo curl) \ && (command -v sha256sum >/dev/null || command -v shasum >/dev/null || echo sha256sum) \ && (command -v git >/dev/null || echo git) \ + && (command -v xargs >/dev/null || echo xargs) \ && (command -v bash >/dev/null || echo bash)) ifneq ($(missing),) $(error Missing required tools: $(missing)) endif +non_go_tool_names := $(filter-out $(go_tool_names),$(tool_names)) + +.PHONY: non-go-tools +## Download and setup all Go tools +## @category [shared] Tools +non-go-tools: $(non_go_tool_names:%=$(bin_dir)/tools/%) + +.PHONY: go-tools +## Download and setup all Non-Go tools +## NOTE: this target is also used to learn the shas of +## these tools (see scripts/learn_tools_shas.sh in the +## Makefile modules repo) +## @category [shared] Tools +go-tools: $(go_tool_names:%=$(bin_dir)/tools/%) + .PHONY: tools ## Download and setup all tools ## @category [shared] Tools -tools: $(tools_paths) +tools: non-go-tools go-tools diff --git a/make/_shared/tools/util/lock.sh b/make/_shared/tools/util/lock.sh index 22564f7c..0b89fda7 100755 --- a/make/_shared/tools/util/lock.sh +++ b/make/_shared/tools/util/lock.sh @@ -29,7 +29,7 @@ set -o pipefail finalfile="$1" lockfile="$finalfile.lock" -# On OSX, flock is not installed, we just skip locking in that case, +# On macOS, flock is not installed, we just skip locking in that case, # this means that running verify in parallel without downloading all # tools first will not work. flock_installed=$(command -v flock >/dev/null && echo "yes" || echo "no") diff --git a/make/config/kaniko/dockerfile b/make/config/kaniko/dockerfile index 8bd0a7f1..5aaf0a28 100644 --- a/make/config/kaniko/dockerfile +++ b/make/config/kaniko/dockerfile @@ -1 +1 @@ -FROM nginx +FROM hello-world diff --git a/make/test-e2e.mk b/make/test-e2e.mk index d462f698..9a84f810 100644 --- a/make/test-e2e.mk +++ b/make/test-e2e.mk @@ -25,15 +25,15 @@ e2e-setup-docker-registry: | kind-cluster $(NEEDS_HELM) $(NEEDS_KUBECTL) -f ./make/config/registry/docker-registry-values.yaml \ docker-registry twuni/docker-registry >/dev/null - + INSTALL_OPTIONS += --set image.repository=$(oci_manager_image_name_development) -INSTALL_OPTIONS += -f ./make/config/version-checker-values.yaml +# INSTALL_OPTIONS += -f ./make/config/version-checker-values.yaml -.PHONY: e2e-setup-deps -e2e-setup-deps: | kind-cluster $(NEEDS_KUBECTL) - $(KUBECTL) apply -f test/e2e/manifests/docker-credentials.yaml - $(KUBECTL) apply -f test/e2e/manifests/kaniko.yaml - $(KUBECTL) wait pod -lapp=e2e-kaniko --timeout=30s --for=jsonpath='{.status.containerStatuses[*].state.terminated.reason}'=Completed +# .PHONY: e2e-setup-deps +# e2e-setup-deps: | kind-cluster $(NEEDS_KUBECTL) +# $(KUBECTL) apply -f test/e2e/manifests/docker-credentials.yaml +# $(KUBECTL) apply -f test/e2e/manifests/kaniko.yaml +# $(KUBECTL) wait pod -lapp=e2e-kaniko --timeout=30s --for=jsonpath='{.status.containerStatuses[*].state.terminated.reason}'=Completed is_e2e_test= @@ -50,8 +50,9 @@ ifdef is_e2e_test install: kind-cluster oci-load-manager endif -test-e2e-deps: e2e-setup-docker-registry -test-e2e-deps: e2e-setup-deps +# test-e2e-deps: e2e-setup-docker-registry +# test-e2e-deps: e2e-setup-deps +test-e2e-deps: INSTALL_OPTIONS += -f ./make/config/version-checker-values.yaml test-e2e-deps: install diff --git a/pkg/client/selfhosted/selfhosted.go b/pkg/client/selfhosted/selfhosted.go index 282f45fd..f393d601 100644 --- a/pkg/client/selfhosted/selfhosted.go +++ b/pkg/client/selfhosted/selfhosted.go @@ -232,11 +232,7 @@ func (c *Client) doRequest(ctx context.Context, url, header string, obj interfac req = req.WithContext(ctx) if len(c.Bearer) > 0 { req.Header.Add("Authorization", "Bearer "+c.Bearer) -<<<<<<< HEAD } else if c.Username != "" && c.Password != "" { -======= - } else if len(c.Username) > 0 && len(c.Password) > 0 { ->>>>>>> 8e64777... Add ginkgo e2e tests req.SetBasicAuth(c.Username, c.Password) } diff --git a/test/e2e/manifests/docker-registry-values.yaml b/test/e2e/manifests/docker-registry-values.yaml new file mode 100644 index 00000000..e175502d --- /dev/null +++ b/test/e2e/manifests/docker-registry-values.yaml @@ -0,0 +1,24 @@ +configData: + version: 0.1 + log: + fields: + service: registry + storage: + cache: + blobdescriptor: inmemory + http: + addr: :5000 + headers: + X-Content-Type-Options: [nosniff] + debug: + addr: :5001 + prometheus: + enabled: false + path: /metrics + health: + storagedriver: + enabled: true + interval: 10s + threshold: 3 + secrets: + htpasswd: "user:$2y$05$zDST8320bM1EcRhcj2nsheN7conl3kkOWxPXESn.HW/1lnThDmoBG" diff --git a/make/_shared/oci-build/image_tool/main.go b/test/e2e/suite/doc.go similarity index 50% rename from make/_shared/oci-build/image_tool/main.go rename to test/e2e/suite/doc.go index 507281e7..98fd94f3 100644 --- a/make/_shared/oci-build/image_tool/main.go +++ b/test/e2e/suite/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2023 The cert-manager Authors. +Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,33 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -package main +package suite import ( - "fmt" - "os" - - "github.com/spf13/cobra" + _ "github.com/jetstack/version-checker/test/e2e/suite/selfhosted" ) - -var CommandRoot = cobra.Command{ - Use: "image-tool", -} - -func main() { - CommandRoot.AddCommand(&CommandAppendLayers) - CommandRoot.AddCommand(&CommandConvertToDockerTar) - CommandRoot.AddCommand(&CommandListDigests) - must("error running command", CommandRoot.Execute()) -} - -func must(msg string, err error) { - if err != nil { - fail(msg+": %w", err) - } -} - -func fail(msg string, a ...any) { - fmt.Fprintf(os.Stderr, msg+"\n", a...) - os.Exit(1) -} diff --git a/test/e2e/suite/version_checker.go b/test/e2e/suite/selfhosted/selfhosted.go similarity index 73% rename from test/e2e/suite/version_checker.go rename to test/e2e/suite/selfhosted/selfhosted.go index af242c26..c2b460e5 100644 --- a/test/e2e/suite/version_checker.go +++ b/test/e2e/suite/selfhosted/selfhosted.go @@ -1,4 +1,4 @@ -package suite +package selfhosted import ( "bytes" @@ -12,23 +12,41 @@ import ( "github.com/itchyny/gojq" ) -var _ = Describe("version-checker", func() { - // BeforeEach(func() { - // cmd := exec.Command("kubectl", "apply", "-f", "./manifests/kaniko.yaml") - // cmd.Stdout = GinkgoWriter - // cmd.Stderr = GinkgoWriter - // Expect(cmd.Run()).NotTo(HaveOccurred()) - // cmd = exec.Command("kubectl", "wait", "pod", "-lapp=e2e-kaniko", "--timeout=30s", "--for=jsonpath='{.status.containerStatuses[*].state.terminated.reason}'=Completed") - // cmd.Stdout = GinkgoWriter - // cmd.Stderr = GinkgoWriter - // Expect(cmd.Run()).NotTo(HaveOccurred()) - // }) - // AfterEach(func() { - // cmd := exec.Command("kubectl", "delete", "-f", "./manifests/kaniko.yaml") - // cmd.Stdout = GinkgoWriter - // cmd.Stderr = GinkgoWriter - // Expect(cmd.Run()).NotTo(HaveOccurred()) - // }) +var _ = BeforeSuite(func() { + cmd := exec.Command("helm", "repo", "add", "twuni", "https://helm.twun.io") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + cmd = exec.Command("helm", "upgrade", "--install", "--create-namespace", "-n", "registry", "--wait", "--set", "service.type=NodePort", "--set", "service.nodePort=30443", "-f", "./manifests/docker-registry-values.yaml", "docker-registry", "twuni/docker-registry") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) +}) + +var _ = AfterSuite(func() { + cmd := exec.Command("helm", "uninstall", "-n", "registry", "--wait", "docker-registry") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) +}) + +var _ = Describe("version-checker selfhosted", func() { + BeforeEach(func() { + cmd := exec.Command("kubectl", "apply", "-f", "./manifests/kaniko.yaml", "-f", "./manifests/docker-credentials.yaml") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + cmd = exec.Command("kubectl", "wait", "pod", "-lapp=e2e-kaniko", "--timeout=30s", "--for=jsonpath={.status.containerStatuses[*].state.terminated.reason}=Completed") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + }) + AfterEach(func() { + cmd := exec.Command("kubectl", "delete", "-f", "./manifests/kaniko.yaml") + cmd.Stdout = GinkgoWriter + cmd.Stderr = GinkgoWriter + Expect(cmd.Run()).NotTo(HaveOccurred()) + }) JustBeforeEach(func() { cmd := exec.Command("kubectl", "apply", "-f", "./manifests/prom2json.yaml") From 46ada5d497fbef58754127b4260ecc2e4105b5aa Mon Sep 17 00:00:00 2001 From: paulwilljones Date: Fri, 25 Apr 2025 15:55:12 +0100 Subject: [PATCH 7/7] Remove GHA make deps --- .github/workflows/build-test.yaml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index b2b3bd23..7d46e6aa 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -45,18 +45,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 # v3.5.3 + uses: actions/checkout@v4.2.2 + with: + fetch-depth: 0 - name: Setup Go uses: actions/setup-go@v5 with: go-version-file: go.mod - - name: Download and required packages - run: | - make deps - - name: Run all unit tests - run: make test + run: make test-unit - name: check test coverage uses: vladopajic/go-test-coverage@v2