├── .github ├── dependabot.yaml └── workflows │ ├── govulncheck.yaml │ ├── make-self-upgrade.yaml │ └── release.yaml ├── .gitignore ├── .golangci.yaml ├── LICENSE ├── LICENSES ├── Makefile ├── OWNERS ├── OWNERS_ALIASES ├── README.md ├── RELEASE.md ├── deploy └── charts │ └── openshift-routes │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── templates │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── rbac.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── servicemonitor.yaml │ ├── values.linter.exceptions │ ├── values.schema.json │ └── values.yaml ├── go.mod ├── go.sum ├── internal ├── cmd │ ├── app │ │ ├── app.go │ │ └── options │ │ │ └── options.go │ └── main.go └── controller │ ├── controller.go │ ├── controller_test.go │ ├── sync.go │ ├── sync_test.go │ ├── util.go │ └── util_test.go ├── klone.yaml ├── make ├── 00_mod.mk ├── 02_mod.mk ├── _shared │ ├── boilerplate │ │ ├── 00_mod.mk │ │ ├── 01_mod.mk │ │ └── template │ │ │ └── boilerplate.go.txt │ ├── cert-manager │ │ ├── 00_mod.mk │ │ └── 01_mod.mk │ ├── controller-gen │ │ └── 01_mod.mk │ ├── generate-verify │ │ ├── 00_mod.mk │ │ ├── 02_mod.mk │ │ └── util │ │ │ └── verify.sh │ ├── go │ │ ├── .golangci.override.yaml │ │ ├── 01_mod.mk │ │ ├── README.md │ │ └── base │ │ │ └── .github │ │ │ └── workflows │ │ │ └── govulncheck.yaml │ ├── helm │ │ ├── 01_mod.mk │ │ ├── crd.template.footer.yaml │ │ ├── crd.template.header.yaml │ │ ├── crds.mk │ │ ├── crds_dir.README.md │ │ ├── deploy.mk │ │ └── helm.mk │ ├── help │ │ ├── 01_mod.mk │ │ └── help.sh │ ├── kind │ │ ├── 00_kind_image_versions.mk │ │ ├── 00_mod.mk │ │ ├── 01_mod.mk │ │ ├── kind-image-preload.mk │ │ └── kind.mk │ ├── klone │ │ └── 01_mod.mk │ ├── licenses │ │ ├── 00_mod.mk │ │ └── 01_mod.mk │ ├── oci-build │ │ ├── 00_mod.mk │ │ └── 01_mod.mk │ ├── oci-publish │ │ ├── 00_mod.mk │ │ ├── 01_mod.mk │ │ └── image-exists.sh │ ├── repository-base │ │ ├── 01_mod.mk │ │ ├── base-dependabot │ │ │ └── .github │ │ │ │ └── dependabot.yaml │ │ └── base │ │ │ ├── .github │ │ │ └── workflows │ │ │ │ └── make-self-upgrade.yaml │ │ │ ├── LICENSE │ │ │ ├── Makefile │ │ │ └── OWNERS_ALIASES │ └── tools │ │ ├── 00_mod.mk │ │ └── util │ │ ├── checkhash.sh │ │ ├── hash.sh │ │ └── lock.sh ├── config │ └── kind │ │ └── cluster.yaml ├── test-smoke.mk └── test-unit.mk └── test └── test-smoke.sh /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base-dependabot/.github/dependabot.yaml instead. 3 | 4 | # Update Go dependencies and GitHub Actions dependencies daily. 5 | version: 2 6 | updates: 7 | - package-ecosystem: gomod 8 | directory: / 9 | schedule: 10 | interval: daily 11 | groups: 12 | all: 13 | patterns: ["*"] 14 | - package-ecosystem: github-actions 15 | directory: / 16 | schedule: 17 | interval: daily 18 | groups: 19 | all: 20 | patterns: ["*"] 21 | -------------------------------------------------------------------------------- /.github/workflows/govulncheck.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/go/base/.github/workflows/govulncheck.yaml instead. 3 | 4 | # Run govulncheck at midnight every night on the main branch, 5 | # to alert us to recent vulnerabilities which affect the Go code in this 6 | # project. 7 | name: govulncheck 8 | on: 9 | workflow_dispatch: {} 10 | schedule: 11 | - cron: '0 0 * * *' 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | govulncheck: 18 | runs-on: ubuntu-latest 19 | 20 | if: github.repository_owner == 'cert-manager' 21 | 22 | steps: 23 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 24 | # Adding `fetch-depth: 0` makes sure tags are also fetched. We need 25 | # the tags so `git describe` returns a valid version. 26 | # see https://github.com/actions/checkout/issues/701 for extra info about this option 27 | with: { fetch-depth: 0 } 28 | 29 | - id: go-version 30 | run: | 31 | make print-go-version >> "$GITHUB_OUTPUT" 32 | 33 | - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 34 | with: 35 | go-version: ${{ steps.go-version.outputs.result }} 36 | 37 | - run: make verify-govulncheck 38 | -------------------------------------------------------------------------------- /.github/workflows/make-self-upgrade.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/.github/workflows/make-self-upgrade.yaml instead. 3 | 4 | name: make-self-upgrade 5 | concurrency: make-self-upgrade 6 | on: 7 | workflow_dispatch: {} 8 | schedule: 9 | - cron: '0 0 * * *' 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | self_upgrade: 16 | runs-on: ubuntu-latest 17 | 18 | if: github.repository_owner == 'cert-manager' 19 | 20 | permissions: 21 | contents: write 22 | pull-requests: write 23 | 24 | env: 25 | SOURCE_BRANCH: "${{ github.ref_name }}" 26 | SELF_UPGRADE_BRANCH: "self-upgrade-${{ github.ref_name }}" 27 | 28 | steps: 29 | - name: Fail if branch is not head of branch. 30 | if: ${{ !startsWith(github.ref, 'refs/heads/') && env.SOURCE_BRANCH != '' && env.SELF_UPGRADE_BRANCH != '' }} 31 | run: | 32 | echo "This workflow should not be run on a non-branch-head." 33 | exit 1 34 | 35 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 36 | # Adding `fetch-depth: 0` makes sure tags are also fetched. We need 37 | # the tags so `git describe` returns a valid version. 38 | # see https://github.com/actions/checkout/issues/701 for extra info about this option 39 | with: { fetch-depth: 0 } 40 | 41 | - id: go-version 42 | run: | 43 | make print-go-version >> "$GITHUB_OUTPUT" 44 | 45 | - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 46 | with: 47 | go-version: ${{ steps.go-version.outputs.result }} 48 | 49 | - run: | 50 | git checkout -B "$SELF_UPGRADE_BRANCH" 51 | 52 | - run: | 53 | make -j upgrade-klone 54 | make -j generate 55 | 56 | - id: is-up-to-date 57 | shell: bash 58 | run: | 59 | git_status=$(git status -s) 60 | is_up_to_date="true" 61 | if [ -n "$git_status" ]; then 62 | is_up_to_date="false" 63 | echo "The following changes will be committed:" 64 | echo "$git_status" 65 | fi 66 | echo "result=$is_up_to_date" >> "$GITHUB_OUTPUT" 67 | 68 | - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} 69 | run: | 70 | git config --global user.name "cert-manager-bot" 71 | git config --global user.email "cert-manager-bot@users.noreply.github.com" 72 | git add -A && git commit -m "BOT: run 'make upgrade-klone' and 'make generate'" --signoff 73 | git push -f origin "$SELF_UPGRADE_BRANCH" 74 | 75 | - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} 76 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 77 | with: 78 | script: | 79 | const { repo, owner } = context.repo; 80 | const pulls = await github.rest.pulls.list({ 81 | owner: owner, 82 | repo: repo, 83 | head: owner + ':' + process.env.SELF_UPGRADE_BRANCH, 84 | base: process.env.SOURCE_BRANCH, 85 | state: 'open', 86 | }); 87 | 88 | if (pulls.data.length < 1) { 89 | const result = await github.rest.pulls.create({ 90 | title: '[CI] Merge ' + process.env.SELF_UPGRADE_BRANCH + ' into ' + process.env.SOURCE_BRANCH, 91 | owner: owner, 92 | repo: repo, 93 | head: process.env.SELF_UPGRADE_BRANCH, 94 | base: process.env.SOURCE_BRANCH, 95 | body: [ 96 | 'This PR is auto-generated to bump the Makefile modules.', 97 | ].join('\n'), 98 | }); 99 | await github.rest.issues.addLabels({ 100 | owner, 101 | repo, 102 | issue_number: result.data.number, 103 | labels: ['skip-review'] 104 | }); 105 | } 106 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: release 2 | on: 3 | push: 4 | tags: 5 | - "v*" 6 | 7 | env: 8 | VERSION: ${{ github.ref_name }} 9 | 10 | jobs: 11 | build_and_push: 12 | runs-on: ubuntu-latest 13 | 14 | permissions: 15 | contents: read # needed for checkout 16 | packages: write # needed for push images 17 | id-token: write # needed for keyless signing 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | - id: go-version 23 | run: | 24 | make print-go-version >> "$GITHUB_OUTPUT" 25 | 26 | - uses: docker/login-action@v3 27 | with: 28 | registry: ghcr.io 29 | username: ${{ github.actor }} 30 | password: ${{ secrets.GITHUB_TOKEN }} 31 | 32 | - uses: actions/setup-go@v5 33 | with: 34 | go-version: ${{ steps.go-version.outputs.result }} 35 | 36 | - id: release 37 | run: make release 38 | 39 | outputs: 40 | RELEASE_OCI_MANAGER_IMAGE: ${{ steps.release.outputs.RELEASE_OCI_MANAGER_IMAGE }} 41 | RELEASE_OCI_MANAGER_TAG: ${{ steps.release.outputs.RELEASE_OCI_MANAGER_TAG }} 42 | RELEASE_HELM_CHART_IMAGE: ${{ steps.release.outputs.RELEASE_HELM_CHART_IMAGE }} 43 | RELEASE_HELM_CHART_VERSION: ${{ steps.release.outputs.RELEASE_HELM_CHART_VERSION }} 44 | 45 | github_release: 46 | runs-on: ubuntu-latest 47 | 48 | needs: build_and_push 49 | 50 | permissions: 51 | contents: write # needed for creating a PR 52 | pull-requests: write # needed for creating a PR 53 | 54 | steps: 55 | - run: | 56 | touch .notes-file 57 | echo "OCI_MANAGER_IMAGE: ${{ needs.build_and_push.outputs.RELEASE_OCI_MANAGER_IMAGE }}" >> .notes-file 58 | echo "OCI_MANAGER_TAG: ${{ needs.build_and_push.outputs.RELEASE_OCI_MANAGER_TAG }}" >> .notes-file 59 | echo "HELM_CHART_IMAGE: ${{ needs.build_and_push.outputs.RELEASE_HELM_CHART_IMAGE }}" >> .notes-file 60 | echo "HELM_CHART_VERSION: ${{ needs.build_and_push.outputs.RELEASE_HELM_CHART_VERSION }}" >> .notes-file 61 | 62 | - env: 63 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 64 | run: | 65 | gh release create "$VERSION" \ 66 | --repo="$GITHUB_REPOSITORY" \ 67 | --title="${VERSION}" \ 68 | --draft \ 69 | --verify-tag \ 70 | --notes-file .notes-file 71 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | _bin 8 | bin 9 | dist/ 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Kubernetes Generated files - skip generated files, except for vendored files 18 | 19 | !vendor/**/zz_generated.* 20 | 21 | # editor and IDE paraphernalia 22 | .idea 23 | *.iml 24 | *.swp 25 | *.swo 26 | *~ 27 | 28 | .vscode 29 | -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | linters: 3 | default: none 4 | exclusions: 5 | generated: lax 6 | presets: [comments, common-false-positives, legacy, std-error-handling] 7 | rules: 8 | - linters: 9 | - dupword 10 | - errcheck 11 | - nilerr 12 | - nilnil 13 | - staticcheck 14 | - unconvert 15 | - unparam 16 | text: .* 17 | paths: [third_party$, builtin$, examples$] 18 | warn-unused: true 19 | settings: 20 | staticcheck: 21 | checks: ["all", "-ST1000", "-ST1001", "-ST1003", "-ST1005", "-ST1012", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-QF1001", "-QF1003", "-QF1008"] 22 | enable: 23 | - asasalint 24 | - asciicheck 25 | - bidichk 26 | - bodyclose 27 | - canonicalheader 28 | - contextcheck 29 | - copyloopvar 30 | - decorder 31 | - dogsled 32 | - dupword 33 | - durationcheck 34 | - errcheck 35 | - errchkjson 36 | - errname 37 | - exhaustive 38 | - exptostd 39 | - forbidigo 40 | - ginkgolinter 41 | - gocheckcompilerdirectives 42 | - gochecksumtype 43 | - gocritic 44 | - goheader 45 | - goprintffuncname 46 | - gosec 47 | - gosmopolitan 48 | - govet 49 | - grouper 50 | - importas 51 | - ineffassign 52 | - interfacebloat 53 | - intrange 54 | - loggercheck 55 | - makezero 56 | - mirror 57 | - misspell 58 | - musttag 59 | - nakedret 60 | - nilerr 61 | - nilnil 62 | - noctx 63 | - nosprintfhostport 64 | - predeclared 65 | - promlinter 66 | - protogetter 67 | - reassign 68 | - sloglint 69 | - staticcheck 70 | - tagalign 71 | - testableexamples 72 | - unconvert 73 | - unparam 74 | - unused 75 | - usestdlibvars 76 | - usetesting 77 | - wastedassign 78 | formatters: 79 | enable: [gci, gofmt] 80 | settings: 81 | gci: 82 | sections: 83 | - standard # Standard section: captures all standard packages. 84 | - default # Default section: contains all imports that could not be matched to another section type. 85 | - prefix(github.com/cert-manager/openshift-routes) # Custom section: groups all imports with the specified Prefix. 86 | - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. 87 | - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. 88 | exclusions: 89 | generated: lax 90 | paths: [third_party$, builtin$, examples$] 91 | -------------------------------------------------------------------------------- /LICENSES: -------------------------------------------------------------------------------- 1 | github.com/Azure/go-ntlmssp,https://github.com/Azure/go-ntlmssp/blob/754e69321358/LICENSE,MIT 2 | github.com/beorn7/perks/quantile,https://github.com/beorn7/perks/blob/v1.0.1/LICENSE,MIT 3 | github.com/blang/semver/v4,https://github.com/blang/semver/blob/v4.0.0/v4/LICENSE,MIT 4 | github.com/cert-manager/cert-manager,https://github.com/cert-manager/cert-manager/blob/v1.17.2/LICENSE,Apache-2.0 5 | github.com/cert-manager/openshift-routes/internal,https://github.com/cert-manager/openshift-routes/blob/HEAD/LICENSE,Apache-2.0 6 | github.com/cespare/xxhash/v2,https://github.com/cespare/xxhash/blob/v2.3.0/LICENSE.txt,MIT 7 | github.com/davecgh/go-spew/spew,https://github.com/davecgh/go-spew/blob/d8f796af33cc/LICENSE,ISC 8 | github.com/emicklei/go-restful/v3,https://github.com/emicklei/go-restful/blob/v3.12.1/LICENSE,MIT 9 | github.com/evanphx/json-patch/v5,https://github.com/evanphx/json-patch/blob/v5.9.11/v5/LICENSE,BSD-3-Clause 10 | github.com/fsnotify/fsnotify,https://github.com/fsnotify/fsnotify/blob/v1.8.0/LICENSE,BSD-3-Clause 11 | github.com/fxamacker/cbor/v2,https://github.com/fxamacker/cbor/blob/v2.7.0/LICENSE,MIT 12 | github.com/go-asn1-ber/asn1-ber,https://github.com/go-asn1-ber/asn1-ber/blob/v1.5.7/LICENSE,MIT 13 | github.com/go-errors/errors,https://github.com/go-errors/errors/blob/v1.5.1/LICENSE.MIT,MIT 14 | github.com/go-ldap/ldap/v3,https://github.com/go-ldap/ldap/blob/v3.4.8/v3/LICENSE,MIT 15 | github.com/go-logr/logr,https://github.com/go-logr/logr/blob/v1.4.2/LICENSE,Apache-2.0 16 | github.com/go-logr/zapr,https://github.com/go-logr/zapr/blob/v1.3.0/LICENSE,Apache-2.0 17 | github.com/go-openapi/jsonpointer,https://github.com/go-openapi/jsonpointer/blob/v0.21.0/LICENSE,Apache-2.0 18 | github.com/go-openapi/jsonreference,https://github.com/go-openapi/jsonreference/blob/v0.21.0/LICENSE,Apache-2.0 19 | github.com/go-openapi/swag,https://github.com/go-openapi/swag/blob/v0.23.0/LICENSE,Apache-2.0 20 | github.com/gogo/protobuf,https://github.com/gogo/protobuf/blob/v1.3.2/LICENSE,BSD-3-Clause 21 | github.com/google/btree,https://github.com/google/btree/blob/v1.1.3/LICENSE,Apache-2.0 22 | github.com/google/gnostic-models,https://github.com/google/gnostic-models/blob/v0.6.9/LICENSE,Apache-2.0 23 | github.com/google/go-cmp/cmp,https://github.com/google/go-cmp/blob/v0.7.0/LICENSE,BSD-3-Clause 24 | github.com/google/shlex,https://github.com/google/shlex/blob/e7afc7fbc510/COPYING,Apache-2.0 25 | github.com/google/uuid,https://github.com/google/uuid/blob/v1.6.0/LICENSE,BSD-3-Clause 26 | github.com/gregjones/httpcache,https://github.com/gregjones/httpcache/blob/901d90724c79/LICENSE.txt,MIT 27 | github.com/josharian/intern,https://github.com/josharian/intern/blob/v1.0.0/license.md,MIT 28 | github.com/json-iterator/go,https://github.com/json-iterator/go/blob/v1.1.12/LICENSE,MIT 29 | github.com/liggitt/tabwriter,https://github.com/liggitt/tabwriter/blob/89fcab3d43de/LICENSE,BSD-3-Clause 30 | github.com/mailru/easyjson,https://github.com/mailru/easyjson/blob/v0.9.0/LICENSE,MIT 31 | github.com/moby/term,https://github.com/moby/term/blob/v0.5.0/LICENSE,Apache-2.0 32 | github.com/modern-go/concurrent,https://github.com/modern-go/concurrent/blob/bacd9c7ef1dd/LICENSE,Apache-2.0 33 | github.com/modern-go/reflect2,https://github.com/modern-go/reflect2/blob/v1.0.2/LICENSE,Apache-2.0 34 | github.com/monochromegane/go-gitignore,https://github.com/monochromegane/go-gitignore/blob/205db1a8cc00/LICENSE,MIT 35 | github.com/munnerz/goautoneg,https://github.com/munnerz/goautoneg/blob/a7dc8b61c822/LICENSE,BSD-3-Clause 36 | github.com/openshift/api/route/v1,https://github.com/openshift/api/blob/5852b58f4b10/LICENSE,Apache-2.0 37 | github.com/openshift/client-go/route,https://github.com/openshift/client-go/blob/b2f7c4ab0984/LICENSE,Apache-2.0 38 | github.com/peterbourgon/diskv,https://github.com/peterbourgon/diskv/blob/v2.0.1/LICENSE,MIT 39 | github.com/pkg/errors,https://github.com/pkg/errors/blob/v0.9.1/LICENSE,BSD-2-Clause 40 | github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil,https://github.com/prometheus/client_golang/blob/v1.22.0/internal/github.com/golang/gddo/LICENSE,BSD-3-Clause 41 | github.com/prometheus/client_golang/prometheus,https://github.com/prometheus/client_golang/blob/v1.22.0/LICENSE,Apache-2.0 42 | github.com/prometheus/client_model/go,https://github.com/prometheus/client_model/blob/v0.6.1/LICENSE,Apache-2.0 43 | github.com/prometheus/common,https://github.com/prometheus/common/blob/v0.62.0/LICENSE,Apache-2.0 44 | github.com/prometheus/procfs,https://github.com/prometheus/procfs/blob/v0.15.1/LICENSE,Apache-2.0 45 | github.com/spf13/cobra,https://github.com/spf13/cobra/blob/v1.9.1/LICENSE.txt,Apache-2.0 46 | github.com/spf13/pflag,https://github.com/spf13/pflag/blob/v1.0.6/LICENSE,BSD-3-Clause 47 | github.com/x448/float16,https://github.com/x448/float16/blob/v0.8.4/LICENSE,MIT 48 | github.com/xlab/treeprint,https://github.com/xlab/treeprint/blob/v1.2.0/LICENSE,MIT 49 | go.opentelemetry.io/otel,https://github.com/open-telemetry/opentelemetry-go/blob/v1.33.0/LICENSE,Apache-2.0 50 | go.opentelemetry.io/otel/trace,https://github.com/open-telemetry/opentelemetry-go/blob/trace/v1.33.0/trace/LICENSE,Apache-2.0 51 | go.uber.org/multierr,https://github.com/uber-go/multierr/blob/v1.11.0/LICENSE.txt,MIT 52 | go.uber.org/zap,https://github.com/uber-go/zap/blob/v1.27.0/LICENSE,MIT 53 | golang.org/x/crypto,https://cs.opensource.google/go/x/crypto/+/v0.36.0:LICENSE,BSD-3-Clause 54 | golang.org/x/net,https://cs.opensource.google/go/x/net/+/v0.38.0:LICENSE,BSD-3-Clause 55 | golang.org/x/oauth2,https://cs.opensource.google/go/x/oauth2/+/v0.28.0:LICENSE,BSD-3-Clause 56 | golang.org/x/sync/errgroup,https://cs.opensource.google/go/x/sync/+/v0.12.0:LICENSE,BSD-3-Clause 57 | golang.org/x/sys/unix,https://cs.opensource.google/go/x/sys/+/v0.31.0:LICENSE,BSD-3-Clause 58 | golang.org/x/term,https://cs.opensource.google/go/x/term/+/v0.30.0:LICENSE,BSD-3-Clause 59 | golang.org/x/text,https://cs.opensource.google/go/x/text/+/v0.23.0:LICENSE,BSD-3-Clause 60 | golang.org/x/time/rate,https://cs.opensource.google/go/x/time/+/v0.9.0:LICENSE,BSD-3-Clause 61 | gomodules.xyz/jsonpatch/v2,https://github.com/gomodules/jsonpatch/blob/v2.4.0/v2/LICENSE,Apache-2.0 62 | google.golang.org/protobuf,https://github.com/protocolbuffers/protobuf-go/blob/v1.36.5/LICENSE,BSD-3-Clause 63 | gopkg.in/evanphx/json-patch.v4,https://github.com/evanphx/json-patch/blob/v4.12.0/LICENSE,BSD-3-Clause 64 | gopkg.in/inf.v0,https://github.com/go-inf/inf/blob/v0.9.1/LICENSE,BSD-3-Clause 65 | gopkg.in/yaml.v3,https://github.com/go-yaml/yaml/blob/v3.0.1/LICENSE,MIT 66 | k8s.io/api,https://github.com/kubernetes/api/blob/v0.33.0/LICENSE,Apache-2.0 67 | k8s.io/apiextensions-apiserver/pkg/apis/apiextensions,https://github.com/kubernetes/apiextensions-apiserver/blob/v0.32.1/LICENSE,Apache-2.0 68 | k8s.io/apimachinery/pkg,https://github.com/kubernetes/apimachinery/blob/v0.33.0/LICENSE,Apache-2.0 69 | k8s.io/apimachinery/third_party/forked/golang,https://github.com/kubernetes/apimachinery/blob/v0.33.0/third_party/forked/golang/LICENSE,BSD-3-Clause 70 | k8s.io/cli-runtime/pkg,https://github.com/kubernetes/cli-runtime/blob/v0.33.0/LICENSE,Apache-2.0 71 | k8s.io/client-go,https://github.com/kubernetes/client-go/blob/v0.33.0/LICENSE,Apache-2.0 72 | k8s.io/client-go/third_party/forked/golang/template,https://github.com/kubernetes/client-go/blob/v0.33.0/third_party/forked/golang/LICENSE,BSD-3-Clause 73 | k8s.io/component-base,https://github.com/kubernetes/component-base/blob/v0.33.0/LICENSE,Apache-2.0 74 | k8s.io/klog/v2,https://github.com/kubernetes/klog/blob/v2.130.1/LICENSE,Apache-2.0 75 | k8s.io/kube-openapi/pkg,https://github.com/kubernetes/kube-openapi/blob/c8a335a9a2ff/LICENSE,Apache-2.0 76 | k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json,https://github.com/kubernetes/kube-openapi/blob/c8a335a9a2ff/pkg/internal/third_party/go-json-experiment/json/LICENSE,BSD-3-Clause 77 | k8s.io/kube-openapi/pkg/validation/spec,https://github.com/kubernetes/kube-openapi/blob/c8a335a9a2ff/pkg/validation/spec/LICENSE,Apache-2.0 78 | k8s.io/utils,https://github.com/kubernetes/utils/blob/24370beab758/LICENSE,Apache-2.0 79 | k8s.io/utils/internal/third_party/forked/golang,https://github.com/kubernetes/utils/blob/24370beab758/internal/third_party/forked/golang/LICENSE,BSD-3-Clause 80 | sigs.k8s.io/controller-runtime,https://github.com/kubernetes-sigs/controller-runtime/blob/v0.20.4/LICENSE,Apache-2.0 81 | sigs.k8s.io/gateway-api/apis/v1,https://github.com/kubernetes-sigs/gateway-api/blob/v1.1.0/LICENSE,Apache-2.0 82 | sigs.k8s.io/json,https://github.com/kubernetes-sigs/json/blob/cfa47c3a1cc8/LICENSE,Apache-2.0 83 | sigs.k8s.io/json,https://github.com/kubernetes-sigs/json/blob/cfa47c3a1cc8/LICENSE,BSD-3-Clause 84 | sigs.k8s.io/kustomize/api,https://github.com/kubernetes-sigs/kustomize/blob/api/v0.19.0/api/LICENSE,Apache-2.0 85 | sigs.k8s.io/kustomize/kyaml,https://github.com/kubernetes-sigs/kustomize/blob/kyaml/v0.19.0/kyaml/LICENSE,Apache-2.0 86 | sigs.k8s.io/randfill,https://github.com/kubernetes-sigs/randfill/blob/v1.0.0/LICENSE,Apache-2.0 87 | sigs.k8s.io/structured-merge-diff/v4,https://github.com/kubernetes-sigs/structured-merge-diff/blob/v4.6.0/LICENSE,Apache-2.0 88 | sigs.k8s.io/yaml,https://github.com/kubernetes-sigs/yaml/blob/v1.4.0/LICENSE,MIT 89 | sigs.k8s.io/yaml,https://github.com/kubernetes-sigs/yaml/blob/v1.4.0/LICENSE,Apache-2.0 90 | sigs.k8s.io/yaml,https://github.com/kubernetes-sigs/yaml/blob/v1.4.0/LICENSE,BSD-3-Clause 91 | sigs.k8s.io/yaml/goyaml.v2,https://github.com/kubernetes-sigs/yaml/blob/v1.4.0/goyaml.v2/LICENSE,Apache-2.0 92 | sigs.k8s.io/yaml/goyaml.v3,https://github.com/kubernetes-sigs/yaml/blob/v1.4.0/goyaml.v3/LICENSE,MIT 93 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 16 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/Makefile instead. 17 | 18 | # NOTE FOR DEVELOPERS: "How do the Makefiles work and how can I extend them?" 19 | # 20 | # Shared Makefile logic lives in the make/_shared/ directory. The source of truth for these files 21 | # lies outside of this repository, eg. in the cert-manager/makefile-modules repository. 22 | # 23 | # Logic specific to this repository must be defined in the make/00_mod.mk and make/02_mod.mk files: 24 | # - The make/00_mod.mk file is included first and contains variable definitions needed by 25 | # the shared Makefile logic. 26 | # - The make/02_mod.mk file is included later, it can make use of most of the shared targets 27 | # defined in the make/_shared/ directory (all targets defined in 00_mod.mk and 01_mod.mk). 28 | # This file should be used to define targets specific to this repository. 29 | 30 | ################################## 31 | 32 | # Some modules build their dependencies from variables, we want these to be 33 | # evaluated at the last possible moment. For this we use second expansion to 34 | # re-evaluate the generate and verify targets a second time. 35 | # 36 | # See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html 37 | .SECONDEXPANSION: 38 | 39 | # For details on some of these "prelude" settings, see: 40 | # https://clarkgrubb.com/makefile-style-guide 41 | MAKEFLAGS += --warn-undefined-variables --no-builtin-rules 42 | SHELL := /usr/bin/env bash 43 | .SHELLFLAGS := -uo pipefail -c 44 | .DEFAULT_GOAL := help 45 | .DELETE_ON_ERROR: 46 | .SUFFIXES: 47 | FORCE: 48 | 49 | noop: # do nothing 50 | 51 | # Set empty value for MAKECMDGOALS to prevent the "warning: undefined variable 'MAKECMDGOALS'" 52 | # warning from happening when running make without arguments 53 | MAKECMDGOALS ?= 54 | 55 | ################################## 56 | # Host OS and architecture setup # 57 | ################################## 58 | 59 | # The reason we don't use "go env GOOS" or "go env GOARCH" is that the "go" 60 | # binary may not be available in the PATH yet when the Makefiles are 61 | # evaluated. HOST_OS and HOST_ARCH only support Linux, *BSD and macOS (M1 62 | # and Intel). 63 | host_os := $(shell uname -s | tr A-Z a-z) 64 | host_arch := $(shell uname -m) 65 | HOST_OS ?= $(host_os) 66 | HOST_ARCH ?= $(host_arch) 67 | 68 | ifeq (x86_64, $(HOST_ARCH)) 69 | HOST_ARCH = amd64 70 | else ifeq (aarch64, $(HOST_ARCH)) 71 | # linux reports the arm64 arch as aarch64 72 | HOST_ARCH = arm64 73 | endif 74 | 75 | ################################## 76 | # Git and versioning information # 77 | ################################## 78 | 79 | git_version := $(shell git describe --tags --always --match='v*' --abbrev=14 --dirty) 80 | VERSION ?= $(git_version) 81 | IS_PRERELEASE := $(shell git describe --tags --always --match='v*' --abbrev=0 | grep -q '-' && echo true || echo false) 82 | GITCOMMIT := $(shell git rev-parse HEAD) 83 | GITEPOCH := $(shell git show -s --format=%ct HEAD) 84 | 85 | ################################## 86 | # Global variables and dirs # 87 | ################################## 88 | 89 | bin_dir := _bin 90 | 91 | # The ARTIFACTS environment variable is set by the CI system to a directory 92 | # where artifacts should be placed. These artifacts are then uploaded to a 93 | # storage bucket by the CI system (https://docs.prow.k8s.io/docs/components/pod-utilities/). 94 | # An example of such an artifact is a jUnit XML file containing test results. 95 | # If the ARTIFACTS environment variable is not set, we default to a local 96 | # directory in the _bin directory. 97 | ARTIFACTS ?= $(bin_dir)/artifacts 98 | 99 | $(bin_dir) $(ARTIFACTS) $(bin_dir)/scratch: 100 | mkdir -p $@ 101 | 102 | .PHONY: clean 103 | ## Clean all temporary files 104 | ## @category [shared] Tools 105 | clean: 106 | rm -rf $(bin_dir) 107 | 108 | ################################## 109 | # Include all the Makefiles # 110 | ################################## 111 | 112 | -include make/00_mod.mk 113 | -include make/_shared/*/00_mod.mk 114 | -include make/_shared/*/01_mod.mk 115 | -include make/02_mod.mk 116 | -include make/_shared/*/02_mod.mk 117 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - cm-maintainers 3 | reviewers: 4 | - cm-maintainers 5 | -------------------------------------------------------------------------------- /OWNERS_ALIASES: -------------------------------------------------------------------------------- 1 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/OWNERS_ALIASES instead. 3 | 4 | aliases: 5 | cm-maintainers: 6 | - munnerz 7 | - joshvanl 8 | - wallrj 9 | - jakexks 10 | - maelvls 11 | - sgtcodfish 12 | - inteon 13 | - thatsmrtalbot 14 | - erikgb 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | cert-manager project logo 3 |

