From 7069d1b336a5b23bc9a1ca1ca6c62ed47207ee72 Mon Sep 17 00:00:00 2001 From: Tim Ramlot <42113979+inteon@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:21:29 +0000 Subject: [PATCH] switch to Makefile modules Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com> --- .dockerignore | 5 - .github/dependabot.yaml | 20 + .github/workflows/govulncheck.yaml | 31 + .github/workflows/make-self-upgrade.yaml | 101 +++ .github/workflows/release.yaml | 122 +++- .github/workflows/test.yaml | 26 - .github/workflows/tests.yaml | 82 +++ .gitignore | 10 +- .golangci.yaml | 68 ++ Dockerfile | 47 -- LICENSE | 201 ++++++ Makefile | 335 ++++------ OWNERS | 16 - OWNERS_ALIASES | 14 + PROJECT | 18 - README.md | 2 +- api/v1alpha1/zz_generated.deepcopy.go | 2 +- config/certmanager/certificate.yaml | 26 - config/certmanager/kustomization.yaml | 5 - config/certmanager/kustomizeconfig.yaml | 16 - ...suer.example.com_sampleclusterissuers.yaml | 140 ---- ...mple-issuer.example.com_sampleissuers.yaml | 140 ---- config/crd/kustomization.yaml | 24 - config/crd/kustomizeconfig.yaml | 17 - .../cainjection_in_clusterissuers.yaml | 8 - .../crd/patches/cainjection_in_issuers.yaml | 8 - .../patches/webhook_in_clusterissuers.yaml | 17 - config/crd/patches/webhook_in_issuers.yaml | 17 - config/default/kustomization.yaml | 72 -- config/default/manager_auth_proxy_patch.yaml | 55 -- config/default/manager_config_patch.yaml | 10 - config/default/manager_webhook_patch.yaml | 23 - config/default/webhookcainjection_patch.yaml | 15 - config/manager/kustomization.yaml | 2 - config/manager/manager.yaml | 90 --- config/prometheus/kustomization.yaml | 2 - config/prometheus/monitor.yaml | 26 - .../rbac/auth_proxy_client_clusterrole.yaml | 16 - config/rbac/auth_proxy_role.yaml | 24 - config/rbac/auth_proxy_role_binding.yaml | 19 - config/rbac/auth_proxy_service.yaml | 21 - ...nager_controller_approver_clusterrole.yaml | 15 - ...ontroller_approver_clusterrolebinding.yaml | 14 - config/rbac/clusterissuer_editor_role.yaml | 24 - config/rbac/clusterissuer_viewer_role.yaml | 20 - config/rbac/issuer_editor_role.yaml | 24 - config/rbac/issuer_viewer_role.yaml | 20 - config/rbac/kustomization.yaml | 23 - config/rbac/leader_election_role.yaml | 44 -- config/rbac/leader_election_role_binding.yaml | 19 - config/rbac/role.yaml | 45 -- config/rbac/role_binding.yaml | 19 - config/rbac/service_account.yaml | 12 - config/webhook/kustomization.yaml | 6 - config/webhook/kustomizeconfig.yaml | 25 - config/webhook/service.yaml | 12 - .../charts/sample-external-issuer/Chart.yaml | 28 + .../charts/sample-external-issuer/README.md | 224 +++++++ .../templates/_helpers.tpl | 46 ++ .../templates/clusterrole.yaml | 108 +++ .../templates/clusterrolebinding.yaml | 29 + ...suer.example.com_sampleclusterissuers.yaml | 143 ++++ ...mple-issuer.example.com_sampleissuers.yaml | 143 ++++ .../templates/deployment.yaml | 64 ++ .../templates/role.yaml | 15 + .../templates/rolebinding.yaml | 15 + .../templates/serviceaccount.yaml | 9 + .../values.linter.exceptions | 0 .../sample-external-issuer/values.schema.json | 295 ++++++++ .../charts/sample-external-issuer/values.yaml | 124 ++++ docs/api/api.md | 294 ++++++++ .../certificate_clusterissuer.yaml | 0 .../certificate_issuer.yaml | 0 .../certificaterequest_clusterissuer.yaml | 0 .../certificaterequest_issuer.yaml | 0 .../sample-issuer_v1alpha1_clusterissuer.yaml | 0 .../sample-issuer_v1alpha1_issuer.yaml | 0 .../secret_clusterissuer.yaml | 0 .../samples => examples}/secret_issuer.yaml | 0 internal/controllers/signer.go | 7 +- klone.yaml | 74 ++ main.go | 98 +-- make/00_mod.mk | 54 ++ make/02_mod.mk | 39 ++ make/_shared/api-docs/01_mod.mk | 55 ++ make/_shared/cert-manager/00_mod.mk | 28 + make/_shared/cert-manager/01_mod.mk | 17 + make/_shared/controller-gen/01_mod.mk | 34 + make/_shared/generate-verify/00_mod.mk | 18 + make/_shared/generate-verify/02_mod.mk | 39 ++ make/_shared/generate-verify/util/verify.sh | 63 ++ make/_shared/go/.golangci.override.yaml | 68 ++ make/_shared/go/01_mod.mk | 147 ++++ make/_shared/go/README.md | 3 + .../base/.github/workflows/govulncheck.yaml | 31 + make/_shared/helm/01_mod.mk | 20 + make/_shared/helm/crd.template.footer.yaml | 1 + make/_shared/helm/crd.template.header.yaml | 11 + make/_shared/helm/crds.mk | 66 ++ make/_shared/helm/deploy.mk | 54 ++ make/_shared/helm/helm.mk | 131 ++++ make/_shared/help/01_mod.mk | 22 + make/_shared/help/help.sh | 115 ++++ make/_shared/kind/00_kind_image_versions.mk | 36 + 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/klone/01_mod.mk | 27 + 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/repository-base/01_mod.mk | 33 + .../base-dependabot/.github/dependabot.yaml | 20 + .../.github/workflows/make-self-upgrade.yaml | 101 +++ 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 | 631 ++++++++++++++++++ make/_shared/tools/util/checkhash.sh | 58 ++ make/_shared/tools/util/hash.sh | 27 + make/_shared/tools/util/lock.sh | 70 ++ {hack => make/config}/boilerplate.go.txt | 2 +- make/config/kind/cluster.yaml | 19 + make/test-smoke.mk | 66 ++ make/test-unit.mk | 28 + 134 files changed, 5998 insertions(+), 1538 deletions(-) delete mode 100644 .dockerignore create mode 100644 .github/dependabot.yaml create mode 100644 .github/workflows/govulncheck.yaml create mode 100644 .github/workflows/make-self-upgrade.yaml delete mode 100644 .github/workflows/test.yaml create mode 100644 .github/workflows/tests.yaml create mode 100644 .golangci.yaml delete mode 100644 Dockerfile create mode 100644 LICENSE delete mode 100644 OWNERS create mode 100644 OWNERS_ALIASES delete mode 100644 PROJECT delete mode 100644 config/certmanager/certificate.yaml delete mode 100644 config/certmanager/kustomization.yaml delete mode 100644 config/certmanager/kustomizeconfig.yaml delete mode 100644 config/crd/bases/sample-issuer.example.com_sampleclusterissuers.yaml delete mode 100644 config/crd/bases/sample-issuer.example.com_sampleissuers.yaml delete mode 100644 config/crd/kustomization.yaml delete mode 100644 config/crd/kustomizeconfig.yaml delete mode 100644 config/crd/patches/cainjection_in_clusterissuers.yaml delete mode 100644 config/crd/patches/cainjection_in_issuers.yaml delete mode 100644 config/crd/patches/webhook_in_clusterissuers.yaml delete mode 100644 config/crd/patches/webhook_in_issuers.yaml delete mode 100644 config/default/kustomization.yaml delete mode 100644 config/default/manager_auth_proxy_patch.yaml delete mode 100644 config/default/manager_config_patch.yaml delete mode 100644 config/default/manager_webhook_patch.yaml delete mode 100644 config/default/webhookcainjection_patch.yaml delete mode 100644 config/manager/kustomization.yaml delete mode 100644 config/manager/manager.yaml delete mode 100644 config/prometheus/kustomization.yaml delete mode 100644 config/prometheus/monitor.yaml delete mode 100644 config/rbac/auth_proxy_client_clusterrole.yaml delete mode 100644 config/rbac/auth_proxy_role.yaml delete mode 100644 config/rbac/auth_proxy_role_binding.yaml delete mode 100644 config/rbac/auth_proxy_service.yaml delete mode 100644 config/rbac/cert_manager_controller_approver_clusterrole.yaml delete mode 100644 config/rbac/cert_manager_controller_approver_clusterrolebinding.yaml delete mode 100644 config/rbac/clusterissuer_editor_role.yaml delete mode 100644 config/rbac/clusterissuer_viewer_role.yaml delete mode 100644 config/rbac/issuer_editor_role.yaml delete mode 100644 config/rbac/issuer_viewer_role.yaml delete mode 100644 config/rbac/kustomization.yaml delete mode 100644 config/rbac/leader_election_role.yaml delete mode 100644 config/rbac/leader_election_role_binding.yaml delete mode 100644 config/rbac/role.yaml delete mode 100644 config/rbac/role_binding.yaml delete mode 100644 config/rbac/service_account.yaml delete mode 100644 config/webhook/kustomization.yaml delete mode 100644 config/webhook/kustomizeconfig.yaml delete mode 100644 config/webhook/service.yaml create mode 100644 deploy/charts/sample-external-issuer/Chart.yaml create mode 100644 deploy/charts/sample-external-issuer/README.md create mode 100644 deploy/charts/sample-external-issuer/templates/_helpers.tpl create mode 100644 deploy/charts/sample-external-issuer/templates/clusterrole.yaml create mode 100644 deploy/charts/sample-external-issuer/templates/clusterrolebinding.yaml create mode 100644 deploy/charts/sample-external-issuer/templates/crd-sample-issuer.example.com_sampleclusterissuers.yaml create mode 100644 deploy/charts/sample-external-issuer/templates/crd-sample-issuer.example.com_sampleissuers.yaml create mode 100644 deploy/charts/sample-external-issuer/templates/deployment.yaml create mode 100644 deploy/charts/sample-external-issuer/templates/role.yaml create mode 100644 deploy/charts/sample-external-issuer/templates/rolebinding.yaml create mode 100644 deploy/charts/sample-external-issuer/templates/serviceaccount.yaml create mode 100644 deploy/charts/sample-external-issuer/values.linter.exceptions create mode 100644 deploy/charts/sample-external-issuer/values.schema.json create mode 100644 deploy/charts/sample-external-issuer/values.yaml create mode 100644 docs/api/api.md rename {config/samples => examples}/certificate_clusterissuer.yaml (100%) rename {config/samples => examples}/certificate_issuer.yaml (100%) rename {config/samples => examples}/certificaterequest_clusterissuer.yaml (100%) rename {config/samples => examples}/certificaterequest_issuer.yaml (100%) rename {config/samples => examples}/sample-issuer_v1alpha1_clusterissuer.yaml (100%) rename {config/samples => examples}/sample-issuer_v1alpha1_issuer.yaml (100%) rename {config/samples => examples}/secret_clusterissuer.yaml (100%) rename {config/samples => examples}/secret_issuer.yaml (100%) create mode 100644 klone.yaml create mode 100644 make/00_mod.mk create mode 100644 make/02_mod.mk create mode 100644 make/_shared/api-docs/01_mod.mk create mode 100644 make/_shared/cert-manager/00_mod.mk create mode 100644 make/_shared/cert-manager/01_mod.mk create mode 100644 make/_shared/controller-gen/01_mod.mk 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/01_mod.mk 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/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/klone/01_mod.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/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 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 rename {hack => make/config}/boilerplate.go.txt (92%) create mode 100644 make/config/kind/cluster.yaml create mode 100644 make/test-smoke.mk create mode 100644 make/test-unit.mk diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 38f5432..0000000 --- a/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file -# Ignore build and test binaries. -bin/ -testbin/ -build/ diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..d950a83 --- /dev/null +++ b/.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/.github/workflows/govulncheck.yaml b/.github/workflows/govulncheck.yaml new file mode 100644 index 0000000..ea70b8e --- /dev/null +++ b/.github/workflows/govulncheck.yaml @@ -0,0 +1,31 @@ +# 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 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - run: make verify-govulncheck diff --git a/.github/workflows/make-self-upgrade.yaml b/.github/workflows/make-self-upgrade.yaml new file mode 100644 index 0000000..c348703 --- /dev/null +++ b/.github/workflows/make-self-upgrade.yaml @@ -0,0 +1,101 @@ +# 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 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.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/.github/workflows/release.yaml b/.github/workflows/release.yaml index 98d7dee..0dda71f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,38 +1,100 @@ name: release on: - release: - types: [published] + push: + tags: + - "v*" + +env: + VERSION: ${{ github.ref_name }} + jobs: - build_push_and_publish: - runs-on: ubuntu-22.04 + build_images: + runs-on: ubuntu-latest + + permissions: + contents: read # needed for checkout + packages: write # needed for push images + id-token: write # needed for keyless signing + steps: - - - name: Checkout code - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: docker/login-action@v3 with: - fetch-depth: 0 + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_PASSWORD }} - - - name: Log in to GitHub Container Registry - uses: docker/login-action@v1 + - uses: actions/setup-go@v5 with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build Docker image - run: make docker-buildx - - - - name: Create install.yaml file - run: make build/install.yaml - - - name: Upload install.yaml file - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + go-version: ${{ steps.go-version.outputs.result }} + + - id: release + run: make release + + - uses: actions/upload-artifact@v4 + with: + name: ${{ steps.release.outputs.RELEASE_HELM_CHART_NAME }}-${{ steps.release.outputs.RELEASE_HELM_CHART_VERSION }}.tgz + path: ${{ steps.release.outputs.RELEASE_HELM_CHART_TAR }} + if-no-files-found: error + + - uses: actions/upload-artifact@v4 + with: + name: install.yaml + path: ${{ steps.release.outputs.RELEASE_YAML }} + if-no-files-found: error + + outputs: + RELEASE_OCI_MANAGER_IMAGE: ${{ steps.release.outputs.RELEASE_OCI_MANAGER_IMAGE }} + RELEASE_OCI_MANAGER_TAG: ${{ steps.release.outputs.RELEASE_OCI_MANAGER_TAG }} + RELEASE_HELM_CHART_NAME: ${{ steps.release.outputs.RELEASE_HELM_CHART_NAME }} + RELEASE_HELM_CHART_VERSION: ${{ steps.release.outputs.RELEASE_HELM_CHART_VERSION }} + + github_release: + runs-on: ubuntu-latest + + needs: build_images + + permissions: + contents: write # needed for creating a PR + pull-requests: write # needed for creating a PR + + steps: + - run: | + touch .notes-file + echo "OCI_MANAGER_IMAGE: ${{ needs.build_images.outputs.RELEASE_OCI_MANAGER_IMAGE }}" >> .notes-file + echo "OCI_MANAGER_TAG: ${{ needs.build_images.outputs.RELEASE_OCI_MANAGER_TAG }}" >> .notes-file + echo "HELM_CHART_NAME: ${{ needs.build_images.outputs.RELEASE_HELM_CHART_NAME }}" >> .notes-file + echo "HELM_CHART_VERSION: ${{ needs.build_images.outputs.RELEASE_HELM_CHART_VERSION }}" >> .notes-file + + - id: chart_download + uses: actions/download-artifact@v4 + with: + name: ${{ needs.build_images.outputs.RELEASE_HELM_CHART_NAME }}-${{ needs.build_images.outputs.RELEASE_HELM_CHART_VERSION }}.tgz + + - id: yaml_download + uses: actions/download-artifact@v4 with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./build/install.yaml - asset_name: install.yaml - asset_content_type: text/yaml + name: install.yaml + + - env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "$VERSION" \ + --repo="$GITHUB_REPOSITORY" \ + --title="${VERSION}" \ + --draft \ + --verify-tag \ + --notes-file .notes-file + + gh release upload "$VERSION" \ + --repo="$GITHUB_REPOSITORY" \ + "${{ steps.chart_download.outputs.download-path }}/${{ needs.build_images.outputs.RELEASE_HELM_CHART_NAME }}-${{ needs.build_images.outputs.RELEASE_HELM_CHART_VERSION }}.tgz" + + gh release upload "$VERSION" \ + --repo="$GITHUB_REPOSITORY" \ + "${{ steps.yaml_download.outputs.download-path }}/install.yaml" diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 65e57d2..0000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: test -on: [pull_request] -jobs: - unit: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v3 - with: - go-version-file: go.mod - cache: true - - run: make test - e2e: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - run: make -j1 kind-cluster deploy-cert-manager docker-build kind-load deploy e2e - - run: make kind-export-logs E2E_ARTIFACTS_DIRECTORY=build/artifacts/e2e-logs - if: failure() - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: e2e-logs - path: build/artifacts/e2e-logs diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000..6c4f915 --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,82 @@ +name: tests +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@v5 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - uses: actions/cache@v4 + with: + path: _bin/downloaded + key: downloaded-${{ runner.os }}-${{ hashFiles('klone.yaml') }}-verify + + - run: make -j verify + + test-unit: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@v5 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - uses: actions/cache@v4 + with: + path: _bin/downloaded + key: downloaded-${{ runner.os }}-${{ hashFiles('klone.yaml') }}-test-unit + + - run: make -j test-unit + + test-smoke: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@v5 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - uses: actions/cache@v4 + with: + path: _bin/downloaded + key: downloaded-${{ runner.os }}-${{ hashFiles('klone.yaml') }}-test-smoke + + - run: make -j test-smoke diff --git a/.gitignore b/.gitignore index 52f0ed7..c797d99 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - # Binaries for programs and plugins *.exe *.exe~ @@ -7,7 +6,6 @@ *.dylib bin testbin/* -Dockerfile.cross # Test binary, build with `go test -c` *.test @@ -16,7 +14,6 @@ Dockerfile.cross *.out # Kubernetes Generated files - skip generated files, except for vendored files - !vendor/**/zz_generated.* # editor and IDE paraphernalia @@ -25,5 +22,8 @@ Dockerfile.cross *.swo *~ -# Build artifacts -build +_bin +.vscode + +# direnv files +.envrc diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..11e71c0 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,68 @@ +linters: + # Explicitly define all enabled linters + disable-all: true + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - contextcheck + - copyloopvar + - decorder + - dogsled + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - exhaustive + - forbidigo + - gci + - ginkgolinter + - gocheckcompilerdirectives + - gochecksumtype + - gocritic + - gofmt + - goheader + - goprintffuncname + - gosec + - gosimple + - gosmopolitan + - govet + - grouper + - importas + - ineffassign + - interfacebloat + - loggercheck + - makezero + - mirror + - misspell + - musttag + - nakedret + - nilerr + - nilnil + - noctx + - nosprintfhostport + - predeclared + - promlinter + - protogetter + - reassign + - sloglint + - staticcheck + - tagalign + - tenv + - testableexamples + - typecheck + - unconvert + - unparam + - unused + - usestdlibvars + - wastedassign +linters-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/cert-manager/sample-external-issuer) # 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. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 22bafdc..0000000 --- a/Dockerfile +++ /dev/null @@ -1,47 +0,0 @@ -# Build the manager binary -FROM golang:1.23 as builder -ARG TARGETOS -ARG TARGETARCH - -WORKDIR /workspace -# Copy the Go Modules manifests -COPY go.mod go.mod -COPY go.sum go.sum -# cache deps before building and copying source so that we don't need to re-download as much -# and so that source changes don't invalidate our downloaded layer -RUN go mod download - -# Copy the go source -COPY main.go main.go -COPY api/ api/ -COPY internal/ internal/ - -# the GOARCH has not a default value to allow the binary be built according to the host where the command -# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO -# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, -# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. -ENV CGO_ENABLED=0 -ENV GOOS=${TARGETOS:-linux} -ENV GOARCH=${TARGETARCH} -ENV GO111MODULE=on - -# Do an initial compilation before setting the version so that there is less to -# re-compile when the version changes -RUN go build -mod=readonly ./... - -ARG VERSION - -# Build -RUN go build \ - -ldflags="-X=github.com/cert-manager/sample-external-issuer/internal/version.Version=${VERSION}" \ - -mod=readonly \ - -o manager main.go - -# Use distroless as minimal base image to package the manager binary -# Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot -WORKDIR / -COPY --from=builder /workspace/manager . -USER 65532:65532 - -ENTRYPOINT ["/manager"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/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/Makefile b/Makefile index 9dc10ce..6a1652d 100644 --- a/Makefile +++ b/Makefile @@ -1,227 +1,116 @@ -MAKEFLAGS += --warn-undefined-variables -SHELL := bash -.SHELLFLAGS := -eu -o pipefail -c +# 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: -.ONESHELL: - -# The version which will be reported by the --version argument of each binary -# and which will be used as the Docker image tag -VERSION ?= $(shell git describe --tags) -# The Docker repository name, overridden in CI. -DOCKER_REGISTRY ?= ghcr.io -DOCKER_IMAGE_NAME ?= cert-manager/sample-external-issuer/controller -# Image URL to use all building/pushing image targets -IMG ?= ${DOCKER_REGISTRY}/${DOCKER_IMAGE_NAME}:${VERSION} - - -# cert-manager -CERT_MANAGER_VERSION ?= 1.11.1 - - -INSTALL_YAML ?= build/install.yaml - -.PHONY: all -all: build - -##@ General - -# The help target prints out all targets with their descriptions organized -# beneath their categories. The categories are represented by '##@' and the -# target descriptions by '##'. The awk commands is responsible for reading the -# entire set of makefiles included in this invocation, looking for lines of the -# file as xyz: ## something, and then pretty-format the target and help. Then, -# if there's a line with ##@ something, that gets pretty-printed as a category. -# More info on the usage of ANSI control characters for terminal formatting: -# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters -# More info on the awk command: -# http://linuxcommand.org/lc3_adv_awk.php - -.PHONY: help -help: ## Display this help. - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) - -##@ Development - -.PHONY: manifests -manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases - -.PHONY: generate -generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. - $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." - -.PHONY: fmt -fmt: ## Run go fmt against code. - go fmt ./... - -.PHONY: vet -vet: ## Run go vet against code. - go vet ./... - -.PHONY: test -test: manifests generate fmt vet ## Run tests - go test ./... -coverprofile cover.out - -##@ E2E testing - -K8S_CLUSTER_NAME := sample-external-issuer-e2e - -.PHONY: kind-cluster -kind-cluster: ## Use Kind to create a Kubernetes cluster for E2E tests -kind-cluster: kind - ${KIND} get clusters | grep ${K8S_CLUSTER_NAME} || ${KIND} create cluster --name ${K8S_CLUSTER_NAME} - -.PHONY: kind-load -kind-load: kind ## Load all the Docker images into Kind - ${KIND} load docker-image --name ${K8S_CLUSTER_NAME} ${IMG} - -.PHONY: kind-export-logs -kind-export-logs: kind ## Export Kind logs - ${KIND} export logs --name ${K8S_CLUSTER_NAME} ${E2E_ARTIFACTS_DIRECTORY} - -.PHONY: deploy-cert-manager -deploy-cert-manager: ## Deploy cert-manager in the configured Kubernetes cluster in ~/.kube/config - kubectl apply --filename=https://github.com/cert-manager/cert-manager/releases/download/v${CERT_MANAGER_VERSION}/cert-manager.yaml - kubectl wait --for=condition=Available --timeout=300s apiservice v1.cert-manager.io - -.PHONY: e2e -e2e: ## Run E2E tests - kubectl apply --filename config/samples - - kubectl wait --for=condition=Ready --timeout=5s sampleissuers.sample-issuer.example.com sampleissuer-sample - kubectl wait --for=condition=Ready --timeout=5s certificaterequests.cert-manager.io sampleissuer-sample - kubectl wait --for=condition=Ready --timeout=5s certificates.cert-manager.io certificate-by-sampleissuer - - kubectl wait --for=condition=Ready --timeout=5s sampleclusterissuers.sample-issuer.example.com sampleclusterissuer-sample - kubectl wait --for=condition=Ready --timeout=5s certificaterequests.cert-manager.io sampleclusterissuer-sample - kubectl wait --for=condition=Ready --timeout=5s certificates.cert-manager.io certificate-by-sampleclusterissuer - - kubectl delete --filename config/samples - -##@ Build - -.PHONY: build -build: manifests generate fmt vet ## Build manager binary - go build -o bin/manager main.go - -.PHONY: run -run: manifests generate fmt vet ## Run a controller from your host. - go run ./main.go - -# If you wish built the manager image targeting other platforms you can use the --platform flag. -# (i.e. docker build --platform linux/arm64 ). However, you must enable docker buildKit for it. -# More info: https://docs.docker.com/develop/develop-images/build_enhancements/ -.PHONY: docker-build -docker-build: ## Build docker image with the manager. - docker build \ - --build-arg VERSION=$(VERSION) \ - --tag ${IMG} \ - --file Dockerfile \ - ${CURDIR} - -# Push the docker image -.PHONY: docker-push -docker-push: ## Push docker image with the manager. - docker push ${IMG} - -# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple -# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: -# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/ -# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/ -# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=> then the export will fail) -# To properly provided solutions that supports more than one platform you should use this option. -# Other platforms include: linux/s390x,linux/ppc64le -PLATFORMS ?= linux/arm64,linux/amd64 -.PHONY: docker-buildx -docker-buildx: ## Build and push docker image for the manager for cross-platform support - # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile - sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross - - docker buildx create --name project-v3-builder - docker buildx use project-v3-builder - - docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross . - - docker buildx rm project-v3-builder - rm Dockerfile.cross - -##@ Deployment - -ifndef ignore-not-found - ignore-not-found = false +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 -.PHONY: install -install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. - $(KUSTOMIZE) build config/crd | kubectl apply -f - - -.PHONY: uninstall -uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. - $(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f - - -# TODO(wallrj): .PHONY ensures that the install file is always regenerated, -# because I this really depends on the checksum of the Docker image and all the -# base Kustomize files. -.PHONY: ${INSTALL_YAML} -${INSTALL_YAML}: manifests kustomize - mkdir -p $(dir $@) - rm -rf build/kustomize - mkdir -p build/kustomize - cd build/kustomize - $(KUSTOMIZE) create --resources ../../config/default - $(KUSTOMIZE) edit set image controller=${IMG} - cd ${CURDIR} - $(KUSTOMIZE) build build/kustomize > $@ - -.PHONY: deploy -deploy: ${INSTALL_YAML} ## Deploy controller to the K8s cluster specified in ~/.kube/config. - kubectl apply -f ${INSTALL_YAML} - -.PHONY: undeploy -undeploy: ${INSTALL_YAML} ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. - kubectl delete -f ${INSTALL_YAML} --ignore-not-found=$(ignore-not-found) - -##@ Build Dependencies - -LOCAL_OS := $(shell go env GOOS) -LOCAL_ARCH := $(shell go env GOARCH) - -## Location to install dependencies to -LOCALBIN ?= $(shell pwd)/bin -$(LOCALBIN): - mkdir -p $(LOCALBIN) - -## Tool Binaries -KUSTOMIZE ?= $(LOCALBIN)/kustomize -CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen -ENVTEST ?= $(LOCALBIN)/setup-envtest -KIND ?= $(LOCALBIN)/kind - -## Tool Versions -KUSTOMIZE_VERSION ?= v3.8.7 -CONTROLLER_TOOLS_VERSION ?= v0.16.1 -KIND_VERSION := 0.18.0 - -KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -.PHONY: kustomize -kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading. -$(KUSTOMIZE): $(LOCALBIN) - @if test -x $(LOCALBIN)/kustomize && ! $(LOCALBIN)/kustomize version | grep -q $(KUSTOMIZE_VERSION); then \ - echo "$(LOCALBIN)/kustomize version is not expected $(KUSTOMIZE_VERSION). Removing it before installing."; \ - rm -rf $(LOCALBIN)/kustomize; \ - fi - test -s $(LOCALBIN)/kustomize || { curl -Ss $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); } - -.PHONY: controller-gen -controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten. -$(CONTROLLER_GEN): $(LOCALBIN) - test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \ - GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) - -.PHONY: envtest -envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. -$(ENVTEST): $(LOCALBIN) - test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest - -.PHONY: kind -kind: $(LOCALBIN) ## Download Kind locally if necessary. - curl -fsSL -o ${KIND} https://github.com/kubernetes-sigs/kind/releases/download/v${KIND_VERSION}/kind-${LOCAL_OS}-${LOCAL_ARCH} - chmod +x ${KIND} +################################## +# 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/OWNERS b/OWNERS deleted file mode 100644 index a4bcf02..0000000 --- a/OWNERS +++ /dev/null @@ -1,16 +0,0 @@ -approvers: -- munnerz -- joshvanl -- wallrj -- jakexks -- maelvls -- irbekrm -- sgtcodfish -reviewers: -- munnerz -- joshvanl -- wallrj -- jakexks -- maelvls -- irbekrm -- sgtcodfish diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES new file mode 100644 index 0000000..10d1279 --- /dev/null +++ b/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 + - irbekrm + - sgtcodfish + - inteon + - thatsmrtalbot diff --git a/PROJECT b/PROJECT deleted file mode 100644 index b6718ca..0000000 --- a/PROJECT +++ /dev/null @@ -1,18 +0,0 @@ -# Code generated by tool. DO NOT EDIT. -# This file is used to track the info used to scaffold your project -# and allow the plugins properly work. -# More info: https://book.kubebuilder.io/reference/project-config.html -domain: example.com -layout: -- go.kubebuilder.io/v3 -projectName: sample-external-issuer -repo: github.com/cert-manager/sample-external-issuer -resources: -- group: sample-issuer - kind: SampleIssuer - version: v1alpha1 -- group: sample-issuer - kind: SampleClusterIssuer - version: v1alpha1 -version: "2" -version: "3" diff --git a/README.md b/README.md index 0d5de6d..1b3519f 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ but also a table of the recent events associated with that resource. The aim is to produce helpful debug output that looks like this: ``` -$ kubectl describe clusterissuers.sample-issuer.example.com clusterissuer-sample +$ kubectl describe sampleclusterissuers.sample-issuer.example.com clusterissuer-sample ... Type: Ready Events: diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index ddf37bb..55f9e80 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated /* -Copyright 2023 The cert-manager Authors. +Copyright 2021 cert-manager Ltd. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/config/certmanager/certificate.yaml b/config/certmanager/certificate.yaml deleted file mode 100644 index 58db114..0000000 --- a/config/certmanager/certificate.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# The following manifests contain a self-signed issuer CR and a certificate CR. -# More document can be found at https://docs.cert-manager.io -# WARNING: Targets CertManager 0.11 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for -# breaking changes -apiVersion: cert-manager.io/v1alpha2 -kind: Issuer -metadata: - name: selfsigned-issuer - namespace: system -spec: - selfSigned: {} ---- -apiVersion: cert-manager.io/v1alpha2 -kind: Certificate -metadata: - name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml - namespace: system -spec: - # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize - dnsNames: - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local - issuerRef: - kind: Issuer - name: selfsigned-issuer - secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize diff --git a/config/certmanager/kustomization.yaml b/config/certmanager/kustomization.yaml deleted file mode 100644 index bebea5a..0000000 --- a/config/certmanager/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -resources: -- certificate.yaml - -configurations: -- kustomizeconfig.yaml diff --git a/config/certmanager/kustomizeconfig.yaml b/config/certmanager/kustomizeconfig.yaml deleted file mode 100644 index 90d7c31..0000000 --- a/config/certmanager/kustomizeconfig.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# This configuration is for teaching kustomize how to update name ref and var substitution -nameReference: -- kind: Issuer - group: cert-manager.io - fieldSpecs: - - kind: Certificate - group: cert-manager.io - path: spec/issuerRef/name - -varReference: -- kind: Certificate - group: cert-manager.io - path: spec/commonName -- kind: Certificate - group: cert-manager.io - path: spec/dnsNames diff --git a/config/crd/bases/sample-issuer.example.com_sampleclusterissuers.yaml b/config/crd/bases/sample-issuer.example.com_sampleclusterissuers.yaml deleted file mode 100644 index 0d9436c..0000000 --- a/config/crd/bases/sample-issuer.example.com_sampleclusterissuers.yaml +++ /dev/null @@ -1,140 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.1 - name: sampleclusterissuers.sample-issuer.example.com -spec: - group: sample-issuer.example.com - names: - kind: SampleClusterIssuer - listKind: SampleClusterIssuerList - plural: sampleclusterissuers - singular: sampleclusterissuer - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Reason - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Message - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].lastTransitionTime - name: LastTransition - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].observedGeneration - name: ObservedGeneration - type: integer - - jsonPath: .metadata.generation - name: Generation - type: integer - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: SampleClusterIssuer is the Schema for the clusterissuers API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IssuerSpec defines the desired state of SampleIssuer - properties: - authSecretName: - description: |- - A reference to a Secret in the same namespace as the referent. If the - referent is a SampleClusterIssuer, the reference instead refers to the resource - with the given name in the configured 'cluster resource namespace', which - is set as a flag on the controller component (and defaults to the - namespace that the controller runs in). - type: string - url: - description: |- - URL is the base URL for the endpoint of the signing service, - for example: "https://sample-signer.example.com/api". - type: string - required: - - authSecretName - - url - type: object - status: - properties: - conditions: - description: |- - List of status conditions to indicate the status of an Issuer. - Known condition types are `Ready`. - items: - description: IssuerCondition contains condition information for - an Issuer. - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the timestamp corresponding to the last status - change of this condition. - format: date-time - type: string - message: - description: |- - Message is a human readable description of the details of the last - transition, complementing reason. - type: string - observedGeneration: - description: |- - If set, this represents the .metadata.generation that the condition was - set based upon. - For instance, if .metadata.generation is currently 12, but the - .status.condition[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the Issuer. - format: int64 - type: integer - reason: - description: |- - Reason is a brief machine readable explanation for the condition's last - transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, - `Unknown`). - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: Type of the condition, known values are (`Ready`). - type: string - required: - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/bases/sample-issuer.example.com_sampleissuers.yaml b/config/crd/bases/sample-issuer.example.com_sampleissuers.yaml deleted file mode 100644 index bc5edf8..0000000 --- a/config/crd/bases/sample-issuer.example.com_sampleissuers.yaml +++ /dev/null @@ -1,140 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.1 - name: sampleissuers.sample-issuer.example.com -spec: - group: sample-issuer.example.com - names: - kind: SampleIssuer - listKind: SampleIssuerList - plural: sampleissuers - singular: sampleissuer - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Reason - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Message - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].lastTransitionTime - name: LastTransition - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].observedGeneration - name: ObservedGeneration - type: integer - - jsonPath: .metadata.generation - name: Generation - type: integer - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: SampleIssuer is the Schema for the issuers API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: IssuerSpec defines the desired state of SampleIssuer - properties: - authSecretName: - description: |- - A reference to a Secret in the same namespace as the referent. If the - referent is a SampleClusterIssuer, the reference instead refers to the resource - with the given name in the configured 'cluster resource namespace', which - is set as a flag on the controller component (and defaults to the - namespace that the controller runs in). - type: string - url: - description: |- - URL is the base URL for the endpoint of the signing service, - for example: "https://sample-signer.example.com/api". - type: string - required: - - authSecretName - - url - type: object - status: - properties: - conditions: - description: |- - List of status conditions to indicate the status of an Issuer. - Known condition types are `Ready`. - items: - description: IssuerCondition contains condition information for - an Issuer. - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the timestamp corresponding to the last status - change of this condition. - format: date-time - type: string - message: - description: |- - Message is a human readable description of the details of the last - transition, complementing reason. - type: string - observedGeneration: - description: |- - If set, this represents the .metadata.generation that the condition was - set based upon. - For instance, if .metadata.generation is currently 12, but the - .status.condition[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the Issuer. - format: int64 - type: integer - reason: - description: |- - Reason is a brief machine readable explanation for the condition's last - transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, - `Unknown`). - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: Type of the condition, known values are (`Ready`). - type: string - required: - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml deleted file mode 100644 index fef7539..0000000 --- a/config/crd/kustomization.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# This kustomization.yaml is not intended to be run by itself, -# since it depends on service name and namespace that are out of this kustomize package. -# It should be run by config/default -resources: -- bases/sample-issuer.example.com_sampleissuers.yaml -- bases/sample-issuer.example.com_sampleclusterissuers.yaml -# +kubebuilder:scaffold:crdkustomizeresource - -patchesStrategicMerge: -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. -# patches here are for enabling the conversion webhook for each CRD -#- patches/webhook_in_sampleissuers.yaml -#- patches/webhook_in_sampleclusterissuers.yaml -# +kubebuilder:scaffold:crdkustomizewebhookpatch - -# [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. -# patches here are for enabling the CA injection for each CRD -#- patches/cainjection_in_sampleissuers.yaml -#- patches/cainjection_in_sampleclusterissuers.yaml -# +kubebuilder:scaffold:crdkustomizecainjectionpatch - -# the following config is for teaching kustomize how to do kustomization for CRDs. -configurations: -- kustomizeconfig.yaml diff --git a/config/crd/kustomizeconfig.yaml b/config/crd/kustomizeconfig.yaml deleted file mode 100644 index 6f83d9a..0000000 --- a/config/crd/kustomizeconfig.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# This file is for teaching kustomize how to substitute name and namespace reference in CRD -nameReference: -- kind: Service - version: v1 - fieldSpecs: - - kind: CustomResourceDefinition - group: apiextensions.k8s.io - path: spec/conversion/webhookClientConfig/service/name - -namespace: -- kind: CustomResourceDefinition - group: apiextensions.k8s.io - path: spec/conversion/webhookClientConfig/service/namespace - create: false - -varReference: -- path: metadata/annotations diff --git a/config/crd/patches/cainjection_in_clusterissuers.yaml b/config/crd/patches/cainjection_in_clusterissuers.yaml deleted file mode 100644 index 8137f7a..0000000 --- a/config/crd/patches/cainjection_in_clusterissuers.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -# CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: sampleclusterissuers.sample-issuer.example.com diff --git a/config/crd/patches/cainjection_in_issuers.yaml b/config/crd/patches/cainjection_in_issuers.yaml deleted file mode 100644 index 7529360..0000000 --- a/config/crd/patches/cainjection_in_issuers.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -# CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: sampleissuers.sample-issuer.example.com diff --git a/config/crd/patches/webhook_in_clusterissuers.yaml b/config/crd/patches/webhook_in_clusterissuers.yaml deleted file mode 100644 index d246e8d..0000000 --- a/config/crd/patches/webhook_in_clusterissuers.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# The following patch enables conversion webhook for CRD -# CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: sampleclusterissuers.sample-issuer.example.com -spec: - conversion: - strategy: Webhook - webhookClientConfig: - # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, - # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) - caBundle: Cg== - service: - namespace: system - name: webhook-service - path: /convert diff --git a/config/crd/patches/webhook_in_issuers.yaml b/config/crd/patches/webhook_in_issuers.yaml deleted file mode 100644 index a902d05..0000000 --- a/config/crd/patches/webhook_in_issuers.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# The following patch enables conversion webhook for CRD -# CRD conversion requires k8s 1.13 or later. -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: sampleissuers.sample-issuer.example.com -spec: - conversion: - strategy: Webhook - webhookClientConfig: - # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, - # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) - caBundle: Cg== - service: - namespace: system - name: webhook-service - path: /convert diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml deleted file mode 100644 index 4ed0209..0000000 --- a/config/default/kustomization.yaml +++ /dev/null @@ -1,72 +0,0 @@ -# Adds namespace to all resources. -namespace: sample-external-issuer-system - -# Value of this field is prepended to the -# names of all resources, e.g. a deployment named -# "wordpress" becomes "alices-wordpress". -# Note that it should also match with the prefix (text before '-') of the namespace -# field above. -namePrefix: sample-external-issuer- - -# Labels to add to all resources and selectors. -#commonLabels: -# someName: someValue - -bases: -- ../crd -- ../rbac -- ../manager -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -#- ../webhook -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. -#- ../certmanager -# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. -#- ../prometheus - -patchesStrategicMerge: -# Protect the /metrics endpoint by putting it behind auth. -# If you want your controller-manager to expose the /metrics -# endpoint w/o any authn/z, please comment the following line. -- manager_auth_proxy_patch.yaml - - - -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -#- manager_webhook_patch.yaml - -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -#- webhookcainjection_patch.yaml - -# the following config is for teaching kustomize how to do var substitution -vars: -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -#- name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -#- name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -#- name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml deleted file mode 100644 index b751266..0000000 --- a/config/default/manager_auth_proxy_patch.yaml +++ /dev/null @@ -1,55 +0,0 @@ -# This patch inject a sidecar container which is a HTTP proxy for the -# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: kubernetes.io/arch - operator: In - values: - - amd64 - - arm64 - - ppc64le - - s390x - - key: kubernetes.io/os - operator: In - values: - - linux - containers: - - name: kube-rbac-proxy - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - "ALL" - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.1 - args: - - "--secure-listen-address=0.0.0.0:8443" - - "--upstream=http://127.0.0.1:8080/" - - "--logtostderr=true" - - "--v=0" - ports: - - containerPort: 8443 - protocol: TCP - name: https - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 5m - memory: 64Mi - - name: manager - args: - - "--health-probe-bind-address=:8081" - - "--metrics-bind-address=127.0.0.1:8080" - - "--leader-elect" diff --git a/config/default/manager_config_patch.yaml b/config/default/manager_config_patch.yaml deleted file mode 100644 index f6f5891..0000000 --- a/config/default/manager_config_patch.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager diff --git a/config/default/manager_webhook_patch.yaml b/config/default/manager_webhook_patch.yaml deleted file mode 100644 index 738de35..0000000 --- a/config/default/manager_webhook_patch.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - ports: - - containerPort: 9443 - name: webhook-server - protocol: TCP - volumeMounts: - - mountPath: /tmp/k8s-webhook-server/serving-certs - name: cert - readOnly: true - volumes: - - name: cert - secret: - defaultMode: 420 - secretName: webhook-server-cert diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml deleted file mode 100644 index 7e79bf9..0000000 --- a/config/default/webhookcainjection_patch.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# This patch add annotation to admission webhook config and -# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: MutatingWebhookConfiguration -metadata: - name: mutating-webhook-configuration - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) ---- -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: ValidatingWebhookConfiguration -metadata: - name: validating-webhook-configuration - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml deleted file mode 100644 index 5c5f0b8..0000000 --- a/config/manager/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: -- manager.yaml diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml deleted file mode 100644 index 42064d1..0000000 --- a/config/manager/manager.yaml +++ /dev/null @@ -1,90 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - control-plane: controller-manager - app.kubernetes.io/name: namespace - app.kubernetes.io/instance: system - app.kubernetes.io/component: manager - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: system ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system - labels: - control-plane: controller-manager - app.kubernetes.io/name: deployment - app.kubernetes.io/instance: controller-manager - app.kubernetes.io/component: manager - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize -spec: - selector: - matchLabels: - control-plane: controller-manager - replicas: 1 - template: - metadata: - annotations: - kubectl.kubernetes.io/default-container: manager - labels: - control-plane: controller-manager - spec: - # TODO(user): Uncomment the following code to configure the nodeAffinity expression - # according to the platforms which are supported by your solution. - # It is considered best practice to support multiple architectures. You can - # build your manager image using the makefile target docker-buildx. - # affinity: - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: kubernetes.io/arch - # operator: In - # values: - # - amd64 - # - arm64 - # - ppc64le - # - s390x - # - key: kubernetes.io/os - # operator: In - # values: - # - linux - securityContext: - runAsNonRoot: true - # TODO(user): For common cases that do not require escalating privileges - # it is recommended to ensure that all your Pods/Containers are restrictive. - # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted - # Please uncomment the following code if your project does NOT have to work on old Kubernetes - # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). - # seccompProfile: - # type: RuntimeDefault - containers: - - command: - - /manager - args: - - --leader-elect - image: controller:latest - name: manager - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - "ALL" - # TODO(user): Configure the resources accordingly based on the project requirements. - # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 10m - memory: 64Mi - serviceAccountName: controller-manager - terminationGracePeriodSeconds: 10 diff --git a/config/prometheus/kustomization.yaml b/config/prometheus/kustomization.yaml deleted file mode 100644 index ed13716..0000000 --- a/config/prometheus/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: -- monitor.yaml diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml deleted file mode 100644 index 61e09f3..0000000 --- a/config/prometheus/monitor.yaml +++ /dev/null @@ -1,26 +0,0 @@ - -# Prometheus Monitor Service (Metrics) -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - labels: - control-plane: controller-manager - app.kubernetes.io/name: servicemonitor - app.kubernetes.io/instance: controller-manager-metrics-monitor - app.kubernetes.io/component: metrics - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: controller-manager-metrics-monitor - namespace: system -spec: - endpoints: - - path: /metrics - port: https - scheme: https - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token - tlsConfig: - insecureSkipVerify: true - selector: - matchLabels: - control-plane: controller-manager diff --git a/config/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/auth_proxy_client_clusterrole.yaml deleted file mode 100644 index ec1e6d3..0000000 --- a/config/rbac/auth_proxy_client_clusterrole.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: metrics-reader - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: metrics-reader -rules: -- nonResourceURLs: - - "/metrics" - verbs: - - get diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac/auth_proxy_role.yaml deleted file mode 100644 index f11211a..0000000 --- a/config/rbac/auth_proxy_role.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: proxy-role - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: proxy-role -rules: -- apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create -- apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml deleted file mode 100644 index a007e4b..0000000 --- a/config/rbac/auth_proxy_role_binding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: clusterrolebinding - app.kubernetes.io/instance: proxy-rolebinding - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: proxy-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: proxy-role -subjects: -- kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/config/rbac/auth_proxy_service.yaml b/config/rbac/auth_proxy_service.yaml deleted file mode 100644 index fbe2a9e..0000000 --- a/config/rbac/auth_proxy_service.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - control-plane: controller-manager - app.kubernetes.io/name: service - app.kubernetes.io/instance: controller-manager-metrics-service - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: controller-manager-metrics-service - namespace: system -spec: - ports: - - name: https - port: 8443 - protocol: TCP - targetPort: https - selector: - control-plane: controller-manager diff --git a/config/rbac/cert_manager_controller_approver_clusterrole.yaml b/config/rbac/cert_manager_controller_approver_clusterrole.yaml deleted file mode 100644 index ae9d468..0000000 --- a/config/rbac/cert_manager_controller_approver_clusterrole.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# permissions to approve all sample-issuer.example.com requests -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cert-manager-controller-approve:sample-issuer-example-com -rules: -- apiGroups: - - cert-manager.io - resources: - - signers - verbs: - - approve - resourceNames: - - sampleissuers.sample-issuer.example.com/* - - sampleclusterissuers.sample-issuer.example.com/* diff --git a/config/rbac/cert_manager_controller_approver_clusterrolebinding.yaml b/config/rbac/cert_manager_controller_approver_clusterrolebinding.yaml deleted file mode 100644 index 7c7ae63..0000000 --- a/config/rbac/cert_manager_controller_approver_clusterrolebinding.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# bind the cert-manager internal approver to approve -# sample-issuer.example.com CertificateRequests -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cert-manager-controller-approve:sample-issuer-example-com -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cert-manager-controller-approve:sample-issuer-example-com -subjects: -- kind: ServiceAccount - name: cert-manager - namespace: cert-manager diff --git a/config/rbac/clusterissuer_editor_role.yaml b/config/rbac/clusterissuer_editor_role.yaml deleted file mode 100644 index 7203f6e..0000000 --- a/config/rbac/clusterissuer_editor_role.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# permissions for end users to edit sampleclusterissuers. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sampleclusterissuer-editor-role -rules: -- apiGroups: - - sample-issuer.example.com - resources: - - sampleclusterissuers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - sample-issuer.example.com - resources: - - sampleclusterissuers/status - verbs: - - get diff --git a/config/rbac/clusterissuer_viewer_role.yaml b/config/rbac/clusterissuer_viewer_role.yaml deleted file mode 100644 index 1a71bca..0000000 --- a/config/rbac/clusterissuer_viewer_role.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# permissions for end users to view sampleclusterissuers. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sampleclusterissuer-viewer-role -rules: -- apiGroups: - - sample-issuer.example.com - resources: - - sampleclusterissuers - verbs: - - get - - list - - watch -- apiGroups: - - sample-issuer.example.com - resources: - - sampleclusterissuers/status - verbs: - - get diff --git a/config/rbac/issuer_editor_role.yaml b/config/rbac/issuer_editor_role.yaml deleted file mode 100644 index 595e299..0000000 --- a/config/rbac/issuer_editor_role.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# permissions for end users to edit sampleissuers. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sampleissuer-editor-role -rules: -- apiGroups: - - sample-issuer.example.com - resources: - - sampleissuers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - sample-issuer.example.com - resources: - - sampleissuers/status - verbs: - - get diff --git a/config/rbac/issuer_viewer_role.yaml b/config/rbac/issuer_viewer_role.yaml deleted file mode 100644 index 51e8e26..0000000 --- a/config/rbac/issuer_viewer_role.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# permissions for end users to view sampleissuers. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: sampleissuer-viewer-role -rules: -- apiGroups: - - sample-issuer.example.com - resources: - - sampleissuers - verbs: - - get - - list - - watch -- apiGroups: - - sample-issuer.example.com - resources: - - sampleissuers/status - verbs: - - get diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml deleted file mode 100644 index e844a30..0000000 --- a/config/rbac/kustomization.yaml +++ /dev/null @@ -1,23 +0,0 @@ -resources: -# All RBAC will be applied under this service account in -# the deployment namespace. You may comment out this resource -# if your manager will use a service account that exists at -# runtime. Be sure to update RoleBinding and ClusterRoleBinding -# subjects if changing service account names. -- service_account.yaml -- role.yaml -- role_binding.yaml -- leader_election_role.yaml -- leader_election_role_binding.yaml -# Comment the following 4 lines if you want to disable -# the auth proxy (https://github.com/brancz/kube-rbac-proxy) -# which protects your /metrics endpoint. -- auth_proxy_service.yaml -- auth_proxy_role.yaml -- auth_proxy_role_binding.yaml -- auth_proxy_client_clusterrole.yaml -# Comment the following 2 lines if you don't wish for the internal cert-manager -# approver to approve all sample-issuer.example.com CertificateRequests by -# default. -- cert_manager_controller_approver_clusterrole.yaml -- cert_manager_controller_approver_clusterrolebinding.yaml diff --git a/config/rbac/leader_election_role.yaml b/config/rbac/leader_election_role.yaml deleted file mode 100644 index f7d8a97..0000000 --- a/config/rbac/leader_election_role.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# permissions to do leader election. -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - labels: - app.kubernetes.io/name: role - app.kubernetes.io/instance: leader-election-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: leader-election-role -rules: -- apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - events - verbs: - - create - - patch diff --git a/config/rbac/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml deleted file mode 100644 index a622fdd..0000000 --- a/config/rbac/leader_election_role_binding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - labels: - app.kubernetes.io/name: rolebinding - app.kubernetes.io/instance: leader-election-rolebinding - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: leader-election-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: leader-election-role -subjects: -- kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml deleted file mode 100644 index 9e13fa1..0000000 --- a/config/rbac/role.yaml +++ /dev/null @@ -1,45 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - creationTimestamp: null - name: manager-role -rules: -- apiGroups: [ "" ] - resources: [ "events" ] - verbs: ["create", "patch"] - -- apiGroups: [ "" ] - resources: [ "secrets" ] - verbs: ["get", "list", "watch"] - -- apiGroups: [ "sample-issuer.example.com" ] - resources: [ "sampleclusterissuers", "sampleissuers" ] - verbs: ["get", "list", "watch"] - -- apiGroups: [ "sample-issuer.example.com" ] - resources: [ "sampleclusterissuers/status", "sampleissuers/status" ] - verbs: [ "patch" ] - - -- apiGroups: [ "cert-manager.io" ] - resources: [ "certificaterequests" ] - verbs: [ "get", "list", "watch" ] - -- apiGroups: [ "cert-manager.io" ] - resources: [ "certificaterequests/status" ] - verbs: [ "patch" ] - -- apiGroups: [ "certificates.k8s.io" ] - resources: [ "certificatesigningrequests" ] - verbs: [ "get", "list", "watch" ] - -- apiGroups: [ "certificates.k8s.io" ] - resources: [ "certificatesigningrequests/status" ] - verbs: [ "patch" ] - -- apiGroups: [ "certificates.k8s.io" ] - resources: [ "signers" ] - verbs: [ "sign" ] - resourceNames: - - sampleclusterissuers.sample-issuer.example.com/* diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml deleted file mode 100644 index 6bf1ddb..0000000 --- a/config/rbac/role_binding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: clusterrolebinding - app.kubernetes.io/instance: manager-rolebinding - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: manager-role -subjects: -- kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/config/rbac/service_account.yaml b/config/rbac/service_account.yaml deleted file mode 100644 index e4da264..0000000 --- a/config/rbac/service_account.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/name: serviceaccount - app.kubernetes.io/instance: controller-manager - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: sample-external-issuer - app.kubernetes.io/part-of: sample-external-issuer - app.kubernetes.io/managed-by: kustomize - name: controller-manager - namespace: system diff --git a/config/webhook/kustomization.yaml b/config/webhook/kustomization.yaml deleted file mode 100644 index 9cf2613..0000000 --- a/config/webhook/kustomization.yaml +++ /dev/null @@ -1,6 +0,0 @@ -resources: -- manifests.yaml -- service.yaml - -configurations: -- kustomizeconfig.yaml diff --git a/config/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml deleted file mode 100644 index 25e21e3..0000000 --- a/config/webhook/kustomizeconfig.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# the following config is for teaching kustomize where to look at when substituting vars. -# It requires kustomize v2.1.0 or newer to work properly. -nameReference: -- kind: Service - version: v1 - fieldSpecs: - - kind: MutatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/name - - kind: ValidatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/name - -namespace: -- kind: MutatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/namespace - create: true -- kind: ValidatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/namespace - create: true - -varReference: -- path: metadata/annotations diff --git a/config/webhook/service.yaml b/config/webhook/service.yaml deleted file mode 100644 index 31e0f82..0000000 --- a/config/webhook/service.yaml +++ /dev/null @@ -1,12 +0,0 @@ - -apiVersion: v1 -kind: Service -metadata: - name: webhook-service - namespace: system -spec: - ports: - - port: 443 - targetPort: 9443 - selector: - control-plane: controller-manager diff --git a/deploy/charts/sample-external-issuer/Chart.yaml b/deploy/charts/sample-external-issuer/Chart.yaml new file mode 100644 index 0000000..51ab4f5 --- /dev/null +++ b/deploy/charts/sample-external-issuer/Chart.yaml @@ -0,0 +1,28 @@ +apiVersion: v2 + +name: sample-external-issuer +type: application +description: A Helm chart for cert-manager/sample-external-issuer + +home: https://github.com/cert-manager/sample-external-issuer +icon: https://raw.githubusercontent.com/cert-manager/community/4d35a69437d21b76322157e6284be4cd64e6d2b7/logo/logo-small.png +keywords: + - cert-manager + - issuer +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/category: security + artifacthub.io/recommendations: | + - url: https://artifacthub.io/packages/helm/cert-manager/cert-manager + artifacthub.io/prerelease: "false" +maintainers: +- name: cert-manager-maintainers + email: cert-manager-maintainers@googlegroups.com + url: https://cert-manager.io +sources: +- https://github.com/cert-manager/sample-external-issuer + +kubeVersion: ">= 1.25.0-0" # The -0 is required for EKS: https://github.com/helm/helm/issues/10375 + +appVersion: v0.0.0 +version: v0.0.0 diff --git a/deploy/charts/sample-external-issuer/README.md b/deploy/charts/sample-external-issuer/README.md new file mode 100644 index 0000000..8972bab --- /dev/null +++ b/deploy/charts/sample-external-issuer/README.md @@ -0,0 +1,224 @@ +# sample-external-issuer + + + +## Helm Values + + + +#### **crds.enabled** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +This option decides if the CRDs should be installed as part of the Helm installation. +#### **crds.keep** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +This option makes it so that the "helm.sh/resource-policy": keep annotation is added to the CRD. This will prevent Helm from uninstalling the CRD when the Helm release is uninstalled. WARNING: when the CRDs are removed, all sample-external-issuer custom resources +(ClusterIssuer, Issuer, ...) will be removed too by the garbage collector. +#### **replicaCount** ~ `number` +> Default value: +> ```yaml +> 1 +> ``` + +Number of replicas of sample-external-issuer to run. +#### **image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/sample-external-issuer +> ``` + +Target image repository. +#### **image.registry** ~ `unknown` +> Default value: +> ```yaml +> null +> ``` + +Target image registry. Will be prepended to the target image repositry if set. +#### **image.tag** ~ `unknown` +> Default value: +> ```yaml +> null +> ``` + +Target image version tag. Defaults to the chart's appVersion. +#### **image.digest** ~ `unknown` +> Default value: +> ```yaml +> null +> ``` + +Target image digest. Will override any tag if set. for example: + +```yaml +digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 +``` +#### **image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +#### **imagePullSecrets** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Optional secrets used for pulling the sample-external-issuer container image. +#### **commonLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Labels to apply to all resources +#### **serviceAccount.annotations** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional annotations to add to the service account +#### **app.logLevel** ~ `number` +> Default value: +> ```yaml +> 1 +> ``` + +Verbosity of sample-external-issuer logging. +#### **app.approval.enabled** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +enabled determines whether the ClusterRole and ClusterRoleBinding for approval is created. You will want to disable this if you are managing approval RBAC elsewhere from this chart, for example if you create them separately for all installed issuers. +#### **app.approval.subjects[0].kind** ~ `string` +> Default value: +> ```yaml +> ServiceAccount +> ``` +#### **app.approval.subjects[0].name** ~ `string` +> Default value: +> ```yaml +> cert-manager +> ``` +#### **app.approval.subjects[0].namespace** ~ `string` +> Default value: +> ```yaml +> cert-manager +> ``` +#### **app.metrics.port** ~ `number` +> Default value: +> ```yaml +> 9402 +> ``` + +Port for exposing Prometheus metrics on 0.0.0.0 on path '/metrics'. +#### **deploymentAnnotations** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional annotations to add to the sample-external-issuer Deployment +#### **podAnnotations** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional annotations to add to the sample-external-issuer Pods +#### **podLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the sample-external-issuer Pods +#### **resources** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Kubernetes pod resource requests/limits for sample-external-issuer. +For example: + +```yaml +limits: + cpu: 100m + memory: 128Mi +requests: + cpu: 100m + memory: 128Mi +``` +#### **nodeSelector** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Kubernetes node selector: node labels for pod assignment +For example: + +```yaml +kubernetes.io/os: linux +``` +#### **affinity** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Kubernetes affinity: constraints for pod assignment +For example: + +```yaml +nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo.bar.com/role + operator: In + values: + - master +``` +#### **tolerations** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Kubernetes pod tolerations for sample-external-issuer +For example: + - operator: "Exists" +#### **priorityClassName** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Optional priority class to be used for the sample-external-issuer pods. +#### **nameOverride** ~ `string` + +Override the "sample-external-issuer.name" value. + +#### **omitHelmLabels** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Omit Helm-specific labels. This is useful when generating a static manifest with `helm template`. + + \ No newline at end of file diff --git a/deploy/charts/sample-external-issuer/templates/_helpers.tpl b/deploy/charts/sample-external-issuer/templates/_helpers.tpl new file mode 100644 index 0000000..dba0811 --- /dev/null +++ b/deploy/charts/sample-external-issuer/templates/_helpers.tpl @@ -0,0 +1,46 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "sample-external-issuer.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "sample-external-issuer.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "sample-external-issuer.labels" -}} +app.kubernetes.io/name: {{ include "sample-external-issuer.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +{{- if not .Values.omitHelmLabels }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ include "sample-external-issuer.chart" . }} +{{- end }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end -}} + +{{/* +Util function for generating the image URL based on the provided options. +IMPORTANT: This function is standarized across all charts in the cert-manager GH organization. +Any changes to this function should also be made in cert-manager, trust-manager, approver-policy, ... +See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linked PRs. +*/}} +{{- define "image" -}} +{{- $defaultTag := index . 1 -}} +{{- with index . 0 -}} +{{- if .registry -}}{{ printf "%s/%s" .registry .repository }}{{- else -}}{{- .repository -}}{{- end -}} +{{- if .digest -}}{{ printf "@%s" .digest }}{{- else -}}{{ printf ":%s" (default $defaultTag .tag) }}{{- end -}} +{{- end }} +{{- end }} diff --git a/deploy/charts/sample-external-issuer/templates/clusterrole.yaml b/deploy/charts/sample-external-issuer/templates/clusterrole.yaml new file mode 100644 index 0000000..83c78ac --- /dev/null +++ b/deploy/charts/sample-external-issuer/templates/clusterrole.yaml @@ -0,0 +1,108 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: +{{ include "sample-external-issuer.labels" . | indent 4 }} + name: {{ include "sample-external-issuer.name" . }} +rules: +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch + +- apiGroups: + - sample-issuer.example.com + resources: + - sampleclusterissuers + verbs: + - get + - list + - watch +- apiGroups: + - sample-issuer.example.com + resources: + - sampleclusterissuers/status + verbs: + - patch +- apiGroups: + - sample-issuer.example.com + resources: + - sampleissuers + verbs: + - get + - list + - watch +- apiGroups: + - sample-issuer.example.com + resources: + - sampleissuers/status + verbs: + - patch +- apiGroups: + - cert-manager.io + resources: + - certificaterequests + verbs: + - get + - list + - watch +- apiGroups: + - cert-manager.io + resources: + - certificaterequests/status + verbs: + - patch + +- apiGroups: + - certificates.k8s.io + resources: + - certificatesigningrequests + verbs: + - get + - list + - watch +- apiGroups: + - certificates.k8s.io" + resources: + - certificatesigningrequests/status + verbs: + - patch +- apiGroups: + - certificates.k8s.io + resources: + - signers + verbs: + - sign + resourceNames: + - sampleclusterissuers.sample-issuer.example.com/* + +--- +{{- if .Values.app.approval.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: +{{ include "sample-external-issuer.labels" . | indent 4 }} + name: {{ include "sample-external-issuer.name" . }}:approval +rules: +- apiGroups: + - cert-manager.io + resourceNames: + - sampleclusterissuers.sample-issuer.example.com/* + - sampleissuers.sample-issuer.example.com/* + resources: + - signers + verbs: + - approve +{{- end }} diff --git a/deploy/charts/sample-external-issuer/templates/clusterrolebinding.yaml b/deploy/charts/sample-external-issuer/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..be7810d --- /dev/null +++ b/deploy/charts/sample-external-issuer/templates/clusterrolebinding.yaml @@ -0,0 +1,29 @@ +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: +{{ include "sample-external-issuer.labels" . | indent 4 }} + name: {{ include "sample-external-issuer.name" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "sample-external-issuer.name" . }} +subjects: +- kind: ServiceAccount + name: {{ include "sample-external-issuer.name" . }} + namespace: {{ .Release.Namespace }} +--- +{{- if .Values.app.approval.enabled }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: +{{ include "sample-external-issuer.labels" . | indent 4 }} + name: {{ include "sample-external-issuer.name" . }}:approval +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "sample-external-issuer.name" . }}:approval +subjects: +{{ .Values.app.approval.subjects | toYaml | indent 2}} +{{- end }} diff --git a/deploy/charts/sample-external-issuer/templates/crd-sample-issuer.example.com_sampleclusterissuers.yaml b/deploy/charts/sample-external-issuer/templates/crd-sample-issuer.example.com_sampleclusterissuers.yaml new file mode 100644 index 0000000..bc11271 --- /dev/null +++ b/deploy/charts/sample-external-issuer/templates/crd-sample-issuer.example.com_sampleclusterissuers.yaml @@ -0,0 +1,143 @@ +{{- if .Values.crds.enabled }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: "sampleclusterissuers.sample-issuer.example.com" + {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + {{- end }} + labels: + {{- include "sample-external-issuer.labels" . | nindent 4 }} +spec: + group: sample-issuer.example.com + names: + kind: SampleClusterIssuer + listKind: SampleClusterIssuerList + plural: sampleclusterissuers + singular: sampleclusterissuer + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Reason + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Message + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].lastTransitionTime + name: LastTransition + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].observedGeneration + name: ObservedGeneration + type: integer + - jsonPath: .metadata.generation + name: Generation + type: integer + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: SampleClusterIssuer is the Schema for the clusterissuers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IssuerSpec defines the desired state of SampleIssuer + properties: + authSecretName: + description: |- + A reference to a Secret in the same namespace as the referent. If the + referent is a SampleClusterIssuer, the reference instead refers to the resource + with the given name in the configured 'cluster resource namespace', which + is set as a flag on the controller component (and defaults to the + namespace that the controller runs in). + type: string + url: + description: |- + URL is the base URL for the endpoint of the signing service, + for example: "https://sample-signer.example.com/api". + type: string + required: + - authSecretName + - url + type: object + status: + properties: + conditions: + description: |- + List of status conditions to indicate the status of an Issuer. + Known condition types are `Ready`. + items: + description: IssuerCondition contains condition information for an Issuer. + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + format: date-time + type: string + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. + format: int64 + type: integer + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: Type of the condition, known values are (`Ready`). + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} \ No newline at end of file diff --git a/deploy/charts/sample-external-issuer/templates/crd-sample-issuer.example.com_sampleissuers.yaml b/deploy/charts/sample-external-issuer/templates/crd-sample-issuer.example.com_sampleissuers.yaml new file mode 100644 index 0000000..0d48742 --- /dev/null +++ b/deploy/charts/sample-external-issuer/templates/crd-sample-issuer.example.com_sampleissuers.yaml @@ -0,0 +1,143 @@ +{{- if .Values.crds.enabled }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: "sampleissuers.sample-issuer.example.com" + {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + {{- end }} + labels: + {{- include "sample-external-issuer.labels" . | nindent 4 }} +spec: + group: sample-issuer.example.com + names: + kind: SampleIssuer + listKind: SampleIssuerList + plural: sampleissuers + singular: sampleissuer + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Reason + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Message + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].lastTransitionTime + name: LastTransition + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].observedGeneration + name: ObservedGeneration + type: integer + - jsonPath: .metadata.generation + name: Generation + type: integer + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: SampleIssuer is the Schema for the issuers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IssuerSpec defines the desired state of SampleIssuer + properties: + authSecretName: + description: |- + A reference to a Secret in the same namespace as the referent. If the + referent is a SampleClusterIssuer, the reference instead refers to the resource + with the given name in the configured 'cluster resource namespace', which + is set as a flag on the controller component (and defaults to the + namespace that the controller runs in). + type: string + url: + description: |- + URL is the base URL for the endpoint of the signing service, + for example: "https://sample-signer.example.com/api". + type: string + required: + - authSecretName + - url + type: object + status: + properties: + conditions: + description: |- + List of status conditions to indicate the status of an Issuer. + Known condition types are `Ready`. + items: + description: IssuerCondition contains condition information for an Issuer. + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + format: date-time + type: string + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. + format: int64 + type: integer + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: Type of the condition, known values are (`Ready`). + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end }} \ No newline at end of file diff --git a/deploy/charts/sample-external-issuer/templates/deployment.yaml b/deploy/charts/sample-external-issuer/templates/deployment.yaml new file mode 100644 index 0000000..db5ed7e --- /dev/null +++ b/deploy/charts/sample-external-issuer/templates/deployment.yaml @@ -0,0 +1,64 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "sample-external-issuer.name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "sample-external-issuer.labels" . | indent 4 }} + {{- with .Values.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ include "sample-external-issuer.name" . }} + template: + metadata: + labels: + app: {{ include "sample-external-issuer.name" . }} + {{- include "sample-external-issuer.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "sample-external-issuer.name" . }} + {{- with .Values.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + containers: + - name: {{ include "sample-external-issuer.name" . }} + image: "{{ template "image" (tuple .Values.image $.Chart.AppVersion) }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - containerPort: {{ .Values.app.metrics.port }} + args: + - --leader-elect + - --zap-log-level={{.Values.app.logLevel}} + - --metrics-bind-address=:{{.Values.app.metrics.port}} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deploy/charts/sample-external-issuer/templates/role.yaml b/deploy/charts/sample-external-issuer/templates/role.yaml new file mode 100644 index 0000000..d96c833 --- /dev/null +++ b/deploy/charts/sample-external-issuer/templates/role.yaml @@ -0,0 +1,15 @@ +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "sample-external-issuer.name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "sample-external-issuer.labels" . | indent 4 }} +rules: +- apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create"] +- apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "update"] + resourceNames: ["54c549fd.sample-external-issuer"] diff --git a/deploy/charts/sample-external-issuer/templates/rolebinding.yaml b/deploy/charts/sample-external-issuer/templates/rolebinding.yaml new file mode 100644 index 0000000..85c91f2 --- /dev/null +++ b/deploy/charts/sample-external-issuer/templates/rolebinding.yaml @@ -0,0 +1,15 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "sample-external-issuer.name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "sample-external-issuer.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "sample-external-issuer.name" . }} +subjects: +- kind: ServiceAccount + name: {{ include "sample-external-issuer.name" . }} + namespace: {{ .Release.Namespace }} diff --git a/deploy/charts/sample-external-issuer/templates/serviceaccount.yaml b/deploy/charts/sample-external-issuer/templates/serviceaccount.yaml new file mode 100644 index 0000000..2a19611 --- /dev/null +++ b/deploy/charts/sample-external-issuer/templates/serviceaccount.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "sample-external-issuer.name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "sample-external-issuer.labels" . | indent 4 }} + annotations: +{{- toYaml .Values.serviceAccount.annotations | nindent 4 }} diff --git a/deploy/charts/sample-external-issuer/values.linter.exceptions b/deploy/charts/sample-external-issuer/values.linter.exceptions new file mode 100644 index 0000000..e69de29 diff --git a/deploy/charts/sample-external-issuer/values.schema.json b/deploy/charts/sample-external-issuer/values.schema.json new file mode 100644 index 0000000..1600efa --- /dev/null +++ b/deploy/charts/sample-external-issuer/values.schema.json @@ -0,0 +1,295 @@ +{ + "$defs": { + "helm-values": { + "additionalProperties": false, + "properties": { + "affinity": { + "$ref": "#/$defs/helm-values.affinity" + }, + "app": { + "$ref": "#/$defs/helm-values.app" + }, + "commonLabels": { + "$ref": "#/$defs/helm-values.commonLabels" + }, + "crds": { + "$ref": "#/$defs/helm-values.crds" + }, + "deploymentAnnotations": { + "$ref": "#/$defs/helm-values.deploymentAnnotations" + }, + "global": { + "$ref": "#/$defs/helm-values.global" + }, + "image": { + "$ref": "#/$defs/helm-values.image" + }, + "imagePullSecrets": { + "$ref": "#/$defs/helm-values.imagePullSecrets" + }, + "nameOverride": { + "$ref": "#/$defs/helm-values.nameOverride" + }, + "nodeSelector": { + "$ref": "#/$defs/helm-values.nodeSelector" + }, + "omitHelmLabels": { + "$ref": "#/$defs/helm-values.omitHelmLabels" + }, + "podAnnotations": { + "$ref": "#/$defs/helm-values.podAnnotations" + }, + "podLabels": { + "$ref": "#/$defs/helm-values.podLabels" + }, + "priorityClassName": { + "$ref": "#/$defs/helm-values.priorityClassName" + }, + "replicaCount": { + "$ref": "#/$defs/helm-values.replicaCount" + }, + "resources": { + "$ref": "#/$defs/helm-values.resources" + }, + "serviceAccount": { + "$ref": "#/$defs/helm-values.serviceAccount" + }, + "tolerations": { + "$ref": "#/$defs/helm-values.tolerations" + } + }, + "type": "object" + }, + "helm-values.affinity": { + "default": {}, + "description": "Kubernetes affinity: constraints for pod assignment\nFor example:\nnodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", + "type": "object" + }, + "helm-values.app": { + "additionalProperties": false, + "properties": { + "approval": { + "$ref": "#/$defs/helm-values.app.approval" + }, + "logLevel": { + "$ref": "#/$defs/helm-values.app.logLevel" + }, + "metrics": { + "$ref": "#/$defs/helm-values.app.metrics" + } + }, + "type": "object" + }, + "helm-values.app.approval": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.app.approval.enabled" + }, + "subjects": { + "$ref": "#/$defs/helm-values.app.approval.subjects" + } + }, + "type": "object" + }, + "helm-values.app.approval.enabled": { + "default": true, + "description": "enabled determines whether the ClusterRole and ClusterRoleBinding for approval is created. You will want to disable this if you are managing approval RBAC elsewhere from this chart, for example if you create them separately for all installed issuers.", + "type": "boolean" + }, + "helm-values.app.approval.subjects": { + "items": { + "$ref": "#/$defs/helm-values.app.approval.subjects[0]" + }, + "type": "array" + }, + "helm-values.app.approval.subjects[0]": { + "additionalProperties": false, + "properties": { + "kind": { + "$ref": "#/$defs/helm-values.app.approval.subjects[0].kind" + }, + "name": { + "$ref": "#/$defs/helm-values.app.approval.subjects[0].name" + }, + "namespace": { + "$ref": "#/$defs/helm-values.app.approval.subjects[0].namespace" + } + }, + "type": "object" + }, + "helm-values.app.approval.subjects[0].kind": { + "default": "ServiceAccount", + "type": "string" + }, + "helm-values.app.approval.subjects[0].name": { + "default": "cert-manager", + "type": "string" + }, + "helm-values.app.approval.subjects[0].namespace": { + "default": "cert-manager", + "type": "string" + }, + "helm-values.app.logLevel": { + "default": 1, + "description": "Verbosity of sample-external-issuer logging.", + "type": "number" + }, + "helm-values.app.metrics": { + "additionalProperties": false, + "properties": { + "port": { + "$ref": "#/$defs/helm-values.app.metrics.port" + } + }, + "type": "object" + }, + "helm-values.app.metrics.port": { + "default": 9402, + "description": "Port for exposing Prometheus metrics on 0.0.0.0 on path '/metrics'.", + "type": "number" + }, + "helm-values.commonLabels": { + "default": {}, + "description": "Labels to apply to all resources", + "type": "object" + }, + "helm-values.crds": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.crds.enabled" + }, + "keep": { + "$ref": "#/$defs/helm-values.crds.keep" + } + }, + "type": "object" + }, + "helm-values.crds.enabled": { + "default": true, + "description": "This option decides if the CRDs should be installed as part of the Helm installation.", + "type": "boolean" + }, + "helm-values.crds.keep": { + "default": true, + "description": "This option makes it so that the \"helm.sh/resource-policy\": keep annotation is added to the CRD. This will prevent Helm from uninstalling the CRD when the Helm release is uninstalled. WARNING: when the CRDs are removed, all sample-external-issuer custom resources\n(ClusterIssuer, Issuer, ...) will be removed too by the garbage collector.", + "type": "boolean" + }, + "helm-values.deploymentAnnotations": { + "default": {}, + "description": "Optional additional annotations to add to the sample-external-issuer Deployment", + "type": "object" + }, + "helm-values.global": { + "description": "Global values shared across all (sub)charts" + }, + "helm-values.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.image.tag" + } + }, + "type": "object" + }, + "helm-values.image.digest": { + "description": "Target image digest. Will override any tag if set. for example:\ndigest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20" + }, + "helm-values.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.image.registry": { + "description": "Target image registry. Will be prepended to the target image repositry if set." + }, + "helm-values.image.repository": { + "default": "quay.io/jetstack/sample-external-issuer", + "description": "Target image repository.", + "type": "string" + }, + "helm-values.image.tag": { + "description": "Target image version tag. Defaults to the chart's appVersion." + }, + "helm-values.imagePullSecrets": { + "default": [], + "description": "Optional secrets used for pulling the sample-external-issuer container image.", + "items": {}, + "type": "array" + }, + "helm-values.nameOverride": { + "description": "Override the \"sample-external-issuer.name\" value.", + "type": "string" + }, + "helm-values.nodeSelector": { + "default": {}, + "description": "Kubernetes node selector: node labels for pod assignment\nFor example:\nkubernetes.io/os: linux", + "type": "object" + }, + "helm-values.omitHelmLabels": { + "default": false, + "description": "Omit Helm-specific labels. This is useful when generating a static manifest with `helm template`.", + "type": "boolean" + }, + "helm-values.podAnnotations": { + "default": {}, + "description": "Optional additional annotations to add to the sample-external-issuer Pods", + "type": "object" + }, + "helm-values.podLabels": { + "default": {}, + "description": "Optional additional labels to add to the sample-external-issuer Pods", + "type": "object" + }, + "helm-values.priorityClassName": { + "default": "", + "description": "Optional priority class to be used for the sample-external-issuer pods.", + "type": "string" + }, + "helm-values.replicaCount": { + "default": 1, + "description": "Number of replicas of sample-external-issuer to run.", + "type": "number" + }, + "helm-values.resources": { + "default": {}, + "description": "Kubernetes pod resource requests/limits for sample-external-issuer.\nFor example:\nlimits:\n cpu: 100m\n memory: 128Mi\nrequests:\n cpu: 100m\n memory: 128Mi", + "type": "object" + }, + "helm-values.serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.serviceAccount.annotations" + } + }, + "type": "object" + }, + "helm-values.serviceAccount.annotations": { + "default": {}, + "description": "Optional annotations to add to the service account", + "type": "object" + }, + "helm-values.tolerations": { + "default": [], + "description": "Kubernetes pod tolerations for sample-external-issuer\nFor example:\n - operator: \"Exists\"", + "items": {}, + "type": "array" + } + }, + "$ref": "#/$defs/helm-values", + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/deploy/charts/sample-external-issuer/values.yaml b/deploy/charts/sample-external-issuer/values.yaml new file mode 100644 index 0000000..ef1699e --- /dev/null +++ b/deploy/charts/sample-external-issuer/values.yaml @@ -0,0 +1,124 @@ +crds: + # This option decides if the CRDs should be installed + # as part of the Helm installation. + enabled: true + + # This option makes it so that the "helm.sh/resource-policy": keep + # annotation is added to the CRD. This will prevent Helm from uninstalling + # the CRD when the Helm release is uninstalled. + # WARNING: when the CRDs are removed, all sample-external-issuer custom resources + # (ClusterIssuer, Issuer, ...) will be removed too by the garbage collector. + keep: true + +# Number of replicas of sample-external-issuer to run. +replicaCount: 1 + +image: + # Target image repository. + repository: quay.io/jetstack/sample-external-issuer + # Target image registry. Will be prepended to the target image repositry if set. + registry: + + # Target image version tag. Defaults to the chart's appVersion. + tag: + + # Target image digest. Will override any tag if set. + # for example: + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + digest: + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + +# Optional secrets used for pulling the sample-external-issuer container image. +imagePullSecrets: [] + +# Labels to apply to all resources +commonLabels: {} + +serviceAccount: + # Optional annotations to add to the service account + annotations: {} + +app: + # Verbosity of sample-external-issuer logging. + logLevel: 1 # 1-5 + + # Handle RBAC permissions for approving Sample External Issuer + # CertificateRequests. + approval: + # enabled determines whether the ClusterRole and ClusterRoleBinding for + # approval is created. You will want to disable this if you are managing + # approval RBAC elsewhere from this chart, for example if you create them + # separately for all installed issuers. + enabled: true + + # subjects is the subject that the approval RBAC permissions will be + # bound to. Here we are binding them to cert-manager's ServiceAccount so + # that the default approve all approver has the permissions to do so. You + # will want to change this subject to approver-policy's ServiceAccount if + # using that project (recommended). + # https://cert-manager.io/docs/projects/approver-policy + # name: cert-manager-approver-policy + # namespace: cert-manager + subjects: + - kind: ServiceAccount + name: cert-manager + namespace: cert-manager + + # metrics controls exposing sample-external-issuer metrics. + metrics: + # Port for exposing Prometheus metrics on 0.0.0.0 on path '/metrics'. + port: 9402 + +# Optional additional annotations to add to the sample-external-issuer Deployment +deploymentAnnotations: {} + +# Optional additional annotations to add to the sample-external-issuer Pods +podAnnotations: {} + +# Optional additional labels to add to the sample-external-issuer Pods +podLabels: {} + +# Kubernetes pod resource requests/limits for sample-external-issuer. +# For example: +# limits: +# cpu: 100m +# memory: 128Mi +# requests: +# cpu: 100m +# memory: 128Mi +resources: {} + +# Kubernetes node selector: node labels for pod assignment +# For example: +# kubernetes.io/os: linux +nodeSelector: {} + +# Kubernetes affinity: constraints for pod assignment +# For example: +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: foo.bar.com/role +# operator: In +# values: +# - master +affinity: {} + +# Kubernetes pod tolerations for sample-external-issuer +# For example: +# - operator: "Exists" +tolerations: [] + +# Optional priority class to be used for the sample-external-issuer pods. +priorityClassName: "" + +# Override the "sample-external-issuer.name" value. +# +docs:property +# nameOverride: "my-sample-external-issuer" + +# Omit Helm-specific labels. This is useful when generating a static manifest +# with `helm template`. +omitHelmLabels: false \ No newline at end of file diff --git a/docs/api/api.md b/docs/api/api.md new file mode 100644 index 0000000..533392e --- /dev/null +++ b/docs/api/api.md @@ -0,0 +1,294 @@ + + +# v1alpha1 + +```go +import "github.com/cert-manager/sample-external-issuer/api/v1alpha1" +``` + +Package v1alpha1 contains API Schema definitions for the sample\-issuer v1alpha1 API group \+kubebuilder:object:generate=true \+groupName=sample\-issuer.example.com + +## Index + +- [Variables](<#variables>) +- [type IssuerSpec](<#IssuerSpec>) + - [func \(in \*IssuerSpec\) DeepCopy\(\) \*IssuerSpec](<#IssuerSpec.DeepCopy>) + - [func \(in \*IssuerSpec\) DeepCopyInto\(out \*IssuerSpec\)](<#IssuerSpec.DeepCopyInto>) +- [type SampleClusterIssuer](<#SampleClusterIssuer>) + - [func \(in \*SampleClusterIssuer\) DeepCopy\(\) \*SampleClusterIssuer](<#SampleClusterIssuer.DeepCopy>) + - [func \(in \*SampleClusterIssuer\) DeepCopyInto\(out \*SampleClusterIssuer\)](<#SampleClusterIssuer.DeepCopyInto>) + - [func \(in \*SampleClusterIssuer\) DeepCopyObject\(\) runtime.Object](<#SampleClusterIssuer.DeepCopyObject>) + - [func \(vi \*SampleClusterIssuer\) GetIssuerTypeIdentifier\(\) string](<#SampleClusterIssuer.GetIssuerTypeIdentifier>) + - [func \(vi \*SampleClusterIssuer\) GetStatus\(\) \*v1alpha1.IssuerStatus](<#SampleClusterIssuer.GetStatus>) +- [type SampleClusterIssuerList](<#SampleClusterIssuerList>) + - [func \(in \*SampleClusterIssuerList\) DeepCopy\(\) \*SampleClusterIssuerList](<#SampleClusterIssuerList.DeepCopy>) + - [func \(in \*SampleClusterIssuerList\) DeepCopyInto\(out \*SampleClusterIssuerList\)](<#SampleClusterIssuerList.DeepCopyInto>) + - [func \(in \*SampleClusterIssuerList\) DeepCopyObject\(\) runtime.Object](<#SampleClusterIssuerList.DeepCopyObject>) +- [type SampleIssuer](<#SampleIssuer>) + - [func \(in \*SampleIssuer\) DeepCopy\(\) \*SampleIssuer](<#SampleIssuer.DeepCopy>) + - [func \(in \*SampleIssuer\) DeepCopyInto\(out \*SampleIssuer\)](<#SampleIssuer.DeepCopyInto>) + - [func \(in \*SampleIssuer\) DeepCopyObject\(\) runtime.Object](<#SampleIssuer.DeepCopyObject>) + - [func \(vi \*SampleIssuer\) GetIssuerTypeIdentifier\(\) string](<#SampleIssuer.GetIssuerTypeIdentifier>) + - [func \(vi \*SampleIssuer\) GetStatus\(\) \*v1alpha1.IssuerStatus](<#SampleIssuer.GetStatus>) +- [type SampleIssuerList](<#SampleIssuerList>) + - [func \(in \*SampleIssuerList\) DeepCopy\(\) \*SampleIssuerList](<#SampleIssuerList.DeepCopy>) + - [func \(in \*SampleIssuerList\) DeepCopyInto\(out \*SampleIssuerList\)](<#SampleIssuerList.DeepCopyInto>) + - [func \(in \*SampleIssuerList\) DeepCopyObject\(\) runtime.Object](<#SampleIssuerList.DeepCopyObject>) + + +## Variables + + + +```go +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "sample-issuer.example.com", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) +``` + + +## type [IssuerSpec]() + +IssuerSpec defines the desired state of SampleIssuer + +```go +type IssuerSpec struct { + // URL is the base URL for the endpoint of the signing service, + // for example: "https://sample-signer.example.com/api". + URL string `json:"url"` + + // A reference to a Secret in the same namespace as the referent. If the + // referent is a SampleClusterIssuer, the reference instead refers to the resource + // with the given name in the configured 'cluster resource namespace', which + // is set as a flag on the controller component (and defaults to the + // namespace that the controller runs in). + AuthSecretName string `json:"authSecretName"` +} +``` + + +### func \(\*IssuerSpec\) [DeepCopy]() + +```go +func (in *IssuerSpec) DeepCopy() *IssuerSpec +``` + +DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IssuerSpec. + + +### func \(\*IssuerSpec\) [DeepCopyInto]() + +```go +func (in *IssuerSpec) DeepCopyInto(out *IssuerSpec) +``` + +DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non\-nil. + + +## type [SampleClusterIssuer]() + +SampleClusterIssuer is the Schema for the clusterissuers API + +```go +type SampleClusterIssuer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec IssuerSpec `json:"spec,omitempty"` + Status v1alpha1.IssuerStatus `json:"status,omitempty"` +} +``` + + +### func \(\*SampleClusterIssuer\) [DeepCopy]() + +```go +func (in *SampleClusterIssuer) DeepCopy() *SampleClusterIssuer +``` + +DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SampleClusterIssuer. + + +### func \(\*SampleClusterIssuer\) [DeepCopyInto]() + +```go +func (in *SampleClusterIssuer) DeepCopyInto(out *SampleClusterIssuer) +``` + +DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non\-nil. + + +### func \(\*SampleClusterIssuer\) [DeepCopyObject]() + +```go +func (in *SampleClusterIssuer) DeepCopyObject() runtime.Object +``` + +DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. + + +### func \(\*SampleClusterIssuer\) [GetIssuerTypeIdentifier]() + +```go +func (vi *SampleClusterIssuer) GetIssuerTypeIdentifier() string +``` + +GetIssuerTypeIdentifier returns a string that uniquely identifies the issuer type. This should be a constant across all instances of this issuer type. This string is used as a prefix when determining the issuer type for a Kubernetes CertificateSigningRequest resource based on the issuerName field. The value should be formatted as follows: "\.\". For example, the value "simpleclusterissuers.issuer.cert\-manager.io" will match all CSRs with an issuerName set to eg. "simpleclusterissuers.issuer.cert\-manager.io/issuer1". + + +### func \(\*SampleClusterIssuer\) [GetStatus]() + +```go +func (vi *SampleClusterIssuer) GetStatus() *v1alpha1.IssuerStatus +``` + + + + +## type [SampleClusterIssuerList]() + +SampleClusterIssuerList contains a list of ClusterIssuer + +```go +type SampleClusterIssuerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []SampleClusterIssuer `json:"items"` +} +``` + + +### func \(\*SampleClusterIssuerList\) [DeepCopy]() + +```go +func (in *SampleClusterIssuerList) DeepCopy() *SampleClusterIssuerList +``` + +DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SampleClusterIssuerList. + + +### func \(\*SampleClusterIssuerList\) [DeepCopyInto]() + +```go +func (in *SampleClusterIssuerList) DeepCopyInto(out *SampleClusterIssuerList) +``` + +DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non\-nil. + + +### func \(\*SampleClusterIssuerList\) [DeepCopyObject]() + +```go +func (in *SampleClusterIssuerList) DeepCopyObject() runtime.Object +``` + +DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. + + +## type [SampleIssuer]() + +SampleIssuer is the Schema for the issuers API + +```go +type SampleIssuer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec IssuerSpec `json:"spec,omitempty"` + Status v1alpha1.IssuerStatus `json:"status,omitempty"` +} +``` + + +### func \(\*SampleIssuer\) [DeepCopy]() + +```go +func (in *SampleIssuer) DeepCopy() *SampleIssuer +``` + +DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SampleIssuer. + + +### func \(\*SampleIssuer\) [DeepCopyInto]() + +```go +func (in *SampleIssuer) DeepCopyInto(out *SampleIssuer) +``` + +DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non\-nil. + + +### func \(\*SampleIssuer\) [DeepCopyObject]() + +```go +func (in *SampleIssuer) DeepCopyObject() runtime.Object +``` + +DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. + + +### func \(\*SampleIssuer\) [GetIssuerTypeIdentifier]() + +```go +func (vi *SampleIssuer) GetIssuerTypeIdentifier() string +``` + +GetIssuerTypeIdentifier returns a string that uniquely identifies the issuer type. This should be a constant across all instances of this issuer type. This string is used as a prefix when determining the issuer type for a Kubernetes CertificateSigningRequest resource based on the issuerName field. The value should be formatted as follows: "\.\". For example, the value "simpleclusterissuers.issuer.cert\-manager.io" will match all CSRs with an issuerName set to eg. "simpleclusterissuers.issuer.cert\-manager.io/issuer1". + + +### func \(\*SampleIssuer\) [GetStatus]() + +```go +func (vi *SampleIssuer) GetStatus() *v1alpha1.IssuerStatus +``` + + + + +## type [SampleIssuerList]() + +SampleIssuerList contains a list of Issuer + +```go +type SampleIssuerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []SampleIssuer `json:"items"` +} +``` + + +### func \(\*SampleIssuerList\) [DeepCopy]() + +```go +func (in *SampleIssuerList) DeepCopy() *SampleIssuerList +``` + +DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SampleIssuerList. + + +### func \(\*SampleIssuerList\) [DeepCopyInto]() + +```go +func (in *SampleIssuerList) DeepCopyInto(out *SampleIssuerList) +``` + +DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non\-nil. + + +### func \(\*SampleIssuerList\) [DeepCopyObject]() + +```go +func (in *SampleIssuerList) DeepCopyObject() runtime.Object +``` + +DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. + +Generated by [gomarkdoc]() diff --git a/config/samples/certificate_clusterissuer.yaml b/examples/certificate_clusterissuer.yaml similarity index 100% rename from config/samples/certificate_clusterissuer.yaml rename to examples/certificate_clusterissuer.yaml diff --git a/config/samples/certificate_issuer.yaml b/examples/certificate_issuer.yaml similarity index 100% rename from config/samples/certificate_issuer.yaml rename to examples/certificate_issuer.yaml diff --git a/config/samples/certificaterequest_clusterissuer.yaml b/examples/certificaterequest_clusterissuer.yaml similarity index 100% rename from config/samples/certificaterequest_clusterissuer.yaml rename to examples/certificaterequest_clusterissuer.yaml diff --git a/config/samples/certificaterequest_issuer.yaml b/examples/certificaterequest_issuer.yaml similarity index 100% rename from config/samples/certificaterequest_issuer.yaml rename to examples/certificaterequest_issuer.yaml diff --git a/config/samples/sample-issuer_v1alpha1_clusterissuer.yaml b/examples/sample-issuer_v1alpha1_clusterissuer.yaml similarity index 100% rename from config/samples/sample-issuer_v1alpha1_clusterissuer.yaml rename to examples/sample-issuer_v1alpha1_clusterissuer.yaml diff --git a/config/samples/sample-issuer_v1alpha1_issuer.yaml b/examples/sample-issuer_v1alpha1_issuer.yaml similarity index 100% rename from config/samples/sample-issuer_v1alpha1_issuer.yaml rename to examples/sample-issuer_v1alpha1_issuer.yaml diff --git a/config/samples/secret_clusterissuer.yaml b/examples/secret_clusterissuer.yaml similarity index 100% rename from config/samples/secret_clusterissuer.yaml rename to examples/secret_clusterissuer.yaml diff --git a/config/samples/secret_issuer.yaml b/examples/secret_issuer.yaml similarity index 100% rename from config/samples/secret_issuer.yaml rename to examples/secret_issuer.yaml diff --git a/internal/controllers/signer.go b/internal/controllers/signer.go index e4dce11..178dcd5 100644 --- a/internal/controllers/signer.go +++ b/internal/controllers/signer.go @@ -40,11 +40,8 @@ var ( errHealthCheckerBuilder = errors.New("failed to build the healthchecker") errHealthCheckerCheck = errors.New("healthcheck failed") - errIssuerRef = errors.New("error interpreting issuerRef") - errGetIssuer = errors.New("error getting issuer") - errIssuerNotReady = errors.New("issuer is not ready") - errSignerBuilder = errors.New("failed to build the signer") - errSignerSign = errors.New("failed to sign") + errSignerBuilder = errors.New("failed to build the signer") + errSignerSign = errors.New("failed to sign") ) type HealthChecker interface { diff --git a/klone.yaml b/klone.yaml new file mode 100644 index 0000000..ce3480a --- /dev/null +++ b/klone.yaml @@ -0,0 +1,74 @@ +# 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: api-docs + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/api-docs + - folder_name: cert-manager + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/cert-manager + - folder_name: controller-gen + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/controller-gen + - folder_name: generate-verify + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/generate-verify + - folder_name: go + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/go + - folder_name: helm + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/helm + - folder_name: help + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/help + - folder_name: kind + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/kind + - folder_name: klone + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/klone + - folder_name: oci-build + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/oci-build + - folder_name: oci-publish + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/oci-publish + - folder_name: repository-base + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/repository-base + - folder_name: tools + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: 17a429b9edf19f9fce5ee6ba22fb9e946e83f6fe + repo_path: modules/tools diff --git a/main.go b/main.go index e3ff1f7..3e72800 100644 --- a/main.go +++ b/main.go @@ -23,15 +23,11 @@ import ( "fmt" "os" - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) - // to ensure that exec-entrypoint and run can make use of them. - _ "k8s.io/client-go/plugin/pkg/client/auth" - "k8s.io/klog/v2" - cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -42,55 +38,70 @@ import ( "github.com/cert-manager/sample-external-issuer/internal/controllers" "github.com/cert-manager/sample-external-issuer/internal/signer" "github.com/cert-manager/sample-external-issuer/internal/version" - //+kubebuilder:scaffold:imports + + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) + // to ensure that exec-entrypoint and run can make use of them. + _ "k8s.io/client-go/plugin/pkg/client/auth" ) const inClusterNamespacePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" +type options struct { + metricsAddr string + probeAddr string + enableLeaderElection bool + clusterResourceNamespace string + printVersion bool + disableApprovedCheck bool +} + func main() { - var metricsAddr string - var probeAddr string - var enableLeaderElection bool - var clusterResourceNamespace string - var printVersion bool - var disableApprovedCheck bool - - flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") - flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") - flag.BoolVar(&enableLeaderElection, "leader-elect", false, + opts := options{} + flag.StringVar(&opts.metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") + flag.StringVar(&opts.probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.BoolVar(&opts.enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") - flag.StringVar(&clusterResourceNamespace, "cluster-resource-namespace", "", "The namespace for secrets in which cluster-scoped resources are found.") - flag.BoolVar(&printVersion, "version", false, "Print version to stdout and exit") - flag.BoolVar(&disableApprovedCheck, "disable-approved-check", false, + flag.StringVar(&opts.clusterResourceNamespace, "cluster-resource-namespace", "", "The namespace for secrets in which cluster-scoped resources are found.") + flag.BoolVar(&opts.printVersion, "version", false, "Print version to stdout and exit") + flag.BoolVar(&opts.disableApprovedCheck, "disable-approved-check", false, "Disables waiting for CertificateRequests to have an approved condition before signing.") // Options for configuring logging - opts := zap.Options{} - opts.BindFlags(flag.CommandLine) + loggerOpts := zap.Options{} + loggerOpts.BindFlags(flag.CommandLine) flag.Parse() - logr := zap.New(zap.UseFlagOptions(&opts)) + logr := zap.New(zap.UseFlagOptions(&loggerOpts)) klog.SetLogger(logr) ctrl.SetLogger(logr) logr.Info("Version", "version", version.Version) - if printVersion { + if opts.printVersion { return } + if err := Main(logr, opts); err != nil { + logr.Error(err, "error running manager") + os.Exit(1) + } +} + +func Main( + logr klog.Logger, + opts options, +) error { setupLog := logr.WithName("setup") - if err := getInClusterNamespace(&clusterResourceNamespace); err != nil { + if err := getInClusterNamespace(&opts.clusterResourceNamespace); err != nil { if errors.Is(err, errNotInCluster) { - setupLog.Error(err, "please supply --cluster-resource-namespace") + return fmt.Errorf("please supply --cluster-resource-namespace: %w", err) } else { - setupLog.Error(err, "unexpected error while getting in-cluster Namespace") + return fmt.Errorf("unexpected error while getting in-cluster Namespace: %w", err) } - os.Exit(1) } scheme := runtime.NewScheme() @@ -102,22 +113,22 @@ func main() { setupLog.Info( "starting", "version", version.Version, - "enable-leader-election", enableLeaderElection, - "metrics-addr", metricsAddr, - "cluster-resource-namespace", clusterResourceNamespace, + "enable-leader-election", opts.enableLeaderElection, + "metrics-addr", opts.metricsAddr, + "cluster-resource-namespace", opts.clusterResourceNamespace, ) mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, Metrics: server.Options{ - BindAddress: metricsAddr, + BindAddress: opts.metricsAddr, }, WebhookServer: webhook.NewServer(webhook.Options{ Port: 9443, }), - HealthProbeBindAddress: probeAddr, - LeaderElection: enableLeaderElection, - LeaderElectionID: "54c549fd.example.com", + HealthProbeBindAddress: opts.probeAddr, + LeaderElection: opts.enableLeaderElection, + LeaderElectionID: "54c549fd.sample-external-issuer", // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily // when the Manager ends. This requires the binary to immediately end when the // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly @@ -131,8 +142,7 @@ func main() { LeaderElectionReleaseOnCancel: true, }) if err != nil { - setupLog.Error(err, "unable to start manager") - os.Exit(1) + return fmt.Errorf("unable to start manager: %w", err) } ctx, cancel := context.WithCancel(ctrl.SetupSignalHandler()) @@ -141,28 +151,26 @@ func main() { if err = (&controllers.Issuer{ HealthCheckerBuilder: signer.ExampleHealthCheckerFromIssuerAndSecretData, SignerBuilder: signer.ExampleSignerFromIssuerAndSecretData, - ClusterResourceNamespace: clusterResourceNamespace, + ClusterResourceNamespace: opts.clusterResourceNamespace, }).SetupWithManager(ctx, mgr); err != nil { - setupLog.Error(err, "unable to create Signer controllers") - os.Exit(1) + return fmt.Errorf("unable to create Signer controllers: %w", err) } // +kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { - setupLog.Error(err, "unable to set up health check") - os.Exit(1) + return fmt.Errorf("unable to set up health check: %w", err) } if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { - setupLog.Error(err, "unable to set up ready check") - os.Exit(1) + return fmt.Errorf("unable to set up ready check: %w", err) } setupLog.Info("starting manager") if err := mgr.Start(ctx); err != nil { - setupLog.Error(err, "problem running manager") - os.Exit(1) + return fmt.Errorf("problem running manager: %w", err) } + + return nil } var errNotInCluster = errors.New("not running in-cluster") diff --git a/make/00_mod.mk b/make/00_mod.mk new file mode 100644 index 0000000..4d6c8aa --- /dev/null +++ b/make/00_mod.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. + +go_header_file := $(CURDIR)/make/config/boilerplate.go.txt + +repo_name := github.com/cert-manager/sample-external-issuer + +kind_cluster_name := sample-external-issuer +kind_cluster_config := $(bin_dir)/scratch/kind_cluster.yaml + +build_names := manager + +go_manager_main_dir := . +go_manager_mod_dir := . +go_manager_ldflags := -X $(repo_name)/pkg/internal/version.Version=$(VERSION) +oci_manager_base_image_flavor := static +oci_manager_image_name := ghcr.io/cert-manager/sample-external-issuer/controller +oci_manager_image_tag := $(VERSION) +oci_manager_image_name_development := cert-manager.local/sample-external-issuer + +deploy_name := sample-external-issuer +deploy_namespace := sample-external-issuer-system + +api_docs_outfile := docs/api/api.md +api_docs_package := $(repo_name)/api/v1alpha1 +api_docs_branch := main + +helm_chart_source_dir := deploy/charts/sample-external-issuer +helm_chart_name := sample-external-issuer +helm_chart_version := $(VERSION) +helm_labels_template_name := sample-external-issuer.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 diff --git a/make/02_mod.mk b/make/02_mod.mk new file mode 100644 index 0000000..ea1f1e8 --- /dev/null +++ b/make/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. + +$(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-smoke.mk +include make/test-unit.mk + +.PHONY: release +## Publish all release artifacts (image + helm chart) +## @category [shared] Release +release: helm-chart | $(NEEDS_CRANE) + $(eval helm_templated_yaml := $(bin_dir)/scratch/$(helm_chart_name)-$(helm_chart_version).yaml) + $(HELM) template sample-external-issuer "$(helm_chart_archive)" --set omitHelmLabels=true > $(helm_templated_yaml) + + $(MAKE) oci-push-manager + + @echo "RELEASE_OCI_MANAGER_IMAGE=$(oci_manager_image_name)" >> "$(GITHUB_OUTPUT)" + @echo "RELEASE_OCI_MANAGER_TAG=$(oci_manager_image_tag)" >> "$(GITHUB_OUTPUT)" + @echo "RELEASE_HELM_CHART_NAME=$(helm_chart_name)" >> "$(GITHUB_OUTPUT)" + @echo "RELEASE_HELM_CHART_VERSION=$(helm_chart_version)" >> "$(GITHUB_OUTPUT)" + @echo "RELEASE_HELM_CHART_TAR=$(helm_chart_archive)" >> "$(GITHUB_OUTPUT)" + @echo "RELEASE_YAML=$(helm_templated_yaml)" >> "$(GITHUB_OUTPUT)" + + @echo "Release complete!" diff --git a/make/_shared/api-docs/01_mod.mk b/make/_shared/api-docs/01_mod.mk new file mode 100644 index 0000000..e395aad --- /dev/null +++ b/make/_shared/api-docs/01_mod.mk @@ -0,0 +1,55 @@ +# 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 repo_name +$(error repo_name is not set) +endif + +ifndef api_docs_outfile +$(error api_docs_outfile is not set) +endif + +ifndef api_docs_package +$(error api_docs_package is not set) +endif + +ifndef api_docs_branch +$(error api_docs_branch is not set) +endif + +########################################## + +GOMARKDOC_FLAGS=--format github --repository.url "https://$(repo_name)" --repository.default-branch $(api_docs_branch) --repository.path / + +.PHONY: generate-api-docs +## Generate API docs for the API types. +## @category [shared] Generate/ Verify +generate-api-docs: | $(NEEDS_GOMARKDOC) + $(GOMARKDOC) \ + $(GOMARKDOC_FLAGS) \ + --output $(api_docs_outfile) \ + $(api_docs_package) + +.PHONY: verify-generate-api-docs +## Verify that the API docs are up to date. +## @category [shared] Generate/ Verify +verify-generate-api-docs: | $(NEEDS_GOMARKDOC) + $(GOMARKDOC) \ + --check \ + $(GOMARKDOC_FLAGS) \ + --output $(api_docs_outfile) \ + $(api_docs_package) \ + || (echo "docs are not up to date; run 'make generate' and commit the result" && exit 1) + +shared_generate_targets += generate-api-docs diff --git a/make/_shared/cert-manager/00_mod.mk b/make/_shared/cert-manager/00_mod.mk new file mode 100644 index 0000000..037d8ac --- /dev/null +++ b/make/_shared/cert-manager/00_mod.mk @@ -0,0 +1,28 @@ +# 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. + +images_amd64 ?= +images_arm64 ?= + +cert_manager_version := v1.16.0 + +images_amd64 += quay.io/jetstack/cert-manager-controller:$(cert_manager_version)@sha256:b45df0d537a7a8ef2d968bd2621547dd43d93230a5b12a89cf496a081db2edd3 +images_amd64 += quay.io/jetstack/cert-manager-cainjector:$(cert_manager_version)@sha256:13d60b82759fec353c5c35280b902bf3f3c8680b471501792b62a7db2ef706e1 +images_amd64 += quay.io/jetstack/cert-manager-webhook:$(cert_manager_version)@sha256:a98cc73669ed5e3220a064732649c541b4d2c272327271f63f9129a6f234ca63 +images_amd64 += quay.io/jetstack/cert-manager-startupapicheck:$(cert_manager_version)@sha256:42b5c24cdf9fb68ccc4de4854e0336ac9e05bfacbd4c6ad9b85787db2e73c646 + +images_arm64 += quay.io/jetstack/cert-manager-controller:$(cert_manager_version)@sha256:af089c67364f0ed282cb11b3994bea7bfa485d75a7b019c2c532ea118455f49b +images_arm64 += quay.io/jetstack/cert-manager-cainjector:$(cert_manager_version)@sha256:53a5206399898f2f754d45943211a38bdd82a23beb7f3ce33c30950117c95ebc +images_arm64 += quay.io/jetstack/cert-manager-webhook:$(cert_manager_version)@sha256:f8f633a1fe9089375e1c0debd5e7b1672ac740f2294453a37863a3d0b6d0a1cc +images_arm64 += quay.io/jetstack/cert-manager-startupapicheck:$(cert_manager_version)@sha256:9ab84f036989c71d531882acb3549799265e7f04b5fb719f4fd1bce6f9e2c9b0 diff --git a/make/_shared/cert-manager/01_mod.mk b/make/_shared/cert-manager/01_mod.mk new file mode 100644 index 0000000..f1af5da --- /dev/null +++ b/make/_shared/cert-manager/01_mod.mk @@ -0,0 +1,17 @@ +# 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. + +cert_manager_crds := $(bin_dir)/scratch/cert-manager-$(cert_manager_version).yaml +$(cert_manager_crds): | $(bin_dir)/scratch + curl -sSLo $@ https://github.com/cert-manager/cert-manager/releases/download/$(cert_manager_version)/cert-manager.crds.yaml diff --git a/make/_shared/controller-gen/01_mod.mk b/make/_shared/controller-gen/01_mod.mk new file mode 100644 index 0000000..7dedf6b --- /dev/null +++ b/make/_shared/controller-gen/01_mod.mk @@ -0,0 +1,34 @@ +# 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 go_header_file +$(error go_header_file is not set) +endif + +################ +# Add targets # +################ + +.PHONY: generate-deepcopy +## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. +## @category [shared] Generate/ Verify +generate-deepcopy: | $(NEEDS_CONTROLLER-GEN) + $(eval directories := $(shell ls -d */ | grep -v '_bin' | grep -v 'make')) + $(CONTROLLER-GEN) object:headerFile=$(go_header_file) $(directories:%=paths=./%...) + +shared_generate_targets += generate-deepcopy diff --git a/make/_shared/generate-verify/00_mod.mk b/make/_shared/generate-verify/00_mod.mk new file mode 100644 index 0000000..4355513 --- /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 0000000..f067729 --- /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 0000000..83109aa --- /dev/null +++ b/make/_shared/generate-verify/util/verify.sh @@ -0,0 +1,63 @@ +#!/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 + +rsync -aEq "${projectdir}/." "${tmp}" --exclude "_bin/" +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 0000000..a40c8de --- /dev/null +++ b/make/_shared/go/.golangci.override.yaml @@ -0,0 +1,68 @@ +linters: + # Explicitly define all enabled linters + disable-all: true + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - contextcheck + - copyloopvar + - decorder + - dogsled + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - exhaustive + - forbidigo + - gci + - ginkgolinter + - gocheckcompilerdirectives + - gochecksumtype + - gocritic + - gofmt + - goheader + - goprintffuncname + - gosec + - gosimple + - gosmopolitan + - govet + - grouper + - importas + - ineffassign + - interfacebloat + - loggercheck + - makezero + - mirror + - misspell + - musttag + - nakedret + - nilerr + - nilnil + - noctx + - nosprintfhostport + - predeclared + - promlinter + - protogetter + - reassign + - sloglint + - staticcheck + - tagalign + - tenv + - testableexamples + - typecheck + - unconvert + - unparam + - unused + - usestdlibvars + - wastedassign +linters-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. diff --git a/make/_shared/go/01_mod.mk b/make/_shared/go/01_mod.mk new file mode 100644 index 0000000..ffacd49 --- /dev/null +++ b/make/_shared/go/01_mod.mk @@ -0,0 +1,147 @@ +# 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 + +go_base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ +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 + +.PHONY: generate-govulncheck +## Generate base files in the repository +## @category [shared] Generate/ Verify +generate-govulncheck: + cp -r $(go_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-govulnecheck` 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_YQ) $(bin_dir)/scratch + 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 + +.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 '$(bin_dir)/tools/golangci-lint run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config)' in directory '$${target}'"; \ + pushd "$${target}" >/dev/null; \ + $(GOLANGCI-LINT) run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config) --timeout 4m || 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 + $(GCI) write \ + --skip-generated \ + --skip-vendor \ + -s "standard" \ + -s "default" \ + -s "prefix($(repo_name))" \ + -s "blank" \ + -s "dot" . + + @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ + | while read d; do \ + target=$$(dirname $${d}); \ + echo "Running '$(bin_dir)/tools/golangci-lint run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config) --fix' in directory '$${target}'"; \ + pushd "$${target}" >/dev/null; \ + $(GOLANGCI-LINT) run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config) --fix || 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 0000000..ad1962b --- /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 0000000..ea70b8e --- /dev/null +++ b/make/_shared/go/base/.github/workflows/govulncheck.yaml @@ -0,0 +1,31 @@ +# 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 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.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 new file mode 100644 index 0000000..45ed301 --- /dev/null +++ b/make/_shared/helm/01_mod.mk @@ -0,0 +1,20 @@ +# 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 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 0000000..0a67617 --- /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 0000000..663d712 --- /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 0000000..bcc208b --- /dev/null +++ b/make/_shared/helm/crds.mk @@ -0,0 +1,66 @@ +# 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 + +.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 + +shared_generate_targets += generate-crds diff --git a/make/_shared/helm/deploy.mk b/make/_shared/helm/deploy.mk new file mode 100644 index 0000000..8bc6ebb --- /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 0000000..d0bf94e --- /dev/null +++ b/make/_shared/helm/helm.mk @@ -0,0 +1,131 @@ +# 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_chart_app_version +# Default to the same as the chart version +helm_chart_app_version = $(helm_chart_version) +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_app_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 0000000..1a6a3b4 --- /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 0000000..400aab3 --- /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 0000000..dead2cb --- /dev/null +++ b/make/_shared/kind/00_kind_image_versions.mk @@ -0,0 +1,36 @@ +# 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.24.0 + +kind_image_kube_1.25_amd64 := docker.io/kindest/node:v1.25.16@sha256:fedeb7ebef9794b3acbe656901f87231fb33381e0f586033ed18d2587bd9b73d +kind_image_kube_1.25_arm64 := docker.io/kindest/node:v1.25.16@sha256:f16a9c7caa65d394176ce2e628eb371d5af8b7bd913e88c826a357cadde698c7 +kind_image_kube_1.26_amd64 := docker.io/kindest/node:v1.26.15@sha256:290e3765fbabbeb2ddcde36bdf3e8452166dc94a4c970a25c10290ebd480ca6e +kind_image_kube_1.26_arm64 := docker.io/kindest/node:v1.26.15@sha256:7b34bc4f381a4aa0bd81239bbc2af5f44d933c11b3510da85f13cf8b2a34c9fd +kind_image_kube_1.27_amd64 := docker.io/kindest/node:v1.27.16@sha256:84aff282b523c3943c374d95807e1e748ccd43432dce614d6c7a148a7028fb01 +kind_image_kube_1.27_arm64 := docker.io/kindest/node:v1.27.16@sha256:2c6de687b6ea20b385c0b18b85d4e55e214882b3cbde857974ccfe010f4a90a9 +kind_image_kube_1.28_amd64 := docker.io/kindest/node:v1.28.13@sha256:d97df9fff48099bf9a94c92fdc39adde65bec2aa1d011f84233b96172c1003c9 +kind_image_kube_1.28_arm64 := docker.io/kindest/node:v1.28.13@sha256:ddef612bb93a9aa3a989f9d3d4e01c0a7c4d866a4b949264146c182cd202d738 +kind_image_kube_1.29_amd64 := docker.io/kindest/node:v1.29.8@sha256:b69a150f9951ef41158ec76de381a920df2be3582fd16fc19cf4757eef0dded9 +kind_image_kube_1.29_arm64 := docker.io/kindest/node:v1.29.8@sha256:0d5623800cf6290edbc1007ca8a33a5f7e2ad92b41dc7022b4d20a66447db23c +kind_image_kube_1.30_amd64 := docker.io/kindest/node:v1.30.4@sha256:34cb98a38a57a3357fde925a41d61232bbbbeb411b45a25c0d766635d6c3b975 +kind_image_kube_1.30_arm64 := docker.io/kindest/node:v1.30.4@sha256:6becd630a18e77730e31f3833f0b129bbcc9c09ee49c3b88429b3c1fdc30bfc4 +kind_image_kube_1.31_amd64 := docker.io/kindest/node:v1.31.0@sha256:919a65376fd11b67df05caa2e60802ad5de2fca250c9fe0c55b0dce5c9591af3 +kind_image_kube_1.31_arm64 := docker.io/kindest/node:v1.31.0@sha256:0ccfb11dc66eae4abc20c30ee95687bab51de8aeb04e325e1c49af0890646548 + +kind_image_latest_amd64 := $(kind_image_kube_1.31_amd64) +kind_image_latest_arm64 := $(kind_image_kube_1.31_arm64) diff --git a/make/_shared/kind/00_mod.mk b/make/_shared/kind/00_mod.mk new file mode 100644 index 0000000..a448915 --- /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 0000000..a7eb1b2 --- /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 0000000..e95c9ee --- /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 0000000..c768c8d --- /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/klone/01_mod.mk b/make/_shared/klone/01_mod.mk new file mode 100644 index 0000000..a3d07dd --- /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 new file mode 100644 index 0000000..fbd4466 --- /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:6dd468efaceafb7d2b5ba437bb81500636237bac747fd751b75b0cb375600fae + +# 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:b88c19bfe28a83799e08817ffb7205a3aac1b99ad07739a5433a7fb554b4d223 + +# 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 0000000..ca6fc92 --- /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 0000000..6af65e8 --- /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 0000000..c6e1e26 --- /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 0000000..51f647b --- /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 0000000..56873bb --- /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 0000000..e08d948 --- /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 0000000..507281e --- /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 0000000..099bff4 --- /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 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) + +# 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 0000000..348490c --- /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 0000000..9ecbb61 --- /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/repository-base/01_mod.mk b/make/_shared/repository-base/01_mod.mk new file mode 100644 index 0000000..aa6b7ee --- /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 0000000..d950a83 --- /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 0000000..c348703 --- /dev/null +++ b/make/_shared/repository-base/base/.github/workflows/make-self-upgrade.yaml @@ -0,0 +1,101 @@ +# 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 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.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 0000000..261eeb9 --- /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 0000000..6a1652d --- /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 0000000..10d1279 --- /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 + - irbekrm + - sgtcodfish + - inteon + - thatsmrtalbot diff --git a/make/_shared/tools/00_mod.mk b/make/_shared/tools/00_mod.mk new file mode 100644 index 0000000..43cbc6b --- /dev/null +++ b/make/_shared/tools/00_mod.mk @@ -0,0 +1,631 @@ +# 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 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 +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.15.4 +# https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl +tools += kubectl=v1.31.0 +# https://github.com/kubernetes-sigs/kind/releases +tools += kind=v0.24.0 +# https://www.vaultproject.io/downloads +tools += vault=1.17.3 +# https://github.com/Azure/azure-workload-identity/releases +tools += azwi=v1.3.0 +# https://github.com/kyverno/kyverno/releases +tools += kyverno=v1.12.5 +# https://github.com/mikefarah/yq/releases +tools += yq=v4.44.3 +# https://github.com/ko-build/ko/releases +tools += ko=0.16.0 +# https://github.com/protocolbuffers/protobuf/releases +tools += protoc=27.3 +# https://github.com/aquasecurity/trivy/releases +tools += trivy=v0.54.1 +# https://github.com/vmware-tanzu/carvel-ytt/releases +tools += ytt=v0.50.0 +# https://github.com/rclone/rclone/releases +tools += rclone=v1.67.0 + +### go packages +# https://pkg.go.dev/sigs.k8s.io/controller-tools/cmd/controller-gen?tab=versions +tools += controller-gen=v0.16.1 +# https://pkg.go.dev/golang.org/x/tools/cmd/goimports?tab=versions +tools += goimports=v0.24.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.12.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.16 +# https://pkg.go.dev/github.com/google/go-containerregistry/pkg/crane?tab=versions +tools += crane=v0.20.2 +# https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go?tab=versions +tools += protoc-gen-go=v1.34.2 +# https://pkg.go.dev/github.com/norwoodj/helm-docs/cmd/helm-docs?tab=versions +tools += helm-docs=v1.14.2 +# https://pkg.go.dev/github.com/sigstore/cosign/v2/cmd/cosign?tab=versions +tools += cosign=v2.4.0 +# 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.2.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.1.0 +# https://pkg.go.dev/github.com/goreleaser/goreleaser?tab=versions +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.3 +# https://github.com/cert-manager/cmctl +tools += cmctl=v2.1.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.61.0 +# https://pkg.go.dev/golang.org/x/vuln?tab=versions +tools += govulncheck=v1.1.3 +# https://pkg.go.dev/github.com/operator-framework/operator-sdk/cmd/operator-sdk?tab=versions +tools += operator-sdk=v1.36.1 +# https://pkg.go.dev/github.com/cli/cli/v2?tab=versions +tools += gh=v2.54.0 +# https:///github.com/redhat-openshift-ecosystem/openshift-preflight/releases +tools += preflight=1.10.0 +# https://github.com/daixiang0/gci/releases +tools += gci=v0.13.4 +# https://github.com/google/yamlfmt/releases +tools += yamlfmt=v0.13.0 + +# https://pkg.go.dev/k8s.io/code-generator/cmd?tab=versions +K8S_CODEGEN_VERSION := v0.31.0 +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=91dab695df6fb4696a1ea93e510a5a4c6d10d369 + +# https://raw.githubusercontent.com/kubernetes-sigs/controller-tools/master/envtest-releases.yaml +KUBEBUILDER_ASSETS_VERSION := v1.31.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.23.3 + +# 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 simultaneously without issues (both +# will perform the action and the second time the link will be overwritten). +# +# -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 \ + $(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=a0afb9744c00648bafb1b90b4aba5bdb86f424f02f9275399ce0c20b93a2c3a8 +go_linux_arm64_SHA256SUM=1f7cbd7f668ea32a107ecd41b6488aaee1f5d77a66efd885b175494439d4e1ce +go_darwin_amd64_SHA256SUM=c7e024d5c0bc81845070f23598caf02f05b8ae88fd4ad2cd3e236ddbea833ad2 +go_darwin_arm64_SHA256SUM=31e119fe9bde6e105407a32558d5b5fa6ca11e2bd17f8b7b2f8a06aba16a0632 + +.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=11400fecfc07fd6f034863e4e0c4c4445594673fd2a129e701fe41f31170cfa9 +helm_linux_arm64_SHA256SUM=fa419ecb139442e8a594c242343fafb7a46af3af34041c4eac1efcc49d74e626 +helm_darwin_amd64_SHA256SUM=1bc3f354f7ce4d7fd9cfa5bcc701c1f32c88d27076d96c2792d5b5226062aee5 +helm_darwin_arm64_SHA256SUM=88115846a1fb58f8eb8f64fec5c343d95ca394f1be811602fa54a887c98730ac + +.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=7c27adc64a84d1c0cc3dcf7bf4b6e916cc00f3f576a2dbac51b318d926032437 +kubectl_linux_arm64_SHA256SUM=f42832db7d77897514639c6df38214a6d8ae1262ee34943364ec1ffaee6c009c +kubectl_darwin_amd64_SHA256SUM=fb6e07a69acc4e16885eda55b524c13b84bfbcf78cfac8d6c378d2bad321e105 +kubectl_darwin_arm64_SHA256SUM=b7472df17a885574ed7273947a8a274c156357db21b981208e8e109b9ed4022d + +.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=b89aada5a39d620da3fcd16435b7f28d858927dd53f92cbac77686b0588b600d +kind_linux_arm64_SHA256SUM=2968808d916e12d0a25c56d07c9a1c987163f972513fa8a94a2125a69f9c50eb +kind_darwin_amd64_SHA256SUM=6cf7ba50b37d3446153bbfb8990f03fb8102778898c84502cdb841710b499ed5 +kind_darwin_arm64_SHA256SUM=8e34f2edc7efc5c7c160487251848a954cd60ccd52b56a3fc360eaab33543fc0 + +.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=146536fd9ef8aa1465894e718a8fe7a9ca13d68761bae900428f01f7ecd83806 +vault_linux_arm64_SHA256SUM=6c7dc39df0058b1fa9e65050227cdb12dc7913153ecd56956911fb973c353590 +vault_darwin_amd64_SHA256SUM=fd7e7c7a467723639cc0b624533a9f7aff0691bfbfe47602abac75af0be4914a +vault_darwin_arm64_SHA256SUM=26f11328a9c9e3b5599ec63efe394aed5fed0879c662f9ca320b8ec63d839582 + +.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=bbc84c7e5fcaf4c6e3e58064dc66b3b7f70f38a6d8f9cdd07f0669a8499bdd47 +azwi_linux_arm64_SHA256SUM=7c4315ec8e21509641d90cf3160a379ae6ec771963df4bac0f18aa0a3ecef4ba +azwi_darwin_amd64_SHA256SUM=998dfaea81b652a5cbe92bb7dd3f770a391b8129f2a57137966d375c9f135062 +azwi_darwin_arm64_SHA256SUM=b8a4a8ebcba2248b439f43c1d2431f469b023894b2f862879dc0999293dc1154 + +.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=b72c0c764c797e6b2cfd6d417abdad7b25d4fbc9f8475edeb44c8dd598999b76 +kubebuilder_tools_linux_arm64_SHA256SUM=087123cfb6ac48a1002db19df7ee96949b54d34860805a41397bcb4cd0b5d5e4 +kubebuilder_tools_darwin_amd64_SHA256SUM=e8a3bc6245dd30597aab163239337cd125194037ac13328798aa17b86aff0cb4 +kubebuilder_tools_darwin_arm64_SHA256SUM=9f2d49e16368aa278adaf3802c7f3a3ca73560345e2634f9af13844a3936dc5b + +.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=962c396cdb149eadc7d6cc0cb345d3c01b6980d5265c8bb585c55ecd4b8a76b9 +kyverno_linux_arm64_SHA256SUM=dd66d363656685af142ec2fcbaa8ff997951df3241b25a3dbe3eb890da124121 +kyverno_darwin_amd64_SHA256SUM=f0053827f59aeed7e26b8ab578e9a86d9c002060414c442a46bfa8c49ac8280c +kyverno_darwin_arm64_SHA256SUM=4467e97fafa5a2067b93a5cbc954069ba00c890e3e867d0702b864ac7242ee0e + +.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=a2c097180dd884a8d50c956ee16a9cec070f30a7947cf4ebf87d5f36213e9ed7 +yq_linux_arm64_SHA256SUM=0e7e1524f68d91b3ff9b089872d185940ab0fa020a5a9052046ef10547023156 +yq_darwin_amd64_SHA256SUM=216ddfa03e7ba0e5aba00b236ec78324b5bfc49b610db254fe92310878baea20 +yq_darwin_arm64_SHA256SUM=559a594ef7a6ebc5b81a67b7717fb3accedd266d8fa7d8352da7fec9e463f48b + +.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=aee2caeced511e60c6889a4cfaf9ebe28ec35acb49531b7a90b09e0a963bcff7 +ko_linux_arm64_SHA256SUM=45b6ba20084b2199c63dcc738c54f7f6c37ea4e9c7f79eefc286d9947b11d0d1 +ko_darwin_amd64_SHA256SUM=5c98d0229fd2a82cc69510705b74a7196fc184641693930b0f9282b6d1f79d95 +ko_darwin_arm64_SHA256SUM=9c75b97f26ba98c62a86f3b39e2c74ced6c97092f301cd73fe4e5b3e16261698 + +.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=6dab2adab83f915126cab53540d48957c40e9e9023969c3e84d44bfb936c7741 +protoc_linux_arm64_SHA256SUM=bdad36f3ad7472281d90568c4956ea2e203c216e0de005c6bd486f1920f2751c +protoc_darwin_amd64_SHA256SUM=ce282648fed0e7fbd6237d606dc9ec168dd2c1863889b04efa0b19c47da65d1b +protoc_darwin_arm64_SHA256SUM=b22116bd97cdbd7ea25346abe635a9df268515fe5ef5afa93cd9a68fc2513f84 + +.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=bbaaf8278b2a9bb49aa848fe23c8bfe19f7db4f5dc7b55a9793357cd78cb5ec5 +trivy_linux_arm64_SHA256SUM=26f8ee5a44ca027082c426d982ce95a37b88cf66defa1e982641eb4497bf1e99 +trivy_darwin_amd64_SHA256SUM=d182c2de5496504120269b8d50b543e88b4837f8c9876055e54248f0a4e93d77 +trivy_darwin_arm64_SHA256SUM=0ea077b074e38c3bce419d3cfaa417581c36e985beb9e571c06c01293158ff6f + +.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=61dec6e00131f990db853afc4b7531c318bd3af3ba18f2cfdbc0d5e83a45c445 +ytt_linux_arm64_SHA256SUM=f38290c2666ddcf6feb4907f91033c4f41022b3fb84893c42d1f48948597b82a +ytt_darwin_amd64_SHA256SUM=d79f0b4189403c4142f5c646989de0769a316896a6096dfd1719605d313e8d1e +ytt_darwin_arm64_SHA256SUM=f3ce72031d34f0a3d909b1c971017bb3788bb786d3bb5cba1bf6d699255be643 + +.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=07c23d21a94d70113d949253478e13261c54d14d72023bb14d96a8da5f3e7722 +rclone_linux_arm64_SHA256SUM=2b44981a1a7d1f432c53c0f2f0b6bcdd410f6491c47dc55428fdac0b85c763f1 +rclone_darwin_amd64_SHA256SUM=1a1a3b080393b721ba5f38597305be2dbac3b654b43dfac3ebe4630b4e6406c3 +rclone_darwin_arm64_SHA256SUM=4dc6142aea78bb86f1236fe38e570b715990503c09733418c0cd2300e45651e4 + +.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=97750df31f31200f073e3b2844628a0a3681a403648c76d12319f83c80666104 +preflight_linux_arm64_SHA256SUM=e12b2afe063c07ee75f69f285f8cc56be99b85e2abac99cbef5fb22b91ef0cb7 + +# 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 +# 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 0000000..62e5489 --- /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 0000000..21d006f --- /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 0000000..22564f7 --- /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/hack/boilerplate.go.txt b/make/config/boilerplate.go.txt similarity index 92% rename from hack/boilerplate.go.txt rename to make/config/boilerplate.go.txt index a086083..cb130f1 100644 --- a/hack/boilerplate.go.txt +++ b/make/config/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright 2023 The cert-manager Authors. +Copyright 2021 cert-manager Ltd. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/make/config/kind/cluster.yaml b/make/config/kind/cluster.yaml new file mode 100644 index 0000000..507f1f9 --- /dev/null +++ b/make/config/kind/cluster.yaml @@ -0,0 +1,19 @@ +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 + + extraMounts: + - hostPath: {{KIND_IMAGES}} + containerPath: /mounted_images diff --git a/make/test-smoke.mk b/make/test-smoke.mk new file mode 100644 index 0000000..ab37cda --- /dev/null +++ b/make/test-smoke.mk @@ -0,0 +1,66 @@ +# 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: smoke-setup-cert-manager +smoke-setup-cert-manager: | kind-cluster $(NEEDS_HELM) $(NEEDS_KUBECTL) + $(HELM) upgrade \ + --install \ + --create-namespace \ + --wait \ + --version $(cert_manager_version) \ + --namespace cert-manager \ + --repo https://charts.jetstack.io \ + --set installCRDs=true \ + --set image.repository=$(quay.io/jetstack/cert-manager-controller.REPO) \ + --set image.tag=$(quay.io/jetstack/cert-manager-controller.TAG) \ + --set image.pullPolicy=Never \ + --set cainjector.image.repository=$(quay.io/jetstack/cert-manager-cainjector.REPO) \ + --set cainjector.image.tag=$(quay.io/jetstack/cert-manager-cainjector.TAG) \ + --set cainjector.image.pullPolicy=Never \ + --set webhook.image.repository=$(quay.io/jetstack/cert-manager-webhook.REPO) \ + --set webhook.image.tag=$(quay.io/jetstack/cert-manager-webhook.TAG) \ + --set webhook.image.pullPolicy=Never \ + --set startupapicheck.image.repository=$(quay.io/jetstack/cert-manager-startupapicheck.REPO) \ + --set startupapicheck.image.tag=$(quay.io/jetstack/cert-manager-startupapicheck.TAG) \ + --set startupapicheck.image.pullPolicy=Never \ + cert-manager cert-manager >/dev/null + +# 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-smoke" is run. +# When a "test-smoke" target is run, the currently active cluster must be the kind +# cluster created by the "kind-cluster" target. +ifeq ($(findstring test-smoke,$(MAKECMDGOALS)),test-smoke) +install: kind-cluster oci-load-manager +endif + +test-smoke-deps: INSTALL_OPTIONS := +test-smoke-deps: INSTALL_OPTIONS += --set image.repository=$(oci_manager_image_name_development) +test-smoke-deps: smoke-setup-cert-manager +test-smoke-deps: install + +.PHONY: test-smoke +## Smoke test +## @category Testing +test-smoke: test-smoke-deps | kind-cluster $(NEEDS_KUBECTL) + $(KUBECTL) apply --filename examples + + $(KUBECTL) wait --for=condition=Ready --timeout=5s sampleissuers.sample-issuer.example.com sampleissuer-sample + $(KUBECTL) wait --for=condition=Ready --timeout=5s certificaterequests.cert-manager.io sampleissuer-sample + $(KUBECTL) wait --for=condition=Ready --timeout=5s certificates.cert-manager.io certificate-by-sampleissuer + + $(KUBECTL) wait --for=condition=Ready --timeout=5s sampleclusterissuers.sample-issuer.example.com sampleclusterissuer-sample + $(KUBECTL) wait --for=condition=Ready --timeout=5s certificaterequests.cert-manager.io sampleclusterissuer-sample + $(KUBECTL) wait --for=condition=Ready --timeout=5s certificates.cert-manager.io certificate-by-sampleclusterissuer + + $(KUBECTL) delete --filename examples diff --git a/make/test-unit.mk b/make/test-unit.mk new file mode 100644 index 0000000..ca07829 --- /dev/null +++ b/make/test-unit.mk @@ -0,0 +1,28 @@ +# 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_GO) $(NEEDS_GOTESTSUM) $(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 \ + ./... \ + -- \ + -ldflags $(go_manager_ldflags) + + $(GO) tool cover -html=$(ARTIFACTS)/filtered.cov -o=$(ARTIFACTS)/filtered.html