├── .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 |
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 |
--------------------------------------------------------------------------------