4 | 5 | # OpenShift Route Support for cert-manager 6 | 7 | This project supports automatically getting a certificate for 8 | OpenShift routes from any cert-manager Issuer, similar to annotating 9 | an Ingress or Gateway resource in vanilla Kubernetes! 10 | 11 | ## Prerequisites: 12 | 13 | 1. Ensure you have [cert-manager installed](https://cert-manager.io/docs/installation/) 14 | through the method of your choice. But make sure you install cert-manager and openshift-routes-deployment in the same namespace. By default this is in the namespace **cert-manager**. 15 | For example, with Helm: 16 | 17 | ```sh 18 | helm repo add jetstack https://charts.jetstack.io --force-update 19 | helm install \ 20 | cert-manager jetstack/cert-manager \ 21 | --namespace cert-manager \ 22 | --create-namespace \ 23 | --set crds.enabled=true 24 | ``` 25 | 26 | Both **ClusterIssuer** and namespace based **Issuer** are possible. Here a **ClusterIssuer** is used: 27 | 28 | 2. For example, create the ClusterIssuer (no additional ingress class is needed for the openshift-ingress router. The example.com email must be replaced by another one): 29 | 30 | ```yaml 31 | apiVersion: v1 32 | items: 33 | - apiVersion: cert-manager.io/v1 34 | kind: ClusterIssuer 35 | metadata: 36 | annotations: 37 | name: letsencrypt-prod 38 | spec: 39 | acme: 40 | email: mymail@example.com 41 | preferredChain: "" 42 | privateKeySecretRef: 43 | name: letsencrypt-prod 44 | server: https://acme-v02.api.letsencrypt.org/directory 45 | solvers: 46 | - http01: 47 | ingress: {} 48 | ``` 49 | 50 | ```sh 51 | oc apply -f clusterissuer.yaml 52 | ``` 53 | 54 | 3. Make sure that there is an A record on the load balancer IP or a CNAME record on the load balancer hostname in your DNS system for the HTTP-01 subdomain. 55 | 56 | ``` 57 | CNAME: 58 | Name: *.service.clustername.domain.com 59 | Alias: your-lb-domain.cloud 60 | ``` 61 | 62 | ## Installation 63 | 64 | The openshift-routes component can be installed using the Helm chart: 65 | 66 | ```shell 67 | helm install openshift-routes -n cert-manager oci://ghcr.io/cert-manager/charts/openshift-routes 68 | ``` 69 | 70 | or using templated static manifests: 71 | 72 | ```shell 73 | oc apply -f <(helm template openshift-routes -n cert-manager oci://ghcr.io/cert-manager/charts/openshift-routes --set omitHelmLabels=true) 74 | ``` 75 | 76 | Please review the [values.yaml](./deploy/chart/values.yaml) file for all configuration options. 77 | 78 | ## Usage 79 | 80 | If you follow the above prerequisites, use this annotations below 81 | 82 | ```yaml 83 | --- 84 | metadata: 85 | annotations: 86 | cert-manager.io/issuer-kind: ClusterIssuer 87 | cert-manager.io/issuer-name: letsencrypt-prod 88 | --- 89 | spec: 90 | host: app.service.clustername.domain.com 91 | ``` 92 | 93 | Annotate your routes: 94 | 95 | ```yaml 96 | apiVersion: route.openshift.io/v1 97 | kind: Route 98 | metadata: 99 | name: example-route 100 | annotations: 101 | cert-manager.io/issuer-name: my-issuer # This is the only required annotation 102 | cert-manager.io/issuer-group: cert-manager.io # Optional, defaults to cert-manager.io 103 | cert-manager.io/issuer-kind: Issuer # Optional, defaults to Issuer, could be ClusterIssuer or an External Issuer 104 | cert-manager.io/duration: 1h # Optional, defaults to 90 days 105 | cert-manager.io/renew-before: 30m # Optional, defaults to 1/3 of total certificate duration. 106 | cert-manager.io/common-name: "My Certificate" # Optional, no default. 107 | cert-manager.io/alt-names: "mycooldomain.com,mysecondarydomain.com" # Optional, no default 108 | cert-manager.io/ip-sans: "10.20.30.40,192.168.192.168" # Optional, no default 109 | cert-manager.io/uri-sans: "spiffe://trustdomain/workload" # Optional, no default 110 | cert-manager.io/private-key-algorithm: "ECDSA" # Optional, defaults to RSA 111 | cert-manager.io/private-key-size: "384" # Optional, defaults to 265 for ECDSA and 2048 for RSA 112 | cert-manager.io/email-sans: "me@example.com,you@example.com" # Optional, no default 113 | cert-manager.io/subject-organizations: "company" # Optional, no default 114 | cert-manager.io/subject-organizationalunits: "company division" # Optional, no default 115 | cert-manager.io/subject-countries: "My Country" # Optional, no default 116 | cert-manager.io/subject-provinces: "My Province" # Optional, no default 117 | cert-manager.io/subject-localities: "My City" # Optional, no default 118 | cert-manager.io/subject-postalcodes: "123ABC" # Optional, no default 119 | cert-manager.io/subject-streetaddresses: "1 Example St" # Optional, no default 120 | cert-manager.io/subject-serialnumber: "123456" # Optional, no default 121 | spec: 122 | host: app.service.clustername.domain.com # will be added to the Subject Alternative Names of the CertificateRequest 123 | port: 124 | targetPort: 8080 125 | to: 126 | kind: Service 127 | name: hello-openshift 128 | ``` 129 | 130 | Observe the `route.Spec.TLS` section of your route being populated automatically by cert-manager. 131 | 132 | The route's TLS certificate will be rotated 2/3 of the way through the certificate's lifetime, or 133 | `cert-manager.io/renew-before` time before it expires. 134 | 135 | Now the website can be called: https://app.service.clustername.domain.com 136 | 137 | ## Development 138 | 139 | The source code for the controller can be found in the `./internal/` folder. 140 | After modifying the source code, you can execute the tests with: 141 | 142 | ```sh 143 | go test ./... 144 | ``` 145 | 146 | # Why is This a Separate Project? 147 | 148 | We do not wish to support non Kubernetes (or kubernetes-sigs) APIs in cert-manager core. This adds 149 | a large maintenance burden, and it's hard for us to e2e test everyone's CRDs. However, OpenShift is 150 | widely used, so it makes sense to have some support for it in the cert-manager ecosystem. 151 | 152 | Ideally we would have contributed this controller to an existing project, e.g. 153 | https://github.com/redhat-cop/cert-utils-operator. Unfortunately, cert-manager is not really designed 154 | to be imported as a module. It has a large number of transitive dependencies that would add an unfair 155 | amount of maintenance to whichever project we submitted it to. In the future, we would like to split 156 | the cert-manager APIs and typed clients out of the main cert-manager repo, at which point it would be 157 | easier for other people to consume in their projects. 158 | 159 | # Release Process 160 | 161 | The release process is documented in [RELEASE.md](RELEASE.md). 162 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Releases 2 | 3 | ## Schedule 4 | 5 | The release schedule for this project is ad-hoc. Given the pre-1.0 status of the project we do not have a fixed release cadence. However if a vulnerability is discovered we will respond in accordance with our [security policy](https://github.com/cert-manager/community/blob/main/SECURITY.md) and this response may include a release. 6 | 7 | ## Process 8 | 9 | There is a semi-automated release process for this project. When you create a Git tag with a tagname that has a `v` prefix and push it to GitHub it will trigger the [release workflow]. 10 | 11 | The release process for this repo is documented below: 12 | 13 | 1. Create a tag for the new release: 14 | ```sh 15 | export VERSION=v0.6.0-alpha.0 16 | git tag --annotate --message="Release ${VERSION}" "${VERSION}" 17 | git push origin "${VERSION}" 18 | ``` 19 | 2. A GitHub action will see the new tag and do the following: 20 | - Build and publish any container images 21 | - Build and publish the Helm chart 22 | - Create a draft GitHub release 23 | 3. Visit the [releases page], edit the draft release, click "Generate release notes", then edit the notes to add the following to the top 24 | ``` 25 | openshift-routes provides OpenShift Route support for cert-manager 26 | ``` 27 | 4. Publish the release. 28 | 29 | ## Artifacts 30 | 31 | This repo will produce the following artifacts each release. For documentation on how those artifacts are produced see the "Process" section. 32 | 33 | - *Container Image* - Container image for openshift-routes is published to `ghcr.io/cert-manager/cert-manager-openshift-routes:vX.Y.Z`. 34 | - *Helm chart* - An official Helm chart is maintained within this repo and published to `ghcr.io/cert-manager/charts/openshift-routes:X.Y.Z`. 35 | 36 | [release workflow]: https://github.com/cert-manager/openshift-routes/actions/workflows/release.yaml 37 | [releases page]: https://github.com/cert-manager/openshift-routes/releases -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | 3 | name: openshift-routes 4 | type: application 5 | description: A Helm chart to deploy openshift-routes adapter for cert-manager on Kubernetes 6 | 7 | home: https://github.com/cert-manager/openshift-routes 8 | icon: https://raw.githubusercontent.com/cert-manager/community/4d35a69437d21b76322157e6284be4cd64e6d2b7/logo/logo-small.png 9 | keywords: 10 | - cert-manager 11 | - openshift 12 | - routes 13 | annotations: 14 | artifacthub.io/alternativeName: openshift-routes 15 | artifacthub.io/license: Apache-2.0 16 | artifacthub.io/category: security 17 | artifacthub.io/recommendations: | 18 | - url: https://artifacthub.io/packages/helm/cert-manager/cert-manager 19 | maintainers: 20 | - name: cert-manager-maintainers 21 | email: cert-manager-maintainers@googlegroups.com 22 | url: https://cert-manager.io 23 | sources: 24 | - https://github.com/cert-manager/openshift-routes 25 | 26 | appVersion: v0.0.0 27 | version: v0.0.0 -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/README.md: -------------------------------------------------------------------------------- 1 | # cert-manager Openshift Routes 2 | 3 | 4 | 5 | ## Helm Values 6 | 7 | 8 | 9 | #### **replicas** ~ `number` 10 | > Default value: 11 | > ```yaml 12 | > 1 13 | > ``` 14 | #### **logLevel** ~ `number` 15 | > Default value: 16 | > ```yaml 17 | > 5 18 | > ``` 19 | #### **namespace** ~ `string` 20 | > Default value: 21 | > ```yaml 22 | > "" 23 | > ``` 24 | 25 | This namespace allows you to define where the services are installed into. If not set then they use the namespace of the release. This is helpful when installing cert manager as a chart dependency (sub chart). 26 | #### **fullnameOverride** ~ `string` 27 | 28 | Override the "cert-manager.fullname" value. This value is used as part of most of the names of the resources created by this Helm chart. 29 | 30 | #### **nameOverride** ~ `string` 31 | 32 | Override the "cert-manager.name" value, which is used to annotate some of the resources that are created by this Chart (using "app.kubernetes.io/name"). NOTE: There are some inconsitencies in the Helm chart when it comes to these annotations (some resources use eg. "cainjector.name" which resolves to the value "cainjector"). 33 | 34 | #### **image.registry** ~ `string` 35 | 36 | Target image registry. This value is prepended to the target image repository, if set. 37 | For example: 38 | 39 | ```yaml 40 | registry: quay.io 41 | repository: jetstack/cert-manager-openshift-routes 42 | ``` 43 | 44 | #### **image.repository** ~ `string` 45 | > Default value: 46 | > ```yaml 47 | > ghcr.io/cert-manager/cert-manager-openshift-routes 48 | > ``` 49 | 50 | Target image repository. 51 | #### **image.tag** ~ `string` 52 | 53 | Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used. 54 | 55 | #### **image.digest** ~ `string` 56 | 57 | Target image digest. Override any tag, if set. 58 | For example: 59 | 60 | ```yaml 61 | digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 62 | ``` 63 | 64 | #### **image.pullPolicy** ~ `string` 65 | > Default value: 66 | > ```yaml 67 | > IfNotPresent 68 | > ``` 69 | 70 | Kubernetes imagePullPolicy on Deployment. 71 | #### **imagePullSecrets** ~ `array` 72 | > Default value: 73 | > ```yaml 74 | > [] 75 | > ``` 76 | 77 | Optional secrets used for pulling the openshift-routes container image. 78 | #### **serviceAccount.create** ~ `bool` 79 | > Default value: 80 | > ```yaml 81 | > true 82 | > ``` 83 | 84 | Specifies whether a service account should be created 85 | #### **serviceAccount.name** ~ `string` 86 | 87 | The name of the service account to use. 88 | If not set and create is true, a name is generated using the fullname template. 89 | 90 | #### **serviceAccount.annotations** ~ `object` 91 | 92 | Optional additional annotations to add to the controller's Service Account. 93 | 94 | #### **rbac.create** ~ `bool` 95 | > Default value: 96 | > ```yaml 97 | > true 98 | > ``` 99 | 100 | create (Cluster-) Roles and RoleBindings for the ServiceAccount 101 | #### **podAnnotations** ~ `object` 102 | > Default value: 103 | > ```yaml 104 | > {} 105 | > ``` 106 | 107 | Annotations to add to the openshift-routes pod. 108 | #### **podSecurityContext** ~ `object` 109 | > Default value: 110 | > ```yaml 111 | > runAsNonRoot: true 112 | > seccompProfile: 113 | > type: RuntimeDefault 114 | > ``` 115 | 116 | Pod Security Context. 117 | For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). 118 | 119 | #### **securityContext** ~ `object` 120 | > Default value: 121 | > ```yaml 122 | > allowPrivilegeEscalation: false 123 | > capabilities: 124 | > drop: 125 | > - ALL 126 | > readOnlyRootFilesystem: true 127 | > ``` 128 | 129 | Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). 130 | 131 | #### **resources** ~ `object` 132 | > Default value: 133 | > ```yaml 134 | > {} 135 | > ``` 136 | 137 | Kubernetes pod resources 138 | ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ 139 | 140 | For example: 141 | 142 | ```yaml 143 | resources: 144 | limits: 145 | memory: 128Mi 146 | requests: 147 | cpu: 100m 148 | memory: 128Mi 149 | ``` 150 | #### **nodeSelector** ~ `object` 151 | > Default value: 152 | > ```yaml 153 | > kubernetes.io/os: linux 154 | > ``` 155 | 156 | The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). 157 | 158 | This default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. 159 | 160 | #### **tolerations** ~ `array` 161 | > Default value: 162 | > ```yaml 163 | > [] 164 | > ``` 165 | 166 | A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). 167 | 168 | For example: 169 | 170 | ```yaml 171 | tolerations: 172 | - key: foo.bar.com/role 173 | operator: Equal 174 | value: master 175 | effect: NoSchedule 176 | ``` 177 | #### **affinity** ~ `object` 178 | > Default value: 179 | > ```yaml 180 | > {} 181 | > ``` 182 | 183 | A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). 184 | 185 | For example: 186 | 187 | ```yaml 188 | affinity: 189 | nodeAffinity: 190 | requiredDuringSchedulingIgnoredDuringExecution: 191 | nodeSelectorTerms: 192 | - matchExpressions: 193 | - key: foo.bar.com/role 194 | operator: In 195 | values: 196 | - master 197 | ``` 198 | #### **metrics.enabled** ~ `bool` 199 | > Default value: 200 | > ```yaml 201 | > false 202 | > ``` 203 | 204 | when enabled, a service is created that exposes the metrics endpoint 205 | #### **metrics.serviceMonitor.enabled** ~ `bool` 206 | > Default value: 207 | > ```yaml 208 | > false 209 | > ``` 210 | 211 | Create a ServiceMonitor to add openshift-routes to Prometheus. 212 | #### **metrics.serviceMonitor.interval** ~ `string` 213 | > Default value: 214 | > ```yaml 215 | > 60s 216 | > ``` 217 | 218 | The interval to scrape metrics. 219 | #### **omitHelmLabels** ~ `bool` 220 | > Default value: 221 | > ```yaml 222 | > false 223 | > ``` 224 | 225 | Omit Helm-specific labels. This is useful when generating a static manifest with `helm template`. 226 | 227 | -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "openshift-routes.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 7 | {{- end }} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "openshift-routes.fullname" -}} 15 | {{- if .Values.fullnameOverride }} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 17 | {{- else }} 18 | {{- $name := default .Chart.Name .Values.nameOverride }} 19 | {{- if contains $name .Release.Name }} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 21 | {{- else }} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 23 | {{- end }} 24 | {{- end }} 25 | {{- end }} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "openshift-routes.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 32 | {{- end }} 33 | 34 | {{/* 35 | Namespace for all resources to be installed into 36 | If not defined in values file then the helm release namespace is used 37 | By default this is not set so the helm release namespace will be used. 38 | 39 | 40 | This gets around an problem within Helm discussed in 41 | https://github.com/helm/helm/issues/5358. 42 | */}} 43 | {{- define "openshift-routes.namespace" -}} 44 | {{ .Values.namespace | default .Release.Namespace }} 45 | {{- end -}} 46 | 47 | {{/* 48 | Common labels 49 | */}} 50 | {{- define "openshift-routes.labels" -}} 51 | {{/* 52 | You can generate generate a static manifest free of Helm-specific labels by 53 | using `--set omitHelmLabels=true`. 54 | */}} 55 | {{- include "openshift-routes.selectorLabels" . }} 56 | app.kubernetes.io/version: {{ .Chart.AppVersion }} 57 | app.kubernetes.io/component: controller 58 | {{- if not .Values.omitHelmLabels }} 59 | app.kubernetes.io/managed-by: {{ .Release.Service }} 60 | helm.sh/chart: {{ include "openshift-routes.chart" . }} 61 | {{- end }} 62 | {{- end }} 63 | 64 | {{/* 65 | Selector labels 66 | */}} 67 | {{- define "openshift-routes.selectorLabels" -}} 68 | app.kubernetes.io/name: {{ include "openshift-routes.name" . }} 69 | {{- if not .Values.omitHelmLabels }} 70 | app.kubernetes.io/instance: {{ .Release.Name }} 71 | {{- end}} 72 | {{- end }} 73 | 74 | {{/* 75 | Create the name of the service account to use 76 | */}} 77 | {{- define "openshift-routes.serviceAccountName" -}} 78 | {{- if .Values.serviceAccount.create }} 79 | {{- default (include "openshift-routes.fullname" .) .Values.serviceAccount.name }} 80 | {{- else }} 81 | {{- default "default" .Values.serviceAccount.name }} 82 | {{- end }} 83 | {{- end }} 84 | 85 | {{/* 86 | Util function for generating the image URL based on the provided options. 87 | IMPORTANT: This function is standarized across all charts in the cert-manager GH organization. 88 | Any changes to this function should also be made in cert-manager, trust-manager, approver-policy, ... 89 | See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linked PRs. 90 | */}} 91 | {{- define "openshift-routes.image" -}} 92 | {{- $defaultTag := index . 1 -}} 93 | {{- with index . 0 -}} 94 | {{- if .registry -}}{{ printf "%s/%s" .registry .repository }}{{- else -}}{{- .repository -}}{{- end -}} 95 | {{- if .digest -}}{{ printf "@%s" .digest }}{{- else -}}{{ printf ":%s" (default $defaultTag .tag) }}{{- end -}} 96 | {{- end }} 97 | {{- end }} 98 | -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "openshift-routes.fullname" . }} 5 | namespace: {{ include "openshift-routes.namespace" . }} 6 | labels: 7 | {{- include "openshift-routes.labels" . | nindent 4 }} 8 | spec: 9 | replicas: {{ .Values.replicas }} 10 | selector: 11 | matchLabels: 12 | {{- include "openshift-routes.selectorLabels" . | nindent 6 }} 13 | template: 14 | metadata: 15 | {{- with .Values.podAnnotations }} 16 | annotations: 17 | {{- toYaml . | nindent 8 }} 18 | {{- end }} 19 | labels: 20 | {{- include "openshift-routes.labels" . | nindent 8 }} 21 | spec: 22 | automountServiceAccountToken: true 23 | {{- with .Values.imagePullSecrets }} 24 | imagePullSecrets: 25 | {{- toYaml . | nindent 8 }} 26 | {{- end }} 27 | serviceAccountName: {{ include "openshift-routes.serviceAccountName" . }} 28 | securityContext: 29 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 30 | containers: 31 | - name: openshift-routes 32 | securityContext: 33 | {{- toYaml .Values.securityContext | nindent 12 }} 34 | image: "{{ template "openshift-routes.image" (tuple .Values.image $.Chart.AppVersion) }}" 35 | imagePullPolicy: {{ .Values.image.pullPolicy }} 36 | args: 37 | - "-v={{ .Values.logLevel }}" 38 | - "--leader-election-namespace={{ .Release.Namespace }}" 39 | ports: 40 | - containerPort: 6060 41 | name: readiness 42 | protocol: TCP 43 | {{- if .Values.metrics.enabled }} 44 | - containerPort: 9402 45 | name: metrics 46 | protocol: TCP 47 | {{- end }} 48 | readinessProbe: 49 | httpGet: 50 | port: readiness 51 | path: "/readyz" 52 | initialDelaySeconds: 3 53 | periodSeconds: 5 54 | timeoutSeconds: 3 55 | resources: 56 | {{- toYaml .Values.resources | nindent 12 }} 57 | {{- with .Values.nodeSelector }} 58 | nodeSelector: 59 | {{- toYaml . | nindent 8 }} 60 | {{- end }} 61 | {{- with .Values.affinity }} 62 | affinity: 63 | {{- toYaml . | nindent 8 }} 64 | {{- end }} 65 | {{- with .Values.tolerations }} 66 | tolerations: 67 | {{- toYaml . | nindent 8 }} 68 | {{- end }} 69 | -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/templates/rbac.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.rbac.create }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: {{ include "openshift-routes.fullname" . }} 6 | labels: 7 | {{- include "openshift-routes.labels" . | nindent 4 }} 8 | rules: 9 | - apiGroups: 10 | - route.openshift.io 11 | resources: 12 | - routes 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - patch 18 | - update 19 | - apiGroups: 20 | - route.openshift.io 21 | resources: 22 | - routes/finalizers 23 | verbs: 24 | - update 25 | - apiGroups: 26 | - route.openshift.io 27 | resources: 28 | - routes/custom-host 29 | verbs: 30 | - create 31 | - update 32 | - apiGroups: 33 | - cert-manager.io 34 | resources: 35 | - certificates 36 | verbs: 37 | - create 38 | - get 39 | - list 40 | - watch 41 | - apiGroups: 42 | - cert-manager.io 43 | resources: 44 | - certificates/status 45 | verbs: 46 | - get 47 | - list 48 | - watch 49 | - apiGroups: 50 | - "" 51 | resources: 52 | - secrets 53 | verbs: 54 | - get 55 | - list 56 | - watch 57 | - apiGroups: 58 | - "" 59 | resources: 60 | - events 61 | verbs: 62 | - create 63 | - patch 64 | - apiGroups: 65 | - coordination.k8s.io 66 | resources: 67 | - leases 68 | verbs: 69 | - create 70 | - get 71 | - list 72 | - update 73 | --- 74 | apiVersion: rbac.authorization.k8s.io/v1 75 | kind: ClusterRoleBinding 76 | metadata: 77 | name: {{ include "openshift-routes.fullname" . }} 78 | labels: 79 | {{- include "openshift-routes.labels" . | nindent 4 }} 80 | roleRef: 81 | apiGroup: rbac.authorization.k8s.io 82 | kind: ClusterRole 83 | name: {{ include "openshift-routes.fullname" . }} 84 | subjects: 85 | - kind: ServiceAccount 86 | name: {{ include "openshift-routes.serviceAccountName" . }} 87 | namespace: {{ .Release.Namespace }} 88 | {{- end }} 89 | -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/templates/service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.metrics.enabled }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ include "openshift-routes.fullname" . }} 6 | namespace: {{ include "openshift-routes.namespace" . }} 7 | labels: 8 | {{- include "openshift-routes.labels" . | nindent 4 }} 9 | spec: 10 | selector: 11 | {{- include "openshift-routes.selectorLabels" . | nindent 4 }} 12 | type: ClusterIP 13 | ports: 14 | - name: metrics 15 | port: 9402 16 | targetPort: metrics 17 | protocol: TCP 18 | {{- end }} 19 | -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "openshift-routes.serviceAccountName" . }} 6 | namespace: {{ include "openshift-routes.namespace" . }} 7 | labels: 8 | {{- include "openshift-routes.labels" . | nindent 4 }} 9 | {{- with .Values.serviceAccount.annotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | automountServiceAccountToken: false 14 | {{- end }} 15 | -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.metrics.serviceMonitor.enabled }} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | name: {{ include "openshift-routes.fullname" . }} 6 | namespace: {{ include "openshift-routes.namespace" . }} 7 | labels: 8 | {{- include "openshift-routes.labels" . | nindent 4 }} 9 | spec: 10 | endpoints: 11 | - honorLabels: false 12 | interval: {{ .Values.metrics.serviceMonitor.interval }} 13 | path: /metrics 14 | scrapeTimeout: 15s 15 | targetPort: metrics 16 | selector: 17 | matchLabels: 18 | {{- include "openshift-routes.labels" . | nindent 6 }} 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/values.linter.exceptions: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cert-manager/openshift-routes/cbb84c1c95f2facc5a1ea5d09230f79d93ed5a06/deploy/charts/openshift-routes/values.linter.exceptions -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/values.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$defs": { 3 | "helm-values": { 4 | "additionalProperties": false, 5 | "properties": { 6 | "affinity": { 7 | "$ref": "#/$defs/helm-values.affinity" 8 | }, 9 | "fullnameOverride": { 10 | "$ref": "#/$defs/helm-values.fullnameOverride" 11 | }, 12 | "global": { 13 | "$ref": "#/$defs/helm-values.global" 14 | }, 15 | "image": { 16 | "$ref": "#/$defs/helm-values.image" 17 | }, 18 | "imagePullSecrets": { 19 | "$ref": "#/$defs/helm-values.imagePullSecrets" 20 | }, 21 | "logLevel": { 22 | "$ref": "#/$defs/helm-values.logLevel" 23 | }, 24 | "metrics": { 25 | "$ref": "#/$defs/helm-values.metrics" 26 | }, 27 | "nameOverride": { 28 | "$ref": "#/$defs/helm-values.nameOverride" 29 | }, 30 | "namespace": { 31 | "$ref": "#/$defs/helm-values.namespace" 32 | }, 33 | "nodeSelector": { 34 | "$ref": "#/$defs/helm-values.nodeSelector" 35 | }, 36 | "omitHelmLabels": { 37 | "$ref": "#/$defs/helm-values.omitHelmLabels" 38 | }, 39 | "podAnnotations": { 40 | "$ref": "#/$defs/helm-values.podAnnotations" 41 | }, 42 | "podSecurityContext": { 43 | "$ref": "#/$defs/helm-values.podSecurityContext" 44 | }, 45 | "rbac": { 46 | "$ref": "#/$defs/helm-values.rbac" 47 | }, 48 | "replicas": { 49 | "$ref": "#/$defs/helm-values.replicas" 50 | }, 51 | "resources": { 52 | "$ref": "#/$defs/helm-values.resources" 53 | }, 54 | "securityContext": { 55 | "$ref": "#/$defs/helm-values.securityContext" 56 | }, 57 | "serviceAccount": { 58 | "$ref": "#/$defs/helm-values.serviceAccount" 59 | }, 60 | "tolerations": { 61 | "$ref": "#/$defs/helm-values.tolerations" 62 | } 63 | }, 64 | "type": "object" 65 | }, 66 | "helm-values.affinity": { 67 | "default": {}, 68 | "description": "A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core).\n\nFor example:\naffinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", 69 | "type": "object" 70 | }, 71 | "helm-values.fullnameOverride": { 72 | "description": "Override the \"cert-manager.fullname\" value. This value is used as part of most of the names of the resources created by this Helm chart.", 73 | "type": "string" 74 | }, 75 | "helm-values.global": { 76 | "description": "Global values shared across all (sub)charts" 77 | }, 78 | "helm-values.image": { 79 | "additionalProperties": false, 80 | "properties": { 81 | "digest": { 82 | "$ref": "#/$defs/helm-values.image.digest" 83 | }, 84 | "pullPolicy": { 85 | "$ref": "#/$defs/helm-values.image.pullPolicy" 86 | }, 87 | "registry": { 88 | "$ref": "#/$defs/helm-values.image.registry" 89 | }, 90 | "repository": { 91 | "$ref": "#/$defs/helm-values.image.repository" 92 | }, 93 | "tag": { 94 | "$ref": "#/$defs/helm-values.image.tag" 95 | } 96 | }, 97 | "type": "object" 98 | }, 99 | "helm-values.image.digest": { 100 | "description": "Target image digest. Override any tag, if set.\nFor example:\ndigest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20", 101 | "type": "string" 102 | }, 103 | "helm-values.image.pullPolicy": { 104 | "default": "IfNotPresent", 105 | "description": "Kubernetes imagePullPolicy on Deployment.", 106 | "type": "string" 107 | }, 108 | "helm-values.image.registry": { 109 | "description": "Target image registry. This value is prepended to the target image repository, if set.\nFor example:\nregistry: quay.io\nrepository: jetstack/cert-manager-openshift-routes", 110 | "type": "string" 111 | }, 112 | "helm-values.image.repository": { 113 | "default": "ghcr.io/cert-manager/cert-manager-openshift-routes", 114 | "description": "Target image repository.", 115 | "type": "string" 116 | }, 117 | "helm-values.image.tag": { 118 | "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used.", 119 | "type": "string" 120 | }, 121 | "helm-values.imagePullSecrets": { 122 | "default": [], 123 | "description": "Optional secrets used for pulling the openshift-routes container image.", 124 | "items": {}, 125 | "type": "array" 126 | }, 127 | "helm-values.logLevel": { 128 | "default": 5, 129 | "type": "number" 130 | }, 131 | "helm-values.metrics": { 132 | "additionalProperties": false, 133 | "properties": { 134 | "enabled": { 135 | "$ref": "#/$defs/helm-values.metrics.enabled" 136 | }, 137 | "serviceMonitor": { 138 | "$ref": "#/$defs/helm-values.metrics.serviceMonitor" 139 | } 140 | }, 141 | "type": "object" 142 | }, 143 | "helm-values.metrics.enabled": { 144 | "default": false, 145 | "description": "when enabled, a service is created that exposes the metrics endpoint", 146 | "type": "boolean" 147 | }, 148 | "helm-values.metrics.serviceMonitor": { 149 | "additionalProperties": false, 150 | "properties": { 151 | "enabled": { 152 | "$ref": "#/$defs/helm-values.metrics.serviceMonitor.enabled" 153 | }, 154 | "interval": { 155 | "$ref": "#/$defs/helm-values.metrics.serviceMonitor.interval" 156 | } 157 | }, 158 | "type": "object" 159 | }, 160 | "helm-values.metrics.serviceMonitor.enabled": { 161 | "default": false, 162 | "description": "Create a ServiceMonitor to add openshift-routes to Prometheus.", 163 | "type": "boolean" 164 | }, 165 | "helm-values.metrics.serviceMonitor.interval": { 166 | "default": "60s", 167 | "description": "The interval to scrape metrics.", 168 | "type": "string" 169 | }, 170 | "helm-values.nameOverride": { 171 | "description": "Override the \"cert-manager.name\" value, which is used to annotate some of the resources that are created by this Chart (using \"app.kubernetes.io/name\"). NOTE: There are some inconsitencies in the Helm chart when it comes to these annotations (some resources use eg. \"cainjector.name\" which resolves to the value \"cainjector\").", 172 | "type": "string" 173 | }, 174 | "helm-values.namespace": { 175 | "default": "", 176 | "description": "This namespace allows you to define where the services are installed into. If not set then they use the namespace of the release. This is helpful when installing cert manager as a chart dependency (sub chart).", 177 | "type": "string" 178 | }, 179 | "helm-values.nodeSelector": { 180 | "default": { 181 | "kubernetes.io/os": "linux" 182 | }, 183 | "description": "The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nThis default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster.", 184 | "type": "object" 185 | }, 186 | "helm-values.omitHelmLabels": { 187 | "default": false, 188 | "description": "Omit Helm-specific labels. This is useful when generating a static manifest with `helm template`.", 189 | "type": "boolean" 190 | }, 191 | "helm-values.podAnnotations": { 192 | "default": {}, 193 | "description": "Annotations to add to the openshift-routes pod.", 194 | "type": "object" 195 | }, 196 | "helm-values.podSecurityContext": { 197 | "default": { 198 | "runAsNonRoot": true, 199 | "seccompProfile": { 200 | "type": "RuntimeDefault" 201 | } 202 | }, 203 | "description": "Pod Security Context.\nFor more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", 204 | "type": "object" 205 | }, 206 | "helm-values.rbac": { 207 | "additionalProperties": false, 208 | "properties": { 209 | "create": { 210 | "$ref": "#/$defs/helm-values.rbac.create" 211 | } 212 | }, 213 | "type": "object" 214 | }, 215 | "helm-values.rbac.create": { 216 | "default": true, 217 | "description": "create (Cluster-) Roles and RoleBindings for the ServiceAccount", 218 | "type": "boolean" 219 | }, 220 | "helm-values.replicas": { 221 | "default": 1, 222 | "type": "number" 223 | }, 224 | "helm-values.resources": { 225 | "default": {}, 226 | "description": "Kubernetes pod resources\nref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/\n\nFor example:\nresources:\n limits:\n memory: 128Mi\n requests:\n cpu: 100m\n memory: 128Mi", 227 | "type": "object" 228 | }, 229 | "helm-values.securityContext": { 230 | "default": { 231 | "allowPrivilegeEscalation": false, 232 | "capabilities": { 233 | "drop": [ 234 | "ALL" 235 | ] 236 | }, 237 | "readOnlyRootFilesystem": true 238 | }, 239 | "description": "Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", 240 | "type": "object" 241 | }, 242 | "helm-values.serviceAccount": { 243 | "additionalProperties": false, 244 | "properties": { 245 | "annotations": { 246 | "$ref": "#/$defs/helm-values.serviceAccount.annotations" 247 | }, 248 | "create": { 249 | "$ref": "#/$defs/helm-values.serviceAccount.create" 250 | }, 251 | "name": { 252 | "$ref": "#/$defs/helm-values.serviceAccount.name" 253 | } 254 | }, 255 | "type": "object" 256 | }, 257 | "helm-values.serviceAccount.annotations": { 258 | "description": "Optional additional annotations to add to the controller's Service Account.", 259 | "type": "object" 260 | }, 261 | "helm-values.serviceAccount.create": { 262 | "default": true, 263 | "description": "Specifies whether a service account should be created", 264 | "type": "boolean" 265 | }, 266 | "helm-values.serviceAccount.name": { 267 | "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template.", 268 | "type": "string" 269 | }, 270 | "helm-values.tolerations": { 271 | "default": [], 272 | "description": "A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core).\n\nFor example:\ntolerations:\n- key: foo.bar.com/role\n operator: Equal\n value: master\n effect: NoSchedule", 273 | "items": {}, 274 | "type": "array" 275 | } 276 | }, 277 | "$ref": "#/$defs/helm-values", 278 | "$schema": "http://json-schema.org/draft-07/schema#" 279 | } 280 | -------------------------------------------------------------------------------- /deploy/charts/openshift-routes/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for openshift-routes. 2 | 3 | replicas: 1 4 | logLevel: 5 5 | 6 | # This namespace allows you to define where the services are installed into. 7 | # If not set then they use the namespace of the release. 8 | # This is helpful when installing cert manager as a chart dependency (sub chart). 9 | namespace: "" 10 | 11 | # Override the "cert-manager.fullname" value. This value is used as part of 12 | # most of the names of the resources created by this Helm chart. 13 | # +docs:property 14 | # fullnameOverride: "my-cert-manager" 15 | 16 | # Override the "cert-manager.name" value, which is used to annotate some of 17 | # the resources that are created by this Chart (using "app.kubernetes.io/name"). 18 | # NOTE: There are some inconsitencies in the Helm chart when it comes to 19 | # these annotations (some resources use eg. "cainjector.name" which resolves 20 | # to the value "cainjector"). 21 | # +docs:property 22 | # nameOverride: "my-cert-manager" 23 | 24 | image: 25 | # Target image registry. This value is prepended to the target image repository, if set. 26 | # For example: 27 | # registry: quay.io 28 | # repository: jetstack/cert-manager-openshift-routes 29 | # +docs:property 30 | # registry: quay.io 31 | 32 | # Target image repository. 33 | repository: ghcr.io/cert-manager/cert-manager-openshift-routes 34 | 35 | # Override the image tag to deploy by setting this variable. 36 | # If no value is set, the chart's appVersion is used. 37 | # +docs:property 38 | # tag: vX.Y.Z 39 | 40 | # Target image digest. Override any tag, if set. 41 | # For example: 42 | # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 43 | # +docs:property 44 | # digest: sha256:... 45 | 46 | # Kubernetes imagePullPolicy on Deployment. 47 | pullPolicy: IfNotPresent 48 | 49 | # Optional secrets used for pulling the openshift-routes container image. 50 | imagePullSecrets: [] 51 | 52 | serviceAccount: 53 | # Specifies whether a service account should be created 54 | create: true 55 | 56 | # The name of the service account to use. 57 | # If not set and create is true, a name is generated using the fullname template. 58 | # +docs:property 59 | # name: "" 60 | 61 | # Optional additional annotations to add to the controller's Service Account. 62 | # +docs:property 63 | # annotations: {} 64 | 65 | rbac: 66 | # create (Cluster-) Roles and RoleBindings for the ServiceAccount 67 | create: true 68 | 69 | # Annotations to add to the openshift-routes pod. 70 | podAnnotations: {} 71 | 72 | # Pod Security Context. 73 | # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). 74 | # +docs:property 75 | podSecurityContext: 76 | runAsNonRoot: true 77 | seccompProfile: 78 | type: RuntimeDefault 79 | 80 | # Container Security Context to be set on the controller component container. 81 | # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). 82 | # +docs:property 83 | securityContext: 84 | allowPrivilegeEscalation: false 85 | capabilities: 86 | drop: 87 | - ALL 88 | readOnlyRootFilesystem: true 89 | 90 | # Kubernetes pod resources 91 | # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ 92 | # 93 | # For example: 94 | # resources: 95 | # limits: 96 | # memory: 128Mi 97 | # requests: 98 | # cpu: 100m 99 | # memory: 128Mi 100 | resources: {} 101 | 102 | # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with 103 | # matching labels. 104 | # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). 105 | # 106 | # This default ensures that Pods are only scheduled to Linux nodes. 107 | # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. 108 | # +docs:property 109 | nodeSelector: 110 | kubernetes.io/os: linux 111 | 112 | # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). 113 | # 114 | # For example: 115 | # tolerations: 116 | # - key: foo.bar.com/role 117 | # operator: Equal 118 | # value: master 119 | # effect: NoSchedule 120 | tolerations: [] 121 | 122 | # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). 123 | # 124 | # For example: 125 | # affinity: 126 | # nodeAffinity: 127 | # requiredDuringSchedulingIgnoredDuringExecution: 128 | # nodeSelectorTerms: 129 | # - matchExpressions: 130 | # - key: foo.bar.com/role 131 | # operator: In 132 | # values: 133 | # - master 134 | affinity: {} 135 | 136 | metrics: 137 | # when enabled, a service is created that exposes the metrics endpoint 138 | enabled: false 139 | 140 | serviceMonitor: 141 | # Create a ServiceMonitor to add openshift-routes to Prometheus. 142 | enabled: false 143 | 144 | # The interval to scrape metrics. 145 | interval: 60s 146 | 147 | # Omit Helm-specific labels. This is useful when generating a static manifest 148 | # with `helm template`. 149 | omitHelmLabels: false 150 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cert-manager/openshift-routes 2 | 3 | go 1.24.0 4 | 5 | // Do not remove this comment: 6 | // please place any replace statements here at the top for visibility and add a 7 | // comment to it as to when it can be removed 8 | 9 | require ( 10 | github.com/cert-manager/cert-manager v1.17.2 11 | github.com/go-logr/logr v1.4.2 12 | github.com/openshift/api v0.0.0-20240909041644-5852b58f4b10 13 | github.com/openshift/client-go v0.0.0-20240906181530-b2f7c4ab0984 14 | github.com/spf13/cobra v1.9.1 15 | github.com/spf13/pflag v1.0.6 16 | github.com/stretchr/testify v1.10.0 17 | k8s.io/api v0.33.0 18 | k8s.io/apimachinery v0.33.0 19 | k8s.io/cli-runtime v0.33.0 20 | k8s.io/client-go v0.33.0 21 | k8s.io/component-base v0.33.0 22 | k8s.io/klog/v2 v2.130.1 23 | sigs.k8s.io/controller-runtime v0.20.4 24 | ) 25 | 26 | require ( 27 | github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect 28 | github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect 29 | github.com/beorn7/perks v1.0.1 // indirect 30 | github.com/blang/semver/v4 v4.0.0 // indirect 31 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 32 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 33 | github.com/emicklei/go-restful/v3 v3.12.1 // indirect 34 | github.com/evanphx/json-patch/v5 v5.9.11 // indirect 35 | github.com/fsnotify/fsnotify v1.8.0 // indirect 36 | github.com/fxamacker/cbor/v2 v2.7.0 // indirect 37 | github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect 38 | github.com/go-errors/errors v1.5.1 // indirect 39 | github.com/go-ldap/ldap/v3 v3.4.8 // indirect 40 | github.com/go-logr/zapr v1.3.0 // indirect 41 | github.com/go-openapi/jsonpointer v0.21.0 // indirect 42 | github.com/go-openapi/jsonreference v0.21.0 // indirect 43 | github.com/go-openapi/swag v0.23.0 // indirect 44 | github.com/gogo/protobuf v1.3.2 // indirect 45 | github.com/google/btree v1.1.3 // indirect 46 | github.com/google/gnostic-models v0.6.9 // indirect 47 | github.com/google/go-cmp v0.7.0 // indirect 48 | github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect 49 | github.com/google/uuid v1.6.0 // indirect 50 | github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect 51 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 52 | github.com/josharian/intern v1.0.0 // indirect 53 | github.com/json-iterator/go v1.1.12 // indirect 54 | github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect 55 | github.com/mailru/easyjson v0.9.0 // indirect 56 | github.com/moby/term v0.5.0 // indirect 57 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 58 | github.com/modern-go/reflect2 v1.0.2 // indirect 59 | github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect 60 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 61 | github.com/peterbourgon/diskv v2.0.1+incompatible // indirect 62 | github.com/pkg/errors v0.9.1 // indirect 63 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 64 | github.com/prometheus/client_golang v1.22.0 // indirect 65 | github.com/prometheus/client_model v0.6.1 // indirect 66 | github.com/prometheus/common v0.62.0 // indirect 67 | github.com/prometheus/procfs v0.15.1 // indirect 68 | github.com/x448/float16 v0.8.4 // indirect 69 | github.com/xlab/treeprint v1.2.0 // indirect 70 | go.opentelemetry.io/otel v1.33.0 // indirect 71 | go.opentelemetry.io/otel/trace v1.33.0 // indirect 72 | go.uber.org/multierr v1.11.0 // indirect 73 | go.uber.org/zap v1.27.0 // indirect 74 | golang.org/x/crypto v0.36.0 // indirect 75 | golang.org/x/net v0.38.0 // indirect 76 | golang.org/x/oauth2 v0.28.0 // indirect 77 | golang.org/x/sync v0.12.0 // indirect 78 | golang.org/x/sys v0.31.0 // indirect 79 | golang.org/x/term v0.30.0 // indirect 80 | golang.org/x/text v0.23.0 // indirect 81 | golang.org/x/time v0.9.0 // indirect 82 | gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect 83 | google.golang.org/protobuf v1.36.5 // indirect 84 | gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect 85 | gopkg.in/inf.v0 v0.9.1 // indirect 86 | gopkg.in/yaml.v3 v3.0.1 // indirect 87 | k8s.io/apiextensions-apiserver v0.32.1 // indirect 88 | k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect 89 | k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect 90 | sigs.k8s.io/gateway-api v1.1.0 // indirect 91 | sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect 92 | sigs.k8s.io/kustomize/api v0.19.0 // indirect 93 | sigs.k8s.io/kustomize/kyaml v0.19.0 // indirect 94 | sigs.k8s.io/randfill v1.0.0 // indirect 95 | sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect 96 | sigs.k8s.io/yaml v1.4.0 // indirect 97 | ) 98 | -------------------------------------------------------------------------------- /internal/cmd/app/app.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The cert-manager Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package app 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "net/http" 23 | "time" 24 | 25 | cmscheme "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned/scheme" 26 | routescheme "github.com/openshift/client-go/route/clientset/versioned/scheme" 27 | "github.com/spf13/cobra" 28 | corev1 "k8s.io/api/core/v1" 29 | "k8s.io/apimachinery/pkg/runtime" 30 | "k8s.io/client-go/kubernetes" 31 | clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" 32 | "k8s.io/client-go/tools/record" 33 | ctrl "sigs.k8s.io/controller-runtime" 34 | "sigs.k8s.io/controller-runtime/pkg/metrics/server" 35 | 36 | "github.com/cert-manager/openshift-routes/internal/cmd/app/options" 37 | "github.com/cert-manager/openshift-routes/internal/controller" 38 | ) 39 | 40 | func Command() *cobra.Command { 41 | opts := options.New() 42 | cmd := &cobra.Command{ 43 | Use: "cert-manager-openshift-routes", 44 | Short: "cert-manager support for openshift routes", 45 | Long: "cert-manager support for openshift routes", 46 | RunE: func(cmd *cobra.Command, args []string) error { 47 | if err := opts.Complete(); err != nil { 48 | return err 49 | } 50 | 51 | cl, err := kubernetes.NewForConfig(opts.RestConfig) 52 | if err != nil { 53 | return fmt.Errorf("error creating kubernetes client: %w", err) 54 | } 55 | 56 | // Check if v1 Openshift Routes exist in the API server 57 | apiServerHasRoutes := false 58 | routeResources, err := cl.Discovery().ServerResourcesForGroupVersion("route.openshift.io/v1") 59 | if err != nil { 60 | return fmt.Errorf("couldn't check if route.openshift.io/v1 exists in the kubernetes API: %w", err) 61 | } 62 | for _, r := range routeResources.APIResources { 63 | if r.Kind == "Route" { 64 | apiServerHasRoutes = true 65 | break 66 | } 67 | } 68 | if !apiServerHasRoutes { 69 | return fmt.Errorf("connected to the Kubernetes API, but the Openshift Route v1 CRD does not appear to be installed") 70 | } 71 | 72 | // Check if v1 cert-manager Certificates exist in the API server 73 | apiServerHasCertificates := false 74 | cmResources, err := cl.Discovery().ServerResourcesForGroupVersion("cert-manager.io/v1") 75 | if err != nil { 76 | return fmt.Errorf("couldn't check if cert-manager.io/v1 exists in the kubernetes API: %w", err) 77 | } 78 | 79 | for _, r := range cmResources.APIResources { 80 | if r.Kind == "Certificate" { 81 | apiServerHasCertificates = true 82 | break 83 | } 84 | } 85 | 86 | if !apiServerHasCertificates { 87 | return fmt.Errorf("connected to the Kubernetes API, but the cert-manager v1 CRDs do not appear to be installed") 88 | } 89 | 90 | logger := opts.Logr.WithName("controller-manager") 91 | eventBroadcaster := record.NewBroadcaster() 92 | eventBroadcaster.StartLogging(func(format string, args ...interface{}) { 93 | logger.V(3).Info(fmt.Sprintf(format, args...)) 94 | }) 95 | eventBroadcaster.StartRecordingToSink(&clientcorev1.EventSinkImpl{Interface: cl.CoreV1().Events("")}) 96 | 97 | combinedScheme := runtime.NewScheme() 98 | if err := cmscheme.AddToScheme(combinedScheme); err != nil { 99 | return err 100 | } 101 | if err := routescheme.AddToScheme(combinedScheme); err != nil { 102 | return err 103 | } 104 | 105 | opts.EventRecorder = eventBroadcaster.NewRecorder(combinedScheme, corev1.EventSource{Component: "cert-manager-openshift-routes"}) 106 | 107 | mgr, err := ctrl.NewManager(opts.RestConfig, ctrl.Options{ 108 | Scheme: combinedScheme, 109 | Logger: logger, 110 | LeaderElection: opts.EnableLeaderElection, 111 | LeaderElectionID: "cert-manager-openshift-routes", 112 | LeaderElectionNamespace: opts.LeaderElectionNamespace, 113 | LeaderElectionResourceLock: "leases", 114 | LeaderElectionReleaseOnCancel: true, 115 | ReadinessEndpointName: opts.ReadyzPath, 116 | HealthProbeBindAddress: fmt.Sprintf("[::]:%d", opts.ReadyzPort), 117 | Metrics: server.Options{ 118 | BindAddress: fmt.Sprintf("[::]:%d", opts.MetricsPort), 119 | }, 120 | }) 121 | if err != nil { 122 | return fmt.Errorf("could not create controller manager: %w", err) 123 | } 124 | mgr.AddReadyzCheck("informers_synced", func(req *http.Request) error { 125 | // haven't got much time to wait in a readiness check 126 | ctx, cancel := context.WithTimeout(req.Context(), 2*time.Second) 127 | defer cancel() 128 | if mgr.GetCache().WaitForCacheSync(ctx) { 129 | return nil 130 | } 131 | return fmt.Errorf("informers not synced") 132 | }) 133 | if err := controller.AddToManager(mgr, opts); err != nil { 134 | return fmt.Errorf("could not add route controller to manager: %w", err) 135 | } 136 | opts.Logr.V(5).Info("starting controller") 137 | return mgr.Start(ctrl.SetupSignalHandler()) 138 | }, 139 | } 140 | opts.Prepare(cmd) 141 | return cmd 142 | } 143 | -------------------------------------------------------------------------------- /internal/cmd/app/options/options.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The cert-manager Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package options 18 | 19 | import ( 20 | "flag" 21 | "fmt" 22 | 23 | "github.com/go-logr/logr" 24 | "github.com/spf13/cobra" 25 | "github.com/spf13/pflag" 26 | "k8s.io/cli-runtime/pkg/genericclioptions" 27 | "k8s.io/client-go/rest" 28 | "k8s.io/client-go/tools/record" 29 | cliflag "k8s.io/component-base/cli/flag" 30 | "k8s.io/klog/v2" 31 | "k8s.io/klog/v2/klogr" 32 | ) 33 | 34 | // Options is the main configuration struct for cert-manager-openshift-routes 35 | type Options struct { 36 | EventRecorder record.EventRecorder 37 | 38 | // ReadyzPort is the port to serve the readiness check on 39 | ReadyzPort int 40 | // ReadyzPath is the path to serve the readiness check on 41 | ReadyzPath string 42 | 43 | // MetricsPort is the port to serve prometheus metrics on 44 | MetricsPort int 45 | 46 | // EnableLeaderElection determines whether to use leader election 47 | EnableLeaderElection bool 48 | 49 | // LeaderElectionNamespace is the namespace to create Leader Election Resources 50 | LeaderElectionNamespace string 51 | 52 | // Logr is the shared base logr.Logger 53 | Logr logr.Logger 54 | 55 | // RestConfig is the Kubernetes config 56 | RestConfig *rest.Config 57 | 58 | logLevel string 59 | kubeConfigFlags *genericclioptions.ConfigFlags 60 | } 61 | 62 | func New() *Options { 63 | return new(Options) 64 | } 65 | 66 | func (o *Options) Prepare(cmd *cobra.Command) *Options { 67 | o.addFlags(cmd) 68 | return o 69 | } 70 | 71 | func (o *Options) Complete() error { 72 | klog.InitFlags(nil) 73 | log := klogr.New() 74 | if err := flag.Set("v", o.logLevel); err != nil { 75 | return err 76 | } 77 | o.Logr = log.WithName("cert-manager-openshift-routes") 78 | 79 | var err error 80 | o.RestConfig, err = o.kubeConfigFlags.ToRESTConfig() 81 | if err != nil { 82 | return fmt.Errorf("failed to build kubernetes rest config: %s", err) 83 | } 84 | 85 | return nil 86 | } 87 | 88 | func (o *Options) addFlags(cmd *cobra.Command) { 89 | var nfs cliflag.NamedFlagSets 90 | 91 | o.addAppFlags(nfs.FlagSet("App")) 92 | o.kubeConfigFlags = genericclioptions.NewConfigFlags(true) 93 | o.kubeConfigFlags.AddFlags(nfs.FlagSet("Kubernetes")) 94 | 95 | usageFmt := "Usage:\n %s\n" 96 | cmd.SetUsageFunc(func(cmd *cobra.Command) error { 97 | fmt.Fprintf(cmd.OutOrStderr(), usageFmt, cmd.UseLine()) 98 | cliflag.PrintSections(cmd.OutOrStderr(), nfs, 0) 99 | return nil 100 | }) 101 | 102 | cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { 103 | fmt.Fprintf(cmd.OutOrStdout(), "%s\n\n"+usageFmt, cmd.Long, cmd.UseLine()) 104 | cliflag.PrintSections(cmd.OutOrStdout(), nfs, 0) 105 | }) 106 | 107 | fs := cmd.Flags() 108 | for _, f := range nfs.FlagSets { 109 | fs.AddFlagSet(f) 110 | } 111 | } 112 | 113 | func (o *Options) addAppFlags(fs *pflag.FlagSet) { 114 | fs.StringVarP(&o.logLevel, 115 | "log-level", "v", "1", 116 | "Log level (1-5).") 117 | 118 | fs.IntVar(&o.ReadyzPort, 119 | "readiness-probe-port", 6060, 120 | "Port to expose the readiness probe.") 121 | 122 | fs.StringVar(&o.ReadyzPath, 123 | "readiness-probe-path", "/readyz", 124 | "HTTP path to expose the readiness probe server.") 125 | 126 | fs.IntVar(&o.MetricsPort, 127 | "metrics-port", 9402, 128 | "Port to expose Prometheus metrics on 0.0.0.0 on path '/metrics'.") 129 | 130 | fs.BoolVar(&o.EnableLeaderElection, 131 | "enable-leader-election", true, 132 | "Whether to enable leader election on the controller.") 133 | 134 | fs.StringVar(&o.LeaderElectionNamespace, 135 | "leader-election-namespace", "cert-manager", 136 | "Namespace to create leader election resources in.") 137 | } 138 | -------------------------------------------------------------------------------- /internal/cmd/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The cert-manager Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "os" 21 | 22 | "github.com/cert-manager/openshift-routes/internal/cmd/app" 23 | ) 24 | 25 | func main() { 26 | if err := app.Command().Execute(); err != nil { 27 | os.Exit(1) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /internal/controller/controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The cert-manager Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "context" 21 | 22 | cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" 23 | cmclient "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned" 24 | "github.com/go-logr/logr" 25 | routev1 "github.com/openshift/api/route/v1" 26 | routev1client "github.com/openshift/client-go/route/clientset/versioned" 27 | "k8s.io/apimachinery/pkg/api/errors" 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | "k8s.io/client-go/kubernetes" 30 | corev1client "k8s.io/client-go/kubernetes/typed/core/v1" 31 | "k8s.io/client-go/rest" 32 | "k8s.io/client-go/tools/record" 33 | "sigs.k8s.io/controller-runtime/pkg/builder" 34 | "sigs.k8s.io/controller-runtime/pkg/manager" 35 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 36 | 37 | "github.com/cert-manager/openshift-routes/internal/cmd/app/options" 38 | ) 39 | 40 | type RouteController struct { 41 | routeClient routev1client.Interface 42 | certClient cmclient.Interface 43 | coreClient corev1client.CoreV1Interface 44 | eventRecorder record.EventRecorder 45 | 46 | log logr.Logger 47 | } 48 | 49 | func shouldSync(log logr.Logger, route *routev1.Route) bool { 50 | if len(route.ObjectMeta.OwnerReferences) > 0 { 51 | for _, o := range route.ObjectMeta.OwnerReferences { 52 | if o.Kind == "Ingress" { 53 | log.V(5).Info("Route is owned by an Ingress") 54 | return false 55 | } 56 | } 57 | } 58 | 59 | if metav1.HasAnnotation(route.ObjectMeta, cmapi.IssuerNameAnnotationKey) { 60 | log.V(5).Info("Route has the annotation", "annotation-key", cmapi.IssuerNameAnnotationKey, "annotation-value", route.Annotations[cmapi.IssuerNameAnnotationKey]) 61 | return true 62 | } 63 | 64 | if metav1.HasAnnotation(route.ObjectMeta, cmapi.IngressIssuerNameAnnotationKey) { 65 | log.V(5).Info("Route has the annotation", "annotation-key", cmapi.IngressIssuerNameAnnotationKey, "annotation-value", route.Annotations[cmapi.IngressIssuerNameAnnotationKey]) 66 | return true 67 | } 68 | 69 | log.V(5).Info("Route does not have the cert-manager issuer annotation") 70 | return false 71 | } 72 | 73 | func (r *RouteController) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { 74 | log := r.log.WithValues("object", req.NamespacedName) 75 | log.V(5).Info("started reconciling") 76 | route, err := r.routeClient.RouteV1().Routes(req.Namespace).Get(ctx, req.Name, metav1.GetOptions{}) 77 | if errors.IsNotFound(err) { 78 | return reconcile.Result{}, nil 79 | } 80 | if err != nil { 81 | return reconcile.Result{}, err 82 | } 83 | log.V(5).Info("retrieved route") 84 | 85 | if !shouldSync(log, route) { 86 | return reconcile.Result{}, nil 87 | } 88 | 89 | return r.sync(ctx, req, route.DeepCopy()) 90 | } 91 | 92 | func New(base logr.Logger, config *rest.Config, recorder record.EventRecorder) (*RouteController, error) { 93 | routeClient, err := routev1client.NewForConfig(config) 94 | if err != nil { 95 | return nil, err 96 | } 97 | certClient, err := cmclient.NewForConfig(config) 98 | if err != nil { 99 | return nil, err 100 | } 101 | clientset, err := kubernetes.NewForConfig(config) 102 | if err != nil { 103 | return nil, err 104 | } 105 | 106 | return &RouteController{ 107 | routeClient: routeClient, 108 | certClient: certClient, 109 | coreClient: clientset.CoreV1(), 110 | log: base.WithName("route"), 111 | eventRecorder: recorder, 112 | }, nil 113 | } 114 | 115 | func AddToManager(mgr manager.Manager, opts *options.Options) error { 116 | controller, err := New(opts.Logr, opts.RestConfig, opts.EventRecorder) 117 | if err != nil { 118 | return err 119 | } 120 | 121 | return builder. 122 | ControllerManagedBy(mgr). 123 | For(&routev1.Route{}). 124 | Owns(&cmapi.Certificate{}). 125 | Complete(controller) 126 | } 127 | -------------------------------------------------------------------------------- /internal/controller/controller_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The cert-manager Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/go-logr/logr" 23 | routev1 "github.com/openshift/api/route/v1" 24 | "github.com/stretchr/testify/assert" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | ) 27 | 28 | func Test_shouldReconcile(t *testing.T) { 29 | tests := []struct { 30 | name string 31 | given *routev1.Route 32 | want bool 33 | }{ 34 | { 35 | name: "should reconcile with cert-manager.io/issuer-name annotation", 36 | given: &routev1.Route{ObjectMeta: metav1.ObjectMeta{ 37 | Annotations: map[string]string{ 38 | "cert-manager.io/issuer-name": "test", 39 | }}, 40 | }, 41 | want: true, 42 | }, 43 | { 44 | name: "should sync with cert-manager.io/issuer annotation", 45 | given: &routev1.Route{ObjectMeta: metav1.ObjectMeta{ 46 | Annotations: map[string]string{ 47 | "cert-manager.io/issuer": "test", 48 | }}, 49 | }, 50 | want: true, 51 | }, 52 | { 53 | name: "should not sync when Route owned by Ingress", 54 | given: &routev1.Route{ObjectMeta: metav1.ObjectMeta{ 55 | OwnerReferences: []metav1.OwnerReference{ 56 | { 57 | Kind: "Ingress", 58 | }, 59 | }}, 60 | }, 61 | want: false, 62 | }, 63 | { 64 | name: "should not sync when Route owned by Ingress", 65 | given: &routev1.Route{ObjectMeta: metav1.ObjectMeta{ 66 | OwnerReferences: []metav1.OwnerReference{ 67 | { 68 | Kind: "Ingress", 69 | }, 70 | }}, 71 | }, 72 | want: false, 73 | }, 74 | { 75 | name: "should not sync when no annotation is found", 76 | given: &routev1.Route{ObjectMeta: metav1.ObjectMeta{}}, 77 | }, 78 | } 79 | for _, tt := range tests { 80 | t.Run(tt.name, func(t *testing.T) { 81 | got := shouldSync(logr.Discard(), tt.given) 82 | assert.Equal(t, tt.want, got) 83 | }) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /internal/controller/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The cert-manager Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "crypto/sha256" 21 | "encoding/hex" 22 | "strings" 23 | ) 24 | 25 | const ( 26 | maxKubernetesResourceNameLength = 253 27 | ) 28 | 29 | func safeKubernetesNameAppend(name string, suffix string) string { 30 | dumbAppend := strings.Join([]string{name, suffix}, "-") 31 | if len(dumbAppend) < maxKubernetesResourceNameLength { 32 | // if simply appending the suffix isn't too long, just do that 33 | return dumbAppend 34 | } 35 | 36 | // We're going to need to remove some of the end of `name` to be able to append `suffix` 37 | // Take a hash of the full name and add it between `name` and `suffix` so that we don't 38 | // risk collisions for long names that only differ in the final few characters 39 | h := sha256.Sum256([]byte(name)) 40 | 41 | hashStr := hex.EncodeToString(h[:])[:6] 42 | 43 | // We'll have the form -- 44 | // Hash is 6 chars long (because we take the last 6 for hashStr below) 45 | // Suffix is len(suffix) charts long 46 | // There are two chars for "-" joining characters 47 | name = name[:len(name)-2-6-len(suffix)] 48 | 49 | return strings.Join([]string{name, hashStr, suffix}, "-") 50 | } 51 | -------------------------------------------------------------------------------- /internal/controller/util_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The cert-manager Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import "testing" 20 | 21 | // For reference below: 22 | // $ echo -n "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" | sha256sum 23 | // 03aaf5773717feae6f704bf2637ae0a9af8b1b26c3493ef29553818378773a04 - 24 | 25 | // $ echo -n "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" | sha256sum 26 | // 9124f8b01de4e3e64e86f1f98309adf6a4cb474aacd78e5f9b7247bbb08a5c20 - 27 | 28 | func Test_safeKubernetesNameAppend(t *testing.T) { 29 | tests := map[string]struct { 30 | name string 31 | expected string 32 | }{ 33 | "short name uses dumb approach": { 34 | name: "short", 35 | expected: "short-test", 36 | }, 37 | "long name has a unique hash and suffix appended": { 38 | // 252 "a" characters 39 | name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 40 | expected: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-03aaf5-test", 41 | }, 42 | "long name with different end has a unique hash and suffix appended": { 43 | // 251 "a" characters followed by a "b" 44 | name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", 45 | expected: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-9124f8-test", 46 | }, 47 | } 48 | 49 | for name, test := range tests { 50 | t.Run(name, func(t *testing.T) { 51 | out := safeKubernetesNameAppend(test.name, "test") 52 | 53 | if test.expected != out { 54 | t.Errorf("wanted %s\n got %s", test.expected, out) 55 | } 56 | }) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /klone.yaml: -------------------------------------------------------------------------------- 1 | # This klone.yaml file describes the Makefile modules and versions that are 2 | # cloned into the "make/_shared" folder. These modules are dynamically imported 3 | # by the root Makefile. The "make upgrade-klone" target can be used to pull 4 | # the latest version from the upstream repositories (using the repo_ref value). 5 | # 6 | # More info can be found here: https://github.com/cert-manager/makefile-modules 7 | 8 | targets: 9 | make/_shared: 10 | - folder_name: boilerplate 11 | repo_url: https://github.com/cert-manager/makefile-modules.git 12 | repo_ref: main 13 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 14 | repo_path: modules/boilerplate 15 | - folder_name: cert-manager 16 | repo_url: https://github.com/cert-manager/makefile-modules.git 17 | repo_ref: main 18 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 19 | repo_path: modules/cert-manager 20 | - folder_name: controller-gen 21 | repo_url: https://github.com/cert-manager/makefile-modules.git 22 | repo_ref: main 23 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 24 | repo_path: modules/controller-gen 25 | - folder_name: generate-verify 26 | repo_url: https://github.com/cert-manager/makefile-modules.git 27 | repo_ref: main 28 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 29 | repo_path: modules/generate-verify 30 | - folder_name: go 31 | repo_url: https://github.com/cert-manager/makefile-modules.git 32 | repo_ref: main 33 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 34 | repo_path: modules/go 35 | - folder_name: helm 36 | repo_url: https://github.com/cert-manager/makefile-modules.git 37 | repo_ref: main 38 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 39 | repo_path: modules/helm 40 | - folder_name: help 41 | repo_url: https://github.com/cert-manager/makefile-modules.git 42 | repo_ref: main 43 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 44 | repo_path: modules/help 45 | - folder_name: kind 46 | repo_url: https://github.com/cert-manager/makefile-modules.git 47 | repo_ref: main 48 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 49 | repo_path: modules/kind 50 | - folder_name: klone 51 | repo_url: https://github.com/cert-manager/makefile-modules.git 52 | repo_ref: main 53 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 54 | repo_path: modules/klone 55 | - folder_name: licenses 56 | repo_url: https://github.com/cert-manager/makefile-modules.git 57 | repo_ref: main 58 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 59 | repo_path: modules/licenses 60 | - folder_name: oci-build 61 | repo_url: https://github.com/cert-manager/makefile-modules.git 62 | repo_ref: main 63 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 64 | repo_path: modules/oci-build 65 | - folder_name: oci-publish 66 | repo_url: https://github.com/cert-manager/makefile-modules.git 67 | repo_ref: main 68 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 69 | repo_path: modules/oci-publish 70 | - folder_name: repository-base 71 | repo_url: https://github.com/cert-manager/makefile-modules.git 72 | repo_ref: main 73 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 74 | repo_path: modules/repository-base 75 | - folder_name: tools 76 | repo_url: https://github.com/cert-manager/makefile-modules.git 77 | repo_ref: main 78 | repo_hash: 5c3266f17637fbd1d4af1191b34674991e2160ab 79 | repo_path: modules/tools 80 | -------------------------------------------------------------------------------- /make/00_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | repo_name := github.com/cert-manager/openshift-routes 16 | 17 | kind_cluster_name := openshift-routes 18 | kind_cluster_config := $(bin_dir)/scratch/kind_cluster.yaml 19 | 20 | build_names := manager 21 | 22 | go_manager_main_dir := ./internal/cmd 23 | go_manager_mod_dir := . 24 | go_manager_ldflags := -X $(repo_name)/pkg/internal/version.AppVersion=$(VERSION) -X $(repo_name)/pkg/internal/version.GitCommit=$(GITCOMMIT) 25 | oci_manager_base_image_flavor := static 26 | oci_manager_image_name := ghcr.io/cert-manager/cert-manager-openshift-routes 27 | oci_manager_image_tag := $(VERSION) 28 | oci_manager_image_name_development := cert-manager.local/cert-manager-openshift-routes 29 | 30 | deploy_name := openshift-routes 31 | deploy_namespace := cert-manager 32 | 33 | helm_chart_source_dir := deploy/charts/openshift-routes 34 | helm_chart_image_name := ghcr.io/cert-manager/charts/openshift-routes 35 | helm_chart_version := $(VERSION) 36 | helm_labels_template_name := cert-manager-openshift-routes.labels 37 | 38 | golangci_lint_config := .golangci.yaml 39 | 40 | define helm_values_mutation_function 41 | $(YQ) \ 42 | '( .image.repository = "$(oci_manager_image_name)" ) | \ 43 | ( .image.tag = "$(oci_manager_image_tag)" )' \ 44 | $1 --inplace 45 | endef 46 | -------------------------------------------------------------------------------- /make/02_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | $(kind_cluster_config): make/config/kind/cluster.yaml | $(bin_dir)/scratch 16 | cat $< | \ 17 | sed -e 's|{{KIND_IMAGES}}|$(CURDIR)/$(images_tar_dir)|g' \ 18 | > $@ 19 | 20 | include make/test-unit.mk 21 | include make/test-smoke.mk 22 | 23 | .PHONY: release 24 | ## Publish all release artifacts (image + helm chart) 25 | ## @category [shared] Release 26 | release: 27 | $(MAKE) oci-push-manager 28 | $(MAKE) helm-chart-oci-push 29 | 30 | @echo "RELEASE_OCI_MANAGER_IMAGE=$(oci_manager_image_name)" >> "$(GITHUB_OUTPUT)" 31 | @echo "RELEASE_OCI_MANAGER_TAG=$(oci_manager_image_tag)" >> "$(GITHUB_OUTPUT)" 32 | @echo "RELEASE_HELM_CHART_IMAGE=$(helm_chart_image_name)" >> "$(GITHUB_OUTPUT)" 33 | @echo "RELEASE_HELM_CHART_VERSION=$(helm_chart_version)" >> "$(GITHUB_OUTPUT)" 34 | 35 | @echo "Release complete!" 36 | -------------------------------------------------------------------------------- /make/_shared/boilerplate/00_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | default_go_header_file := $(dir $(lastword $(MAKEFILE_LIST)))/template/boilerplate.go.txt 16 | 17 | go_header_file ?= $(default_go_header_file) 18 | -------------------------------------------------------------------------------- /make/_shared/boilerplate/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | .PHONY: verify-boilerplate 16 | ## Verify that all files have the correct boilerplate. 17 | ## @category [shared] Generate/ Verify 18 | verify-boilerplate: | $(NEEDS_BOILERSUITE) 19 | $(BOILERSUITE) . 20 | 21 | shared_verify_targets += verify-boilerplate 22 | -------------------------------------------------------------------------------- /make/_shared/boilerplate/template/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The cert-manager Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /make/_shared/cert-manager/00_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | images_amd64 ?= 16 | images_arm64 ?= 17 | 18 | cert_manager_version := v1.17.0 19 | 20 | images_amd64 += quay.io/jetstack/cert-manager-controller:$(cert_manager_version)@sha256:7722bca28c95b4c568f3d4cd2debc9286e0c4b092f0426840ed4d8ed314c09db 21 | images_amd64 += quay.io/jetstack/cert-manager-cainjector:$(cert_manager_version)@sha256:d99797c5d6e702416e69defb4c28a978d515a37a8a03b4405c4991b818cc791c 22 | images_amd64 += quay.io/jetstack/cert-manager-webhook:$(cert_manager_version)@sha256:e43e270c7c50a3c1872e115df93458a78c230118cc3d12e9f6c848956e94c151 23 | images_amd64 += quay.io/jetstack/cert-manager-startupapicheck:$(cert_manager_version)@sha256:ce2f25777ad4a159b736e47dbaabfd62bf2c339c6f49fb6a6de79fb6b4a8ebed 24 | 25 | images_arm64 += quay.io/jetstack/cert-manager-controller:$(cert_manager_version)@sha256:d63cd0d15a3ed99736dd5623b798a3dd78fc36495623528d1bf58df37bc4a6cd 26 | images_arm64 += quay.io/jetstack/cert-manager-cainjector:$(cert_manager_version)@sha256:aaae16a38c8f4176b9645ff3069797ca2ec6e3262142794729440b342d759b89 27 | images_arm64 += quay.io/jetstack/cert-manager-webhook:$(cert_manager_version)@sha256:45e8765b48d913ef26188782ec8dbee32f132c142249456a4e06c5c5c41e3927 28 | images_arm64 += quay.io/jetstack/cert-manager-startupapicheck:$(cert_manager_version)@sha256:c29e6270e6fc78181bb3a956c0714df24ea56840b9d3916122a36ee25ec6eac6 29 | -------------------------------------------------------------------------------- /make/_shared/cert-manager/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cert_manager_crds := $(bin_dir)/scratch/cert-manager-$(cert_manager_version).yaml 16 | $(cert_manager_crds): | $(bin_dir)/scratch 17 | curl -sSLo $@ https://github.com/cert-manager/cert-manager/releases/download/$(cert_manager_version)/cert-manager.crds.yaml 18 | -------------------------------------------------------------------------------- /make/_shared/controller-gen/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ################ 16 | # Check Inputs # 17 | ################ 18 | 19 | ifndef go_header_file 20 | $(error go_header_file is not set) 21 | endif 22 | 23 | ################ 24 | # Add targets # 25 | ################ 26 | 27 | .PHONY: generate-deepcopy 28 | ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. 29 | ## @category [shared] Generate/ Verify 30 | generate-deepcopy: | $(NEEDS_CONTROLLER-GEN) 31 | $(eval directories := $(shell ls -d */ | grep -v '_bin' | grep -v 'make')) 32 | $(CONTROLLER-GEN) object:headerFile=$(go_header_file) $(directories:%=paths=./%...) 33 | 34 | shared_generate_targets += generate-deepcopy 35 | -------------------------------------------------------------------------------- /make/_shared/generate-verify/00_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | shared_generate_targets ?= 16 | shared_generate_targets_dirty ?= 17 | shared_verify_targets ?= 18 | shared_verify_targets_dirty ?= 19 | -------------------------------------------------------------------------------- /make/_shared/generate-verify/02_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | .PHONY: generate 16 | ## Generate all generate targets. 17 | ## @category [shared] Generate/ Verify 18 | generate: $$(shared_generate_targets) 19 | @echo "The following targets cannot be run simultaneously with each other or other generate scripts:" 20 | $(foreach TARGET,$(shared_generate_targets_dirty), $(MAKE) $(TARGET)) 21 | 22 | verify_script := $(dir $(lastword $(MAKEFILE_LIST)))/util/verify.sh 23 | 24 | # Run the supplied make target argument in a temporary workspace and diff the results. 25 | verify-%: FORCE 26 | +$(verify_script) $(MAKE) $* 27 | 28 | verify_generated_targets = $(shared_generate_targets:%=verify-%) 29 | verify_generated_targets_dirty = $(shared_generate_targets_dirty:%=verify-%) 30 | 31 | verify_targets = $(sort $(verify_generated_targets) $(shared_verify_targets)) 32 | verify_targets_dirty = $(sort $(verify_generated_targets_dirty) $(shared_verify_targets_dirty)) 33 | 34 | .PHONY: verify 35 | ## Verify code and generate targets. 36 | ## @category [shared] Generate/ Verify 37 | verify: $$(verify_targets) 38 | @echo "The following targets create temporary files in the current directory, that is why they have to be run last:" 39 | $(foreach TARGET,$(verify_targets_dirty), $(MAKE) $(TARGET)) 40 | -------------------------------------------------------------------------------- /make/_shared/generate-verify/util/verify.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2023 The cert-manager Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Verify that the supplied command does not make any changes to the repository. 18 | # 19 | # This is called from the Makefile to verify that all code generation scripts 20 | # have been run and that their changes have been committed to the repository. 21 | # 22 | # Runs any of the scripts or Make targets in this repository, after making a 23 | # copy of the repository, then reports any changes to the files in the copy. 24 | 25 | # For example: 26 | # 27 | # make verify-helm-chart-update || \ 28 | # make helm-chart-update 29 | # 30 | set -o errexit 31 | set -o nounset 32 | set -o pipefail 33 | 34 | projectdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../../../.." && pwd )" 35 | 36 | cd "${projectdir}" 37 | 38 | # Use short form arguments here to support BSD/macOS. `-d` instructs 39 | # it to make a directory, `-t` provides a prefix to use for the directory name. 40 | tmp="$(mktemp -d /tmp/verify.sh.XXXXXXXX)" 41 | 42 | cleanup() { 43 | rm -rf "${tmp}" 44 | } 45 | trap "cleanup" EXIT SIGINT 46 | 47 | # Why not just "cp" to the tmp dir? 48 | # A dumb "cp" will fail sometimes since _bin can get changed while it's being copied if targets are run in parallel, 49 | # and cp doesn't have some universal "exclude" option to ignore "_bin" 50 | # 51 | # We previously used "rsync" here, but: 52 | # 1. That's another tool we need to depend on 53 | # 2. rsync on macOS 15.4 and newer is actually openrsync, which has different permissions and throws errors when copying git objects 54 | # 55 | # So, we use find to list all files except _bin, and then copy each in turn 56 | find . -maxdepth 1 -not \( -path "./_bin" \) -not \( -path "." \) | xargs -I% cp -af "${projectdir}/%" "${tmp}/" 57 | 58 | pushd "${tmp}" >/dev/null 59 | 60 | "$@" 61 | 62 | popd >/dev/null 63 | 64 | if ! diff \ 65 | --exclude=".git" \ 66 | --exclude="_bin" \ 67 | --new-file --unified --show-c-function --recursive "${projectdir}" "${tmp}" 68 | then 69 | echo 70 | echo "Project '${projectdir}' is out of date." 71 | echo "Please run '${*}' or apply the above diffs" 72 | exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /make/_shared/go/.golangci.override.yaml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | linters: 3 | default: none 4 | exclusions: 5 | generated: lax 6 | presets: [ comments, common-false-positives, legacy, std-error-handling ] 7 | paths: [ third_party$, builtin$, examples$ ] 8 | warn-unused: true 9 | settings: 10 | staticcheck: 11 | checks: [ "all", "-ST1000", "-ST1001", "-ST1003", "-ST1005", "-ST1012", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-QF1001", "-QF1003", "-QF1008" ] 12 | enable: 13 | - asasalint 14 | - asciicheck 15 | - bidichk 16 | - bodyclose 17 | - canonicalheader 18 | - contextcheck 19 | - copyloopvar 20 | - decorder 21 | - dogsled 22 | - dupword 23 | - durationcheck 24 | - errcheck 25 | - errchkjson 26 | - errname 27 | - exhaustive 28 | - exptostd 29 | - forbidigo 30 | - ginkgolinter 31 | - gocheckcompilerdirectives 32 | - gochecksumtype 33 | - gocritic 34 | - goheader 35 | - goprintffuncname 36 | - gosec 37 | - gosmopolitan 38 | - govet 39 | - grouper 40 | - importas 41 | - ineffassign 42 | - interfacebloat 43 | - intrange 44 | - loggercheck 45 | - makezero 46 | - mirror 47 | - misspell 48 | - musttag 49 | - nakedret 50 | - nilerr 51 | - nilnil 52 | - noctx 53 | - nosprintfhostport 54 | - predeclared 55 | - promlinter 56 | - protogetter 57 | - reassign 58 | - sloglint 59 | - staticcheck 60 | - tagalign 61 | - testableexamples 62 | - unconvert 63 | - unparam 64 | - unused 65 | - usestdlibvars 66 | - usetesting 67 | - wastedassign 68 | formatters: 69 | enable: [ gci, gofmt ] 70 | settings: 71 | gci: 72 | sections: 73 | - standard # Standard section: captures all standard packages. 74 | - default # Default section: contains all imports that could not be matched to another section type. 75 | - prefix({{REPO-NAME}}) # Custom section: groups all imports with the specified Prefix. 76 | - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. 77 | - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. 78 | exclusions: 79 | generated: lax 80 | paths: [ third_party$, builtin$, examples$ ] 81 | -------------------------------------------------------------------------------- /make/_shared/go/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef bin_dir 16 | $(error bin_dir is not set) 17 | endif 18 | 19 | ifndef repo_name 20 | $(error repo_name is not set) 21 | endif 22 | 23 | golangci_lint_override := $(dir $(lastword $(MAKEFILE_LIST)))/.golangci.override.yaml 24 | 25 | .PHONY: go-workspace 26 | go-workspace: export GOWORK?=$(abspath go.work) 27 | ## Create a go.work file in the repository root (or GOWORK) 28 | ## 29 | ## @category Development 30 | go-workspace: | $(NEEDS_GO) 31 | @rm -f $(GOWORK) 32 | $(GO) work init 33 | @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ 34 | | while read d; do \ 35 | target=$$(dirname $${d}); \ 36 | $(GO) work use "$${target}"; \ 37 | done 38 | 39 | .PHONY: go-tidy 40 | ## Alias for `make generate-go-mod-tidy` 41 | ## @category [shared] Generate/ Verify 42 | go-tidy: generate-go-mod-tidy 43 | 44 | .PHONY: generate-go-mod-tidy 45 | ## Run `go mod tidy` on all Go modules 46 | ## @category [shared] Generate/ Verify 47 | generate-go-mod-tidy: | $(NEEDS_GO) 48 | @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ 49 | | while read d; do \ 50 | target=$$(dirname $${d}); \ 51 | echo "Running 'go mod tidy' in directory '$${target}'"; \ 52 | pushd "$${target}" >/dev/null; \ 53 | $(GO) mod tidy || exit; \ 54 | popd >/dev/null; \ 55 | echo ""; \ 56 | done 57 | 58 | shared_generate_targets += generate-go-mod-tidy 59 | 60 | default_govulncheck_generate_base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ 61 | # The base directory used to copy the govulncheck GH action from. This can be 62 | # overwritten with an action with extra authentication or with a totally different 63 | # pipeline (eg. a GitLab pipeline). 64 | govulncheck_generate_base_dir ?= $(default_govulncheck_generate_base_dir) 65 | 66 | .PHONY: generate-govulncheck 67 | ## Generate base files in the repository 68 | ## @category [shared] Generate/ Verify 69 | generate-govulncheck: 70 | cp -r $(govulncheck_generate_base_dir)/. ./ 71 | 72 | shared_generate_targets += generate-govulncheck 73 | 74 | .PHONY: verify-govulncheck 75 | ## Verify all Go modules for vulnerabilities using govulncheck 76 | ## @category [shared] Generate/ Verify 77 | # 78 | # Runs `govulncheck` on all Go modules related to the project. 79 | # Ignores Go modules among the temporary build artifacts in _bin, to avoid 80 | # scanning the code of the vendored Go, after running make vendor-go. 81 | # Ignores Go modules in make/_shared, because those will be checked in centrally 82 | # in the makefile_modules repository. 83 | # 84 | # `verify-govulncheck` not added to the `shared_verify_targets` variable and is 85 | # not run by `make verify`, because `make verify` is run for each PR, and we do 86 | # not want new vulnerabilities in existing code to block the merging of PRs. 87 | # Instead `make verify-govulncheck` is intended to be run periodically by a CI job. 88 | verify-govulncheck: | $(NEEDS_GOVULNCHECK) 89 | @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ 90 | | while read d; do \ 91 | target=$$(dirname $${d}); \ 92 | echo "Running 'GOTOOLCHAIN=go$(VENDORED_GO_VERSION) $(bin_dir)/tools/govulncheck ./...' in directory '$${target}'"; \ 93 | pushd "$${target}" >/dev/null; \ 94 | GOTOOLCHAIN=go$(VENDORED_GO_VERSION) $(GOVULNCHECK) ./... || exit; \ 95 | popd >/dev/null; \ 96 | echo ""; \ 97 | done 98 | 99 | ifdef golangci_lint_config 100 | 101 | .PHONY: generate-golangci-lint-config 102 | ## Generate a golangci-lint configuration file 103 | ## @category [shared] Generate/ Verify 104 | generate-golangci-lint-config: | $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(bin_dir)/scratch 105 | if [ "$$($(YQ) eval 'has("version") | not' $(golangci_lint_config))" == "true" ]; then \ 106 | $(GOLANGCI-LINT) migrate -c $(golangci_lint_config); \ 107 | rm $(basename $(golangci_lint_config)).bck$(suffix $(golangci_lint_config)); \ 108 | fi 109 | 110 | cp $(golangci_lint_config) $(bin_dir)/scratch/golangci-lint.yaml.tmp 111 | $(YQ) -i 'del(.linters.enable)' $(bin_dir)/scratch/golangci-lint.yaml.tmp 112 | $(YQ) eval-all -i '. as $$item ireduce ({}; . * $$item)' $(bin_dir)/scratch/golangci-lint.yaml.tmp $(golangci_lint_override) 113 | $(YQ) -i '(.. | select(tag == "!!str")) |= sub("{{REPO-NAME}}", "$(repo_name)")' $(bin_dir)/scratch/golangci-lint.yaml.tmp 114 | mv $(bin_dir)/scratch/golangci-lint.yaml.tmp $(golangci_lint_config) 115 | 116 | shared_generate_targets += generate-golangci-lint-config 117 | 118 | golangci_lint_timeout ?= 10m 119 | 120 | .PHONY: verify-golangci-lint 121 | ## Verify all Go modules using golangci-lint 122 | ## @category [shared] Generate/ Verify 123 | verify-golangci-lint: | $(NEEDS_GO) $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(bin_dir)/scratch 124 | @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ 125 | | while read d; do \ 126 | target=$$(dirname $${d}); \ 127 | echo "Running 'GOVERSION=$(VENDORED_GO_VERSION) $(bin_dir)/tools/golangci-lint run -c $(CURDIR)/$(golangci_lint_config) --timeout $(golangci_lint_timeout)' in directory '$${target}'"; \ 128 | pushd "$${target}" >/dev/null; \ 129 | GOVERSION=$(VENDORED_GO_VERSION) $(GOLANGCI-LINT) run -c $(CURDIR)/$(golangci_lint_config) --timeout $(golangci_lint_timeout) || exit; \ 130 | popd >/dev/null; \ 131 | echo ""; \ 132 | done 133 | 134 | shared_verify_targets_dirty += verify-golangci-lint 135 | 136 | .PHONY: fix-golangci-lint 137 | ## Fix all Go modules using golangci-lint 138 | ## @category [shared] Generate/ Verify 139 | fix-golangci-lint: | $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(NEEDS_GCI) $(bin_dir)/scratch 140 | @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ 141 | | while read d; do \ 142 | target=$$(dirname $${d}); \ 143 | echo "Running 'GOVERSION=$(VENDORED_GO_VERSION) $(bin_dir)/tools/golangci-lint fmt -c $(CURDIR)/$(golangci_lint_config)' in directory '$${target}'"; \ 144 | pushd "$${target}" >/dev/null; \ 145 | GOVERSION=$(VENDORED_GO_VERSION) $(GOLANGCI-LINT) fmt -c $(CURDIR)/$(golangci_lint_config) || exit; \ 146 | popd >/dev/null; \ 147 | echo ""; \ 148 | done 149 | 150 | endif 151 | -------------------------------------------------------------------------------- /make/_shared/go/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | A module for various Go static checks. 4 | -------------------------------------------------------------------------------- /make/_shared/go/base/.github/workflows/govulncheck.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/go/base/.github/workflows/govulncheck.yaml instead. 3 | 4 | # Run govulncheck at midnight every night on the main branch, 5 | # to alert us to recent vulnerabilities which affect the Go code in this 6 | # project. 7 | name: govulncheck 8 | on: 9 | workflow_dispatch: {} 10 | schedule: 11 | - cron: '0 0 * * *' 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | govulncheck: 18 | runs-on: ubuntu-latest 19 | 20 | if: github.repository_owner == 'cert-manager' 21 | 22 | steps: 23 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 24 | # Adding `fetch-depth: 0` makes sure tags are also fetched. We need 25 | # the tags so `git describe` returns a valid version. 26 | # see https://github.com/actions/checkout/issues/701 for extra info about this option 27 | with: { fetch-depth: 0 } 28 | 29 | - id: go-version 30 | run: | 31 | make print-go-version >> "$GITHUB_OUTPUT" 32 | 33 | - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 34 | with: 35 | go-version: ${{ steps.go-version.outputs.result }} 36 | 37 | - run: make verify-govulncheck 38 | -------------------------------------------------------------------------------- /make/_shared/helm/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef helm_dont_include_crds 16 | include $(dir $(lastword $(MAKEFILE_LIST)))/crds.mk 17 | endif 18 | 19 | include $(dir $(lastword $(MAKEFILE_LIST)))/helm.mk 20 | include $(dir $(lastword $(MAKEFILE_LIST)))/deploy.mk 21 | -------------------------------------------------------------------------------- /make/_shared/helm/crd.template.footer.yaml: -------------------------------------------------------------------------------- 1 | {{- end }} -------------------------------------------------------------------------------- /make/_shared/helm/crd.template.header.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.crds.enabled }} 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: "REPLACE_CRD_NAME" 6 | {{- if .Values.crds.keep }} 7 | annotations: 8 | helm.sh/resource-policy: keep 9 | {{- end }} 10 | labels: 11 | {{- include "REPLACE_LABELS_TEMPLATE" . | nindent 4 }} -------------------------------------------------------------------------------- /make/_shared/helm/crds.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ################ 16 | # Check Inputs # 17 | ################ 18 | 19 | ifndef helm_chart_source_dir 20 | $(error helm_chart_source_dir is not set) 21 | endif 22 | 23 | ifndef helm_labels_template_name 24 | $(error helm_labels_template_name is not set) 25 | endif 26 | 27 | ################ 28 | # Add targets # 29 | ################ 30 | 31 | crd_template_header := $(dir $(lastword $(MAKEFILE_LIST)))/crd.template.header.yaml 32 | crd_template_footer := $(dir $(lastword $(MAKEFILE_LIST)))/crd.template.footer.yaml 33 | 34 | # see https://stackoverflow.com/a/53408233 35 | sed_inplace := sed -i'' 36 | ifeq ($(HOST_OS),darwin) 37 | sed_inplace := sed -i '' 38 | endif 39 | 40 | crds_dir ?= deploy/crds 41 | crds_dir_readme := $(dir $(lastword $(MAKEFILE_LIST)))/crds_dir.README.md 42 | 43 | .PHONY: generate-crds 44 | ## Generate CRD manifests. 45 | ## @category [shared] Generate/ Verify 46 | generate-crds: | $(NEEDS_CONTROLLER-GEN) $(NEEDS_YQ) 47 | $(eval crds_gen_temp := $(bin_dir)/scratch/crds) 48 | $(eval directories := $(shell ls -d */ | grep -v -e 'make' $(shell git check-ignore -- * | sed 's/^/-e /'))) 49 | 50 | rm -rf $(crds_gen_temp) 51 | mkdir -p $(crds_gen_temp) 52 | 53 | $(CONTROLLER-GEN) crd \ 54 | $(directories:%=paths=./%...) \ 55 | output:crd:artifacts:config=$(crds_gen_temp) 56 | 57 | @echo "Updating CRDs with helm templating, writing to $(helm_chart_source_dir)/templates" 58 | 59 | @for i in $$(ls $(crds_gen_temp)); do \ 60 | crd_name=$$($(YQ) eval '.metadata.name' $(crds_gen_temp)/$$i); \ 61 | cat $(crd_template_header) > $(helm_chart_source_dir)/templates/crd-$$i; \ 62 | echo "" >> $(helm_chart_source_dir)/templates/crd-$$i; \ 63 | $(sed_inplace) "s/REPLACE_CRD_NAME/$$crd_name/g" $(helm_chart_source_dir)/templates/crd-$$i; \ 64 | $(sed_inplace) "s/REPLACE_LABELS_TEMPLATE/$(helm_labels_template_name)/g" $(helm_chart_source_dir)/templates/crd-$$i; \ 65 | $(YQ) -I2 '{"spec": .spec}' $(crds_gen_temp)/$$i >> $(helm_chart_source_dir)/templates/crd-$$i; \ 66 | cat $(crd_template_footer) >> $(helm_chart_source_dir)/templates/crd-$$i; \ 67 | done 68 | 69 | @if [ -n "$$(ls $(crds_gen_temp) 2>/dev/null)" ]; then \ 70 | cp $(crds_gen_temp)/* $(crds_dir)/ ; \ 71 | cp $(crds_dir_readme) $(crds_dir)/README.md ; \ 72 | fi 73 | 74 | shared_generate_targets += generate-crds 75 | -------------------------------------------------------------------------------- /make/_shared/helm/crds_dir.README.md: -------------------------------------------------------------------------------- 1 | # CRDs source directory 2 | 3 | > **WARNING**: if you are an end-user, you probably should NOT need to use the 4 | > files in this directory. These files are for **reference, development and testing purposes only**. 5 | 6 | This directory contains 'source code' used to build our CustomResourceDefinition 7 | resources consumed by our officially supported deployment methods (e.g. the Helm chart). 8 | The CRDs in this directory might be incomplete, and should **NOT** be used to provision the operator. -------------------------------------------------------------------------------- /make/_shared/helm/deploy.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef deploy_name 16 | $(error deploy_name is not set) 17 | endif 18 | 19 | ifndef deploy_namespace 20 | $(error deploy_namespace is not set) 21 | endif 22 | 23 | # Install options allows the user configuration of extra flags 24 | INSTALL_OPTIONS ?= 25 | 26 | ########################################## 27 | 28 | .PHONY: install 29 | ## Install controller helm chart on the current active K8S cluster. 30 | ## @category [shared] Deployment 31 | install: $(helm_chart_archive) | $(NEEDS_HELM) 32 | $(HELM) upgrade $(deploy_name) $(helm_chart_archive) \ 33 | --wait \ 34 | --install \ 35 | --create-namespace \ 36 | $(INSTALL_OPTIONS) \ 37 | --namespace $(deploy_namespace) 38 | 39 | .PHONY: uninstall 40 | ## Uninstall controller helm chart from the current active K8S cluster. 41 | ## @category [shared] Deployment 42 | uninstall: | $(NEEDS_HELM) 43 | $(HELM) uninstall $(deploy_name) \ 44 | --wait \ 45 | --namespace $(deploy_namespace) 46 | 47 | .PHONY: template 48 | ## Template the helm chart. 49 | ## @category [shared] Deployment 50 | template: $(helm_chart_archive) | $(NEEDS_HELM) 51 | @$(HELM) template $(deploy_name) $(helm_chart_archive) \ 52 | --create-namespace \ 53 | $(INSTALL_OPTIONS) \ 54 | --namespace $(deploy_namespace) 55 | -------------------------------------------------------------------------------- /make/_shared/helm/helm.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef bin_dir 16 | $(error bin_dir is not set) 17 | endif 18 | 19 | ifndef repo_name 20 | $(error repo_name is not set) 21 | endif 22 | 23 | ifndef helm_chart_source_dir 24 | $(error helm_chart_source_dir is not set) 25 | endif 26 | 27 | ifndef helm_chart_image_name 28 | $(error helm_chart_image_name is not set) 29 | endif 30 | 31 | ifndef helm_chart_version 32 | $(error helm_chart_version is not set) 33 | endif 34 | ifneq ($(helm_chart_version:v%=v),v) 35 | $(error helm_chart_version "$(helm_chart_version)" should start with a "v") 36 | endif 37 | 38 | ifndef helm_values_mutation_function 39 | $(error helm_values_mutation_function is not set) 40 | endif 41 | 42 | ########################################## 43 | 44 | helm_chart_name := $(notdir $(helm_chart_image_name)) 45 | helm_chart_image_registry := $(dir $(helm_chart_image_name)) 46 | helm_chart_image_tag := $(helm_chart_version) 47 | helm_chart_sources := $(shell find $(helm_chart_source_dir) -maxdepth 1 -type f) $(shell find $(helm_chart_source_dir)/templates -type f) 48 | helm_chart_archive := $(bin_dir)/scratch/helm/$(helm_chart_name)-$(helm_chart_version).tgz 49 | helm_digest_path := $(bin_dir)/scratch/helm/$(helm_chart_name)-$(helm_chart_version).digests 50 | helm_digest = $(shell head -1 $(helm_digest_path) 2> /dev/null) 51 | 52 | $(bin_dir)/scratch/helm: 53 | @mkdir -p $@ 54 | 55 | $(helm_chart_archive): $(helm_chart_sources) | $(NEEDS_HELM) $(NEEDS_YQ) $(bin_dir)/scratch/helm 56 | $(eval helm_chart_source_dir_versioned := $@.tmp) 57 | rm -rf $(helm_chart_source_dir_versioned) 58 | mkdir -p $(dir $(helm_chart_source_dir_versioned)) 59 | cp -a $(helm_chart_source_dir) $(helm_chart_source_dir_versioned) 60 | 61 | $(call helm_values_mutation_function,$(helm_chart_source_dir_versioned)/values.yaml) 62 | 63 | @if ! $(YQ) -oy '.name' $(helm_chart_source_dir_versioned)/Chart.yaml | grep -q '^$(helm_chart_name)$$'; then \ 64 | echo "Chart name does not match the name in the helm_chart_name variable"; \ 65 | exit 1; \ 66 | fi 67 | 68 | $(YQ) '.annotations."artifacthub.io/prerelease" = "$(IS_PRERELEASE)"' \ 69 | --inplace $(helm_chart_source_dir_versioned)/Chart.yaml 70 | 71 | mkdir -p $(dir $@) 72 | $(HELM) package $(helm_chart_source_dir_versioned) \ 73 | --app-version $(helm_chart_version) \ 74 | --version $(helm_chart_version) \ 75 | --destination $(dir $@) 76 | 77 | .PHONY: helm-chart-oci-push 78 | ## Create and push Helm chart to OCI registry. 79 | ## Will also create a non-v-prefixed tag for the OCI image. 80 | ## @category [shared] Publish 81 | helm-chart-oci-push: $(helm_chart_archive) | $(NEEDS_HELM) $(NEEDS_CRANE) 82 | $(HELM) push "$(helm_chart_archive)" "oci://$(helm_chart_image_registry)" 2>&1 \ 83 | | tee >(grep -o "sha256:.\+" | tee $(helm_digest_path)) 84 | 85 | @# $(helm_chart_image_tag:v%=%) removes the v prefix from the value stored in helm_chart_image_tag. 86 | @# See https://www.gnu.org/software/make/manual/html_node/Substitution-Refs.html for the manual on the syntax. 87 | helm_digest=$$(cat $(helm_digest_path)) && \ 88 | $(CRANE) copy "$(helm_chart_image_name)@$$helm_digest" "$(helm_chart_image_name):$(helm_chart_image_tag:v%=%)" 89 | 90 | .PHONY: helm-chart 91 | ## Create a helm chart 92 | ## @category [shared] Helm Chart 93 | helm-chart: $(helm_chart_archive) 94 | 95 | helm_tool_header_search ?= ^ 96 | helm_tool_footer_search ?= ^ 97 | 98 | .PHONY: generate-helm-docs 99 | ## Generate Helm chart documentation. 100 | ## @category [shared] Generate/ Verify 101 | generate-helm-docs: | $(NEEDS_HELM-TOOL) 102 | $(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)" 103 | 104 | shared_generate_targets += generate-helm-docs 105 | 106 | .PHONY: generate-helm-schema 107 | ## Generate Helm chart schema. 108 | ## @category [shared] Generate/ Verify 109 | generate-helm-schema: | $(NEEDS_HELM-TOOL) $(NEEDS_GOJQ) 110 | $(HELM-TOOL) schema -i $(helm_chart_source_dir)/values.yaml | $(GOJQ) > $(helm_chart_source_dir)/values.schema.json 111 | 112 | shared_generate_targets += generate-helm-schema 113 | 114 | .PHONY: verify-helm-values 115 | ## Verify Helm chart values using helm-tool. 116 | ## @category [shared] Generate/ Verify 117 | verify-helm-values: | $(NEEDS_HELM-TOOL) $(NEEDS_GOJQ) 118 | $(HELM-TOOL) lint -i $(helm_chart_source_dir)/values.yaml -d $(helm_chart_source_dir)/templates -e $(helm_chart_source_dir)/values.linter.exceptions 119 | 120 | shared_verify_targets += verify-helm-values 121 | 122 | $(bin_dir)/scratch/kyverno: 123 | @mkdir -p $@ 124 | 125 | $(bin_dir)/scratch/kyverno/pod-security-policy.yaml: | $(NEEDS_KUSTOMIZE) $(bin_dir)/scratch/kyverno 126 | @$(KUSTOMIZE) build https://github.com/kyverno/policies/pod-security/enforce > $@ 127 | 128 | # Extra arguments for kyverno apply. 129 | kyverno_apply_extra_args := 130 | # Allows known policy violations to be skipped by supplying Kyverno policy 131 | # exceptions as a Kyverno YAML resource, e.g.: 132 | # apiVersion: kyverno.io/v2 133 | # kind: PolicyException 134 | # metadata: 135 | # name: pod-security-exceptions 136 | # spec: 137 | # exceptions: 138 | # - policyName: disallow-privilege-escalation 139 | # ruleNames: 140 | # - autogen-privilege-escalation 141 | # - policyName: restrict-seccomp-strict 142 | # ruleNames: 143 | # - autogen-check-seccomp-strict 144 | # match: 145 | # any: 146 | # - resources: 147 | # kinds: 148 | # - Deployment 149 | # namespaces: 150 | # - mynamespace 151 | # names: 152 | # - my-deployment 153 | ifneq ("$(wildcard make/verify-pod-security-standards-exceptions.yaml)","") 154 | kyverno_apply_extra_args += --exceptions make/verify-pod-security-standards-exceptions.yaml 155 | endif 156 | 157 | .PHONY: verify-pod-security-standards 158 | ## Verify that the Helm chart complies with the pod security standards. 159 | ## 160 | ## You can add Kyverno policy exceptions to 161 | ## `make/verify-pod-security-standards-exceptions.yaml`, to skip some of the pod 162 | ## security policy rules. 163 | ## 164 | ## @category [shared] Generate/ Verify 165 | verify-pod-security-standards: $(helm_chart_archive) $(bin_dir)/scratch/kyverno/pod-security-policy.yaml | $(NEEDS_KYVERNO) $(NEEDS_HELM) 166 | @$(HELM) template $(helm_chart_archive) $(INSTALL_OPTIONS) \ 167 | | $(KYVERNO) apply $(bin_dir)/scratch/kyverno/pod-security-policy.yaml \ 168 | $(kyverno_apply_extra_args) \ 169 | --resource - \ 170 | --table 171 | 172 | shared_verify_targets_dirty += verify-pod-security-standards 173 | 174 | .PHONY: verify-helm-lint 175 | ## Verify that the Helm chart is linted. 176 | ## @category [shared] Generate/ Verify 177 | verify-helm-lint: $(helm_chart_archive) | $(NEEDS_HELM) 178 | $(HELM) lint $(helm_chart_archive) 179 | 180 | shared_verify_targets_dirty += verify-helm-lint 181 | 182 | .PHONY: verify-helm-kubeconform 183 | ## Verify that the Helm chart passes a strict check using kubeconform 184 | ## @category [shared] Generate/ Verify 185 | verify-helm-kubeconform: $(helm_chart_archive) | $(NEEDS_KUBECONFORM) 186 | @$(HELM) template $(helm_chart_archive) $(INSTALL_OPTIONS) \ 187 | | $(KUBECONFORM) \ 188 | -schema-location default \ 189 | -schema-location "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{{.NormalizedKubernetesVersion}}/{{.ResourceKind}}.json" \ 190 | -schema-location "https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json" \ 191 | -strict 192 | 193 | shared_verify_targets_dirty += verify-helm-kubeconform 194 | -------------------------------------------------------------------------------- /make/_shared/help/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | help_sh := $(dir $(lastword $(MAKEFILE_LIST)))/help.sh 17 | 18 | .PHONY: help 19 | help: 20 | @MAKEFILE_LIST="$(MAKEFILE_LIST)" \ 21 | MAKE="$(MAKE)" \ 22 | $(help_sh) 23 | -------------------------------------------------------------------------------- /make/_shared/help/help.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2023 The cert-manager Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | ## 1. Build set of extracted line items 22 | 23 | EMPTYLINE_REGEX="^[[:space:]]*$" 24 | DOCBLOCK_REGEX="^##[[:space:]]*(.*)$" 25 | CATEGORY_REGEX="^##[[:space:]]*@category[[:space:]]*(.*)$" 26 | TARGET_REGEX="^(([a-zA-Z0-9\_\/\%\$\(\)]|-)+):.*$" 27 | 28 | EMPTY_ITEM="" 29 | 30 | # shellcheck disable=SC2086 31 | raw_lines=$(cat ${MAKEFILE_LIST} | tr '\t' ' ' | grep -E "($TARGET_REGEX|$DOCBLOCK_REGEX|$EMPTYLINE_REGEX)") 32 | extracted_lines="" 33 | extracted_current="$EMPTY_ITEM" 34 | max_target_length=0 35 | 36 | ## Extract all the commented targets from the Makefile 37 | while read -r line; do 38 | if [[ $line =~ $EMPTYLINE_REGEX ]]; then 39 | # Reset current item. 40 | extracted_current="$EMPTY_ITEM" 41 | elif [[ $line =~ $CATEGORY_REGEX ]]; then 42 | extracted_current=${extracted_current///${BASH_REMATCH[1]}} 43 | elif [[ $line =~ $TARGET_REGEX ]]; then 44 | # only keep the target if there is a comment 45 | if [[ $extracted_current != *""* ]]; then 46 | max_target_length=$(( ${#BASH_REMATCH[1]} > max_target_length ? ${#BASH_REMATCH[1]} : max_target_length )) 47 | extracted_current=${extracted_current///${BASH_REMATCH[1]}} 48 | extracted_lines="$extracted_lines\n$extracted_current" 49 | fi 50 | 51 | extracted_current="$EMPTY_ITEM" 52 | elif [[ $line =~ $DOCBLOCK_REGEX ]]; then 53 | extracted_current=${extracted_current///${BASH_REMATCH[1]}} 54 | fi 55 | done <<< "$raw_lines" 56 | 57 | ## 2. Build mapping for expanding targets 58 | 59 | ASSIGNMENT_REGEX="^(([a-zA-Z0-9\_\/\%\$\(\)]|-)+)[[:space:]]*:=[[:space:]]*(.*)$" 60 | 61 | raw_expansions=$(${MAKE} --dry-run --print-data-base noop | tr '\t' ' ' | grep -E "$ASSIGNMENT_REGEX") 62 | extracted_expansions="" 63 | 64 | while read -r line; do 65 | if [[ $line =~ $ASSIGNMENT_REGEX ]]; then 66 | target=${BASH_REMATCH[1]} 67 | expansion=${BASH_REMATCH[3]// /, } 68 | extracted_expansions="$extracted_expansions\n$target$expansion" 69 | fi 70 | done <<< "$raw_expansions" 71 | 72 | ## 3. Sort and print the extracted line items 73 | 74 | RULE_COLOR="$(TERM=xterm tput setaf 6)" 75 | CATEGORY_COLOR="$(TERM=xterm tput setaf 3)" 76 | CLEAR_STYLE="$(TERM=xterm tput sgr0)" 77 | PURPLE=$(TERM=xterm tput setaf 125) 78 | 79 | extracted_lines=$(echo -e "$extracted_lines" | LC_ALL=C sort -r) 80 | current_category="" 81 | 82 | ## Print the help 83 | echo "Usage: make [target1] [target2] ..." 84 | 85 | IFS=$'\n'; for line in $extracted_lines; do 86 | category=$([[ $line =~ \(.*)\ ]] && echo "${BASH_REMATCH[1]}") 87 | target=$([[ $line =~ \(.*)\ ]] && echo "${BASH_REMATCH[1]}") 88 | comment=$([[ $line =~ \(.*)\ ]] && echo -e "${BASH_REMATCH[1]///\\n}") 89 | 90 | # Print the category header if it's changed 91 | if [[ "$current_category" != "$category" ]]; then 92 | current_category=$category 93 | echo -e "\n${CATEGORY_COLOR}${current_category}${CLEAR_STYLE}" 94 | fi 95 | 96 | # replace any $(...) with the actual value 97 | if [[ $target =~ \$\((.*)\) ]]; then 98 | new_target=$(echo -e "$extracted_expansions" | grep "${BASH_REMATCH[1]}" || true) 99 | if [[ -n "$new_target" ]]; then 100 | target=$([[ $new_target =~ \(.*)\ ]] && echo -e "${BASH_REMATCH[1]}") 101 | fi 102 | fi 103 | 104 | # Print the target and its multiline comment 105 | is_first_line=true 106 | while read -r comment_line; do 107 | if [[ "$is_first_line" == true ]]; then 108 | is_first_line=false 109 | padding=$(( max_target_length - ${#target} )) 110 | printf " %s%${padding}s ${PURPLE}>${CLEAR_STYLE} %s\n" "${RULE_COLOR}${target}${CLEAR_STYLE}" "" "${comment_line}" 111 | else 112 | printf " %${max_target_length}s %s\n" "" "${comment_line}" 113 | fi 114 | done <<< "$comment" 115 | done 116 | -------------------------------------------------------------------------------- /make/_shared/kind/00_kind_image_versions.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2024 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This file is auto-generated by the learn_kind_images.sh script in the makefile-modules repo. 16 | # Do not edit manually. 17 | 18 | kind_image_kindversion := v0.27.0 19 | 20 | kind_image_kube_1.29_amd64 := docker.io/kindest/node:v1.29.14@sha256:e7858e6394f5e834802ce573ab340a0584d8314f909cb0717e14b57f2dd97257 21 | kind_image_kube_1.29_arm64 := docker.io/kindest/node:v1.29.14@sha256:6eed9bfd0313cc3574c4613adeb7f53832cb8d9c0ca9ffa8b8221716fd96dc18 22 | kind_image_kube_1.30_amd64 := docker.io/kindest/node:v1.30.10@sha256:e382f9b891474f1c4b0b5cfcf27f8e471f1bdc1f285afe38adeec1bd5b856cfe 23 | kind_image_kube_1.30_arm64 := docker.io/kindest/node:v1.30.10@sha256:ca8e16c04ee9ebaeb9a4dd85abbe188f3893fb39bd658d6d3e639d16cf46e3da 24 | kind_image_kube_1.31_amd64 := docker.io/kindest/node:v1.31.6@sha256:37d52dc19f59394f9347b00547c3ed2d73eb301a60294b9b05fbe56fb6196517 25 | kind_image_kube_1.31_arm64 := docker.io/kindest/node:v1.31.6@sha256:4e6223faa19178922d30e7b62546c5464fdf9bc66a3df64073424a51ab44f2ab 26 | kind_image_kube_1.32_amd64 := docker.io/kindest/node:v1.32.2@sha256:a37b679ad8c1cfa7c64aca1734cc4299dc833258d6c131ed0204c8cd2bd56ff7 27 | kind_image_kube_1.32_arm64 := docker.io/kindest/node:v1.32.2@sha256:4d0e1b60f1da0d1349996a9778f8bace905189af5e05e04618eae0a155dd9f9c 28 | kind_image_kube_1.33_amd64 := docker.io/kindest/node:v1.33.0@sha256:c9ec7bf998c310c5a6c903d66c2e595fb3e2eb53fb626cd53d07a3a5499de412 29 | kind_image_kube_1.33_arm64 := docker.io/kindest/node:v1.33.0@sha256:96ae3b980f87769e0117c2a89ec74fc660b84eedb573432abd2a682af3eccc02 30 | 31 | kind_image_latest_amd64 := $(kind_image_kube_1.33_amd64) 32 | kind_image_latest_arm64 := $(kind_image_kube_1.33_arm64) 33 | -------------------------------------------------------------------------------- /make/_shared/kind/00_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | include $(dir $(lastword $(MAKEFILE_LIST)))/00_kind_image_versions.mk 16 | 17 | images_amd64 ?= 18 | images_arm64 ?= 19 | 20 | # K8S_VERSION can be used to specify a specific 21 | # kubernetes version to use with Kind. 22 | K8S_VERSION ?= 23 | ifeq ($(K8S_VERSION),) 24 | images_amd64 += $(kind_image_latest_amd64) 25 | images_arm64 += $(kind_image_latest_arm64) 26 | else 27 | fatal_if_undefined = $(if $(findstring undefined,$(origin $1)),$(error $1 is not set)) 28 | $(call fatal_if_undefined,kind_image_kube_$(K8S_VERSION)_amd64) 29 | $(call fatal_if_undefined,kind_image_kube_$(K8S_VERSION)_arm64) 30 | 31 | images_amd64 += $(kind_image_kube_$(K8S_VERSION)_amd64) 32 | images_arm64 += $(kind_image_kube_$(K8S_VERSION)_arm64) 33 | endif 34 | -------------------------------------------------------------------------------- /make/_shared/kind/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | include $(dir $(lastword $(MAKEFILE_LIST)))/kind.mk 16 | include $(dir $(lastword $(MAKEFILE_LIST)))/kind-image-preload.mk 17 | -------------------------------------------------------------------------------- /make/_shared/kind/kind-image-preload.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef bin_dir 16 | $(error bin_dir is not set) 17 | endif 18 | 19 | ifndef images_amd64 20 | $(error images_amd64 is not set) 21 | endif 22 | 23 | ifndef images_arm64 24 | $(error images_arm64 is not set) 25 | endif 26 | 27 | ########################################## 28 | 29 | images := $(images_$(HOST_ARCH)) 30 | 31 | images_tar_dir := $(bin_dir)/downloaded/containers/$(HOST_ARCH) 32 | images_tars := $(foreach image,$(images),$(images_tar_dir)/$(subst :,+,$(image)).tar) 33 | 34 | # Download the images as tarballs. After downloading the image using 35 | # its digest, we use image-tool to modify the .[0].RepoTags[0] value in 36 | # the manifest.json file to have the correct tag (instead of "i-was-a-digest" 37 | # which is set when the image is pulled using its digest). This tag is used 38 | # to reference the image after it has been imported using docker or kind. Otherwise, 39 | # the image would be imported with the tag "i-was-a-digest" which is not very useful. 40 | # We would have to use digests to reference the image everywhere which might 41 | # not always be possible and does not match the default behavior of eg. our helm charts. 42 | # NOTE: the tag is fully determined based on the input, we fully allow the remote 43 | # tag to point to a different digest. This prevents CI from breaking due to upstream 44 | # changes. However, it also means that we can incorrectly combine digests with tags, 45 | # hence caution is advised. 46 | $(images_tars): $(images_tar_dir)/%.tar: | $(NEEDS_IMAGE-TOOL) $(NEEDS_CRANE) $(NEEDS_GOJQ) 47 | @$(eval full_image=$(subst +,:,$*)) 48 | @$(eval bare_image=$(word 1,$(subst :, ,$(full_image)))) 49 | @$(eval digest=$(word 2,$(subst @, ,$(full_image)))) 50 | @$(eval tag=$(word 2,$(subst :, ,$(word 1,$(subst @, ,$(full_image)))))) 51 | @mkdir -p $(dir $@) 52 | $(CRANE) pull "$(bare_image)@$(digest)" $@ --platform=linux/$(HOST_ARCH) 53 | $(IMAGE-TOOL) tag-docker-tar $@ "$(bare_image):$(tag)" 54 | 55 | # $1 = image 56 | # $2 = image:tag@sha256:digest 57 | define image_variables 58 | $1.TAR := $(images_tar_dir)/$(subst :,+,$2).tar 59 | $1.REPO := $1 60 | $1.TAG := $(word 2,$(subst :, ,$(word 1,$(subst @, ,$2)))) 61 | $1.FULL := $(word 1,$(subst @, ,$2)) 62 | endef 63 | 64 | $(foreach image,$(images),$(eval $(call image_variables,$(word 1,$(subst :, ,$(image))),$(image)))) 65 | 66 | .PHONY: images-preload 67 | ## Preload images. 68 | ## @category [shared] Kind cluster 69 | images-preload: | $(images_tars) 70 | -------------------------------------------------------------------------------- /make/_shared/kind/kind.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ifndef bin_dir 16 | $(error bin_dir is not set) 17 | endif 18 | 19 | ifndef kind_cluster_name 20 | $(error kind_cluster_name is not set) 21 | endif 22 | 23 | ifndef kind_cluster_config 24 | $(error kind_cluster_config is not set) 25 | endif 26 | 27 | ########################################## 28 | 29 | kind_kubeconfig := $(bin_dir)/scratch/kube.config 30 | absolute_kubeconfig := $(CURDIR)/$(kind_kubeconfig) 31 | 32 | $(bin_dir)/scratch/cluster-check: FORCE | $(NEEDS_KIND) $(bin_dir)/scratch 33 | @if ! $(KIND) get clusters -q | grep -q "^$(kind_cluster_name)\$$"; then \ 34 | echo "❌ cluster $(kind_cluster_name) not found. Starting ..."; \ 35 | echo "trigger" > $@; \ 36 | else \ 37 | echo "✅ existing cluster $(kind_cluster_name) found"; \ 38 | fi 39 | $(eval export KUBECONFIG=$(absolute_kubeconfig)) 40 | 41 | kind_post_create_hook ?= 42 | $(kind_kubeconfig): $(kind_cluster_config) $(bin_dir)/scratch/cluster-check | images-preload $(bin_dir)/scratch $(NEEDS_KIND) $(NEEDS_KUBECTL) $(NEEDS_CTR) 43 | @[ -f "$(bin_dir)/scratch/cluster-check" ] && ( \ 44 | $(KIND) delete cluster --name $(kind_cluster_name); \ 45 | $(CTR) load -i $(docker.io/kindest/node.TAR); \ 46 | $(KIND) create cluster \ 47 | --image $(docker.io/kindest/node.FULL) \ 48 | --name $(kind_cluster_name) \ 49 | --config "$<"; \ 50 | $(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 {} \; ; \ 51 | $(MAKE) --no-print-directory noop $(kind_post_create_hook); \ 52 | $(KUBECTL) config use-context kind-$(kind_cluster_name); \ 53 | ) || true 54 | 55 | $(KIND) get kubeconfig --name $(kind_cluster_name) > $@ 56 | 57 | .PHONY: kind-cluster 58 | kind-cluster: $(kind_kubeconfig) 59 | 60 | .PHONY: kind-cluster-load 61 | ## Create Kind cluster and wait for nodes to be ready 62 | ## Load the kubeconfig into the default location so that 63 | ## it can be easily queried by kubectl. This target is 64 | ## meant to be used directly, NOT as a dependency. 65 | ## Use `kind-cluster` as a dependency instead. 66 | ## @category [shared] Kind cluster 67 | kind-cluster-load: kind-cluster | $(NEEDS_KUBECTL) 68 | mkdir -p ~/.kube 69 | KUBECONFIG=~/.kube/config:$(kind_kubeconfig) $(KUBECTL) config view --flatten > ~/.kube/config 70 | $(KUBECTL) config use-context kind-$(kind_cluster_name) 71 | 72 | .PHONY: kind-cluster-clean 73 | ## Delete the Kind cluster 74 | ## @category [shared] Kind cluster 75 | kind-cluster-clean: $(NEEDS_KIND) 76 | $(KIND) delete cluster --name $(kind_cluster_name) 77 | rm -rf $(kind_kubeconfig) 78 | $(MAKE) --no-print-directory noop $(kind_post_create_hook) 79 | 80 | .PHONY: kind-logs 81 | ## Get the Kind cluster 82 | ## @category [shared] Kind cluster 83 | kind-logs: | kind-cluster $(NEEDS_KIND) $(ARTIFACTS) 84 | rm -rf $(ARTIFACTS)/e2e-logs 85 | mkdir -p $(ARTIFACTS)/e2e-logs 86 | $(KIND) export logs $(ARTIFACTS)/e2e-logs --name=$(kind_cluster_name) 87 | -------------------------------------------------------------------------------- /make/_shared/klone/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | .PHONY: generate-klone 16 | ## Generate klone shared Makefiles 17 | ## @category [shared] Generate/ Verify 18 | generate-klone: | $(NEEDS_KLONE) 19 | $(KLONE) sync 20 | 21 | shared_generate_targets += generate-klone 22 | 23 | .PHONY: upgrade-klone 24 | ## Upgrade klone Makefile modules to latest version 25 | ## @category [shared] Self-upgrade 26 | upgrade-klone: | $(NEEDS_KLONE) 27 | $(KLONE) upgrade 28 | -------------------------------------------------------------------------------- /make/_shared/licenses/00_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2024 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Define default config for generating licenses 16 | license_ignore ?= 17 | -------------------------------------------------------------------------------- /make/_shared/licenses/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2024 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ###################### Generate LICENSES files ###################### 16 | 17 | # Create a go.work file so that go-licenses can discover the LICENSE file of the 18 | # other modules in the repo. 19 | # 20 | # Without this, go-licenses *guesses* the wrong LICENSE for local dependencies and 21 | # links to the wrong versions of LICENSES for transitive dependencies. 22 | licenses_go_work := $(bin_dir)/scratch/LICENSES.go.work 23 | $(licenses_go_work): $(bin_dir)/scratch 24 | GOWORK=$(abspath $@) \ 25 | $(MAKE) go-workspace 26 | 27 | ## Generate licenses for the golang dependencies 28 | ## @category [shared] Generate/Verify 29 | generate-go-licenses: # 30 | shared_generate_targets += generate-go-licenses 31 | 32 | define licenses_target 33 | $1/LICENSES: $1/go.mod $(licenses_go_work) | $(NEEDS_GO-LICENSES) 34 | cd $$(dir $$@) && \ 35 | GOWORK=$(abspath $(licenses_go_work)) \ 36 | GOOS=linux GOARCH=amd64 \ 37 | $(GO-LICENSES) report --ignore "$$(license_ignore)" ./... > LICENSES 38 | 39 | generate-go-licenses: $1/LICENSES 40 | # The /LICENSE targets make sure these files exist. 41 | # Otherwise, make will error. 42 | generate-go-licenses: $1/LICENSE 43 | endef 44 | 45 | # Calculate all the go.mod directories, build targets may share go.mod dirs so 46 | # we use $(sort) to de-duplicate. 47 | go_mod_dirs := $(foreach build_name,$(build_names),$(go_$(build_name)_mod_dir)) 48 | ifneq ("$(wildcard go.mod)","") 49 | go_mod_dirs += . 50 | endif 51 | go_mod_dirs := $(sort $(go_mod_dirs)) 52 | $(foreach go_mod_dir,$(go_mod_dirs),$(eval $(call licenses_target,$(go_mod_dir)))) 53 | 54 | ###################### Include LICENSES in OCI image ###################### 55 | 56 | define license_layer 57 | license_layer_path_$1 := $$(abspath $(bin_dir)/scratch/licenses-$1) 58 | 59 | # Target to generate image layer containing license information 60 | .PHONY: oci-license-layer-$1 61 | oci-license-layer-$1: | $(bin_dir)/scratch $(NEEDS_GO-LICENSES) 62 | rm -rf $$(license_layer_path_$1) 63 | mkdir -p $$(license_layer_path_$1)/licenses 64 | cp $$(go_$1_mod_dir)/LICENSE $$(license_layer_path_$1)/licenses/LICENSE 65 | cp $$(go_$1_mod_dir)/LICENSES $$(license_layer_path_$1)/licenses/LICENSES 66 | 67 | oci-build-$1: oci-license-layer-$1 68 | oci_$1_additional_layers += $$(license_layer_path_$1) 69 | endef 70 | 71 | $(foreach build_name,$(build_names),$(eval $(call license_layer,$(build_name)))) 72 | -------------------------------------------------------------------------------- /make/_shared/oci-build/00_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | oci_platforms ?= linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le 16 | 17 | # Use distroless as minimal base image to package the manager binary 18 | # To get latest SHA run "crane digest quay.io/jetstack/base-static:latest" 19 | base_image_static := quay.io/jetstack/base-static@sha256:01d887b98d90226dbaeb32b9cab0dbede410a652fa16829c6fd2f94df55d7757 20 | 21 | # Use custom apko-built image as minimal base image to package the manager binary 22 | # To get latest SHA run "crane digest quay.io/jetstack/base-static-csi:latest" 23 | base_image_csi-static := quay.io/jetstack/base-static-csi@sha256:35531ca8c25f441a15b9ae211aaa2a9978334c45dd2a9c130525aa73c8bdf5af 24 | 25 | # Utility functions 26 | fatal_if_undefined = $(if $(findstring undefined,$(origin $1)),$(error $1 is not set)) 27 | fatal_if_deprecated_defined = $(if $(findstring undefined,$(origin $1)),,$(error $1 is deprecated, use $2 instead)) 28 | 29 | # Validate globals that are required 30 | $(call fatal_if_undefined,bin_dir) 31 | $(call fatal_if_undefined,build_names) 32 | 33 | # Set default config values 34 | CGO_ENABLED ?= 0 35 | GOEXPERIMENT ?= # empty by default 36 | 37 | # Default variables per build_names entry 38 | # 39 | # $1 - build_name 40 | define default_per_build_variables 41 | go_$1_cgo_enabled ?= $(CGO_ENABLED) 42 | go_$1_goexperiment ?= $(GOEXPERIMENT) 43 | go_$1_flags ?= -tags= 44 | oci_$1_additional_layers ?= 45 | oci_$1_linux_capabilities ?= 46 | oci_$1_build_args ?= 47 | endef 48 | 49 | $(foreach build_name,$(build_names),$(eval $(call default_per_build_variables,$(build_name)))) 50 | 51 | # Validate variables per build_names entry 52 | # 53 | # $1 - build_name 54 | define check_per_build_variables 55 | # Validate deprecated variables 56 | $(call fatal_if_deprecated_defined,cgo_enabled_$1,go_$1_cgo_enabled) 57 | $(call fatal_if_deprecated_defined,goexperiment_$1,go_$1_goexperiment) 58 | $(call fatal_if_deprecated_defined,oci_additional_layers_$1,oci_$1_additional_layers) 59 | 60 | # Validate required config exists 61 | $(call fatal_if_undefined,go_$1_ldflags) 62 | $(call fatal_if_undefined,go_$1_main_dir) 63 | $(call fatal_if_undefined,go_$1_mod_dir) 64 | $(call fatal_if_undefined,oci_$1_base_image_flavor) 65 | $(call fatal_if_undefined,oci_$1_image_name_development) 66 | 67 | # Validate we have valid base image config 68 | ifeq ($(oci_$1_base_image_flavor),static) 69 | oci_$1_base_image := $(base_image_static) 70 | else ifeq ($(oci_$1_base_image_flavor),csi-static) 71 | oci_$1_base_image := $(base_image_csi-static) 72 | else ifeq ($(oci_$1_base_image_flavor),custom) 73 | $$(call fatal_if_undefined,oci_$1_base_image) 74 | else 75 | $$(error oci_$1_base_image_flavor has unknown value "$(oci_$1_base_image_flavor)") 76 | endif 77 | 78 | # Validate the config required to build the golang based images 79 | ifneq ($(go_$1_main_dir:.%=.),.) 80 | $$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES start with ".") 81 | endif 82 | ifeq ($(go_$1_main_dir:%/=/),/) 83 | $$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES NOT end with "/") 84 | endif 85 | ifeq ($(go_$1_main_dir:%.go=.go),.go) 86 | $$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES NOT end with ".go") 87 | endif 88 | ifneq ($(go_$1_mod_dir:.%=.),.) 89 | $$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES start with ".") 90 | endif 91 | ifeq ($(go_$1_mod_dir:%/=/),/) 92 | $$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES NOT end with "/") 93 | endif 94 | ifeq ($(go_$1_mod_dir:%.go=.go),.go) 95 | $$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES NOT end with ".go") 96 | endif 97 | ifeq ($(wildcard $(go_$1_mod_dir)/go.mod),) 98 | $$(error go_$1_mod_dir "$(go_$1_mod_dir)" does not contain a go.mod file) 99 | endif 100 | ifeq ($(wildcard $(go_$1_mod_dir)/$(go_$1_main_dir)/main.go),) 101 | $$(error go_$1_main_dir "$(go_$1_mod_dir)" does not contain a main.go file) 102 | endif 103 | 104 | # Validate the config required to build OCI images 105 | ifneq ($(words $(oci_$1_image_name_development)),1) 106 | $$(error oci_$1_image_name_development "$(oci_$1_image_name_development)" should be a single image name) 107 | endif 108 | 109 | endef 110 | 111 | $(foreach build_name,$(build_names),$(eval $(call check_per_build_variables,$(build_name)))) 112 | 113 | # Create variables holding targets 114 | # 115 | # We create the following targets for each $(build_names) 116 | # - oci-build-$(build_name) = build the oci directory 117 | # - oci-load-$(build_name) = load the image into docker using the oci_$(build_name)_image_name_development variable 118 | # - docker-tarball-$(build_name) = build a "docker load" compatible tarball of the image 119 | # - ko-config-$(build_name) = generate "ko" config for a given build 120 | oci_build_targets := $(build_names:%=oci-build-%) 121 | oci_load_targets := $(build_names:%=oci-load-%) 122 | docker_tarball_targets := $(build_names:%=docker-tarball-%) 123 | ko_config_targets := $(build_names:%=ko-config-%) 124 | 125 | # Derive config based on user config 126 | # 127 | # - oci_layout_path_$(build_name) = path that the OCI image will be saved in OCI layout directory format 128 | # - oci_digest_path_$(build_name) = path to the file that will contain the digests 129 | # - ko_config_path_$(build_name) = path to the ko config file 130 | # - docker_tarball_path_$(build_name) = path that the docker tarball that the docker-tarball-$(build_name) will produce 131 | $(foreach build_name,$(build_names),$(eval oci_layout_path_$(build_name) := $(bin_dir)/scratch/image/oci-layout-$(build_name))) 132 | $(foreach build_name,$(build_names),$(eval oci_digest_path_$(build_name) := $(CURDIR)/$(oci_layout_path_$(build_name)).digests)) 133 | $(foreach build_name,$(build_names),$(eval ko_config_path_$(build_name) := $(CURDIR)/$(oci_layout_path_$(build_name)).ko_config.yaml)) 134 | $(foreach build_name,$(build_names),$(eval docker_tarball_path_$(build_name) := $(CURDIR)/$(oci_layout_path_$(build_name)).docker.tar)) 135 | -------------------------------------------------------------------------------- /make/_shared/oci-build/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | $(bin_dir)/scratch/image: 16 | @mkdir -p $@ 17 | 18 | define ko_config_target 19 | .PHONY: $(ko_config_path_$1:$(CURDIR)/%=%) 20 | $(ko_config_path_$1:$(CURDIR)/%=%): | $(NEEDS_YQ) $(bin_dir)/scratch/image 21 | echo '{}' | \ 22 | $(YQ) '.defaultBaseImage = "$(oci_$1_base_image)"' | \ 23 | $(YQ) '.builds[0].id = "$1"' | \ 24 | $(YQ) '.builds[0].dir = "$(go_$1_mod_dir)"' | \ 25 | $(YQ) '.builds[0].main = "$(go_$1_main_dir)"' | \ 26 | $(YQ) '.builds[0].env[0] = "CGO_ENABLED=$(go_$1_cgo_enabled)"' | \ 27 | $(YQ) '.builds[0].env[1] = "GOEXPERIMENT=$(go_$1_goexperiment)"' | \ 28 | $(YQ) '.builds[0].ldflags[0] = "-s"' | \ 29 | $(YQ) '.builds[0].ldflags[1] = "-w"' | \ 30 | $(YQ) '.builds[0].ldflags[2] = "{{.Env.LDFLAGS}}"' | \ 31 | $(YQ) '.builds[0].flags[0] = "$(go_$1_flags)"' | \ 32 | $(YQ) '.builds[0].linux_capabilities = "$(oci_$1_linux_capabilities)"' \ 33 | > $(CURDIR)/$(oci_layout_path_$1).ko_config.yaml 34 | 35 | ko-config-$1: $(ko_config_path_$1:$(CURDIR)/%=%) 36 | endef 37 | 38 | .PHONY: $(ko_config_targets) 39 | $(foreach build_name,$(build_names),$(eval $(call ko_config_target,$(build_name)))) 40 | 41 | .PHONY: $(oci_build_targets) 42 | ## Build the OCI image. 43 | ## @category [shared] Build 44 | $(oci_build_targets): oci-build-%: ko-config-% | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS_YQ) $(NEEDS_IMAGE-TOOL) $(bin_dir)/scratch/image 45 | rm -rf $(CURDIR)/$(oci_layout_path_$*) 46 | GOWORK=off \ 47 | KO_DOCKER_REPO=$(oci_$*_image_name_development) \ 48 | KOCACHE=$(CURDIR)/$(bin_dir)/scratch/image/ko_cache \ 49 | KO_CONFIG_PATH=$(ko_config_path_$*) \ 50 | SOURCE_DATE_EPOCH=$(GITEPOCH) \ 51 | KO_GO_PATH=$(GO) \ 52 | LDFLAGS="$(go_$*_ldflags)" \ 53 | $(KO) build $(go_$*_mod_dir)/$(go_$*_main_dir) \ 54 | --platform=$(oci_platforms) \ 55 | $(oci_$*_build_args) \ 56 | --oci-layout-path=$(oci_layout_path_$*) \ 57 | --sbom-dir=$(CURDIR)/$(oci_layout_path_$*).sbom \ 58 | --sbom=spdx \ 59 | --push=false \ 60 | --bare 61 | 62 | $(IMAGE-TOOL) append-layers \ 63 | $(CURDIR)/$(oci_layout_path_$*) \ 64 | $(oci_$*_additional_layers) 65 | 66 | $(IMAGE-TOOL) list-digests \ 67 | $(CURDIR)/$(oci_layout_path_$*) \ 68 | > $(oci_digest_path_$*) 69 | 70 | # Only include the oci-load target if kind is provided by the kind makefile-module 71 | ifdef kind_cluster_name 72 | .PHONY: $(oci_load_targets) 73 | ## Build OCI image for the local architecture and load 74 | ## it into the $(kind_cluster_name) kind cluster. 75 | ## @category [shared] Build 76 | $(oci_load_targets): oci-load-%: docker-tarball-% | kind-cluster $(NEEDS_KIND) 77 | $(KIND) load image-archive --name $(kind_cluster_name) $(docker_tarball_path_$*) 78 | endif 79 | 80 | ## Build Docker tarball image for the local architecture 81 | ## @category [shared] Build 82 | .PHONY: $(docker_tarball_targets) 83 | $(docker_tarball_targets): oci_platforms := "linux/$(HOST_ARCH)" 84 | $(docker_tarball_targets): docker-tarball-%: oci-build-% | $(NEEDS_GO) $(NEEDS_IMAGE-TOOL) 85 | $(IMAGE-TOOL) convert-to-docker-tar $(CURDIR)/$(oci_layout_path_$*) $(docker_tarball_path_$*) $(oci_$*_image_name_development):$(oci_$*_image_tag) 86 | -------------------------------------------------------------------------------- /make/_shared/oci-publish/00_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Push names is equivalent to build_names, additional names can be added for 16 | # pushing images that are not build with the oci-build module 17 | push_names ?= 18 | push_names += $(build_names) 19 | 20 | # Sometimes we need to push to one registry, but pull from another. This allows 21 | # that. 22 | # 23 | # The lines should be in the format a=b 24 | # 25 | # The value on the left is the domain you include in your oci__image_name 26 | # variable, the one on the right is the domain that is actually pushed to. 27 | # 28 | # For example, if we set up a vanity domain for the current quay: 29 | # 30 | # oci_controller_image_name = registry.cert-manager.io/cert-manager-controller` 31 | # image_registry_rewrite += registry.cert-manager.io=quay.io/jetstack 32 | # 33 | # This would push to quay.io/jetstack/cert-manager-controller. 34 | # 35 | # The general idea is oci__image_name contains the final image name, after replication, after vanity domains etc. 36 | 37 | image_registry_rewrite ?= 38 | 39 | # Utilities for extracting the key and value from a foo=bar style line 40 | kv_key = $(word 1,$(subst =, ,$1)) 41 | kv_value = $(word 2,$(subst =, ,$1)) 42 | 43 | # Apply the image_registry_rewrite rules, if no rules match an image then the 44 | # image name is not changed. Any rules that match will be applied. 45 | # 46 | # For example, if there was a rule vanity-domain.com=real-registry.com/foo 47 | # then any references to vanity-domain.com/image would be rewritten to 48 | # real-registry.com/foo/image 49 | image_registry_rewrite_rules_for_image = $(strip $(sort $(foreach rule,$(image_registry_rewrite),$(if $(findstring $(call kv_key,$(rule)),$1),$(rule))))) 50 | apply_image_registry_rewrite_rules_to_image = $(if $(call image_registry_rewrite_rules_for_image,$1),\ 51 | $(foreach rule,$(call image_registry_rewrite_rules_for_image,$1),$(subst $(call kv_key,$(rule)),$(call kv_value,$(rule)),$1)),\ 52 | $1) 53 | apply_image_registry_rewrite_rules = $(foreach image_name,$1,$(call apply_image_registry_rewrite_rules_to_image,$(image_name))) 54 | 55 | # This is a helper function to return the image names for a given build_name. 56 | # It will apply all rewrite rules to the image names 57 | oci_image_names_for = $(call apply_image_registry_rewrite_rules,$(oci_$1_image_name)) 58 | oci_image_tag_for = $(oci_$1_image_tag) -------------------------------------------------------------------------------- /make/_shared/oci-publish/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Utility functions 16 | fatal_if_undefined = $(if $(findstring undefined,$(origin $1)),$(error $1 is not set)) 17 | oci_digest = $(shell head -1 $(oci_digest_path_$1) 2> /dev/null) 18 | sanitize_target = $(subst :,-,$1) 19 | registry_for = $(firstword $(subst /, ,$1)) 20 | 21 | # Utility variables 22 | current_makefile_directory := $(dir $(lastword $(MAKEFILE_LIST))) 23 | image_exists_script := $(current_makefile_directory)/image-exists.sh 24 | 25 | # Validate globals that are required 26 | $(call fatal_if_undefined,bin_dir) 27 | $(call fatal_if_undefined,push_names) 28 | 29 | # Set default config values 30 | RELEASE_DRYRUN ?= false 31 | CRANE_FLAGS ?= # empty by default 32 | COSIGN_FLAGS ?= # empty by default 33 | OCI_SIGN_ON_PUSH ?= true 34 | 35 | # Default variables per push_names entry 36 | # 37 | # $1 - build_name 38 | define default_per_build_variables 39 | release_dryrun_$1 ?= $(RELEASE_DRYRUN) 40 | crane_flags_$1 ?= $(CRANE_FLAGS) 41 | cosign_flags_$1 ?= $(COSIGN_FLAGS) 42 | oci_sign_on_push_$1 ?= $(OCI_SIGN_ON_PUSH) 43 | endef 44 | 45 | $(foreach build_name,$(push_names),$(eval $(call default_per_build_variables,$(build_name)))) 46 | 47 | # Validate variables per push_names entry 48 | # 49 | # $1 - build_name 50 | define check_per_build_variables 51 | $(call fatal_if_undefined,oci_digest_path_$1) 52 | $(call fatal_if_undefined,oci_layout_path_$1) 53 | $(call fatal_if_undefined,oci_$1_image_name) 54 | $(call fatal_if_undefined,oci_$1_image_tag) 55 | endef 56 | 57 | $(foreach build_name,$(push_names),$(eval $(call check_per_build_variables,$(build_name)))) 58 | 59 | # Create variables holding targets 60 | # 61 | # We create the following targets for each $(push_names) 62 | # - oci-build-$(build_name) = build the oci directory 63 | # - oci-load-$(build_name) = load the image into docker using the oci_$(build_name)_image_name_development variable 64 | # - docker-tarball-$(build_name) = build a "docker load" compatible tarball of the image 65 | # - ko-config-$(build_name) = generate "ko" config for a given build 66 | oci_push_targets := $(push_names:%=oci-push-%) 67 | oci_sign_targets := $(push_names:%=oci-sign-%) 68 | oci_maybe_push_targets := $(push_names:%=oci-maybe-push-%) 69 | 70 | # Define push target 71 | # $1 - build_name 72 | # $2 - image_name 73 | define oci_push_target 74 | .PHONY: $(call sanitize_target,oci-push-$2) 75 | $(call sanitize_target,oci-push-$2): oci-build-$1 | $(NEEDS_CRANE) 76 | $$(CRANE) $(crane_flags_$1) push "$(oci_layout_path_$1)" "$2:$(call oci_image_tag_for,$1)" 77 | $(if $(filter true,$(oci_sign_on_push_$1)),$(MAKE) $(call sanitize_target,oci-sign-$2)) 78 | 79 | .PHONY: $(call sanitize_target,oci-maybe-push-$2) 80 | $(call sanitize_target,oci-maybe-push-$2): oci-build-$1 | $(NEEDS_CRANE) 81 | CRANE="$$(CRANE) $(crane_flags_$1)" \ 82 | source $(image_exists_script) $2:$(call oci_image_tag_for,$1); \ 83 | $$(CRANE) $(crane_flags_$1) push "$(oci_layout_path_$1)" "$2:$(call oci_image_tag_for,$1)"; \ 84 | $(if $(filter true,$(oci_sign_on_push_$1)),$(MAKE) $(call sanitize_target,oci-sign-$2)) 85 | 86 | oci-push-$1: $(call sanitize_target,oci-push-$2) 87 | oci-maybe-push-$1: $(call sanitize_target,oci-maybe-push-$2) 88 | endef 89 | 90 | oci_push_target_per_image = $(foreach image_name,$2,$(eval $(call oci_push_target,$1,$(image_name)))) 91 | $(foreach build_name,$(push_names),$(eval $(call oci_push_target_per_image,$(build_name),$(call oci_image_names_for,$(build_name))))) 92 | 93 | .PHONY: $(oci_push_targets) 94 | ## Build and push OCI image. 95 | ## If the tag already exists, this target will overwrite it. 96 | ## If an identical image was already built before, we will add a new tag to it, but we will not sign it again. 97 | ## Expected pushed images: 98 | ## - :v1.2.3, @sha256:0000001 99 | ## - :v1.2.3.sig, :sha256-0000001.sig 100 | ## @category [shared] Publish 101 | $(oci_push_targets): 102 | 103 | .PHONY: $(oci_maybe_push_targets) 104 | ## Push image if tag does not already exist in registry. 105 | ## @category [shared] Publish 106 | $(oci_maybe_push_targets): 107 | 108 | # Define sign target 109 | # $1 - build_name 110 | # $2 - image_name 111 | define oci_sign_target 112 | .PHONY: $(call sanitize_target,oci-sign-$2) 113 | $(call sanitize_target,oci-sign-$2): $(oci_digest_path_$1) | $(NEEDS_CRANE) $(NEEDS_COSIGN) 114 | $$(CRANE) $(crane_flags_$1) manifest $2:$$(subst :,-,$$(call oci_digest,$1)).sig > /dev/null 2>&1 || \ 115 | $$(COSIGN) sign --yes=true $(cosign_flags_$1) "$2@$$(call oci_digest,$1)" 116 | 117 | oci-sign-$1: $(call sanitize_target,oci-sign-$2) 118 | endef 119 | 120 | oci_sign_target_per_image = $(foreach image_name,$2,$(eval $(call oci_sign_target,$1,$(image_name)))) 121 | $(foreach build_name,$(push_names),$(eval $(call oci_sign_target_per_image,$(build_name),$(call oci_image_names_for,$(build_name))))) 122 | 123 | .PHONY: $(oci_sign_targets) 124 | ## Sign an OCI image. 125 | ## If a signature already exists, this will not overwrite it. 126 | ## @category [shared] Publish 127 | $(oci_sign_targets): -------------------------------------------------------------------------------- /make/_shared/oci-publish/image-exists.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2022 The cert-manager Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | # This script checks if a given image exists in the upstream registry, and if it 22 | # does, whether it contains all the expected architectures. 23 | 24 | crane=${CRANE:-} 25 | 26 | FULL_IMAGE=${1:-} 27 | 28 | function print_usage() { 29 | echo "usage: $0 [commands...]" 30 | } 31 | 32 | if [[ -z $FULL_IMAGE ]]; then 33 | print_usage 34 | echo "Missing full-image" 35 | exit 1 36 | fi 37 | 38 | if [[ -z $crane ]]; then 39 | echo "CRANE environment variable must be set to the path of the crane binary" 40 | exit 1 41 | fi 42 | 43 | shift 1 44 | 45 | manifest=$(mktemp) 46 | trap 'rm -f "$manifest"' EXIT SIGINT 47 | 48 | manifest_error=$(mktemp) 49 | trap 'rm -f "$manifest_error"' EXIT SIGINT 50 | 51 | echo "+++ searching for $FULL_IMAGE in upstream registry" 52 | 53 | set +o errexit 54 | $crane manifest "$FULL_IMAGE" > "$manifest" 2> "$manifest_error" 55 | exit_code=$? 56 | set -o errexit 57 | 58 | manifest_error_data=$(cat "$manifest_error") 59 | if [[ $exit_code -eq 0 ]]; then 60 | echo "+++ upstream registry appears to contain $FULL_IMAGE, exiting" 61 | exit 0 62 | 63 | elif [[ "$manifest_error_data" == *"MANIFEST_UNKNOWN"* ]]; then 64 | echo "+++ upstream registry does not contain $FULL_IMAGE, will build and push" 65 | # fall through to run the commands passed to this script 66 | 67 | else 68 | echo "FATAL: upstream registry returned an unexpected error: $manifest_error_data, exiting" 69 | exit 1 70 | fi 71 | -------------------------------------------------------------------------------- /make/_shared/repository-base/01_mod.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ 16 | base_dependabot_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base-dependabot/ 17 | 18 | ifdef repository_base_no_dependabot 19 | .PHONY: generate-base 20 | ## Generate base files in the repository 21 | ## @category [shared] Generate/ Verify 22 | generate-base: 23 | cp -r $(base_dir)/. ./ 24 | else 25 | .PHONY: generate-base 26 | ## Generate base files in the repository 27 | ## @category [shared] Generate/ Verify 28 | generate-base: 29 | cp -r $(base_dir)/. ./ 30 | cp -r $(base_dependabot_dir)/. ./ 31 | endif 32 | 33 | shared_generate_targets += generate-base 34 | -------------------------------------------------------------------------------- /make/_shared/repository-base/base-dependabot/.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base-dependabot/.github/dependabot.yaml instead. 3 | 4 | # Update Go dependencies and GitHub Actions dependencies daily. 5 | version: 2 6 | updates: 7 | - package-ecosystem: gomod 8 | directory: / 9 | schedule: 10 | interval: daily 11 | groups: 12 | all: 13 | patterns: ["*"] 14 | - package-ecosystem: github-actions 15 | directory: / 16 | schedule: 17 | interval: daily 18 | groups: 19 | all: 20 | patterns: ["*"] 21 | -------------------------------------------------------------------------------- /make/_shared/repository-base/base/.github/workflows/make-self-upgrade.yaml: -------------------------------------------------------------------------------- 1 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/.github/workflows/make-self-upgrade.yaml instead. 3 | 4 | name: make-self-upgrade 5 | concurrency: make-self-upgrade 6 | on: 7 | workflow_dispatch: {} 8 | schedule: 9 | - cron: '0 0 * * *' 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | self_upgrade: 16 | runs-on: ubuntu-latest 17 | 18 | if: github.repository_owner == 'cert-manager' 19 | 20 | permissions: 21 | contents: write 22 | pull-requests: write 23 | 24 | env: 25 | SOURCE_BRANCH: "${{ github.ref_name }}" 26 | SELF_UPGRADE_BRANCH: "self-upgrade-${{ github.ref_name }}" 27 | 28 | steps: 29 | - name: Fail if branch is not head of branch. 30 | if: ${{ !startsWith(github.ref, 'refs/heads/') && env.SOURCE_BRANCH != '' && env.SELF_UPGRADE_BRANCH != '' }} 31 | run: | 32 | echo "This workflow should not be run on a non-branch-head." 33 | exit 1 34 | 35 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 36 | # Adding `fetch-depth: 0` makes sure tags are also fetched. We need 37 | # the tags so `git describe` returns a valid version. 38 | # see https://github.com/actions/checkout/issues/701 for extra info about this option 39 | with: { fetch-depth: 0 } 40 | 41 | - id: go-version 42 | run: | 43 | make print-go-version >> "$GITHUB_OUTPUT" 44 | 45 | - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 46 | with: 47 | go-version: ${{ steps.go-version.outputs.result }} 48 | 49 | - run: | 50 | git checkout -B "$SELF_UPGRADE_BRANCH" 51 | 52 | - run: | 53 | make -j upgrade-klone 54 | make -j generate 55 | 56 | - id: is-up-to-date 57 | shell: bash 58 | run: | 59 | git_status=$(git status -s) 60 | is_up_to_date="true" 61 | if [ -n "$git_status" ]; then 62 | is_up_to_date="false" 63 | echo "The following changes will be committed:" 64 | echo "$git_status" 65 | fi 66 | echo "result=$is_up_to_date" >> "$GITHUB_OUTPUT" 67 | 68 | - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} 69 | run: | 70 | git config --global user.name "cert-manager-bot" 71 | git config --global user.email "cert-manager-bot@users.noreply.github.com" 72 | git add -A && git commit -m "BOT: run 'make upgrade-klone' and 'make generate'" --signoff 73 | git push -f origin "$SELF_UPGRADE_BRANCH" 74 | 75 | - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} 76 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 77 | with: 78 | script: | 79 | const { repo, owner } = context.repo; 80 | const pulls = await github.rest.pulls.list({ 81 | owner: owner, 82 | repo: repo, 83 | head: owner + ':' + process.env.SELF_UPGRADE_BRANCH, 84 | base: process.env.SOURCE_BRANCH, 85 | state: 'open', 86 | }); 87 | 88 | if (pulls.data.length < 1) { 89 | const result = await github.rest.pulls.create({ 90 | title: '[CI] Merge ' + process.env.SELF_UPGRADE_BRANCH + ' into ' + process.env.SOURCE_BRANCH, 91 | owner: owner, 92 | repo: repo, 93 | head: process.env.SELF_UPGRADE_BRANCH, 94 | base: process.env.SOURCE_BRANCH, 95 | body: [ 96 | 'This PR is auto-generated to bump the Makefile modules.', 97 | ].join('\n'), 98 | }); 99 | await github.rest.issues.addLabels({ 100 | owner, 101 | repo, 102 | issue_number: result.data.number, 103 | labels: ['skip-review'] 104 | }); 105 | } 106 | -------------------------------------------------------------------------------- /make/_shared/repository-base/base/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 16 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/Makefile instead. 17 | 18 | # NOTE FOR DEVELOPERS: "How do the Makefiles work and how can I extend them?" 19 | # 20 | # Shared Makefile logic lives in the make/_shared/ directory. The source of truth for these files 21 | # lies outside of this repository, eg. in the cert-manager/makefile-modules repository. 22 | # 23 | # Logic specific to this repository must be defined in the make/00_mod.mk and make/02_mod.mk files: 24 | # - The make/00_mod.mk file is included first and contains variable definitions needed by 25 | # the shared Makefile logic. 26 | # - The make/02_mod.mk file is included later, it can make use of most of the shared targets 27 | # defined in the make/_shared/ directory (all targets defined in 00_mod.mk and 01_mod.mk). 28 | # This file should be used to define targets specific to this repository. 29 | 30 | ################################## 31 | 32 | # Some modules build their dependencies from variables, we want these to be 33 | # evaluated at the last possible moment. For this we use second expansion to 34 | # re-evaluate the generate and verify targets a second time. 35 | # 36 | # See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html 37 | .SECONDEXPANSION: 38 | 39 | # For details on some of these "prelude" settings, see: 40 | # https://clarkgrubb.com/makefile-style-guide 41 | MAKEFLAGS += --warn-undefined-variables --no-builtin-rules 42 | SHELL := /usr/bin/env bash 43 | .SHELLFLAGS := -uo pipefail -c 44 | .DEFAULT_GOAL := help 45 | .DELETE_ON_ERROR: 46 | .SUFFIXES: 47 | FORCE: 48 | 49 | noop: # do nothing 50 | 51 | # Set empty value for MAKECMDGOALS to prevent the "warning: undefined variable 'MAKECMDGOALS'" 52 | # warning from happening when running make without arguments 53 | MAKECMDGOALS ?= 54 | 55 | ################################## 56 | # Host OS and architecture setup # 57 | ################################## 58 | 59 | # The reason we don't use "go env GOOS" or "go env GOARCH" is that the "go" 60 | # binary may not be available in the PATH yet when the Makefiles are 61 | # evaluated. HOST_OS and HOST_ARCH only support Linux, *BSD and macOS (M1 62 | # and Intel). 63 | host_os := $(shell uname -s | tr A-Z a-z) 64 | host_arch := $(shell uname -m) 65 | HOST_OS ?= $(host_os) 66 | HOST_ARCH ?= $(host_arch) 67 | 68 | ifeq (x86_64, $(HOST_ARCH)) 69 | HOST_ARCH = amd64 70 | else ifeq (aarch64, $(HOST_ARCH)) 71 | # linux reports the arm64 arch as aarch64 72 | HOST_ARCH = arm64 73 | endif 74 | 75 | ################################## 76 | # Git and versioning information # 77 | ################################## 78 | 79 | git_version := $(shell git describe --tags --always --match='v*' --abbrev=14 --dirty) 80 | VERSION ?= $(git_version) 81 | IS_PRERELEASE := $(shell git describe --tags --always --match='v*' --abbrev=0 | grep -q '-' && echo true || echo false) 82 | GITCOMMIT := $(shell git rev-parse HEAD) 83 | GITEPOCH := $(shell git show -s --format=%ct HEAD) 84 | 85 | ################################## 86 | # Global variables and dirs # 87 | ################################## 88 | 89 | bin_dir := _bin 90 | 91 | # The ARTIFACTS environment variable is set by the CI system to a directory 92 | # where artifacts should be placed. These artifacts are then uploaded to a 93 | # storage bucket by the CI system (https://docs.prow.k8s.io/docs/components/pod-utilities/). 94 | # An example of such an artifact is a jUnit XML file containing test results. 95 | # If the ARTIFACTS environment variable is not set, we default to a local 96 | # directory in the _bin directory. 97 | ARTIFACTS ?= $(bin_dir)/artifacts 98 | 99 | $(bin_dir) $(ARTIFACTS) $(bin_dir)/scratch: 100 | mkdir -p $@ 101 | 102 | .PHONY: clean 103 | ## Clean all temporary files 104 | ## @category [shared] Tools 105 | clean: 106 | rm -rf $(bin_dir) 107 | 108 | ################################## 109 | # Include all the Makefiles # 110 | ################################## 111 | 112 | -include make/00_mod.mk 113 | -include make/_shared/*/00_mod.mk 114 | -include make/_shared/*/01_mod.mk 115 | -include make/02_mod.mk 116 | -include make/_shared/*/02_mod.mk 117 | -------------------------------------------------------------------------------- /make/_shared/repository-base/base/OWNERS_ALIASES: -------------------------------------------------------------------------------- 1 | # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/OWNERS_ALIASES instead. 3 | 4 | aliases: 5 | cm-maintainers: 6 | - munnerz 7 | - joshvanl 8 | - wallrj 9 | - jakexks 10 | - maelvls 11 | - sgtcodfish 12 | - inteon 13 | - thatsmrtalbot 14 | - erikgb 15 | -------------------------------------------------------------------------------- /make/_shared/tools/util/checkhash.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2023 The cert-manager Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 22 | 23 | # This script takes the hash of its first argument and verifies it against the 24 | # hex hash given in its second argument 25 | 26 | function usage_and_exit() { 27 | echo "usage: $0 " 28 | echo "or: LEARN_FILE= $0 " 29 | exit 1 30 | } 31 | 32 | HASH_TARGET=${1:-} 33 | EXPECTED_HASH=${2:-} 34 | 35 | if [[ -z $HASH_TARGET ]]; then 36 | usage_and_exit 37 | fi 38 | 39 | if [[ -z $EXPECTED_HASH ]]; then 40 | usage_and_exit 41 | fi 42 | 43 | SHASUM=$("${SCRIPT_DIR}/hash.sh" "$HASH_TARGET") 44 | 45 | if [[ "$SHASUM" == "$EXPECTED_HASH" ]]; then 46 | exit 0 47 | fi 48 | 49 | # When running 'make learn-sha-tools', we don't want this script to fail. 50 | # Instead we log what sha values are wrong, so the make.mk file can be updated. 51 | 52 | if [ "${LEARN_FILE:-}" != "" ]; then 53 | echo "s/$EXPECTED_HASH/$SHASUM/g" >> "${LEARN_FILE:-}" 54 | exit 0 55 | fi 56 | 57 | echo "invalid checksum for \"$HASH_TARGET\": wanted \"$EXPECTED_HASH\" but got \"$SHASUM\"" 58 | exit 1 59 | -------------------------------------------------------------------------------- /make/_shared/tools/util/hash.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2023 The cert-manager Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | # This script is a wrapper for outputting purely the sha256 hash of the input file, 22 | # ideally in a portable way. 23 | 24 | case "$(uname -s)" in 25 | Darwin*) shasum -a 256 "$1";; 26 | *) sha256sum "$1" 27 | esac | cut -d" " -f1 -------------------------------------------------------------------------------- /make/_shared/tools/util/lock.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2023 The cert-manager Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | # This script is used to lock a file while it is being downloaded. It prevents 22 | # multiple processes from downloading the same file at the same time or from reading 23 | # a half-downloaded file. 24 | # We need this solution because we have recursive $(MAKE) calls in our makefile 25 | # which each will try to download a set of tools. To prevent them from all downloading 26 | # the same files, we re-use the same downloads folder for all $(MAKE) invocations and 27 | # use this script to deduplicate the download processes. 28 | 29 | finalfile="$1" 30 | lockfile="$finalfile.lock" 31 | 32 | # On macOS, flock is not installed, we just skip locking in that case, 33 | # this means that running verify in parallel without downloading all 34 | # tools first will not work. 35 | flock_installed=$(command -v flock >/dev/null && echo "yes" || echo "no") 36 | 37 | if [[ "$flock_installed" == "yes" ]]; then 38 | mkdir -p "$(dirname "$lockfile")" 39 | touch "$lockfile" 40 | exec {FD}<>"$lockfile" 41 | 42 | # wait for the file to be unlocked 43 | if ! flock -x $FD; then 44 | echo "Failed to obtain a lock for $lockfile" 45 | exit 1 46 | fi 47 | fi 48 | 49 | # now that we have the lock, check if file is already there 50 | if [[ -e "$finalfile" ]]; then 51 | exit 0 52 | fi 53 | 54 | # use a temporary file to prevent Make from thinking the file is ready 55 | # while in reality is is only a partial download 56 | # shellcheck disable=SC2034 57 | outfile="$finalfile.tmp" 58 | 59 | finish() { 60 | rv=$? 61 | if [[ $rv -eq 0 ]]; then 62 | mv "$outfile" "$finalfile" 63 | echo "[info]: downloaded $finalfile" 64 | else 65 | rm -rf "$outfile" || true 66 | rm -rf "$finalfile" || true 67 | fi 68 | rm -rf "$lockfile" || true 69 | } 70 | trap finish EXIT SIGINT 71 | -------------------------------------------------------------------------------- /make/config/kind/cluster.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kind.x-k8s.io/v1alpha4 2 | kind: Cluster 3 | kubeadmConfigPatches: 4 | - | 5 | kind: ClusterConfiguration 6 | metadata: 7 | name: config 8 | etcd: 9 | local: 10 | extraArgs: 11 | unsafe-no-fsync: "true" 12 | networking: 13 | serviceSubnet: 10.0.0.0/16 14 | nodes: 15 | - role: control-plane 16 | 17 | extraMounts: 18 | - hostPath: {{KIND_IMAGES}} 19 | containerPath: /mounted_images 20 | -------------------------------------------------------------------------------- /make/test-smoke.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | .PHONY: smoke-setup-cert-manager 16 | smoke-setup-cert-manager: | kind-cluster $(NEEDS_HELM) $(NEEDS_KUBECTL) 17 | $(HELM) upgrade \ 18 | --install \ 19 | --create-namespace \ 20 | --wait \ 21 | --version $(cert_manager_version) \ 22 | --namespace cert-manager \ 23 | --repo https://charts.jetstack.io \ 24 | --set crds.enabled=true \ 25 | --set image.repository=$(quay.io/jetstack/cert-manager-controller.REPO) \ 26 | --set image.tag=$(quay.io/jetstack/cert-manager-controller.TAG) \ 27 | --set image.pullPolicy=Never \ 28 | --set cainjector.image.repository=$(quay.io/jetstack/cert-manager-cainjector.REPO) \ 29 | --set cainjector.image.tag=$(quay.io/jetstack/cert-manager-cainjector.TAG) \ 30 | --set cainjector.image.pullPolicy=Never \ 31 | --set webhook.image.repository=$(quay.io/jetstack/cert-manager-webhook.REPO) \ 32 | --set webhook.image.tag=$(quay.io/jetstack/cert-manager-webhook.TAG) \ 33 | --set webhook.image.pullPolicy=Never \ 34 | --set startupapicheck.image.repository=$(quay.io/jetstack/cert-manager-startupapicheck.REPO) \ 35 | --set startupapicheck.image.tag=$(quay.io/jetstack/cert-manager-startupapicheck.TAG) \ 36 | --set startupapicheck.image.pullPolicy=Never \ 37 | cert-manager cert-manager >/dev/null 38 | 39 | openshift_branch := release-4.18 40 | .PHONY: smoke-setup-routes-crd 41 | smoke-setup-routes-crd: | kind-cluster $(NEEDS_KUBECTL) 42 | $(KUBECTL) apply -f https://raw.githubusercontent.com/openshift/api/$(openshift_branch)/route/v1/zz_generated.crd-manifests/routes-Default.crd.yaml 43 | 44 | # The "install" target can be run on its own with any currently active cluster, 45 | # we can't use any other cluster then a target containing "test-smoke" is run. 46 | # When a "test-smoke" target is run, the currently active cluster must be the kind 47 | # cluster created by the "kind-cluster" target. 48 | ifeq ($(findstring test-smoke,$(MAKECMDGOALS)),test-smoke) 49 | install: kind-cluster oci-load-manager 50 | endif 51 | 52 | test-smoke-deps: INSTALL_OPTIONS := 53 | test-smoke-deps: INSTALL_OPTIONS += --set image.repository=$(oci_manager_image_name_development) 54 | test-smoke-deps: smoke-setup-cert-manager 55 | test-smoke-deps: smoke-setup-routes-crd 56 | test-smoke-deps: install 57 | 58 | .PHONY: test-smoke 59 | ## Smoke end-to-end tests 60 | ## @category Testing 61 | test-smoke: test-smoke-deps | kind-cluster $(NEEDS_YQ) 62 | ./test/test-smoke.sh $(YQ) 63 | -------------------------------------------------------------------------------- /make/test-unit.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2023 The cert-manager Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | .PHONY: test-unit 16 | ## Unit tests 17 | ## @category Testing 18 | test-unit: | $(NEEDS_GOTESTSUM) $(ARTIFACTS) 19 | $(GOTESTSUM) \ 20 | --junitfile=$(ARTIFACTS)/junit-go-e2e.xml \ 21 | -- \ 22 | -coverprofile=$(ARTIFACTS)/filtered.cov \ 23 | ./internal/... \ 24 | -- \ 25 | -ldflags $(go_manager_ldflags) \ 26 | -test.timeout 2m 27 | -------------------------------------------------------------------------------- /test/test-smoke.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2023 The cert-manager Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | YQ=${1:-yq} 22 | 23 | # Create a self-signed root CA certificate and Issuer 24 | # Then create an intermediate CA and issuer 25 | 26 | cat < /dev/null && echo "Found 'provinces = [Ontario]' in Certificate YAML" 222 | echo "$cert_yaml" | $YQ eval --exit-status 'select(.spec.subject.streetAddresses[0] == "1725 Slough Avenue")' > /dev/null && echo "Found 'streetAddresses = [1725 Slough Avenue]' in Certificate YAML" 223 | echo "$cert_yaml" | $YQ eval --exit-status 'select(.spec.subject.countries[0] == "UK")' > /dev/null && echo "Found 'countries = [UK]' in Certificate YAML" 224 | echo "$cert_yaml" | $YQ eval --exit-status 'select(.spec.subject.postalCodes[0] == "SW1A 2AA")' > /dev/null && echo "Found 'postal codes = [SW1A 2AA]' in Certificate YAML" 225 | echo "$cert_yaml" | $YQ eval --exit-status 'select(.spec.subject.organizations[0] == "cert-manager")' > /dev/null && echo "Found 'organizations = [cert-manager]' in Certificate YAML" 226 | echo "$cert_yaml" | $YQ eval --exit-status 'select(.spec.subject.organizationalUnits[0] == "my-ou")' > /dev/null && echo "Found 'organizationalUnits = [my-ou]' in Certificate YAML" 227 | 228 | echo "$cert_yaml" | $YQ eval --exit-status 'select(.spec.privateKey.rotationPolicy == "Always")' > /dev/null && echo "Found 'rotationPolicy == Always' in Certificate YAML" 229 | 230 | echo "$cert_yaml" | $YQ eval --exit-status 'select(.spec.renewBefore == "30m0s")' > /dev/null && echo "Found 'renewBefore == 30m0s' in Certificate YAML" 231 | 232 | echo "$cert_yaml" | $YQ eval --exit-status 'select(.spec.revisionHistoryLimit == 2)' > /dev/null && echo "Found 'revisionHistoryLimit == 2' in Certificate YAML" 233 | 234 | kubectl delete route "$route_name" 235 | --------------------------------------------------------------------------------