Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
devel:kubic
cmctl
cmctl-2.1.1.obscpio
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File cmctl-2.1.1.obscpio of Package cmctl
07070100000000000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001400000000cmctl-2.1.1/.github07070100000001000081A400000000000000000000000166DFF09D000001F9000000000000000000000000000000000000002400000000cmctl-2.1.1/.github/dependabot.yaml# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/.github/dependabot.yaml instead. # Update Go dependencies and GitHub Actions dependencies daily. version: 2 updates: - package-ecosystem: gomod directory: / schedule: interval: daily groups: all: patterns: ["*"] - package-ecosystem: github-actions directory: / schedule: interval: daily groups: all: patterns: ["*"] 07070100000002000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001E00000000cmctl-2.1.1/.github/workflows07070100000003000081A400000000000000000000000166DFF09D00000363000000000000000000000000000000000000002F00000000cmctl-2.1.1/.github/workflows/govulncheck.yaml# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/go/base/.github/workflows/govulncheck.yaml instead. # Run govulncheck at midnight every night on the main branch, # to alert us to recent vulnerabilities which affect the Go code in this # project. name: govulncheck on: workflow_dispatch: {} schedule: - cron: '0 0 * * *' permissions: contents: read jobs: govulncheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - id: go-version run: | make print-go-version >> "$GITHUB_OUTPUT" - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ steps.go-version.outputs.result }} - run: make verify-govulncheck 07070100000004000081A400000000000000000000000166DFF09D00000D50000000000000000000000000000000000000003500000000cmctl-2.1.1/.github/workflows/make-self-upgrade.yaml# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/.github/workflows/make-self-upgrade.yaml instead. name: make-self-upgrade concurrency: make-self-upgrade on: workflow_dispatch: {} schedule: - cron: '0 0 * * *' permissions: contents: read jobs: self_upgrade: runs-on: ubuntu-latest if: github.repository_owner == 'cert-manager' permissions: contents: write pull-requests: write env: SOURCE_BRANCH: "${{ github.ref_name }}" SELF_UPGRADE_BRANCH: "self-upgrade-${{ github.ref_name }}" steps: - name: Fail if branch is not head of branch. if: ${{ !startsWith(github.ref, 'refs/heads/') && env.SOURCE_BRANCH != '' && env.SELF_UPGRADE_BRANCH != '' }} run: | echo "This workflow should not be run on a non-branch-head." exit 1 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - id: go-version run: | make print-go-version >> "$GITHUB_OUTPUT" - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ steps.go-version.outputs.result }} - run: | git checkout -B "$SELF_UPGRADE_BRANCH" - run: | make -j upgrade-klone make -j generate - id: is-up-to-date shell: bash run: | git_status=$(git status -s) is_up_to_date="true" if [ -n "$git_status" ]; then is_up_to_date="false" echo "The following changes will be committed:" echo "$git_status" fi echo "result=$is_up_to_date" >> "$GITHUB_OUTPUT" - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} run: | git config --global user.name "cert-manager-bot" git config --global user.email "cert-manager-bot@users.noreply.github.com" git add -A && git commit -m "BOT: run 'make upgrade-klone' and 'make generate'" --signoff git push -f origin "$SELF_UPGRADE_BRANCH" - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const { repo, owner } = context.repo; const pulls = await github.rest.pulls.list({ owner: owner, repo: repo, head: owner + ':' + process.env.SELF_UPGRADE_BRANCH, base: process.env.SOURCE_BRANCH, state: 'open', }); if (pulls.data.length < 1) { const result = await github.rest.pulls.create({ title: '[CI] Merge ' + process.env.SELF_UPGRADE_BRANCH + ' into ' + process.env.SOURCE_BRANCH, owner: owner, repo: repo, head: process.env.SELF_UPGRADE_BRANCH, base: process.env.SOURCE_BRANCH, body: [ 'This PR is auto-generated to bump the Makefile modules.', ].join('\n'), }); await github.rest.issues.addLabels({ owner, repo, issue_number: result.data.number, labels: ['skip-review'] }); } 07070100000005000081A400000000000000000000000166DFF09D0000032B000000000000000000000000000000000000002B00000000cmctl-2.1.1/.github/workflows/release.yamlname: release on: push: tags: - "v*" env: VERSION: ${{ github.ref_name }} jobs: build_images: runs-on: ubuntu-latest permissions: contents: write # needed to write releases packages: write # needed for push images id-token: write # needed for keyless signing steps: - uses: actions/checkout@v4 - id: go-version run: | make print-go-version >> "$GITHUB_OUTPUT" - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: actions/setup-go@v5 with: go-version: ${{ steps.go-version.outputs.result }} - env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: make release 07070100000006000081A400000000000000000000000166DFF09D00000006000000000000000000000000000000000000001700000000cmctl-2.1.1/.gitignore/_bin 07070100000007000081A400000000000000000000000166DFF09D00000656000000000000000000000000000000000000001B00000000cmctl-2.1.1/.golangci.yamlissues: exclude-rules: - linters: - nilnil text: ".*" linters: # Explicitly define all enabled linters disable-all: true enable: - asasalint - asciicheck - bidichk - bodyclose - contextcheck - decorder - dogsled - dupword - durationcheck - errcheck - errchkjson - errname - exhaustive - exportloopref - forbidigo - gci - ginkgolinter - gocheckcompilerdirectives - gochecksumtype - gocritic - gofmt - goheader - goprintffuncname - gosec - gosimple - gosmopolitan - govet - grouper - importas - ineffassign - interfacebloat - loggercheck - makezero - mirror - misspell - musttag - nakedret - nilerr - nilnil - noctx - nosprintfhostport - predeclared - promlinter - protogetter - reassign - sloglint - staticcheck - tagalign - tenv - testableexamples - typecheck - unconvert - unparam - unused - usestdlibvars - wastedassign linters-settings: gci: sections: - standard # Standard section: captures all standard packages. - default # Default section: contains all imports that could not be matched to another section type. - prefix(github.com/cert-manager/cmctl/v2) # Custom section: groups all imports with the specified Prefix. - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. 07070100000008000081A400000000000000000000000166DFF09D0000047B000000000000000000000000000000000000001C00000000cmctl-2.1.1/.goreleaser.yml# Our Makefile will automatically add additional settings # to this builds array (environment variables, flags, ...) builds: - id: cmctl # config the checksum filename # https://goreleaser.com/customization/checksum checksum: name_template: 'checksums.txt' # creates SBOMs of all archives and the source tarball using syft # https://goreleaser.com/customization/sbom sboms: - artifacts: binary documents: - "{{ .ArtifactName }}{{ .ArtifactExt }}.spdx.sbom" # signs the checksum file # all files (including the sboms) are included in the checksum, so we don't need to sign each one if we don't want to # https://goreleaser.com/customization/sign signs: - cmd: cosign signature: "${artifact}.cosign.bundle" env: - COSIGN_EXPERIMENTAL=1 args: - sign-blob - '--bundle=${signature}' - '${artifact}' - "--yes" # needed on cosign 2.0.0+ artifacts: checksum output: true archives: - name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}" format: binary - id: tar-gz-archives name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}" format: tar.gz release: draft: true make_latest: false 07070100000009000081A400000000000000000000000166DFF09D00002C5D000000000000000000000000000000000000001400000000cmctl-2.1.1/LICENSE Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 0707010000000A000081A400000000000000000000000166DFF09D00001124000000000000000000000000000000000000001500000000cmctl-2.1.1/Makefile# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/Makefile instead. # NOTE FOR DEVELOPERS: "How do the Makefiles work and how can I extend them?" # # Shared Makefile logic lives in the make/_shared/ directory. The source of truth for these files # lies outside of this repository, eg. in the cert-manager/makefile-modules repository. # # Logic specific to this repository must be defined in the make/00_mod.mk and make/02_mod.mk files: # - The make/00_mod.mk file is included first and contains variable definitions needed by # the shared Makefile logic. # - The make/02_mod.mk file is included later, it can make use of most of the shared targets # defined in the make/_shared/ directory (all targets defined in 00_mod.mk and 01_mod.mk). # This file should be used to define targets specific to this repository. ################################## # Some modules build their dependencies from variables, we want these to be # evaluated at the last possible moment. For this we use second expansion to # re-evaluate the generate and verify targets a second time. # # See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html .SECONDEXPANSION: # For details on some of these "prelude" settings, see: # https://clarkgrubb.com/makefile-style-guide MAKEFLAGS += --warn-undefined-variables --no-builtin-rules SHELL := /usr/bin/env bash .SHELLFLAGS := -uo pipefail -c .DEFAULT_GOAL := help .DELETE_ON_ERROR: .SUFFIXES: FORCE: noop: # do nothing # Set empty value for MAKECMDGOALS to prevent the "warning: undefined variable 'MAKECMDGOALS'" # warning from happening when running make without arguments MAKECMDGOALS ?= ################################## # Host OS and architecture setup # ################################## # The reason we don't use "go env GOOS" or "go env GOARCH" is that the "go" # binary may not be available in the PATH yet when the Makefiles are # evaluated. HOST_OS and HOST_ARCH only support Linux, *BSD and macOS (M1 # and Intel). host_os := $(shell uname -s | tr A-Z a-z) host_arch := $(shell uname -m) HOST_OS ?= $(host_os) HOST_ARCH ?= $(host_arch) ifeq (x86_64, $(HOST_ARCH)) HOST_ARCH = amd64 else ifeq (aarch64, $(HOST_ARCH)) # linux reports the arm64 arch as aarch64 HOST_ARCH = arm64 endif ################################## # Git and versioning information # ################################## git_version := $(shell git describe --tags --always --match='v*' --abbrev=14 --dirty) VERSION ?= $(git_version) IS_PRERELEASE := $(shell git describe --tags --always --match='v*' --abbrev=0 | grep -q '-' && echo true || echo false) GITCOMMIT := $(shell git rev-parse HEAD) GITEPOCH := $(shell git show -s --format=%ct HEAD) ################################## # Global variables and dirs # ################################## bin_dir := _bin # The ARTIFACTS environment variable is set by the CI system to a directory # where artifacts should be placed. These artifacts are then uploaded to a # storage bucket by the CI system (https://docs.prow.k8s.io/docs/components/pod-utilities/). # An example of such an artifact is a jUnit XML file containing test results. # If the ARTIFACTS environment variable is not set, we default to a local # directory in the _bin directory. ARTIFACTS ?= $(bin_dir)/artifacts $(bin_dir) $(ARTIFACTS) $(bin_dir)/scratch: mkdir -p $@ .PHONY: clean ## Clean all temporary files ## @category [shared] Tools clean: rm -rf $(bin_dir) ################################## # Include all the Makefiles # ################################## -include make/00_mod.mk -include make/_shared/*/00_mod.mk -include make/_shared/*/01_mod.mk -include make/02_mod.mk -include make/_shared/*/02_mod.mk 0707010000000B000081A400000000000000000000000166DFF09D00000048000000000000000000000000000000000000001300000000cmctl-2.1.1/OWNERSapprovers: - cm-maintainers reviewers: - cm-maintainers - thatsmrtalbot 0707010000000C000081A400000000000000000000000166DFF09D0000014E000000000000000000000000000000000000001B00000000cmctl-2.1.1/OWNERS_ALIASES# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/OWNERS_ALIASES instead. aliases: cm-maintainers: - munnerz - joshvanl - wallrj - jakexks - maelvls - irbekrm - sgtcodfish - inteon - thatsmrtalbot 0707010000000D000081A400000000000000000000000166DFF09D00000B15000000000000000000000000000000000000001600000000cmctl-2.1.1/README.md<p align="center"> <img src="https://raw.githubusercontent.com/cert-manager/cert-manager/d53c0b9270f8cd90d908460d69502694e1838f5f/logo/logo-small.png" height="256" width="256" alt="cert-manager project logo" /> </p> # cmctl - The cert-manager Command Line Tool `cmctl` is a command line tool that can help you manage cert-manager and its resources inside your cluster. ## Documentation The documentation for `cmctl` can be found on the [cert-manager website](https://cert-manager.io/docs/usage/cmctl/). ## Installation > [!Note] > These instructions are a copy of the [official installation instructions](https://cert-manager.io/docs/usage/cmctl/#installation). ### Homebrew On Mac or Linux if you have [Homebrew](https://brew.sh/) installed, you can install `cmctl` with: ```sh brew install cmctl ``` This will also install shell completion. ### Go install If you have Go installed, you can install `cmctl` with: ```sh go install github.com/cert-manager/cmctl/v2@latest ``` ### Manual Installation You need the `cmctl` file for the platform you're using, these can be found on our [cmctl GitHub releases page](https://github.com/cert-manager/cmctl/releases). In order to use `cmctl` you need its binary to be accessible under the name `cmctl` in your `$PATH`. Run the following commands to set up the CLI. Replace OS and ARCH with your systems equivalents: ```sh OS=$(uname -s | tr A-Z a-z); ARCH=$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/'); curl -fsSL -o cmctl https://github.com/cert-manager/cmctl/releases/latest/download/cmctl_${OS}_${ARCH} chmod +x cmctl sudo mv cmctl /usr/local/bin # or `sudo mv cmctl /usr/local/bin/kubectl-cert_manager` to use `kubectl cert-manager` instead. ``` ### Shell Completion `cmctl` supports shell completion for most popular shells. To get help on how to enable shell completion, run the following commands: ```sh $ cmctl completion --help # or `kubectl cert-manager completion --help` ... Available Commands: bash Generate cert-manager CLI scripts for a Bash shell fish Generate cert-manager CLI scripts for a Fish shell powershell Generate cert-manager CLI scripts for a PowerShell shell zsh Generation cert-manager CLI scripts for a ZSH shell $ cmctl completion bash --help To load completions: Bash: $ source <(cmctl completion bash) # To load completions for each session, execute once: # Linux: $ cmctl completion bash > /etc/bash_completion.d/cmctl # macOS: $ cmctl completion bash > /usr/local/etc/bash_completion.d/cmctl ... ``` ## Versioning Before v2, `cmctl` was located in the cert-manager repository and versioned together with cert-manager. Starting from v2, `cmctl` is versioned seperately from cert-manager itself. ## Release Process The release process is documented in [RELEASE.md](RELEASE.md).0707010000000E000081A400000000000000000000000166DFF09D000006B6000000000000000000000000000000000000001700000000cmctl-2.1.1/RELEASE.md# Releases ## Schedule 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. ## Process 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]. The release process for this repo is documented below: 1. Create a tag for the new release: ```sh export VERSION=v0.5.0-alpha.0 git tag --annotate --message="Release ${VERSION}" "${VERSION}" git push origin "${VERSION}" ``` 2. A GitHub action will see the new tag and do the following: - Build the binaries - Create checksums for the binaries - Sign the checksums - Create a draft GitHub release - Upload binaries, checksums and signature to the GitHub release 3. Visit the [releases page], edit the draft release, click "Generate release notes", then edit the notes to add the following to the top ``` cmctl is the command line tool for interacting with cert-manager. ``` 4. Publish the release. ## Artifacts This repo will produce the following artifacts each release. For documentation on how those artifacts are produced see the "Process" section. - *Binaries* - The `cmctl` binary is created and attached to the GitHub release, along with its shasum [release workflow]: https://github.com/cert-manager/cmctl/actions/workflows/release.yaml [releases page]: https://github.com/cert-manager/cmctl/releases0707010000000F000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001000000000cmctl-2.1.1/cmd07070100000010000081A400000000000000000000000166DFF09D00000830000000000000000000000000000000000000001700000000cmctl-2.1.1/cmd/cmd.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package cmd import ( "context" "io" logf "github.com/cert-manager/cert-manager/pkg/logs" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/component-base/logs" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/build/commands" ) func NewCertManagerCtlCommand(ctx context.Context, in io.Reader, out, err io.Writer) *cobra.Command { logOptions := logs.NewOptions() cmds := &cobra.Command{ Use: build.Name(ctx), Annotations: map[string]string{ // For commands that have a space (eg. kubectl cert-manager), the name // is not correctly determined based on just the Use field. cobra.CommandDisplayNameAnnotation: build.Name(ctx), }, Short: "cert-manager CLI tool to manage and configure cert-manager resources", Long: build.WithTemplate(ctx, ` {{.BuildName}} is a CLI tool manage and configure cert-manager resources for Kubernetes`), CompletionOptions: cobra.CompletionOptions{ DisableDefaultCmd: true, }, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { return logf.ValidateAndApply(logOptions) }, SilenceErrors: true, // Errors are already logged when calling cmd.Execute() SilenceUsage: true, // Don't print usage when an error occurs } logf.AddFlagsNonDeprecated(logOptions, cmds.PersistentFlags()) ioStreams := genericclioptions.IOStreams{In: in, Out: out, ErrOut: err} for _, registerCmd := range commands.Commands() { cmds.AddCommand(registerCmd(ctx, ioStreams)) } return cmds } 07070100000011000081A400000000000000000000000166DFF09D0000238F000000000000000000000000000000000000001300000000cmctl-2.1.1/go.modmodule github.com/cert-manager/cmctl/v2 go 1.22.0 require ( github.com/cert-manager/cert-manager v1.15.3 github.com/go-logr/logr v1.4.2 github.com/google/gofuzz v1.2.0 github.com/sergi/go-diff v1.3.1 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.27.0 golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 golang.org/x/sync v0.8.0 helm.sh/helm/v3 v3.15.4 k8s.io/api v0.31.0 k8s.io/apiextensions-apiserver v0.31.0 k8s.io/apimachinery v0.31.0 k8s.io/cli-runtime v0.31.0 k8s.io/client-go v0.31.0 k8s.io/component-base v0.31.0 k8s.io/kube-aggregator v0.31.0 k8s.io/kubectl v0.31.0 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 sigs.k8s.io/controller-runtime v0.19.0 sigs.k8s.io/gateway-api v1.1.0 sigs.k8s.io/yaml v1.4.0 ) require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/log v0.1.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.5.0 // indirect github.com/docker/cli v25.0.1+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker v25.0.6+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/emicklei/go-restful/v3 v3.12.0 // indirect github.com/evanphx/json-patch v5.9.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fatih/camelcase v1.0.0 // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.6 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-ldap/ldap/v3 v3.4.8 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/cel-go v0.20.1 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/huandu/xstrings v1.4.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmoiron/sqlx v1.3.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.16.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.4.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc6 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rubenv/sql-migrate v1.5.2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect go.etcd.io/etcd/api/v3 v3.5.14 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect go.etcd.io/etcd/client/v3 v3.5.14 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/sdk v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect golang.org/x/text v0.18.0 // indirect golang.org/x/time v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiserver v0.31.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f // indirect oras.land/oras-go v1.2.5 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.17.2 // indirect sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) 07070100000012000081A400000000000000000000000166DFF09D0001079C000000000000000000000000000000000000001300000000cmctl-2.1.1/go.sumcloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cert-manager/cert-manager v1.15.3 h1:/u9T0griwd5MegPfWbB7v0KcVcT9OJrEvPNhc9tl7xQ= github.com/cert-manager/cert-manager v1.15.3/go.mod h1:stBge/DTvrhfQMB/93+Y62s+gQgZBsfL1o0C/4AL/mI= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v25.0.1+incompatible h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbTO1lpcGSkU= github.com/docker/cli v25.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg= github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI= github.com/foxcpp/go-mockdns v1.0.0/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-asn1-ber/asn1-ber v1.5.6 h1:CYsqysemXfEaQbyrLJmdsCRuufHoLa3P/gGWGl5TDrM= github.com/go-asn1-ber/asn1-ber v1.5.6/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ= github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg= github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU= github.com/opencontainers/image-spec v1.1.0-rc6/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0= github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8= go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M= go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0= go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA= go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw= go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok= go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda h1:wu/KJm9KJwpfHWhkkZGohVC6KRrc1oJNr4jwtQMOQXw= google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= helm.sh/helm/v3 v3.15.4 h1:UFHd6oZ1IN3FsUZ7XNhOQDyQ2QYknBNWRHH57e9cbHY= helm.sh/helm/v3 v3.15.4/go.mod h1:phOwlxqGSgppCY/ysWBNRhG3MtnpsttOzxaTK+Mt40E= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY= k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk= k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA= k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw= k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-aggregator v0.31.0 h1:3DqSpmqHF8rey7fY+qYXLJms0tYPhxrgWvjpnKVnS0Y= k8s.io/kube-aggregator v0.31.0/go.mod h1:Fa+OVSpMQC7zbTTz7/QG7FXe9jZ8usuJQej5sMdCrkM= k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f h1:0LQagt0gDpKqvIkAMPaRGcXawNMouPECM1+F9BVxEaM= k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f/go.mod h1:S9tOR0FxgyusSNR+MboCuiDpVWkAifZvaYI1Q2ubgro= k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg= k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM= sigs.k8s.io/gateway-api v1.1.0/go.mod h1:ZH4lHrL2sDi0FHZ9jjneb8kKnGzFWyrTya35sWUTrRs= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= 07070100000013000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001500000000cmctl-2.1.1/internal07070100000014000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001A00000000cmctl-2.1.1/internal/util07070100000015000081A400000000000000000000000166DFF09D00000568000000000000000000000000000000000000002200000000cmctl-2.1.1/internal/util/exit.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package util import ( "context" "errors" ) // SetExitCode sets the exit code to 1 if the error is not a context.Canceled error. func SetExitCode(err error) { switch { case err == nil || errors.Is(err, context.Canceled): // If the context was canceled, we don't need to set the exit code case errors.Is(err, context.DeadlineExceeded): SetExitCodeValue(124) // Indicate that there was a timeout error default: SetExitCodeValue(1) // Indicate that there was an error } } // SetExitCode sets the exit code to 1 if the error is not a context.Canceled error. func SetExitCodeValue(code int) { if code != 0 { select { case errorExitCodeChannel <- code: default: // The exit code has already been set to a non-zero value. } } // If the exit code is 0, we don't need to set the exit code } 07070100000016000081A400000000000000000000000166DFF09D00000681000000000000000000000000000000000000002700000000cmctl-2.1.1/internal/util/exit_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package util import ( "context" "errors" "fmt" "testing" ) func TestSetExitCode(t *testing.T) { tests := []struct { name string err error expCode int }{ {"Test context.Canceled", context.Canceled, 0}, {"Test wrapped context.Canceled", fmt.Errorf("wrapped: %w", context.Canceled), 0}, {"Test context.DeadlineExceeded", context.DeadlineExceeded, 124}, {"Test wrapped context.DeadlineExceeded", fmt.Errorf("wrapped: %w", context.DeadlineExceeded), 124}, {"Test error", errors.New("error"), 1}, {"Test nil", nil, 0}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Every testExitCode call has to be run in its own test, because // it calls the test again filtered by the name of the subtest with // the variable BE_CRASHER=1. exitCode := testExitCode(t, func(t *testing.T) { SetExitCode(tt.err) _, complete := SetupExitHandler(context.Background(), AlwaysErrCode) complete() }) if exitCode != tt.expCode { t.Errorf("Test %s: expected exit code %d, got %d", tt.name, tt.expCode, exitCode) } }) } } 07070100000017000081A400000000000000000000000166DFF09D00000A6F000000000000000000000000000000000000002400000000cmctl-2.1.1/internal/util/signal.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package util import ( "context" "fmt" "os" "os/signal" "syscall" ) var onlyOneSignalHandler = make(chan struct{}) var errorExitCodeChannel = make(chan int, 1) // ExitBehavior controls how the program should be terminated // in response to a shutdown signal. type ExitBehavior int const ( // AlwaysErrCode indicates the exit code of the program should always be nonzero // and should correspond to the numeric value of the signal that was received. AlwaysErrCode ExitBehavior = iota // GracefulShutdown treats a shutdown signal as a request to exit gracefully, terminating // goroutines and returning an exit code of 0 if there are no errors during shutdown. GracefulShutdown ExitBehavior = iota ) // SetupExitHandler: // A context is returned which is canceled on receiving a shutdown signal (SIGTERM // or SIGINT). If a second signal is caught, the program is terminated directly with // exit code 130. // SetupExitHandler also returns an exit function, this exit function calls os.Exit(...) // if there is a exit code in the errorExitCodeChannel. // The errorExitCodeChannel receives exit codes when SetExitCode is called or when // a shutdown signal is received (only if exitBehavior is AlwaysErrCode). func SetupExitHandler(parentCtx context.Context, exitBehavior ExitBehavior) (context.Context, func()) { close(onlyOneSignalHandler) // panics when called twice ctx, cancel := context.WithCancelCause(parentCtx) c := make(chan os.Signal, 2) signal.Notify(c, shutdownSignals...) go func() { // first signal. Cancel context and pass exit code to errorExitCodeChannel. signalInt := int((<-c).(syscall.Signal)) if exitBehavior == AlwaysErrCode { errorExitCodeChannel <- (128 + signalInt) } cancel(fmt.Errorf("received signal %d", signalInt)) // second signal. Exit directly. <-c os.Exit(130) }() return ctx, func() { select { case signalInt := <-errorExitCodeChannel: os.Exit(signalInt) default: // Do not exit, there are no exit codes in the channel, // so just continue and let the main function go out of // scope instead. } } } 07070100000018000081A400000000000000000000000166DFF09D000002BE000000000000000000000000000000000000002A00000000cmctl-2.1.1/internal/util/signal_posix.go//go:build !windows /* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package util import ( "os" "syscall" ) var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} 07070100000019000081A400000000000000000000000166DFF09D00000BAB000000000000000000000000000000000000002900000000cmctl-2.1.1/internal/util/signal_test.go//go:build !windows /* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package util import ( "context" "os" "os/exec" "syscall" "testing" ) // based on https://go.dev/talks/2014/testing.slide#23 and // https://stackoverflow.com/a/33404435 func testExitCode( t *testing.T, fn func(t *testing.T), ) int { if os.Getenv("BE_CRASHER") == "1" { fn(t) os.Exit(0) } // #nosec G204 cmd := exec.Command(os.Args[0], "-test.run="+t.Name()) cmd.Env = append(os.Environ(), "BE_CRASHER=1") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if e, ok := err.(*exec.ExitError); ok { return e.ExitCode() } return 0 } func TestSetupExitHandlerAlwaysErrCodeSIGTERM(t *testing.T) { exitCode := testExitCode(t, func(t *testing.T) { ctx := context.Background() ctx, complete := SetupExitHandler(ctx, AlwaysErrCode) defer complete() if err := syscall.Kill(syscall.Getpid(), syscall.SIGTERM); err != nil { t.Fatal(err) os.Exit(99) } // Wait for the program to shut down. <-ctx.Done() if context.Cause(ctx).Error() != "received signal 15" { t.Errorf("expected signal 15, got %s", ctx.Err().Error()) os.Exit(99) } }) if exitCode != 143 { t.Errorf("expected exit code 143, got %d", exitCode) } } func TestSetupExitHandlerAlwaysErrCodeSIGINT(t *testing.T) { exitCode := testExitCode(t, func(t *testing.T) { ctx := context.Background() ctx, complete := SetupExitHandler(ctx, AlwaysErrCode) defer complete() if err := syscall.Kill(syscall.Getpid(), syscall.SIGINT); err != nil { t.Fatal(err) os.Exit(99) } // Wait for the program to shut down. <-ctx.Done() if context.Cause(ctx).Error() != "received signal 2" { t.Errorf("expected signal 2, got %s", ctx.Err().Error()) os.Exit(99) } }) if exitCode != 130 { t.Errorf("expected exit code 130, got %d", exitCode) } } func TestSetupExitHandlerGracefulShutdownSIGINT(t *testing.T) { exitCode := testExitCode(t, func(t *testing.T) { ctx := context.Background() ctx, complete := SetupExitHandler(ctx, GracefulShutdown) defer complete() if err := syscall.Kill(syscall.Getpid(), syscall.SIGINT); err != nil { t.Fatal(err) os.Exit(99) } // Wait for the program to shut down. <-ctx.Done() if context.Cause(ctx).Error() != "received signal 2" { t.Errorf("expected signal 2, got %s", ctx.Err().Error()) os.Exit(99) } }) if exitCode != 0 { t.Errorf("expected exit code 0, got %d", exitCode) } } 0707010000001A000081A400000000000000000000000166DFF09D0000028D000000000000000000000000000000000000002C00000000cmctl-2.1.1/internal/util/signal_windows.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package util import ( "os" ) var shutdownSignals = []os.Signal{os.Interrupt} 0707010000001B000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002400000000cmctl-2.1.1/internal/versionchecker0707010000001C000081A400000000000000000000000166DFF09D00000B2A000000000000000000000000000000000000002F00000000cmctl-2.1.1/internal/versionchecker/fromcrd.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package versionchecker import ( "context" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" ) func (o *VersionChecker) extractVersionFromCrd(ctx context.Context, crdName string) error { crdKey := client.ObjectKey{Name: crdName} objv1 := &apiextensionsv1.CustomResourceDefinition{} err := o.client.Get(ctx, crdKey, objv1) if err == nil { if label := extractVersionFromLabels(objv1.Labels); label != "" { o.versionSources["crdLabelVersion"] = label } return o.extractVersionFromCrdv1(ctx, objv1) } // If error differs from not found, don't continue and return error if !apierrors.IsNotFound(err) { return err } objv1beta1 := &apiextensionsv1beta1.CustomResourceDefinition{} err = o.client.Get(ctx, crdKey, objv1beta1) if err == nil { if label := extractVersionFromLabels(objv1beta1.Labels); label != "" { o.versionSources["crdLabelVersion"] = label } return o.extractVersionFromCrdv1beta1(ctx, objv1beta1) } // If error differs from not found, don't continue and return error if !apierrors.IsNotFound(err) { return err } return ErrCertManagerCRDsNotFound } func (o *VersionChecker) extractVersionFromCrdv1(ctx context.Context, crd *apiextensionsv1.CustomResourceDefinition) error { if (crd.Spec.Conversion == nil) || (crd.Spec.Conversion.Webhook == nil) || (crd.Spec.Conversion.Webhook.ClientConfig == nil) || (crd.Spec.Conversion.Webhook.ClientConfig.Service == nil) { return nil } return o.extractVersionFromService( ctx, crd.Spec.Conversion.Webhook.ClientConfig.Service.Namespace, crd.Spec.Conversion.Webhook.ClientConfig.Service.Name, ) } func (o *VersionChecker) extractVersionFromCrdv1beta1(ctx context.Context, crd *apiextensionsv1beta1.CustomResourceDefinition) error { if (crd.Spec.Conversion == nil) || (crd.Spec.Conversion.WebhookClientConfig == nil) || (crd.Spec.Conversion.WebhookClientConfig.Service == nil) { return nil } return o.extractVersionFromService( ctx, crd.Spec.Conversion.WebhookClientConfig.Service.Namespace, crd.Spec.Conversion.WebhookClientConfig.Service.Name, ) } 0707010000001D000081A400000000000000000000000166DFF09D000004AC000000000000000000000000000000000000003200000000cmctl-2.1.1/internal/versionchecker/fromlabels.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package versionchecker import ( "regexp" ) var helmChartVersion = regexp.MustCompile(`-(v(?:\d+)\.(?:\d+)\.(?:\d+)(?:.*))$`) func extractVersionFromLabels(crdLabels map[string]string) string { if version, ok := crdLabels["app.kubernetes.io/version"]; ok { return version } if chartName, ok := crdLabels["helm.sh/chart"]; ok { version := helmChartVersion.FindStringSubmatch(chartName) if len(version) == 2 { return version[1] } } if chartName, ok := crdLabels["chart"]; ok { version := helmChartVersion.FindStringSubmatch(chartName) if len(version) == 2 { return version[1] } } return "" } 0707010000001E000081A400000000000000000000000166DFF09D000007B5000000000000000000000000000000000000003300000000cmctl-2.1.1/internal/versionchecker/fromservice.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package versionchecker import ( "context" "regexp" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" ) var imageVersion = regexp.MustCompile(`^quay\.io/jetstack/cert-manager-webhook:(v(?:\d+)\.(?:\d+)\.(?:\d+)(?:.*))$`) func (o *VersionChecker) extractVersionFromService( ctx context.Context, namespace string, serviceName string, ) error { service := &corev1.Service{} serviceKey := client.ObjectKey{Namespace: namespace, Name: serviceName} err := o.client.Get(ctx, serviceKey, service) if err != nil { return err } if label := extractVersionFromLabels(service.Labels); label != "" { o.versionSources["webhookServiceLabelVersion"] = label } listOptions := client.MatchingLabelsSelector{ Selector: labels.Set(service.Spec.Selector).AsSelector(), } pods := &corev1.PodList{} err = o.client.List(ctx, pods, listOptions) if err != nil { return err } for _, pod := range pods.Items { if pod.Status.Phase != corev1.PodRunning { continue } if label := extractVersionFromLabels(pod.Labels); label != "" { o.versionSources["webhookPodLabelVersion"] = label } for _, container := range pod.Spec.Containers { version := imageVersion.FindStringSubmatch(container.Image) if len(version) == 2 { o.versionSources["webhookPodImageVersion"] = version[1] return nil } } } return nil } 0707010000001F000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002900000000cmctl-2.1.1/internal/versionchecker/test07070100000020000081A400000000000000000000000166DFF09D00000B25000000000000000000000000000000000000004400000000cmctl-2.1.1/internal/versionchecker/test/getpodfromtemplate_test.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package versionchecker import ( "fmt" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/validation" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/rand" ) // Based on https://github.com/kubernetes/kubernetes/blob/ca643a4d1f7bfe34773c74f79527be4afd95bf39/pkg/controller/controller_utils.go#L542 var validatePodName = validation.NameIsDNSSubdomain func getPodFromTemplate(template *v1.PodTemplateSpec, parentObject runtime.Object, controllerRef *metav1.OwnerReference) (*v1.Pod, error) { desiredLabels := getPodsLabelSet(template) desiredFinalizers := getPodsFinalizers(template) desiredAnnotations := getPodsAnnotationSet(template) accessor, err := meta.Accessor(parentObject) if err != nil { return nil, fmt.Errorf("parentObject does not have ObjectMeta, %v", err) } prefix := getPodsPrefix(accessor.GetName()) pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels: desiredLabels, Annotations: desiredAnnotations, GenerateName: prefix, Name: prefix + rand.String(5), Finalizers: desiredFinalizers, }, Status: v1.PodStatus{ Phase: v1.PodRunning, }, } if controllerRef != nil { pod.OwnerReferences = append(pod.OwnerReferences, *controllerRef) } pod.Spec = *template.Spec.DeepCopy() return pod, nil } func getPodsLabelSet(template *v1.PodTemplateSpec) labels.Set { desiredLabels := make(labels.Set) for k, v := range template.Labels { desiredLabels[k] = v } return desiredLabels } func getPodsFinalizers(template *v1.PodTemplateSpec) []string { desiredFinalizers := make([]string, len(template.Finalizers)) copy(desiredFinalizers, template.Finalizers) return desiredFinalizers } func getPodsAnnotationSet(template *v1.PodTemplateSpec) labels.Set { desiredAnnotations := make(labels.Set) for k, v := range template.Annotations { desiredAnnotations[k] = v } return desiredAnnotations } func getPodsPrefix(controllerName string) string { // use the dash (if the name isn't too long) to make the pod name a bit prettier prefix := fmt.Sprintf("%s-", controllerName) if len(validatePodName(prefix, true)) != 0 { prefix = controllerName } return prefix } 07070100000021000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003200000000cmctl-2.1.1/internal/versionchecker/test/testdata07070100000022000081A400000000000000000000000166DFF09D00002DB7000000000000000000000000000000000000003B00000000cmctl-2.1.1/internal/versionchecker/test/testdata/fetch.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package main import ( "bytes" "context" "encoding/hex" "errors" "fmt" "hash/fnv" "io" "net/http" "os" "os/exec" "slices" "strings" "golang.org/x/mod/semver" "golang.org/x/sync/errgroup" "gopkg.in/yaml.v2" ) const minVersion = "v1.0.0" const repoURL = "https://github.com/cert-manager/cert-manager" const downloadURL = "https://github.com/cert-manager/cert-manager/releases/download/%s/cert-manager.yaml" const dummyVersion = "v99.99.99" var ignoredVersions = map[string]struct{}{ "v1.15.0-beta.0": {}, // This beta release was abandoned when we detected a bug in the release process. "v1.15.2-alpha.0": {}, // This beta release was abandoned when we detected a bug in the release process. } func main() { ctx := context.Background() stdOut := os.Stdout if len(os.Args) != 3 && len(os.Args) != 4 { fmt.Fprintf(stdOut, "Usage: %s <test_manifests.yaml> <max_version> [<force:bool>]\n", os.Args[0]) os.Exit(1) } manifestsPath := os.Args[1] maxVersion := os.Args[2] force := false if len(os.Args) == 4 { if strings.ToLower(os.Args[3])[0] == 't' { force = true } } // Read the inventory file var inv Inventory if err := inv.read(manifestsPath); err != nil { fmt.Fprintf(stdOut, "Error reading inventory: %v\n", err) inv.reset() } // If the passed version is identical to the latest version, we don't need to do anything if inv.LatestVersion == maxVersion && !force { fmt.Fprintf(stdOut, "Version %s is already the latest version\n", maxVersion) os.Exit(0) } // Fetch the list of remote versions remoteVersions, err := listVersions(ctx, maxVersion) if err != nil { fmt.Fprintf(stdOut, "Error listing versions: %v\n", err) os.Exit(1) } // Remove any ignored versions for version := range ignoredVersions { delete(remoteVersions, version) } // List the remote versions that are not in the inventory newVersions := make([]string, 0, len(remoteVersions)) for version := range remoteVersions { if _, ok := inv.Versions[version]; !ok || force { newVersions = append(newVersions, version) } } // Download the new versions type versionManifest struct { version string manifest []byte } results := make(chan versionManifest, len(newVersions)) group, gctx := errgroup.WithContext(ctx) for _, version := range newVersions { version := version group.Go(func() error { manifests, err := downloadManifests(gctx, version) if err != nil { return fmt.Errorf("error downloading CRD for version %s: %v", version, err) } // Cleanup the manifests manifests, err = cleanupManifests(manifests, version) if err != nil { return fmt.Errorf("error cleaning up manifests for version %s: %v", version, err) } results <- versionManifest{ version: version, manifest: manifests, } return nil }) } if err := group.Wait(); err != nil { fmt.Fprintf(stdOut, "Error downloading manifests: %v\n", err) os.Exit(1) } close(results) for result := range results { hash, err := manifestHash(result.manifest) if err != nil { fmt.Fprintf(stdOut, "Error hashing manifest: %v\n", err) os.Exit(1) } inv.Versions[result.version] = hash inv.Manifests[hash] = result.manifest } // Update the latest version inv.LatestVersion = maxVersion // Write the inventory file if err := inv.write(manifestsPath); err != nil { fmt.Fprintf(stdOut, "Error writing inventory: %v\n", err) os.Exit(1) } fmt.Fprintf(stdOut, "Updated inventory to version %s\n", maxVersion) } type Inventory struct { LatestVersion string Versions map[string]string Manifests map[string][]byte } func (inv *Inventory) reset() { *inv = Inventory{ LatestVersion: "v0.0.0", Versions: make(map[string]string), Manifests: make(map[string][]byte), } } func (inv *Inventory) read(manifestsPath string) error { inv.reset() // Read the inventory file manfestsBytes, err := os.ReadFile(manifestsPath) if err != nil { return fmt.Errorf("failed to read inventory file: %v", err) } // Read latest version from first line fileSplit := bytes.SplitN(manfestsBytes, []byte("\n"), 2) if len(fileSplit) != 2 { return fmt.Errorf("failed read latest version from first line in manifest file") } latestVersion := string(fileSplit[0]) latestVersion = strings.TrimSpace(latestVersion) latestVersion = strings.TrimPrefix(latestVersion, "# [CHK_LATEST_VERSION]: ") latestVersion = semver.Canonical(latestVersion) if latestVersion == "" { return fmt.Errorf("failed to parse latest version from first line in manifest file") } inv.LatestVersion = latestVersion // Split the rest of the file into the manifests manfestsBytes = fileSplit[1] manifests := bytes.Split(manfestsBytes, []byte("---\n# [CHK_VERSIONS]: ")) for _, manifest := range manifests { if len(manifest) == 0 { continue } parts := bytes.SplitN(manifest, []byte("\n"), 2) if len(parts) != 2 { return fmt.Errorf("failed to read versions from manifest file") } versions := string(parts[0]) versions = strings.TrimSpace(versions) manifest = parts[1] manifest, err = cleanupManifests(manifest, dummyVersion) if err != nil { return fmt.Errorf("failed to cleanup manifest: %v", err) } manifestHasher := fnv.New64() if _, err := manifestHasher.Write(manifest); err != nil { return fmt.Errorf("failed to hash manifest: %v", err) } manifestHash := hex.EncodeToString(manifestHasher.Sum([]byte{})) // Split the versions versionsSplit := strings.Split(versions, ",") for _, version := range versionsSplit { version = strings.TrimSpace(version) version = semver.Canonical(version) if version == "" { return fmt.Errorf("failed to parse version from manifest file") } inv.Versions[version] = manifestHash } if len(inv.Versions) > 0 { inv.Manifests[manifestHash] = manifest } } return nil } func (inv *Inventory) write(manifestsPath string) error { // Write the inventory file var invBytes bytes.Buffer invBytes.WriteString("# [CHK_LATEST_VERSION]: ") invBytes.WriteString(inv.LatestVersion) invBytes.WriteString("\n---\n") type versionManifest struct { versions []string manifest []byte } var manifests []versionManifest for manifestHash, manifest := range inv.Manifests { var versions []string for version, hash := range inv.Versions { if hash == manifestHash { versions = append(versions, version) } } if len(versions) == 0 { continue } slices.SortFunc(versions, semver.Compare) manifests = append(manifests, versionManifest{ versions: versions, manifest: manifest, }) } slices.SortFunc(manifests, func(a, b versionManifest) int { return semver.Compare(a.versions[0], b.versions[0]) }) for _, manifest := range manifests { invBytes.WriteString("# [CHK_VERSIONS]: ") invBytes.WriteString(strings.Join(manifest.versions, ", ")) invBytes.WriteString("\n") invBytes.Write(manifest.manifest) invBytes.WriteString("\n---\n") } if err := os.WriteFile(manifestsPath, invBytes.Bytes(), 0600); err != nil { return fmt.Errorf("failed to write inventory file: %v", err) } return nil } func listVersions(ctx context.Context, maxVersion string) (map[string]struct{}, error) { result := bytes.Buffer{} cmd := exec.CommandContext(ctx, "git", "ls-remote", "--tags", "--sort=version:refname", "--refs", repoURL) cmd.Stdout = &result cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { return nil, fmt.Errorf("failed to list tags: %v", err) } // Parse the output of the git command lines := bytes.Split(result.Bytes(), []byte("\n")) versions := make(map[string]struct{}, len(lines)) for _, line := range lines { if len(line) == 0 { continue } parts := bytes.Split(line, []byte("refs/tags/")) if len(parts) != 2 { return nil, fmt.Errorf("unexpected output from git command: %s", line) } version := string(parts[1]) // Skip any non-semver tags version = semver.Canonical(version) if version == "" { continue } // Skip any versions that are less than the min version if semver.Compare(version, minVersion) < 0 { continue } // Skip any versions that are greater than the max version if semver.Compare(version, maxVersion) > 0 { continue } versions[version] = struct{}{} } return versions, nil } func downloadManifests(ctx context.Context, version string) ([]byte, error) { url := fmt.Sprintf(downloadURL, version) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return nil, err } resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } return body, nil } // cleanupManifests makes the manifests smaller, so they take up less space in the repo // 1. Remove all comments from the yaml file // 2. Remove all openapi CRD schemas // 3. Keep only the CRD, Service and Deployment resources func cleanupManifests(manifests []byte, version string) ([]byte, error) { resources := make([][]byte, 0) decoder := yaml.NewDecoder(bytes.NewBuffer(manifests)) for { var manifest map[string]interface{} err := decoder.Decode(&manifest) if errors.Is(err, io.EOF) { break } if err != nil { return nil, fmt.Errorf("failed to decode manifest: %v", err) } if manifest == nil { continue } kind, ok := manifest["kind"].(string) if !ok { return nil, fmt.Errorf("kind is missing from manifest") } switch kind { case "CustomResourceDefinition": // remove all CRD schemas from yaml file switch spec := manifest["spec"].(type) { case map[string]interface{}: spec["versions"] = []interface{}{} case map[interface{}]interface{}: spec["versions"] = []interface{}{} } // remove status from CRD delete(manifest, "status") case "Service", "Deployment": // keep only the CRD, Service and Deployment resources from yaml file default: continue } yamlData, err := yaml.Marshal(manifest) if err != nil { return nil, fmt.Errorf("failed to marshal manifest: %v", err) } resources = append(resources, yamlData) } manifests = bytes.Join(resources, []byte("\n---\n")) // Replace version with v99.99.99, this allows us to deduplicate the manifests // and reduce the size of the test_manifests.yaml file manifests = bytes.ReplaceAll(manifests, []byte(version), []byte(dummyVersion)) for bytes.HasPrefix(manifests, []byte("\n")) || bytes.HasSuffix(manifests, []byte("\n---")) { manifests = bytes.TrimPrefix(manifests, []byte("\n")) manifests = bytes.TrimSuffix(manifests, []byte("\n---")) } for bytes.HasSuffix(manifests, []byte("\n")) || bytes.HasPrefix(manifests, []byte("\n---")) { manifests = bytes.TrimSuffix(manifests, []byte("\n")) manifests = bytes.TrimPrefix(manifests, []byte("\n---")) } return manifests, nil } func manifestHash(manifests []byte) (string, error) { hash := fnv.New64() if _, err := hash.Write(manifests); err != nil { return "", fmt.Errorf("failed to hash manifest: %v", err) } return hex.EncodeToString(hash.Sum([]byte{})), nil } 07070100000023000081A400000000000000000000000166DFF09D00000070000000000000000000000000000000000000003900000000cmctl-2.1.1/internal/versionchecker/test/testdata/go.modmodule fetch go 1.21 require ( golang.org/x/mod v0.16.0 golang.org/x/sync v0.6.0 gopkg.in/yaml.v2 v2.4.0 ) 07070100000024000081A400000000000000000000000166DFF09D0000029A000000000000000000000000000000000000003900000000cmctl-2.1.1/internal/versionchecker/test/testdata/go.sumgolang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 07070100000025000081A400000000000000000000000166DFF09D00041E6F000000000000000000000000000000000000004600000000cmctl-2.1.1/internal/versionchecker/test/testdata/test_manifests.yaml# [CHK_LATEST_VERSION]: v1.15.3 --- # [CHK_VERSIONS]: v1.0.0, v1.0.1, v1.0.2, v1.0.3, v1.0.4, v1.1.0-alpha.0, v1.1.0-alpha.1, v1.1.0, v1.1.1 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: certificaterequests.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: certificates.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: challenges.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: clusterissuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: issuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: orders.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: cert-manager namespace: cert-manager spec: ports: - port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 targetPort: 10250 selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager resources: {} serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 protocol: TCP resources: {} serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: {} serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.2.0-alpha.0 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: certificaterequests.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: certificates.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: challenges.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: clusterissuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: issuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: orders.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: webhook helm.sh/chart: cert-manager-v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 targetPort: 10250 selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cainjector helm.sh/chart: cert-manager-v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cainjector helm.sh/chart: cert-manager-v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager resources: {} serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 protocol: TCP resources: {} serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: webhook helm.sh/chart: cert-manager-v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: webhook helm.sh/chart: cert-manager-v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: {} serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.2.0-alpha.1 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: certificaterequests.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: certificates.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: challenges.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: clusterissuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: issuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: orders.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: certificaterequests.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: certificates.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: challenges.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: clusterissuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: issuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: orders.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: cert-manager namespace: cert-manager spec: ports: - port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 targetPort: 10250 selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager resources: {} serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 protocol: TCP resources: {} serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: {} serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.2.0-alpha.2, v1.2.0, v1.3.0-alpha.0, v1.3.0-alpha.1, v1.3.0-beta.0, v1.3.0, v1.3.1, v1.3.2, v1.3.3, v1.4.0-alpha.0, v1.4.0-alpha.1 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: certificaterequests.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: certificates.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: challenges.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: clusterissuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: issuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: orders.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: cert-manager namespace: cert-manager spec: ports: - port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 targetPort: 10250 selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager resources: {} serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 protocol: TCP resources: {} serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: {} serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.4.0-beta.0, v1.4.0-beta.1, v1.4.0, v1.4.1, v1.4.2, v1.4.3, v1.4.4 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: certificaterequests.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: certificates.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: challenges.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: clusterissuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: issuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: orders.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: webhook helm.sh/chart: cert-manager-v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 targetPort: 10250 selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cainjector helm.sh/chart: cert-manager-v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cainjector helm.sh/chart: cert-manager-v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager resources: {} securityContext: runAsNonRoot: true serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cert-manager helm.sh/chart: cert-manager-v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 protocol: TCP resources: {} securityContext: runAsNonRoot: true serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: webhook helm.sh/chart: cert-manager-v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: webhook helm.sh/chart: cert-manager-v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: {} securityContext: runAsNonRoot: true serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.5.0-alpha.0 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 targetPort: 10250 selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager resources: {} securityContext: runAsNonRoot: true serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 protocol: TCP resources: {} securityContext: runAsNonRoot: true serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: {} securityContext: runAsNonRoot: true serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.5.0-beta.0, v1.5.0-beta.1, v1.5.0, v1.5.1, v1.5.2, v1.5.3, v1.5.4, v1.5.5, v1.6.0-alpha.0, v1.6.0-alpha.1, v1.6.0-alpha.2, v1.6.0-beta.0, v1.6.0, v1.6.1, v1.6.2, v1.6.3 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: cert-manager-webhook namespace: cert-manager path: /convert conversionReviewVersions: - v1 - v1beta1 group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: 10250 selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager resources: {} securityContext: runAsNonRoot: true serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 protocol: TCP resources: {} securityContext: runAsNonRoot: true serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: {} securityContext: runAsNonRoot: true serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.7.0-alpha.0, v1.7.0-alpha.1, v1.7.0-beta.0, v1.7.0, v1.7.1, v1.7.2, v1.7.3 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager securityContext: runAsNonRoot: true serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 protocol: TCP securityContext: runAsNonRoot: true serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: runAsNonRoot: true serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.8.0-alpha.0, v1.8.0-alpha.1 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager securityContext: allowPrivilegeEscalation: false securityContext: runAsNonRoot: true serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 name: http-metrics protocol: TCP securityContext: allowPrivilegeEscalation: false securityContext: runAsNonRoot: true serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false securityContext: runAsNonRoot: true serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.8.0-alpha.2, v1.8.0-beta.0, v1.8.0, v1.8.1, v1.8.2 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 name: http-metrics protocol: TCP securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.9.0-alpha.0, v1.9.0-beta.0, v1.9.0-beta.1, v1.9.0, v1.9.1, v1.9.2-beta.0, v1.9.2 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager ports: - containerPort: 9402 name: http-metrics protocol: TCP securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook,cert-manager-webhook.cert-manager,cert-manager-webhook.cert-manager.svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager ports: - containerPort: 10250 name: https protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.10.0-alpha.0, v1.10.0-beta.0, v1.10.0, v1.10.1, v1.10.2, v1.11.0-alpha.0, v1.11.0-alpha.1 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.11.0-alpha.2 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.11.0-beta.0 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --max-concurrent-challenges=60 - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.11.0-beta.1, v1.11.0, v1.11.1-beta.0, v1.11.1, v1.11.3, v1.12.0-alpha.0, v1.12.0-alpha.1, v1.12.0-alpha.2 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.11.2, v1.11.4, v1.11.5, v1.12.0-beta.0 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.12.0-beta.1, v1.12.0-beta.2, v1.12.0, v1.12.1, v1.12.2, v1.12.3, v1.12.4, v1.12.5, v1.12.6, v1.12.7, v1.12.9, v1.12.10, v1.12.11, v1.12.12, v1.12.13 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.12.8 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.13.0-alpha.0, v1.13.0-beta.0 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.13.0, v1.13.1, v1.13.2, v1.13.3, v1.13.4, v1.13.5, v1.13.6 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.14.0-alpha.0 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: path: /livez port: http-healthz scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 15 name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.14.0-alpha.1 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 revisionHistoryLimit: null selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 revisionHistoryLimit: null selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: path: /livez port: http-healthz scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 15 name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 revisionHistoryLimit: null selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.14.0-beta.0 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 revisionHistoryLimit: null selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 revisionHistoryLimit: null selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: path: /livez port: http-healthz scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 15 name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 revisionHistoryLimit: null selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.14.0, v1.14.1 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 revisionHistoryLimit: null selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 revisionHistoryLimit: null selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: path: /livez port: http-healthz scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 15 name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 revisionHistoryLimit: null selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.14.2, v1.14.3, v1.14.4, v1.14.5, v1.14.6, v1.14.7 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: path: /livez port: http-healthz scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 15 name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- # [CHK_VERSIONS]: v1.15.0-alpha.0, v1.15.0-beta.1, v1.15.0-beta.2, v1.15.0, v1.15.1, v1.15.2-alpha.1, v1.15.2, v1.15.3 apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: helm.sh/resource-policy: keep labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificaterequests.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: CertificateRequest listKind: CertificateRequestList plural: certificaterequests shortNames: - cr - crs singular: certificaterequest scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: helm.sh/resource-policy: keep labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: certificates.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Certificate listKind: CertificateList plural: certificates shortNames: - cert - certs singular: certificate scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: helm.sh/resource-policy: keep labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: challenges.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Challenge listKind: ChallengeList plural: challenges singular: challenge scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: helm.sh/resource-policy: keep labels: app: cert-manager app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: clusterissuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: ClusterIssuer listKind: ClusterIssuerList plural: clusterissuers singular: clusterissuer scope: Cluster versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: helm.sh/resource-policy: keep labels: app: cert-manager app.kubernetes.io/component: crds app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: issuers.cert-manager.io spec: group: cert-manager.io names: categories: - cert-manager kind: Issuer listKind: IssuerList plural: issuers singular: issuer scope: Namespaced versions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: helm.sh/resource-policy: keep labels: app: cert-manager app.kubernetes.io/component: crds app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: orders.acme.cert-manager.io spec: group: acme.cert-manager.io names: categories: - cert-manager - cert-manager-acme kind: Order listKind: OrderList plural: orders singular: order scope: Namespaced versions: [] --- apiVersion: v1 kind: Service metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: ports: - name: tcp-prometheus-servicemonitor port: 9402 protocol: TCP targetPort: 9402 selector: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: ports: - name: https port: 443 protocol: TCP targetPort: https selector: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 name: cert-manager-cainjector namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector template: metadata: labels: app: cainjector app.kubernetes.io/component: cainjector app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cainjector app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --leader-election-namespace=kube-system env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-cainjector:v99.99.99 imagePullPolicy: IfNotPresent name: cert-manager-cainjector securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-cainjector --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 name: cert-manager namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager template: metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9402" prometheus.io/scrape: "true" labels: app: cert-manager app.kubernetes.io/component: controller app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: cert-manager app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --cluster-resource-namespace=$(POD_NAMESPACE) - --leader-election-namespace=kube-system - --acme-http01-solver-image=quay.io/jetstack/cert-manager-acmesolver:v99.99.99 - --max-concurrent-challenges=60 env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-controller:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: path: /livez port: http-healthz scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 15 name: cert-manager-controller ports: - containerPort: 9402 name: http-metrics protocol: TCP - containerPort: 9403 name: http-healthz protocol: TCP securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 name: cert-manager-webhook namespace: cert-manager spec: replicas: 1 selector: matchLabels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook template: metadata: labels: app: webhook app.kubernetes.io/component: webhook app.kubernetes.io/instance: cert-manager app.kubernetes.io/name: webhook app.kubernetes.io/version: v99.99.99 spec: containers: - args: - --v=2 - --secure-port=10250 - --dynamic-serving-ca-secret-namespace=$(POD_NAMESPACE) - --dynamic-serving-ca-secret-name=cert-manager-webhook-ca - --dynamic-serving-dns-names=cert-manager-webhook - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE) - --dynamic-serving-dns-names=cert-manager-webhook.$(POD_NAMESPACE).svc env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: quay.io/jetstack/cert-manager-webhook:v99.99.99 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: 6080 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 name: cert-manager-webhook ports: - containerPort: 10250 name: https protocol: TCP - containerPort: 6080 name: healthcheck protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 6080 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true enableServiceLinks: false nodeSelector: kubernetes.io/os: linux securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cert-manager-webhook --- 07070100000026000081A400000000000000000000000166DFF09D00001463000000000000000000000000000000000000004000000000cmctl-2.1.1/internal/versionchecker/test/versionchecker_test.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package versionchecker import ( "bytes" "context" "errors" "fmt" "io" "os" "strings" "testing" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/cli-runtime/pkg/resource" kscheme "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/client/fake" "github.com/cert-manager/cmctl/v2/internal/versionchecker" _ "embed" ) const dummyVersion = "v99.99.99" type testManifest struct { versions []string manifest []byte } func loadManifests(t *testing.T) []testManifest { testManifestBytes, err := os.ReadFile("testdata/test_manifests.yaml") if err != nil { t.Fatal(err) } // Read latest version from first line split := bytes.SplitN(testManifestBytes, []byte("\n"), 2) if len(split) != 2 { t.Fatal(fmt.Errorf("invalid test manifest: %s", testManifestBytes)) } latestVersion := strings.TrimSpace(string(split[0])) latestVersion = strings.TrimPrefix(latestVersion, "# [CHK_LATEST_VERSION]: ") if latestVersion == "" { t.Fatal(fmt.Errorf("invalid test manifest: %s", testManifestBytes)) } t.Log("Latest version:", latestVersion) testManifestBytes = split[1] var manifests []testManifest for _, manifest := range bytes.Split(testManifestBytes, []byte("---\n# [CHK_VERSIONS]: ")) { if len(manifest) == 0 { continue } parts := bytes.SplitN(manifest, []byte("\n"), 2) if len(parts) != 2 { t.Fatal(fmt.Errorf("invalid test manifest: %s", manifest)) } versions := string(parts[0]) versions = strings.TrimSpace(versions) manifests = append(manifests, testManifest{ versions: strings.Split(versions, ", "), manifest: parts[1], }) } return manifests } func manifestToObject(manifest io.Reader) ([]runtime.Object, error) { obj, err := resource. NewLocalBuilder(). Flatten(). Unstructured(). Stream(manifest, ""). Do(). Object() if err != nil { return nil, err } list, ok := obj.(*corev1.List) if !ok { return nil, errors.New("Could not get list") } return transformObjects(list.Items) } func transformObjects(objects []runtime.RawExtension) ([]runtime.Object, error) { transformedObjects := []runtime.Object{} for _, resource := range objects { var err error gvk := resource.Object.GetObjectKind().GroupVersionKind() // Create a pod for a Deployment resource if gvk.Group == "apps" && gvk.Version == "v1" && gvk.Kind == "Deployment" { unstr := resource.Object.(*unstructured.Unstructured) var deployment appsv1.Deployment err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstr.Object, &deployment) if err != nil { return nil, err } pod, err := getPodFromTemplate(&deployment.Spec.Template, resource.Object, nil) if err != nil { return nil, err } transformedObjects = append(transformedObjects, pod) } transformedObjects = append(transformedObjects, resource.Object) } return transformedObjects, nil } func setupFakeVersionChecker(manifest io.Reader) (*versionchecker.VersionChecker, error) { scheme := runtime.NewScheme() if err := kscheme.AddToScheme(scheme); err != nil { return nil, err } if err := appsv1.AddToScheme(scheme); err != nil { return nil, err } if err := apiextensionsv1.AddToScheme(scheme); err != nil { return nil, err } if err := apiextensionsv1beta1.AddToScheme(scheme); err != nil { return nil, err } objs, err := manifestToObject(manifest) if err != nil { return nil, err } cl := fake. NewClientBuilder(). WithScheme(scheme). WithRuntimeObjects(objs...). Build() return versionchecker.NewFromClient(cl), nil } func TestVersionChecker(t *testing.T) { for _, item := range loadManifests(t) { for _, version := range item.versions { if version == "v1.2.0-alpha.1" { // Skip this version as it has a known issue: the CRDs are double continue } version := version manifest := item.manifest manifest = bytes.ReplaceAll(manifest, []byte(dummyVersion), []byte(version)) t.Run(version, func(t *testing.T) { checker, err := setupFakeVersionChecker(bytes.NewReader(manifest)) if err != nil { t.Fatal(err) } versionGuess, err := checker.Version(context.TODO()) if err != nil { t.Fatalf("failed to detect expected version %s: %s", version, err) } if version != versionGuess.Detected { t.Fatalf("wrong -> expected: %s vs detected: %s", version, versionGuess) } }) } } } 07070100000027000081A400000000000000000000000166DFF09D000014D4000000000000000000000000000000000000003600000000cmctl-2.1.1/internal/versionchecker/versionchecker.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package versionchecker import ( "context" "errors" "fmt" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" ) const certificatesCertManagerCrdName = "certificates.cert-manager.io" const certificatesCertManagerOldCrdName = "certificates.certmanager.k8s.io" var ( ErrCertManagerCRDsNotFound = fmt.Errorf("the cert-manager CRDs are not yet installed on the Kubernetes API server") ErrVersionNotDetected = fmt.Errorf("could not detect the cert-manager version") ErrMultipleVersionsDetected = fmt.Errorf("detect multiple different cert-manager versions") ) type Version struct { // If all found versions are the same, // this field will contain that version Detected string `json:"detected,omitempty"` Sources map[string]string `json:"sources"` } // Interface is used to check what cert-manager version is installed type Interface interface { Version(context.Context) (*Version, error) } // VersionChecker implements a version checker using a controller-runtime client type VersionChecker struct { client client.Client versionSources map[string]string } // New returns a cert-manager version checker. Prefer New over NewFromClient // since New will ensure the scheme is configured correctly. func New(restcfg *rest.Config, scheme *runtime.Scheme) (*VersionChecker, error) { if err := corev1.AddToScheme(scheme); err != nil { return nil, err } if err := apiextensionsv1.AddToScheme(scheme); err != nil { return nil, err } if err := apiextensionsv1beta1.AddToScheme(scheme); err != nil { return nil, err } cl, err := client.New(restcfg, client.Options{ Scheme: scheme, }) if err != nil { return nil, err } return &VersionChecker{ client: cl, versionSources: map[string]string{}, }, nil } // NewFromClient initialises a VersionChecker using the given client. Prefer New // instead, which will ensure that the scheme on the client is configured correctly. func NewFromClient(cl client.Client) *VersionChecker { return &VersionChecker{ client: cl, versionSources: map[string]string{}, } } // Version determines the installed cert-manager version. First, we look for // the "certificates.cert-manager.io" CRD and try to extract the version from that // resource's labels. Then, if it uses a webhook, that webhook service resource's // labels are checked for a label. Lastly the pods linked to the webhook its labels // are checked and the image tag is used to determine the version. // If no "certificates.cert-manager.io" CRD is found, the older // "certificates.certmanager.k8s.io" CRD is tried too. func (o *VersionChecker) Version(ctx context.Context) (*Version, error) { // Use the "certificates.cert-manager.io" CRD as a starting point err := o.extractVersionFromCrd(ctx, certificatesCertManagerCrdName) if err != nil && errors.Is(err, ErrCertManagerCRDsNotFound) { // Retry using the old CRD name "certificates.certmanager.k8s.io" as // a starting point and overwrite ErrCertManagerCRDsNotFound error err = o.extractVersionFromCrd(ctx, certificatesCertManagerOldCrdName) } // From the found versions, now determine if we have found any/ // if they are all the same version version, detectionError := o.determineVersion() if err != nil && detectionError != nil { // There was an error while determining the version (which is probably // caused by a bad setup/ permission or networking issue) and there also // was an error while trying to reduce the found versions to 1 version // Display both. err = fmt.Errorf("%v: %v", detectionError, err) } else if detectionError != nil { // An error occurred while trying to reduce the found versions to 1 version err = detectionError } return version, err } // determineVersion attempts to determine the version of the cert-manager install based on all found // versions. The function tries to reduce the found versions to 1 correct version. // An error is returned if no sources were found or if multiple different versions // were found. func (o *VersionChecker) determineVersion() (*Version, error) { if len(o.versionSources) == 0 { return nil, ErrVersionNotDetected } var detectedVersion string for _, version := range o.versionSources { if detectedVersion != "" && version != detectedVersion { // We have found a conflicting version return &Version{ Sources: o.versionSources, }, ErrMultipleVersionsDetected } detectedVersion = version } return &Version{ Detected: detectedVersion, Sources: o.versionSources, }, nil } 07070100000028000081A400000000000000000000000166DFF09D00000914000000000000000000000000000000000000001700000000cmctl-2.1.1/klone.yaml# This klone.yaml file describes the Makefile modules and versions that are # cloned into the "make/_shared" folder. These modules are dynamically imported # by the root Makefile. The "make upgrade-klone" target can be used to pull # the latest version from the upstream repositories (using the repo_ref value). # # More info can be found here: https://github.com/cert-manager/makefile-modules targets: make/_shared: - folder_name: boilerplate repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main repo_hash: 0cd95bf3efc50f1a7bacd033ebfd3179b50bc038 repo_path: modules/boilerplate - folder_name: cert-manager repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main repo_hash: 0cd95bf3efc50f1a7bacd033ebfd3179b50bc038 repo_path: modules/cert-manager - folder_name: executable repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main repo_hash: 0cd95bf3efc50f1a7bacd033ebfd3179b50bc038 repo_path: modules/executable - folder_name: generate-verify repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main repo_hash: 0cd95bf3efc50f1a7bacd033ebfd3179b50bc038 repo_path: modules/generate-verify - folder_name: go repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main repo_hash: 0cd95bf3efc50f1a7bacd033ebfd3179b50bc038 repo_path: modules/go - folder_name: help repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main repo_hash: 0cd95bf3efc50f1a7bacd033ebfd3179b50bc038 repo_path: modules/help - folder_name: klone repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main repo_hash: 0cd95bf3efc50f1a7bacd033ebfd3179b50bc038 repo_path: modules/klone - folder_name: repository-base repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main repo_hash: 0cd95bf3efc50f1a7bacd033ebfd3179b50bc038 repo_path: modules/repository-base - folder_name: tools repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main repo_hash: 0cd95bf3efc50f1a7bacd033ebfd3179b50bc038 repo_path: modules/tools 07070100000029000081A400000000000000000000000166DFF09D0000090D000000000000000000000000000000000000001400000000cmctl-2.1.1/main.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package main import ( "context" "fmt" "os" "runtime" "strings" logf "github.com/cert-manager/cert-manager/pkg/logs" cmdutil "k8s.io/kubectl/pkg/cmd/util" ctrl "sigs.k8s.io/controller-runtime" ctlcmd "github.com/cert-manager/cmctl/v2/cmd" "github.com/cert-manager/cmctl/v2/internal/util" "github.com/cert-manager/cmctl/v2/pkg/build" ) func main() { ctx, exit := util.SetupExitHandler(context.Background(), util.AlwaysErrCode) defer exit() // This function might call os.Exit, so defer last ctlName, isKubectlPlugin := build.DetectCtlInfo(os.Args) logf.InitLogs() defer logf.FlushLogs() ctrl.SetLogger(logf.Log) ctx = logf.NewContext(ctx, logf.Log, ctlName) ctx = build.WithCtlInfo(ctx, ctlName, isKubectlPlugin) // In cmctl, we are using cmdutil.CheckErr, a kubectl utility function that creates human readable // error messages from errors. By default, this function will call os.Exit(1) if it receives an error. // Instead, we want to do a soft exit, and use SetExitCode to set the correct exit code. // Additionally, we make sure to output the final error message to stdout, as we do not want this // message to be mixed with other log outputs from the execution of the command. // To do this, we need to set a custom error handler. cmdutil.BehaviorOnFatal(func(msg string, code int) { if len(msg) > 0 { // add newline if needed if !strings.HasSuffix(msg, "\n") { msg += "\n" } fmt.Fprint(os.Stdout, msg) } util.SetExitCodeValue(code) runtime.Goexit() // Do soft exit (handle all defers, that should set correct exit code) }) cmd := ctlcmd.NewCertManagerCtlCommand(ctx, os.Stdin, os.Stdout, os.Stderr) if err := cmd.ExecuteContext(ctx); err != nil { cmdutil.CheckErr(err) } } 0707010000002A000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001100000000cmctl-2.1.1/make0707010000002B000081A400000000000000000000000166DFF09D000003BA000000000000000000000000000000000000001B00000000cmctl-2.1.1/make/00_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. repo_name := github.com/cert-manager/cmctl/v2 exe_build_names := cmctl gorelease_file := .goreleaser.yml go_cmctl_main_dir := . go_cmctl_mod_dir := . go_cmctl_ldflags := \ -X github.com/cert-manager/cert-manager/pkg/util.AppVersion=$(VERSION) \ -X github.com/cert-manager/cert-manager/pkg/util.AppGitCommit=$(GITCOMMIT) golangci_lint_config := .golangci.yaml 0707010000002C000081A400000000000000000000000166DFF09D000003E3000000000000000000000000000000000000001B00000000cmctl-2.1.1/make/02_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. include make/test-unit.mk include make/test-integration.mk .PHONY: dryrun-release ## Dry-run release process ## @category [shared] Release dryrun-release: export RELEASE_DRYRUN := true dryrun-release: release .PHONY: release ## Publish all release artifacts (image + helm chart) ## @category [shared] Release release: | $(NEEDS_CRANE) $(bin_dir)/scratch $(MAKE) exe-publish @echo "Release complete!" 0707010000002D000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001900000000cmctl-2.1.1/make/_shared0707010000002E000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002500000000cmctl-2.1.1/make/_shared/boilerplate0707010000002F000081A400000000000000000000000166DFF09D000002D5000000000000000000000000000000000000002F00000000cmctl-2.1.1/make/_shared/boilerplate/00_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. default_go_header_file := $(dir $(lastword $(MAKEFILE_LIST)))/template/boilerplate.go.txt go_header_file ?= $(default_go_header_file) 07070100000030000081A400000000000000000000000166DFF09D00000331000000000000000000000000000000000000002F00000000cmctl-2.1.1/make/_shared/boilerplate/01_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. .PHONY: verify-boilerplate ## Verify that all files have the correct boilerplate. ## @category [shared] Generate/ Verify verify-boilerplate: | $(NEEDS_BOILERSUITE) $(BOILERSUITE) . shared_verify_targets += verify-boilerplate 07070100000031000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002E00000000cmctl-2.1.1/make/_shared/boilerplate/template07070100000032000081A400000000000000000000000166DFF09D00000236000000000000000000000000000000000000004100000000cmctl-2.1.1/make/_shared/boilerplate/template/boilerplate.go.txt/* Copyright The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */07070100000033000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002600000000cmctl-2.1.1/make/_shared/cert-manager07070100000034000081A400000000000000000000000166DFF09D0000075D000000000000000000000000000000000000003000000000cmctl-2.1.1/make/_shared/cert-manager/00_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. images_amd64 ?= images_arm64 ?= cert_manager_version := v1.15.3 images_amd64 += quay.io/jetstack/cert-manager-controller:$(cert_manager_version)@sha256:631ba2b3bf7be0bd0d446b8bfcbeb56f8fe735cd02a267567a8d94682d03165b images_amd64 += quay.io/jetstack/cert-manager-cainjector:$(cert_manager_version)@sha256:6802c6afea2da91f5782880b79008179bb98147a23ce00f3cab5ba799807b5d6 images_amd64 += quay.io/jetstack/cert-manager-webhook:$(cert_manager_version)@sha256:373e3acd7b96c87a574f9234bb4fbfd576e3205c502d6da5dade41165c9dc828 images_amd64 += quay.io/jetstack/cert-manager-startupapicheck:$(cert_manager_version)@sha256:a896ff5d8029e5a040643935089ef0466fe0c1f6b2fe591f342994c53aada6e2 images_arm64 += quay.io/jetstack/cert-manager-controller:$(cert_manager_version)@sha256:06fed982efd0c2b59736718ace9f7d482fda550d9398cc90b01a9ceb98c3fbb5 images_arm64 += quay.io/jetstack/cert-manager-cainjector:$(cert_manager_version)@sha256:549347a89682abc0ede551b253a617defc398c7b2b1ede4c66cb71f33326c2d1 images_arm64 += quay.io/jetstack/cert-manager-webhook:$(cert_manager_version)@sha256:51fe148d9e5269511f5fdac2db8cb64611acd6b118e5fcade00302442da33a8a images_arm64 += quay.io/jetstack/cert-manager-startupapicheck:$(cert_manager_version)@sha256:a15bfed2b625f7c97029ac4ba2777a13897a4492cc995cafda4594d30ab3d721 07070100000035000081A400000000000000000000000166DFF09D00000348000000000000000000000000000000000000003000000000cmctl-2.1.1/make/_shared/cert-manager/01_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. cert_manager_crds := $(bin_dir)/scratch/cert-manager-$(cert_manager_version).yaml $(cert_manager_crds): | $(bin_dir)/scratch curl -sSLo $@ https://github.com/cert-manager/cert-manager/releases/download/$(cert_manager_version)/cert-manager.crds.yaml 07070100000036000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002400000000cmctl-2.1.1/make/_shared/executable07070100000037000081A400000000000000000000000166DFF09D00001564000000000000000000000000000000000000002E00000000cmctl-2.1.1/make/_shared/executable/01_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. exe_targets ?= darwin_amd64_v1,darwin_arm64,linux_amd64_v1,linux_arm_7,linux_arm64,linux_ppc64le,linux_s390x,windows_amd64_v1,windows_arm64 ifndef bin_dir $(error bin_dir is not set) endif ifndef build_names ifndef exe_build_names $(error build_names and exe_build_names are not set) endif build_names := # empty endif all_exe_build_names := $(sort $(build_names) $(exe_build_names)) fatal_if_undefined = $(if $(findstring undefined,$(origin $1)),$(error $1 is not set)) define check_variables $(call fatal_if_undefined,go_$1_ldflags) $(call fatal_if_undefined,go_$1_main_dir) $(call fatal_if_undefined,go_$1_mod_dir) ifneq ($(go_$1_main_dir:.%=.),.) $$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES start with ".") endif ifeq ($(go_$1_main_dir:%/=/),/) $$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES NOT end with "/") endif ifeq ($(go_$1_main_dir:%.go=.go),.go) $$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES NOT end with ".go") endif ifneq ($(go_$1_mod_dir:\.%=\.),.) $$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES start with ".") endif ifeq ($(go_$1_mod_dir:%/=/),/) $$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES NOT end with "/") endif ifeq ($(go_$1_mod_dir:%.go=.go),.go) $$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES NOT end with ".go") endif endef $(foreach build_name,$(all_exe_build_names),$(eval $(call check_variables,$(build_name)))) ifdef exe_build_names $(call fatal_if_undefined,gorelease_file) endif ########################################## RELEASE_DRYRUN ?= false CGO_ENABLED ?= 0 GOEXPERIMENT ?= # empty by default run_targets := $(all_exe_build_names:%=run-%) build_targets := $(all_exe_build_names:%=$(bin_dir)/bin/%) $(bin_dir)/bin: mkdir -p $@ .PHONY: $(run_targets) ARGS ?= # default empty ## Directly run the go source locally. ## Any Go workfile is ignored. ## @category [shared] Build $(run_targets): run-%: | $(NEEDS_GO) cd $(go_$*_mod_dir) && \ GOWORK=off \ CGO_ENABLED=$(CGO_ENABLED) \ GOEXPERIMENT=$(GOEXPERIMENT) \ $(GO) run \ -ldflags '$(go_$*_ldflags)' \ $(go_$*_main_dir) $(ARGS) ## Build the go source locally for development/ testing ## on the local platform. Any Go workfile is ignored. ## @category [shared] Build $(build_targets): $(bin_dir)/bin/%: FORCE | $(NEEDS_GO) cd $(go_$*_mod_dir) && \ GOWORK=off \ CGO_ENABLED=$(CGO_ENABLED) \ GOEXPERIMENT=$(GOEXPERIMENT) \ $(GO) build \ -ldflags '$(go_$*_ldflags)' \ -o $@ \ $(go_$*_main_dir) define template_for_target $(YQ) 'with(.builds[]; select(.id == "$(1)") | .binary = "$(1)")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .main = "$(go_$(1)_main_dir)")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .dir = "$(go_$(1)_mod_dir)")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .env[0] = "CGO_ENABLED={{.Env.CGO_ENABLED}}")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .env[1] = "GOEXPERIMENT={{.Env.GOEXPERIMENT}}")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .mod_timestamp = "{{.Env.SOURCE_DATE_EPOCH}}")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .flags[0] = "-trimpath")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .ldflags[0] = "-s")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .ldflags[1] = "-w")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .ldflags[2] = "$(go_$(1)_ldflags)")' | \ $(YQ) 'with(.builds[]; select(.id == "$(1)") | .gobinary = "$(GO)")' | \ targets=$(exe_targets) $(YQ) 'with(.builds[]; select(.id == "$(1)") | .targets = (env(targets) | split(",")))' | endef ## Build the go source for release. This will build the source ## for all release platforms and architectures. Additionally, ## this will create a checksums file, sboms and sign the binaries. ## @category [shared] Build exe-publish: | $(NEEDS_GO) $(NEEDS_GORELEASER) $(NEEDS_SYFT) $(NEEDS_YQ) $(NEEDS_COSIGN) $(eval go_releaser_path := $(bin_dir)/scratch/exe-publish) rm -rf $(CURDIR)/$(go_releaser_path) cat $(gorelease_file) | \ $(foreach target,$(exe_build_names),$(call template_for_target,$(target))) \ $(YQ) '.dist = "$(CURDIR)/$(go_releaser_path)"' | \ $(YQ) 'with(.sboms[]; .cmd = "$(SYFT)" | .args = ["$$artifact", "--output", "spdx-json=$$document"] | .env = ["SYFT_FILE_METADATA_CATALOGER_ENABLED=true"])' | \ $(YQ) 'with(.signs[]; .cmd = "$(COSIGN)")' \ > $(CURDIR)/$(go_releaser_path).goreleaser_config.yaml $(eval extra_args := ) ifeq ($(RELEASE_DRYRUN),true) $(eval extra_args := $(extra_args) --skip=announce,publish,validate,sign) endif GOWORK=off \ SOURCE_DATE_EPOCH=$(GITEPOCH) \ CGO_ENABLED=$(CGO_ENABLED) \ GOEXPERIMENT=$(GOEXPERIMENT) \ $(GORELEASER) release \ $(extra_args) \ --fail-fast \ --config=$(CURDIR)/$(go_releaser_path).goreleaser_config.yaml 07070100000038000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002900000000cmctl-2.1.1/make/_shared/generate-verify07070100000039000081A400000000000000000000000166DFF09D000002C2000000000000000000000000000000000000003300000000cmctl-2.1.1/make/_shared/generate-verify/00_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. shared_generate_targets ?= shared_generate_targets_dirty ?= shared_verify_targets ?= shared_verify_targets_dirty ?= 0707010000003A000081A400000000000000000000000166DFF09D000006B0000000000000000000000000000000000000003300000000cmctl-2.1.1/make/_shared/generate-verify/02_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. .PHONY: generate ## Generate all generate targets. ## @category [shared] Generate/ Verify generate: $$(shared_generate_targets) @echo "The following targets cannot be run simultaneously with each other or other generate scripts:" $(foreach TARGET,$(shared_generate_targets_dirty), $(MAKE) $(TARGET)) verify_script := $(dir $(lastword $(MAKEFILE_LIST)))/util/verify.sh # Run the supplied make target argument in a temporary workspace and diff the results. verify-%: FORCE +$(verify_script) $(MAKE) $* verify_generated_targets = $(shared_generate_targets:%=verify-%) verify_generated_targets_dirty = $(shared_generate_targets_dirty:%=verify-%) verify_targets = $(sort $(verify_generated_targets) $(shared_verify_targets)) verify_targets_dirty = $(sort $(verify_generated_targets_dirty) $(shared_verify_targets_dirty)) .PHONY: verify ## Verify code and generate targets. ## @category [shared] Generate/ Verify verify: $$(verify_targets) @echo "The following targets create temporary files in the current directory, that is why they have to be run last:" $(foreach TARGET,$(verify_targets_dirty), $(MAKE) $(TARGET)) 0707010000003B000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002E00000000cmctl-2.1.1/make/_shared/generate-verify/util0707010000003C000081ED00000000000000000000000166DFF09D00000731000000000000000000000000000000000000003800000000cmctl-2.1.1/make/_shared/generate-verify/util/verify.sh#!/usr/bin/env bash # Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Verify that the supplied command does not make any changes to the repository. # # This is called from the Makefile to verify that all code generation scripts # have been run and that their changes have been committed to the repository. # # Runs any of the scripts or Make targets in this repository, after making a # copy of the repository, then reports any changes to the files in the copy. # For example: # # make verify-helm-chart-update || \ # make helm-chart-update # set -o errexit set -o nounset set -o pipefail projectdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../../../.." && pwd )" cd "${projectdir}" # Use short form arguments here to support BSD/macOS. `-d` instructs # it to make a directory, `-t` provides a prefix to use for the directory name. tmp="$(mktemp -d /tmp/verify.sh.XXXXXXXX)" cleanup() { rm -rf "${tmp}" } trap "cleanup" EXIT SIGINT rsync -aEq "${projectdir}/." "${tmp}" --exclude "_bin/" pushd "${tmp}" >/dev/null "$@" popd >/dev/null if ! diff \ --exclude=".git" \ --exclude="_bin" \ --new-file --unified --show-c-function --recursive "${projectdir}" "${tmp}" then echo echo "Project '${projectdir}' is out of date." echo "Please run '${*}'" exit 1 fi 0707010000003D000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001C00000000cmctl-2.1.1/make/_shared/go0707010000003E000081A400000000000000000000000166DFF09D000005F9000000000000000000000000000000000000003400000000cmctl-2.1.1/make/_shared/go/.golangci.override.yamllinters: # Explicitly define all enabled linters disable-all: true enable: - asasalint - asciicheck - bidichk - bodyclose - contextcheck - decorder - dogsled - dupword - durationcheck - errcheck - errchkjson - errname - exhaustive - exportloopref - forbidigo - gci - ginkgolinter - gocheckcompilerdirectives - gochecksumtype - gocritic - gofmt - goheader - goprintffuncname - gosec - gosimple - gosmopolitan - govet - grouper - importas - ineffassign - interfacebloat - loggercheck - makezero - mirror - misspell - musttag - nakedret - nilerr - nilnil - noctx - nosprintfhostport - predeclared - promlinter - protogetter - reassign - sloglint - staticcheck - tagalign - tenv - testableexamples - typecheck - unconvert - unparam - unused - usestdlibvars - wastedassign linters-settings: gci: sections: - standard # Standard section: captures all standard packages. - default # Default section: contains all imports that could not be matched to another section type. - prefix({{REPO-NAME}}) # Custom section: groups all imports with the specified Prefix. - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. 0707010000003F000081A400000000000000000000000166DFF09D0000161C000000000000000000000000000000000000002600000000cmctl-2.1.1/make/_shared/go/01_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ifndef bin_dir $(error bin_dir is not set) endif ifndef repo_name $(error repo_name is not set) endif go_base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ golangci_lint_override := $(dir $(lastword $(MAKEFILE_LIST)))/.golangci.override.yaml .PHONY: go-workspace go-workspace: export GOWORK?=$(abspath go.work) ## Create a go.work file in the repository root (or GOWORK) ## ## @category Development go-workspace: | $(NEEDS_GO) @rm -f $(GOWORK) $(GO) work init @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ | while read d; do \ target=$$(dirname $${d}); \ $(GO) work use "$${target}"; \ done .PHONY: go-tidy ## Alias for `make generate-go-mod-tidy` ## @category [shared] Generate/ Verify go-tidy: generate-go-mod-tidy .PHONY: generate-go-mod-tidy ## Run `go mod tidy` on all Go modules ## @category [shared] Generate/ Verify generate-go-mod-tidy: | $(NEEDS_GO) @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ | while read d; do \ target=$$(dirname $${d}); \ echo "Running 'go mod tidy' in directory '$${target}'"; \ pushd "$${target}" >/dev/null; \ $(GO) mod tidy || exit; \ popd >/dev/null; \ echo ""; \ done shared_generate_targets += generate-go-mod-tidy .PHONY: generate-govulncheck ## Generate base files in the repository ## @category [shared] Generate/ Verify generate-govulncheck: cp -r $(go_base_dir)/. ./ shared_generate_targets += generate-govulncheck .PHONY: verify-govulncheck ## Verify all Go modules for vulnerabilities using govulncheck ## @category [shared] Generate/ Verify # # Runs `govulncheck` on all Go modules related to the project. # Ignores Go modules among the temporary build artifacts in _bin, to avoid # scanning the code of the vendored Go, after running make vendor-go. # Ignores Go modules in make/_shared, because those will be checked in centrally # in the makefile_modules repository. # # `verify-govulncheck` not added to the `shared_verify_targets` variable and is # not run by `make verify`, because `make verify` is run for each PR, and we do # not want new vulnerabilities in existing code to block the merging of PRs. # Instead `make verify-govulnecheck` is intended to be run periodically by a CI job. verify-govulncheck: | $(NEEDS_GOVULNCHECK) @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ | while read d; do \ target=$$(dirname $${d}); \ echo "Running 'GOTOOLCHAIN=go$(VENDORED_GO_VERSION) $(bin_dir)/tools/govulncheck ./...' in directory '$${target}'"; \ pushd "$${target}" >/dev/null; \ GOTOOLCHAIN=go$(VENDORED_GO_VERSION) $(GOVULNCHECK) ./... || exit; \ popd >/dev/null; \ echo ""; \ done ifdef golangci_lint_config .PHONY: generate-golangci-lint-config ## Generate a golangci-lint configuration file ## @category [shared] Generate/ Verify generate-golangci-lint-config: | $(NEEDS_YQ) $(bin_dir)/scratch cp $(golangci_lint_config) $(bin_dir)/scratch/golangci-lint.yaml.tmp $(YQ) -i 'del(.linters.enable)' $(bin_dir)/scratch/golangci-lint.yaml.tmp $(YQ) eval-all -i '. as $$item ireduce ({}; . * $$item)' $(bin_dir)/scratch/golangci-lint.yaml.tmp $(golangci_lint_override) $(YQ) -i '(.. | select(tag == "!!str")) |= sub("{{REPO-NAME}}", "$(repo_name)")' $(bin_dir)/scratch/golangci-lint.yaml.tmp mv $(bin_dir)/scratch/golangci-lint.yaml.tmp $(golangci_lint_config) shared_generate_targets += generate-golangci-lint-config .PHONY: verify-golangci-lint ## Verify all Go modules using golangci-lint ## @category [shared] Generate/ Verify verify-golangci-lint: | $(NEEDS_GO) $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(bin_dir)/scratch @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ | while read d; do \ target=$$(dirname $${d}); \ echo "Running '$(bin_dir)/tools/golangci-lint run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config)' in directory '$${target}'"; \ pushd "$${target}" >/dev/null; \ $(GOLANGCI-LINT) run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config) --timeout 4m || exit; \ popd >/dev/null; \ echo ""; \ done shared_verify_targets_dirty += verify-golangci-lint .PHONY: fix-golangci-lint ## Fix all Go modules using golangci-lint ## @category [shared] Generate/ Verify fix-golangci-lint: | $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(NEEDS_GCI) $(bin_dir)/scratch $(GCI) write \ --skip-generated \ --skip-vendor \ -s "standard" \ -s "default" \ -s "prefix($(repo_name))" \ -s "blank" \ -s "dot" . @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) \ | while read d; do \ target=$$(dirname $${d}); \ echo "Running '$(bin_dir)/tools/golangci-lint run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config) --fix' in directory '$${target}'"; \ pushd "$${target}" >/dev/null; \ $(GOLANGCI-LINT) run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config) --fix || exit; \ popd >/dev/null; \ echo ""; \ done endif 07070100000040000081A400000000000000000000000166DFF09D00000031000000000000000000000000000000000000002600000000cmctl-2.1.1/make/_shared/go/README.md# README A module for various Go static checks. 07070100000041000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002100000000cmctl-2.1.1/make/_shared/go/base07070100000042000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002900000000cmctl-2.1.1/make/_shared/go/base/.github07070100000043000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003300000000cmctl-2.1.1/make/_shared/go/base/.github/workflows07070100000044000081A400000000000000000000000166DFF09D00000363000000000000000000000000000000000000004400000000cmctl-2.1.1/make/_shared/go/base/.github/workflows/govulncheck.yaml# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/go/base/.github/workflows/govulncheck.yaml instead. # Run govulncheck at midnight every night on the main branch, # to alert us to recent vulnerabilities which affect the Go code in this # project. name: govulncheck on: workflow_dispatch: {} schedule: - cron: '0 0 * * *' permissions: contents: read jobs: govulncheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - id: go-version run: | make print-go-version >> "$GITHUB_OUTPUT" - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ steps.go-version.outputs.result }} - run: make verify-govulncheck 07070100000045000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001E00000000cmctl-2.1.1/make/_shared/help07070100000046000081A400000000000000000000000166DFF09D000002DF000000000000000000000000000000000000002800000000cmctl-2.1.1/make/_shared/help/01_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. help_sh := $(dir $(lastword $(MAKEFILE_LIST)))/help.sh .PHONY: help help: @MAKEFILE_LIST="$(MAKEFILE_LIST)" \ MAKE="$(MAKE)" \ $(help_sh) 07070100000047000081ED00000000000000000000000166DFF09D00001227000000000000000000000000000000000000002600000000cmctl-2.1.1/make/_shared/help/help.sh#!/usr/bin/env bash # Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. set -o errexit set -o nounset set -o pipefail ## 1. Build set of extracted line items EMPTYLINE_REGEX="^[[:space:]]*$" DOCBLOCK_REGEX="^##[[:space:]]*(.*)$" CATEGORY_REGEX="^##[[:space:]]*@category[[:space:]]*(.*)$" TARGET_REGEX="^(([a-zA-Z0-9\_\/\%\$\(\)]|-)+):.*$" EMPTY_ITEM="<start-category><end-category><start-target><end-target><start-comment><end-comment>" # shellcheck disable=SC2086 raw_lines=$(cat ${MAKEFILE_LIST} | tr '\t' ' ' | grep -E "($TARGET_REGEX|$DOCBLOCK_REGEX|$EMPTYLINE_REGEX)") extracted_lines="" extracted_current="$EMPTY_ITEM" max_target_length=0 ## Extract all the commented targets from the Makefile while read -r line; do if [[ $line =~ $EMPTYLINE_REGEX ]]; then # Reset current item. extracted_current="$EMPTY_ITEM" elif [[ $line =~ $CATEGORY_REGEX ]]; then extracted_current=${extracted_current//<start-category><end-category>/<start-category>${BASH_REMATCH[1]}<end-category>} elif [[ $line =~ $TARGET_REGEX ]]; then # only keep the target if there is a comment if [[ $extracted_current != *"<start-comment><end-comment>"* ]]; then max_target_length=$(( ${#BASH_REMATCH[1]} > max_target_length ? ${#BASH_REMATCH[1]} : max_target_length )) extracted_current=${extracted_current//<start-target><end-target>/<start-target>${BASH_REMATCH[1]}<end-target>} extracted_lines="$extracted_lines\n$extracted_current" fi extracted_current="$EMPTY_ITEM" elif [[ $line =~ $DOCBLOCK_REGEX ]]; then extracted_current=${extracted_current//<end-comment>/${BASH_REMATCH[1]}<newline><end-comment>} fi done <<< "$raw_lines" ## 2. Build mapping for expanding targets ASSIGNMENT_REGEX="^(([a-zA-Z0-9\_\/\%\$\(\)]|-)+)[[:space:]]*:=[[:space:]]*(.*)$" raw_expansions=$(${MAKE} --dry-run --print-data-base noop | tr '\t' ' ' | grep -E "$ASSIGNMENT_REGEX") extracted_expansions="" while read -r line; do if [[ $line =~ $ASSIGNMENT_REGEX ]]; then target=${BASH_REMATCH[1]} expansion=${BASH_REMATCH[3]// /, } extracted_expansions="$extracted_expansions\n<start-target>$target<end-target><start-expansion>$expansion<end-expansion>" fi done <<< "$raw_expansions" ## 3. Sort and print the extracted line items RULE_COLOR="$(TERM=xterm tput setaf 6)" CATEGORY_COLOR="$(TERM=xterm tput setaf 3)" CLEAR_STYLE="$(TERM=xterm tput sgr0)" PURPLE=$(TERM=xterm tput setaf 125) extracted_lines=$(echo -e "$extracted_lines" | LC_ALL=C sort -r) current_category="" ## Print the help echo "Usage: make [target1] [target2] ..." IFS=$'\n'; for line in $extracted_lines; do category=$([[ $line =~ \<start-category\>(.*)\<end-category\> ]] && echo "${BASH_REMATCH[1]}") target=$([[ $line =~ \<start-target\>(.*)\<end-target\> ]] && echo "${BASH_REMATCH[1]}") comment=$([[ $line =~ \<start-comment\>(.*)\<end-comment\> ]] && echo -e "${BASH_REMATCH[1]//<newline>/\\n}") # Print the category header if it's changed if [[ "$current_category" != "$category" ]]; then current_category=$category echo -e "\n${CATEGORY_COLOR}${current_category}${CLEAR_STYLE}" fi # replace any $(...) with the actual value if [[ $target =~ \$\((.*)\) ]]; then new_target=$(echo -e "$extracted_expansions" | grep "<start-target>${BASH_REMATCH[1]}<end-target>" || true) if [[ -n "$new_target" ]]; then target=$([[ $new_target =~ \<start-expansion\>(.*)\<end-expansion\> ]] && echo -e "${BASH_REMATCH[1]}") fi fi # Print the target and its multiline comment is_first_line=true while read -r comment_line; do if [[ "$is_first_line" == true ]]; then is_first_line=false padding=$(( max_target_length - ${#target} )) printf " %s%${padding}s ${PURPLE}>${CLEAR_STYLE} %s\n" "${RULE_COLOR}${target}${CLEAR_STYLE}" "" "${comment_line}" else printf " %${max_target_length}s %s\n" "" "${comment_line}" fi done <<< "$comment" done 07070100000048000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001F00000000cmctl-2.1.1/make/_shared/klone07070100000049000081A400000000000000000000000166DFF09D000003AA000000000000000000000000000000000000002900000000cmctl-2.1.1/make/_shared/klone/01_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. .PHONY: generate-klone ## Generate klone shared Makefiles ## @category [shared] Generate/ Verify generate-klone: | $(NEEDS_KLONE) $(KLONE) sync shared_generate_targets += generate-klone .PHONY: upgrade-klone ## Upgrade klone Makefile modules to latest version ## @category [shared] Self-upgrade upgrade-klone: | $(NEEDS_KLONE) $(KLONE) upgrade 0707010000004A000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002900000000cmctl-2.1.1/make/_shared/repository-base0707010000004B000081A400000000000000000000000166DFF09D00000467000000000000000000000000000000000000003300000000cmctl-2.1.1/make/_shared/repository-base/01_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ base_dependabot_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base-dependabot/ ifdef repository_base_no_dependabot .PHONY: generate-base ## Generate base files in the repository ## @category [shared] Generate/ Verify generate-base: cp -r $(base_dir)/. ./ else .PHONY: generate-base ## Generate base files in the repository ## @category [shared] Generate/ Verify generate-base: cp -r $(base_dir)/. ./ cp -r $(base_dependabot_dir)/. ./ endif shared_generate_targets += generate-base 0707010000004C000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002E00000000cmctl-2.1.1/make/_shared/repository-base/base0707010000004D000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003900000000cmctl-2.1.1/make/_shared/repository-base/base-dependabot0707010000004E000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000004100000000cmctl-2.1.1/make/_shared/repository-base/base-dependabot/.github0707010000004F000081A400000000000000000000000166DFF09D000001F9000000000000000000000000000000000000005100000000cmctl-2.1.1/make/_shared/repository-base/base-dependabot/.github/dependabot.yaml# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/.github/dependabot.yaml instead. # Update Go dependencies and GitHub Actions dependencies daily. version: 2 updates: - package-ecosystem: gomod directory: / schedule: interval: daily groups: all: patterns: ["*"] - package-ecosystem: github-actions directory: / schedule: interval: daily groups: all: patterns: ["*"] 07070100000050000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003600000000cmctl-2.1.1/make/_shared/repository-base/base/.github07070100000051000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000004000000000cmctl-2.1.1/make/_shared/repository-base/base/.github/workflows07070100000052000081A400000000000000000000000166DFF09D00000D50000000000000000000000000000000000000005700000000cmctl-2.1.1/make/_shared/repository-base/base/.github/workflows/make-self-upgrade.yaml# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/.github/workflows/make-self-upgrade.yaml instead. name: make-self-upgrade concurrency: make-self-upgrade on: workflow_dispatch: {} schedule: - cron: '0 0 * * *' permissions: contents: read jobs: self_upgrade: runs-on: ubuntu-latest if: github.repository_owner == 'cert-manager' permissions: contents: write pull-requests: write env: SOURCE_BRANCH: "${{ github.ref_name }}" SELF_UPGRADE_BRANCH: "self-upgrade-${{ github.ref_name }}" steps: - name: Fail if branch is not head of branch. if: ${{ !startsWith(github.ref, 'refs/heads/') && env.SOURCE_BRANCH != '' && env.SELF_UPGRADE_BRANCH != '' }} run: | echo "This workflow should not be run on a non-branch-head." exit 1 - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - id: go-version run: | make print-go-version >> "$GITHUB_OUTPUT" - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version: ${{ steps.go-version.outputs.result }} - run: | git checkout -B "$SELF_UPGRADE_BRANCH" - run: | make -j upgrade-klone make -j generate - id: is-up-to-date shell: bash run: | git_status=$(git status -s) is_up_to_date="true" if [ -n "$git_status" ]; then is_up_to_date="false" echo "The following changes will be committed:" echo "$git_status" fi echo "result=$is_up_to_date" >> "$GITHUB_OUTPUT" - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} run: | git config --global user.name "cert-manager-bot" git config --global user.email "cert-manager-bot@users.noreply.github.com" git add -A && git commit -m "BOT: run 'make upgrade-klone' and 'make generate'" --signoff git push -f origin "$SELF_UPGRADE_BRANCH" - if: ${{ steps.is-up-to-date.outputs.result != 'true' }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const { repo, owner } = context.repo; const pulls = await github.rest.pulls.list({ owner: owner, repo: repo, head: owner + ':' + process.env.SELF_UPGRADE_BRANCH, base: process.env.SOURCE_BRANCH, state: 'open', }); if (pulls.data.length < 1) { const result = await github.rest.pulls.create({ title: '[CI] Merge ' + process.env.SELF_UPGRADE_BRANCH + ' into ' + process.env.SOURCE_BRANCH, owner: owner, repo: repo, head: process.env.SELF_UPGRADE_BRANCH, base: process.env.SOURCE_BRANCH, body: [ 'This PR is auto-generated to bump the Makefile modules.', ].join('\n'), }); await github.rest.issues.addLabels({ owner, repo, issue_number: result.data.number, labels: ['skip-review'] }); } 07070100000053000081A400000000000000000000000166DFF09D00002C5D000000000000000000000000000000000000003600000000cmctl-2.1.1/make/_shared/repository-base/base/LICENSE Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 07070100000054000081A400000000000000000000000166DFF09D00001124000000000000000000000000000000000000003700000000cmctl-2.1.1/make/_shared/repository-base/base/Makefile# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/Makefile instead. # NOTE FOR DEVELOPERS: "How do the Makefiles work and how can I extend them?" # # Shared Makefile logic lives in the make/_shared/ directory. The source of truth for these files # lies outside of this repository, eg. in the cert-manager/makefile-modules repository. # # Logic specific to this repository must be defined in the make/00_mod.mk and make/02_mod.mk files: # - The make/00_mod.mk file is included first and contains variable definitions needed by # the shared Makefile logic. # - The make/02_mod.mk file is included later, it can make use of most of the shared targets # defined in the make/_shared/ directory (all targets defined in 00_mod.mk and 01_mod.mk). # This file should be used to define targets specific to this repository. ################################## # Some modules build their dependencies from variables, we want these to be # evaluated at the last possible moment. For this we use second expansion to # re-evaluate the generate and verify targets a second time. # # See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html .SECONDEXPANSION: # For details on some of these "prelude" settings, see: # https://clarkgrubb.com/makefile-style-guide MAKEFLAGS += --warn-undefined-variables --no-builtin-rules SHELL := /usr/bin/env bash .SHELLFLAGS := -uo pipefail -c .DEFAULT_GOAL := help .DELETE_ON_ERROR: .SUFFIXES: FORCE: noop: # do nothing # Set empty value for MAKECMDGOALS to prevent the "warning: undefined variable 'MAKECMDGOALS'" # warning from happening when running make without arguments MAKECMDGOALS ?= ################################## # Host OS and architecture setup # ################################## # The reason we don't use "go env GOOS" or "go env GOARCH" is that the "go" # binary may not be available in the PATH yet when the Makefiles are # evaluated. HOST_OS and HOST_ARCH only support Linux, *BSD and macOS (M1 # and Intel). host_os := $(shell uname -s | tr A-Z a-z) host_arch := $(shell uname -m) HOST_OS ?= $(host_os) HOST_ARCH ?= $(host_arch) ifeq (x86_64, $(HOST_ARCH)) HOST_ARCH = amd64 else ifeq (aarch64, $(HOST_ARCH)) # linux reports the arm64 arch as aarch64 HOST_ARCH = arm64 endif ################################## # Git and versioning information # ################################## git_version := $(shell git describe --tags --always --match='v*' --abbrev=14 --dirty) VERSION ?= $(git_version) IS_PRERELEASE := $(shell git describe --tags --always --match='v*' --abbrev=0 | grep -q '-' && echo true || echo false) GITCOMMIT := $(shell git rev-parse HEAD) GITEPOCH := $(shell git show -s --format=%ct HEAD) ################################## # Global variables and dirs # ################################## bin_dir := _bin # The ARTIFACTS environment variable is set by the CI system to a directory # where artifacts should be placed. These artifacts are then uploaded to a # storage bucket by the CI system (https://docs.prow.k8s.io/docs/components/pod-utilities/). # An example of such an artifact is a jUnit XML file containing test results. # If the ARTIFACTS environment variable is not set, we default to a local # directory in the _bin directory. ARTIFACTS ?= $(bin_dir)/artifacts $(bin_dir) $(ARTIFACTS) $(bin_dir)/scratch: mkdir -p $@ .PHONY: clean ## Clean all temporary files ## @category [shared] Tools clean: rm -rf $(bin_dir) ################################## # Include all the Makefiles # ################################## -include make/00_mod.mk -include make/_shared/*/00_mod.mk -include make/_shared/*/01_mod.mk -include make/02_mod.mk -include make/_shared/*/02_mod.mk 07070100000055000081A400000000000000000000000166DFF09D0000014E000000000000000000000000000000000000003D00000000cmctl-2.1.1/make/_shared/repository-base/base/OWNERS_ALIASES# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/repository-base/base/OWNERS_ALIASES instead. aliases: cm-maintainers: - munnerz - joshvanl - wallrj - jakexks - maelvls - irbekrm - sgtcodfish - inteon - thatsmrtalbot 07070100000056000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001F00000000cmctl-2.1.1/make/_shared/tools07070100000057000081A400000000000000000000000166DFF09D00007DC5000000000000000000000000000000000000002900000000cmctl-2.1.1/make/_shared/tools/00_mod.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ifndef bin_dir $(error bin_dir is not set) endif ########################################## export DOWNLOAD_DIR ?= $(CURDIR)/$(bin_dir)/downloaded export GOVENDOR_DIR ?= $(CURDIR)/$(bin_dir)/go_vendor $(bin_dir)/scratch/image $(bin_dir)/tools $(DOWNLOAD_DIR)/tools: @mkdir -p $@ checkhash_script := $(dir $(lastword $(MAKEFILE_LIST)))/util/checkhash.sh lock_script := $(dir $(lastword $(MAKEFILE_LIST)))/util/lock.sh # $outfile is a variable in the lock script outfile := $$outfile for_each_kv = $(foreach item,$2,$(eval $(call $1,$(word 1,$(subst =, ,$(item))),$(word 2,$(subst =, ,$(item)))))) # To make sure we use the right version of each tool, we put symlink in # $(bin_dir)/tools, and the actual binaries are in $(bin_dir)/downloaded. When bumping # the version of the tools, this symlink gets updated. # Let's have $(bin_dir)/tools in front of the PATH so that we don't inadvertently # pick up the wrong binary somewhere. Watch out, $(shell echo $$PATH) will # still print the original PATH, since GNU make does not honor exported # variables: https://stackoverflow.com/questions/54726457 export PATH := $(CURDIR)/$(bin_dir)/tools:$(PATH) CTR ?= docker .PHONY: __require-ctr ifneq ($(shell command -v $(CTR) >/dev/null || echo notfound),) __require-ctr: @:$(error "$(CTR) (or set CTR to a docker-compatible tool)") endif NEEDS_CTR = __require-ctr tools := # https://github.com/helm/helm/releases tools += helm=v3.15.4 # https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl tools += kubectl=v1.31.0 # https://github.com/kubernetes-sigs/kind/releases tools += kind=v0.24.0 # https://www.vaultproject.io/downloads tools += vault=1.17.3 # https://github.com/Azure/azure-workload-identity/releases tools += azwi=v1.3.0 # https://github.com/kyverno/kyverno/releases tools += kyverno=v1.12.5 # https://github.com/mikefarah/yq/releases tools += yq=v4.44.3 # https://github.com/ko-build/ko/releases tools += ko=0.16.0 # https://github.com/protocolbuffers/protobuf/releases tools += protoc=27.3 # https://github.com/aquasecurity/trivy/releases tools += trivy=v0.54.1 # https://github.com/vmware-tanzu/carvel-ytt/releases tools += ytt=v0.50.0 # https://github.com/rclone/rclone/releases tools += rclone=v1.67.0 ### go packages # https://pkg.go.dev/sigs.k8s.io/controller-tools/cmd/controller-gen?tab=versions tools += controller-gen=v0.16.1 # https://pkg.go.dev/golang.org/x/tools/cmd/goimports?tab=versions tools += goimports=v0.24.0 # https://pkg.go.dev/github.com/google/go-licenses/licenses?tab=versions tools += go-licenses=706b9c60edd424a8b6d253fe10dfb7b8e942d4a5 # https://pkg.go.dev/gotest.tools/gotestsum?tab=versions tools += gotestsum=v1.12.0 # https://pkg.go.dev/sigs.k8s.io/kustomize/kustomize/v4?tab=versions tools += kustomize=v4.5.7 # https://pkg.go.dev/github.com/itchyny/gojq?tab=versions tools += gojq=v0.12.16 # https://pkg.go.dev/github.com/google/go-containerregistry/pkg/crane?tab=versions tools += crane=v0.20.2 # https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go?tab=versions tools += protoc-gen-go=v1.34.2 # https://pkg.go.dev/github.com/norwoodj/helm-docs/cmd/helm-docs?tab=versions tools += helm-docs=v1.14.2 # https://pkg.go.dev/github.com/sigstore/cosign/v2/cmd/cosign?tab=versions tools += cosign=v2.4.0 # https://pkg.go.dev/github.com/cert-manager/boilersuite?tab=versions tools += boilersuite=v0.1.0 # https://pkg.go.dev/github.com/princjef/gomarkdoc/cmd/gomarkdoc?tab=versions tools += gomarkdoc=v1.1.0 # https://pkg.go.dev/oras.land/oras/cmd/oras?tab=versions tools += oras=v1.2.0 # https://pkg.go.dev/github.com/onsi/ginkgo/v2/ginkgo?tab=versions # The gingko version should be kept in sync with the version used in code. # If there is no go.mod file (which is only the case for the makefile-modules # repo), then we default to a version that we know exists. We have to do this # because otherwise the awk failure renders the whole makefile unusable. detected_ginkgo_version := $(shell [[ -f go.mod ]] && awk '/ginkgo\/v2/ {print $$2}' go.mod || echo "v2.13.2") tools += ginkgo=$(detected_ginkgo_version) # https://pkg.go.dev/github.com/cert-manager/klone?tab=versions tools += klone=v0.1.0 # https://pkg.go.dev/github.com/goreleaser/goreleaser?tab=versions tools += goreleaser=v1.26.2 # https://pkg.go.dev/github.com/anchore/syft/cmd/syft?tab=versions tools += syft=v0.100.0 # https://github.com/cert-manager/helm-tool tools += helm-tool=v0.5.1 # https://github.com/cert-manager/cmctl tools += cmctl=v2.1.0 # https://pkg.go.dev/github.com/cert-manager/release/cmd/cmrel?tab=versions tools += cmrel=e4c3a4dc07df5c7c0379d334c5bb00e172462551 # https://github.com/golangci/golangci-lint/releases tools += golangci-lint=v1.60.1 # https://pkg.go.dev/golang.org/x/vuln?tab=versions tools += govulncheck=v1.1.3 # https://pkg.go.dev/github.com/operator-framework/operator-sdk/cmd/operator-sdk?tab=versions tools += operator-sdk=v1.36.1 # https://pkg.go.dev/github.com/cli/cli/v2?tab=versions tools += gh=v2.54.0 # https:///github.com/redhat-openshift-ecosystem/openshift-preflight/releases tools += preflight=1.10.0 # https://github.com/daixiang0/gci/releases tools += gci=v0.13.4 # https://github.com/google/yamlfmt/releases tools += yamlfmt=v0.13.0 # https://pkg.go.dev/k8s.io/code-generator/cmd?tab=versions K8S_CODEGEN_VERSION := v0.31.0 tools += client-gen=$(K8S_CODEGEN_VERSION) tools += deepcopy-gen=$(K8S_CODEGEN_VERSION) tools += informer-gen=$(K8S_CODEGEN_VERSION) tools += lister-gen=$(K8S_CODEGEN_VERSION) tools += applyconfiguration-gen=$(K8S_CODEGEN_VERSION) tools += defaulter-gen=$(K8S_CODEGEN_VERSION) tools += conversion-gen=$(K8S_CODEGEN_VERSION) # https://github.com/kubernetes/kube-openapi tools += openapi-gen=91dab695df6fb4696a1ea93e510a5a4c6d10d369 # https://raw.githubusercontent.com/kubernetes-sigs/controller-tools/master/envtest-releases.yaml KUBEBUILDER_ASSETS_VERSION := v1.31.0 tools += etcd=$(KUBEBUILDER_ASSETS_VERSION) tools += kube-apiserver=$(KUBEBUILDER_ASSETS_VERSION) # Additional tools can be defined to reuse the tooling in this file ADDITIONAL_TOOLS ?= tools += $(ADDITIONAL_TOOLS) # https://go.dev/dl/ VENDORED_GO_VERSION := 1.23.1 # Print the go version which can be used in GH actions .PHONY: print-go-version print-go-version: @echo result=$(VENDORED_GO_VERSION) # When switching branches which use different versions of the tools, we # need a way to re-trigger the symlinking from $(bin_dir)/downloaded to $(bin_dir)/tools. $(bin_dir)/scratch/%_VERSION: FORCE | $(bin_dir)/scratch @test "$($*_VERSION)" == "$(shell cat $@ 2>/dev/null)" || echo $($*_VERSION) > $@ # --silent = don't print output like progress meters # --show-error = but do print errors when they happen # --fail = exit with a nonzero error code without the response from the server when there's an HTTP error # --location = follow redirects from the server # --retry = the number of times to retry a failed attempt to connect # --retry-connrefused = retry even if the initial connection was refused CURL := curl --silent --show-error --fail --location --retry 10 --retry-connrefused # LN is expected to be an atomic action, meaning that two Make processes # can run the "link $(DOWNLOAD_DIR)/tools/xxx@$(XXX_VERSION)_$(HOST_OS)_$(HOST_ARCH) # to $(bin_dir)/tools/xxx" operation simultaneously without issues (both # will perform the action and the second time the link will be overwritten). LN := ln -fs upper_map := a:A b:B c:C d:D e:E f:F g:G h:H i:I j:J k:K l:L m:M n:N o:O p:P q:Q r:R s:S t:T u:U v:V w:W x:X y:Y z:Z uc = $(strip \ $(eval __upper := $1) \ $(foreach p,$(upper_map), \ $(eval __upper := $(subst $(word 1,$(subst :, ,$p)),$(word 2,$(subst :, ,$p)),$(__upper))) \ ) \ )$(__upper) tool_names := # for each item `xxx` in the tools variable: # - a $(XXX_VERSION) variable is generated # -> this variable contains the version of the tool # - a $(NEEDS_XXX) variable is generated # -> this variable contains the target name for the tool, # which is the relative path of the binary, this target # should be used when adding the tool as a dependency to # your target, you can't use $(XXX) as a dependency because # make does not support an absolute path as a dependency # - a $(XXX) variable is generated # -> this variable contains the absolute path of the binary, # the absolute path should be used when executing the binary # in targets or in scripts, because it is agnostic to the # working directory # - an unversioned target $(bin_dir)/tools/xxx is generated that # creates a link to the corresponding versioned target: # $(DOWNLOAD_DIR)/tools/xxx@$(XXX_VERSION)_$(HOST_OS)_$(HOST_ARCH) define tool_defs tool_names += $1 $(call uc,$1)_VERSION ?= $2 NEEDS_$(call uc,$1) := $$(bin_dir)/tools/$1 $(call uc,$1) := $$(CURDIR)/$$(bin_dir)/tools/$1 $$(bin_dir)/tools/$1: $$(bin_dir)/scratch/$(call uc,$1)_VERSION | $$(DOWNLOAD_DIR)/tools/$1@$$($(call uc,$1)_VERSION)_$$(HOST_OS)_$$(HOST_ARCH) $$(bin_dir)/tools @cd $$(dir $$@) && $$(LN) $$(patsubst $$(bin_dir)/%,../%,$$(word 1,$$|)) $$(notdir $$@) @touch $$@ # making sure the target of the symlink is newer than *_VERSION endef $(foreach tool,$(tools),$(eval $(call tool_defs,$(word 1,$(subst =, ,$(tool))),$(word 2,$(subst =, ,$(tool)))))) tools_paths := $(tool_names:%=$(bin_dir)/tools/%) ###### # Go # ###### # $(NEEDS_GO) is a target that is set as an order-only prerequisite in # any target that calls $(GO), e.g.: # # $(bin_dir)/tools/crane: $(NEEDS_GO) # $(GO) build -o $(bin_dir)/tools/crane # # $(NEEDS_GO) is empty most of the time, except when running "make vendor-go" # or when "make vendor-go" was previously run, in which case $(NEEDS_GO) is set # to $(bin_dir)/tools/go, since $(bin_dir)/tools/go is a prerequisite of # any target depending on Go when "make vendor-go" was run. detected_vendoring := $(findstring vendor-go,$(MAKECMDGOALS))$(shell [ -f $(bin_dir)/tools/go ] && echo yes) export VENDOR_GO ?= $(detected_vendoring) ifeq ($(VENDOR_GO),) .PHONY: __require-go ifneq ($(shell command -v go >/dev/null || echo notfound),) __require-go: @:$(error "$(GO) (or run 'make vendor-go')") endif GO := go NEEDS_GO = __require-go else export GOROOT := $(CURDIR)/$(bin_dir)/tools/goroot export PATH := $(CURDIR)/$(bin_dir)/tools/goroot/bin:$(PATH) GO := $(CURDIR)/$(bin_dir)/tools/go NEEDS_GO := $(bin_dir)/tools/go MAKE := $(MAKE) vendor-go endif .PHONY: vendor-go ## By default, this Makefile uses the system's Go. You can use a "vendored" ## version of Go that will get downloaded by running this command once. To ## disable vendoring, run "make unvendor-go". When vendoring is enabled, ## you will want to set the following: ## ## export PATH="$PWD/$(bin_dir)/tools:$PATH" ## export GOROOT="$PWD/$(bin_dir)/tools/goroot" ## @category [shared] Tools vendor-go: $(bin_dir)/tools/go .PHONY: unvendor-go unvendor-go: $(bin_dir)/tools/go rm -rf $(bin_dir)/tools/go $(bin_dir)/tools/goroot .PHONY: which-go ## Print the version and path of go which will be used for building and ## testing in Makefile commands. Vendored go will have a path in ./bin ## @category [shared] Tools which-go: | $(NEEDS_GO) @$(GO) version @echo "go binary used for above version information: $(GO)" $(bin_dir)/tools/go: $(bin_dir)/scratch/VENDORED_GO_VERSION | $(bin_dir)/tools/goroot $(bin_dir)/tools @cd $(dir $@) && $(LN) ./goroot/bin/go $(notdir $@) @touch $@ # making sure the target of the symlink is newer than *_VERSION # The "_" in "_bin" prevents "go mod tidy" from trying to tidy the vendored goroot. $(bin_dir)/tools/goroot: $(bin_dir)/scratch/VENDORED_GO_VERSION | $(GOVENDOR_DIR)/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH)/goroot $(bin_dir)/tools @cd $(dir $@) && $(LN) $(patsubst $(bin_dir)/%,../%,$(word 1,$|)) $(notdir $@) @touch $@ # making sure the target of the symlink is newer than *_VERSION # Extract the tar to the $(GOVENDOR_DIR) directory, this directory is not cached across CI runs. $(GOVENDOR_DIR)/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH)/goroot: | $(DOWNLOAD_DIR)/tools/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz @source $(lock_script) $@; \ mkdir -p $(outfile).dir; \ tar xzf $| -C $(outfile).dir; \ mv $(outfile).dir/go $(outfile); \ rm -rf $(outfile).dir ################### # go dependencies # ################### go_dependencies := go_dependencies += ginkgo=github.com/onsi/ginkgo/v2/ginkgo go_dependencies += controller-gen=sigs.k8s.io/controller-tools/cmd/controller-gen go_dependencies += goimports=golang.org/x/tools/cmd/goimports go_dependencies += go-licenses=github.com/google/go-licenses go_dependencies += gotestsum=gotest.tools/gotestsum go_dependencies += kustomize=sigs.k8s.io/kustomize/kustomize/v4 go_dependencies += gojq=github.com/itchyny/gojq/cmd/gojq go_dependencies += crane=github.com/google/go-containerregistry/cmd/crane go_dependencies += protoc-gen-go=google.golang.org/protobuf/cmd/protoc-gen-go go_dependencies += helm-docs=github.com/norwoodj/helm-docs/cmd/helm-docs go_dependencies += cosign=github.com/sigstore/cosign/v2/cmd/cosign go_dependencies += boilersuite=github.com/cert-manager/boilersuite go_dependencies += gomarkdoc=github.com/princjef/gomarkdoc/cmd/gomarkdoc go_dependencies += oras=oras.land/oras/cmd/oras go_dependencies += klone=github.com/cert-manager/klone go_dependencies += goreleaser=github.com/goreleaser/goreleaser go_dependencies += syft=github.com/anchore/syft/cmd/syft go_dependencies += client-gen=k8s.io/code-generator/cmd/client-gen go_dependencies += deepcopy-gen=k8s.io/code-generator/cmd/deepcopy-gen go_dependencies += informer-gen=k8s.io/code-generator/cmd/informer-gen go_dependencies += lister-gen=k8s.io/code-generator/cmd/lister-gen go_dependencies += applyconfiguration-gen=k8s.io/code-generator/cmd/applyconfiguration-gen go_dependencies += defaulter-gen=k8s.io/code-generator/cmd/defaulter-gen go_dependencies += conversion-gen=k8s.io/code-generator/cmd/conversion-gen go_dependencies += openapi-gen=k8s.io/kube-openapi/cmd/openapi-gen go_dependencies += helm-tool=github.com/cert-manager/helm-tool go_dependencies += cmctl=github.com/cert-manager/cmctl/v2 go_dependencies += cmrel=github.com/cert-manager/release/cmd/cmrel go_dependencies += golangci-lint=github.com/golangci/golangci-lint/cmd/golangci-lint go_dependencies += govulncheck=golang.org/x/vuln/cmd/govulncheck go_dependencies += operator-sdk=github.com/operator-framework/operator-sdk/cmd/operator-sdk go_dependencies += gh=github.com/cli/cli/v2/cmd/gh go_dependencies += gci=github.com/daixiang0/gci go_dependencies += yamlfmt=github.com/google/yamlfmt/cmd/yamlfmt ################# # go build tags # ################# go_tags := # Additional Go dependencies can be defined to re-use the tooling in this file ADDITIONAL_GO_DEPENDENCIES ?= ADDITIONAL_GO_TAGS ?= go_dependencies += $(ADDITIONAL_GO_DEPENDENCIES) go_tags += $(ADDITIONAL_GO_TAGS) go_tags_init = go_tags_$1 := $(call for_each_kv,go_tags_init,$(go_dependencies)) go_tags_defs = go_tags_$1 += $2 $(call for_each_kv,go_tags_defs,$(go_tags)) define go_dependency $$(DOWNLOAD_DIR)/tools/$1@$($(call uc,$1)_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $$(NEEDS_GO) $$(DOWNLOAD_DIR)/tools @source $$(lock_script) $$@; \ mkdir -p $$(outfile).dir; \ GOWORK=off GOBIN=$$(outfile).dir $$(GO) install --tags "$(strip $(go_tags_$1))" $2@$($(call uc,$1)_VERSION); \ mv $$(outfile).dir/$1 $$(outfile); \ rm -rf $$(outfile).dir endef $(call for_each_kv,go_dependency,$(go_dependencies)) ################## # File downloads # ################## go_linux_amd64_SHA256SUM=49bbb517cfa9eee677e1e7897f7cf9cfdbcf49e05f61984a2789136de359f9bd go_linux_arm64_SHA256SUM=faec7f7f8ae53fda0f3d408f52182d942cc89ef5b7d3d9f23ff117437d4b2d2f go_darwin_amd64_SHA256SUM=488d9e4ca3e3ed513ee4edd91bef3a2360c65fa6d6be59cf79640bf840130a58 go_darwin_arm64_SHA256SUM=e223795ca340e285a760a6446ce57a74500b30e57469a4109961d36184d3c05a .PRECIOUS: $(DOWNLOAD_DIR)/tools/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz $(DOWNLOAD_DIR)/tools/go@$(VENDORED_GO_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz: | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) https://go.dev/dl/go$(VENDORED_GO_VERSION).$(HOST_OS)-$(HOST_ARCH).tar.gz -o $(outfile); \ $(checkhash_script) $(outfile) $(go_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM) helm_linux_amd64_SHA256SUM=11400fecfc07fd6f034863e4e0c4c4445594673fd2a129e701fe41f31170cfa9 helm_linux_arm64_SHA256SUM=fa419ecb139442e8a594c242343fafb7a46af3af34041c4eac1efcc49d74e626 helm_darwin_amd64_SHA256SUM=1bc3f354f7ce4d7fd9cfa5bcc701c1f32c88d27076d96c2792d5b5226062aee5 helm_darwin_arm64_SHA256SUM=88115846a1fb58f8eb8f64fec5c343d95ca394f1be811602fa54a887c98730ac .PRECIOUS: $(DOWNLOAD_DIR)/tools/helm@$(HELM_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/helm@$(HELM_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) https://get.helm.sh/helm-$(HELM_VERSION)-$(HOST_OS)-$(HOST_ARCH).tar.gz -o $(outfile).tar.gz; \ $(checkhash_script) $(outfile).tar.gz $(helm_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ tar xfO $(outfile).tar.gz $(HOST_OS)-$(HOST_ARCH)/helm > $(outfile); \ chmod +x $(outfile); \ rm -f $(outfile).tar.gz kubectl_linux_amd64_SHA256SUM=7c27adc64a84d1c0cc3dcf7bf4b6e916cc00f3f576a2dbac51b318d926032437 kubectl_linux_arm64_SHA256SUM=f42832db7d77897514639c6df38214a6d8ae1262ee34943364ec1ffaee6c009c kubectl_darwin_amd64_SHA256SUM=fb6e07a69acc4e16885eda55b524c13b84bfbcf78cfac8d6c378d2bad321e105 kubectl_darwin_arm64_SHA256SUM=b7472df17a885574ed7273947a8a274c156357db21b981208e8e109b9ed4022d .PRECIOUS: $(DOWNLOAD_DIR)/tools/kubectl@$(KUBECTL_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/kubectl@$(KUBECTL_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) https://dl.k8s.io/release/$(KUBECTL_VERSION)/bin/$(HOST_OS)/$(HOST_ARCH)/kubectl -o $(outfile); \ $(checkhash_script) $(outfile) $(kubectl_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ chmod +x $(outfile) kind_linux_amd64_SHA256SUM=b89aada5a39d620da3fcd16435b7f28d858927dd53f92cbac77686b0588b600d kind_linux_arm64_SHA256SUM=2968808d916e12d0a25c56d07c9a1c987163f972513fa8a94a2125a69f9c50eb kind_darwin_amd64_SHA256SUM=6cf7ba50b37d3446153bbfb8990f03fb8102778898c84502cdb841710b499ed5 kind_darwin_arm64_SHA256SUM=8e34f2edc7efc5c7c160487251848a954cd60ccd52b56a3fc360eaab33543fc0 .PRECIOUS: $(DOWNLOAD_DIR)/tools/kind@$(KIND_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/kind@$(KIND_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) https://github.com/kubernetes-sigs/kind/releases/download/$(KIND_VERSION)/kind-$(HOST_OS)-$(HOST_ARCH) -o $(outfile); \ $(checkhash_script) $(outfile) $(kind_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ chmod +x $(outfile) vault_linux_amd64_SHA256SUM=146536fd9ef8aa1465894e718a8fe7a9ca13d68761bae900428f01f7ecd83806 vault_linux_arm64_SHA256SUM=6c7dc39df0058b1fa9e65050227cdb12dc7913153ecd56956911fb973c353590 vault_darwin_amd64_SHA256SUM=fd7e7c7a467723639cc0b624533a9f7aff0691bfbfe47602abac75af0be4914a vault_darwin_arm64_SHA256SUM=26f11328a9c9e3b5599ec63efe394aed5fed0879c662f9ca320b8ec63d839582 .PRECIOUS: $(DOWNLOAD_DIR)/tools/vault@$(VAULT_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/vault@$(VAULT_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) https://releases.hashicorp.com/vault/$(VAULT_VERSION)/vault_$(VAULT_VERSION)_$(HOST_OS)_$(HOST_ARCH).zip -o $(outfile).zip; \ $(checkhash_script) $(outfile).zip $(vault_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ unzip -qq -c $(outfile).zip > $(outfile); \ chmod +x $(outfile); \ rm -f $(outfile).zip azwi_linux_amd64_SHA256SUM=bbc84c7e5fcaf4c6e3e58064dc66b3b7f70f38a6d8f9cdd07f0669a8499bdd47 azwi_linux_arm64_SHA256SUM=7c4315ec8e21509641d90cf3160a379ae6ec771963df4bac0f18aa0a3ecef4ba azwi_darwin_amd64_SHA256SUM=998dfaea81b652a5cbe92bb7dd3f770a391b8129f2a57137966d375c9f135062 azwi_darwin_arm64_SHA256SUM=b8a4a8ebcba2248b439f43c1d2431f469b023894b2f862879dc0999293dc1154 .PRECIOUS: $(DOWNLOAD_DIR)/tools/azwi@$(AZWI_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/azwi@$(AZWI_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) https://github.com/Azure/azure-workload-identity/releases/download/$(AZWI_VERSION)/azwi-$(AZWI_VERSION)-$(HOST_OS)-$(HOST_ARCH).tar.gz -o $(outfile).tar.gz; \ $(checkhash_script) $(outfile).tar.gz $(azwi_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ tar xfO $(outfile).tar.gz azwi > $(outfile) && chmod 775 $(outfile); \ rm -f $(outfile).tar.gz kubebuilder_tools_linux_amd64_SHA256SUM=b72c0c764c797e6b2cfd6d417abdad7b25d4fbc9f8475edeb44c8dd598999b76 kubebuilder_tools_linux_arm64_SHA256SUM=087123cfb6ac48a1002db19df7ee96949b54d34860805a41397bcb4cd0b5d5e4 kubebuilder_tools_darwin_amd64_SHA256SUM=e8a3bc6245dd30597aab163239337cd125194037ac13328798aa17b86aff0cb4 kubebuilder_tools_darwin_arm64_SHA256SUM=9f2d49e16368aa278adaf3802c7f3a3ca73560345e2634f9af13844a3936dc5b .PRECIOUS: $(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz $(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz: | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) https://github.com/kubernetes-sigs/controller-tools/releases/download/envtest-$(KUBEBUILDER_ASSETS_VERSION)/envtest-$(KUBEBUILDER_ASSETS_VERSION)-$(HOST_OS)-$(HOST_ARCH).tar.gz -o $(outfile); \ $(checkhash_script) $(outfile) $(kubebuilder_tools_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM) $(DOWNLOAD_DIR)/tools/etcd@$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH): $(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ tar xfO $< controller-tools/envtest/etcd > $(outfile) && chmod 775 $(outfile) $(DOWNLOAD_DIR)/tools/kube-apiserver@$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH): $(DOWNLOAD_DIR)/tools/kubebuilder_tools_$(KUBEBUILDER_ASSETS_VERSION)_$(HOST_OS)_$(HOST_ARCH).tar.gz | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ tar xfO $< controller-tools/envtest/kube-apiserver > $(outfile) && chmod 775 $(outfile) kyverno_linux_amd64_SHA256SUM=962c396cdb149eadc7d6cc0cb345d3c01b6980d5265c8bb585c55ecd4b8a76b9 kyverno_linux_arm64_SHA256SUM=dd66d363656685af142ec2fcbaa8ff997951df3241b25a3dbe3eb890da124121 kyverno_darwin_amd64_SHA256SUM=f0053827f59aeed7e26b8ab578e9a86d9c002060414c442a46bfa8c49ac8280c kyverno_darwin_arm64_SHA256SUM=4467e97fafa5a2067b93a5cbc954069ba00c890e3e867d0702b864ac7242ee0e .PRECIOUS: $(DOWNLOAD_DIR)/tools/kyverno@$(KYVERNO_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/kyverno@$(KYVERNO_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools $(eval ARCH := $(subst amd64,x86_64,$(HOST_ARCH))) @source $(lock_script) $@; \ $(CURL) https://github.com/kyverno/kyverno/releases/download/$(KYVERNO_VERSION)/kyverno-cli_$(KYVERNO_VERSION)_$(HOST_OS)_$(ARCH).tar.gz -o $(outfile).tar.gz; \ $(checkhash_script) $(outfile).tar.gz $(kyverno_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ tar xfO $(outfile).tar.gz kyverno > $(outfile); \ chmod +x $(outfile); \ rm -f $(outfile).tar.gz yq_linux_amd64_SHA256SUM=a2c097180dd884a8d50c956ee16a9cec070f30a7947cf4ebf87d5f36213e9ed7 yq_linux_arm64_SHA256SUM=0e7e1524f68d91b3ff9b089872d185940ab0fa020a5a9052046ef10547023156 yq_darwin_amd64_SHA256SUM=216ddfa03e7ba0e5aba00b236ec78324b5bfc49b610db254fe92310878baea20 yq_darwin_arm64_SHA256SUM=559a594ef7a6ebc5b81a67b7717fb3accedd266d8fa7d8352da7fec9e463f48b .PRECIOUS: $(DOWNLOAD_DIR)/tools/yq@$(YQ_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/yq@$(YQ_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) https://github.com/mikefarah/yq/releases/download/$(YQ_VERSION)/yq_$(HOST_OS)_$(HOST_ARCH) -o $(outfile); \ $(checkhash_script) $(outfile) $(yq_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ chmod +x $(outfile) ko_linux_amd64_SHA256SUM=aee2caeced511e60c6889a4cfaf9ebe28ec35acb49531b7a90b09e0a963bcff7 ko_linux_arm64_SHA256SUM=45b6ba20084b2199c63dcc738c54f7f6c37ea4e9c7f79eefc286d9947b11d0d1 ko_darwin_amd64_SHA256SUM=5c98d0229fd2a82cc69510705b74a7196fc184641693930b0f9282b6d1f79d95 ko_darwin_arm64_SHA256SUM=9c75b97f26ba98c62a86f3b39e2c74ced6c97092f301cd73fe4e5b3e16261698 .PRECIOUS: $(DOWNLOAD_DIR)/tools/ko@$(KO_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/ko@$(KO_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools $(eval OS := $(subst linux,Linux,$(subst darwin,Darwin,$(HOST_OS)))) $(eval ARCH := $(subst amd64,x86_64,$(HOST_ARCH))) @source $(lock_script) $@; \ $(CURL) https://github.com/ko-build/ko/releases/download/v$(KO_VERSION)/ko_$(KO_VERSION)_$(OS)_$(ARCH).tar.gz -o $(outfile).tar.gz; \ $(checkhash_script) $(outfile).tar.gz $(ko_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ tar xfO $(outfile).tar.gz ko > $(outfile); \ chmod +x $(outfile); \ rm -f $(outfile).tar.gz protoc_linux_amd64_SHA256SUM=6dab2adab83f915126cab53540d48957c40e9e9023969c3e84d44bfb936c7741 protoc_linux_arm64_SHA256SUM=bdad36f3ad7472281d90568c4956ea2e203c216e0de005c6bd486f1920f2751c protoc_darwin_amd64_SHA256SUM=ce282648fed0e7fbd6237d606dc9ec168dd2c1863889b04efa0b19c47da65d1b protoc_darwin_arm64_SHA256SUM=b22116bd97cdbd7ea25346abe635a9df268515fe5ef5afa93cd9a68fc2513f84 .PRECIOUS: $(DOWNLOAD_DIR)/tools/protoc@$(PROTOC_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/protoc@$(PROTOC_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools $(eval OS := $(subst darwin,osx,$(HOST_OS))) $(eval ARCH := $(subst arm64,aarch_64,$(subst amd64,x86_64,$(HOST_ARCH)))) @source $(lock_script) $@; \ $(CURL) https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-$(OS)-$(ARCH).zip -o $(outfile).zip; \ $(checkhash_script) $(outfile).zip $(protoc_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ unzip -qq -c $(outfile).zip bin/protoc > $(outfile); \ chmod +x $(outfile); \ rm -f $(outfile).zip trivy_linux_amd64_SHA256SUM=bbaaf8278b2a9bb49aa848fe23c8bfe19f7db4f5dc7b55a9793357cd78cb5ec5 trivy_linux_arm64_SHA256SUM=26f8ee5a44ca027082c426d982ce95a37b88cf66defa1e982641eb4497bf1e99 trivy_darwin_amd64_SHA256SUM=d182c2de5496504120269b8d50b543e88b4837f8c9876055e54248f0a4e93d77 trivy_darwin_arm64_SHA256SUM=0ea077b074e38c3bce419d3cfaa417581c36e985beb9e571c06c01293158ff6f .PRECIOUS: $(DOWNLOAD_DIR)/tools/trivy@$(TRIVY_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/trivy@$(TRIVY_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools $(eval OS := $(subst linux,Linux,$(subst darwin,macOS,$(HOST_OS)))) $(eval ARCH := $(subst amd64,64bit,$(subst arm64,ARM64,$(HOST_ARCH)))) @source $(lock_script) $@; \ $(CURL) https://github.com/aquasecurity/trivy/releases/download/$(TRIVY_VERSION)/trivy_$(patsubst v%,%,$(TRIVY_VERSION))_$(OS)-$(ARCH).tar.gz -o $(outfile).tar.gz; \ $(checkhash_script) $(outfile).tar.gz $(trivy_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ tar xfO $(outfile).tar.gz trivy > $(outfile); \ chmod +x $(outfile); \ rm $(outfile).tar.gz ytt_linux_amd64_SHA256SUM=61dec6e00131f990db853afc4b7531c318bd3af3ba18f2cfdbc0d5e83a45c445 ytt_linux_arm64_SHA256SUM=f38290c2666ddcf6feb4907f91033c4f41022b3fb84893c42d1f48948597b82a ytt_darwin_amd64_SHA256SUM=d79f0b4189403c4142f5c646989de0769a316896a6096dfd1719605d313e8d1e ytt_darwin_arm64_SHA256SUM=f3ce72031d34f0a3d909b1c971017bb3788bb786d3bb5cba1bf6d699255be643 .PRECIOUS: $(DOWNLOAD_DIR)/tools/ytt@$(YTT_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/ytt@$(YTT_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) -sSfL https://github.com/vmware-tanzu/carvel-ytt/releases/download/$(YTT_VERSION)/ytt-$(HOST_OS)-$(HOST_ARCH) -o $(outfile); \ $(checkhash_script) $(outfile) $(ytt_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ chmod +x $(outfile) rclone_linux_amd64_SHA256SUM=07c23d21a94d70113d949253478e13261c54d14d72023bb14d96a8da5f3e7722 rclone_linux_arm64_SHA256SUM=2b44981a1a7d1f432c53c0f2f0b6bcdd410f6491c47dc55428fdac0b85c763f1 rclone_darwin_amd64_SHA256SUM=1a1a3b080393b721ba5f38597305be2dbac3b654b43dfac3ebe4630b4e6406c3 rclone_darwin_arm64_SHA256SUM=4dc6142aea78bb86f1236fe38e570b715990503c09733418c0cd2300e45651e4 .PRECIOUS: $(DOWNLOAD_DIR)/tools/rclone@$(RCLONE_VERSION)_$(HOST_OS)_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/rclone@$(RCLONE_VERSION)_$(HOST_OS)_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools $(eval OS := $(subst darwin,osx,$(HOST_OS))) @source $(lock_script) $@; \ $(CURL) https://github.com/rclone/rclone/releases/download/$(RCLONE_VERSION)/rclone-$(RCLONE_VERSION)-$(OS)-$(HOST_ARCH).zip -o $(outfile).zip; \ $(checkhash_script) $(outfile).zip $(rclone_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM); \ unzip -p $(outfile).zip rclone-$(RCLONE_VERSION)-$(OS)-$(HOST_ARCH)/rclone > $(outfile); \ chmod +x $(outfile); \ rm -f $(outfile).zip preflight_linux_amd64_SHA256SUM=97750df31f31200f073e3b2844628a0a3681a403648c76d12319f83c80666104 preflight_linux_arm64_SHA256SUM=e12b2afe063c07ee75f69f285f8cc56be99b85e2abac99cbef5fb22b91ef0cb7 # Currently there are no official releases for darwin, you cannot submit results # on non-official binaries, but we can still run tests. # # Once https://github.com/redhat-openshift-ecosystem/openshift-preflight/pull/942 is merged # we can remove this darwin specific hack .PRECIOUS: $(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_darwin_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_darwin_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ mkdir -p $(outfile).dir; \ GOWORK=off GOBIN=$(outfile).dir $(GO) install github.com/redhat-openshift-ecosystem/openshift-preflight/cmd/preflight@$(PREFLIGHT_VERSION); \ mv $(outfile).dir/preflight $(outfile); \ rm -rf $(outfile).dir .PRECIOUS: $(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_linux_$(HOST_ARCH) $(DOWNLOAD_DIR)/tools/preflight@$(PREFLIGHT_VERSION)_linux_$(HOST_ARCH): | $(DOWNLOAD_DIR)/tools @source $(lock_script) $@; \ $(CURL) https://github.com/redhat-openshift-ecosystem/openshift-preflight/releases/download/$(PREFLIGHT_VERSION)/preflight-linux-$(HOST_ARCH) -o $(outfile); \ $(checkhash_script) $(outfile) $(preflight_linux_$(HOST_ARCH)_SHA256SUM); \ chmod +x $(outfile) ################# # Other Targets # ################# # Although we "vendor" most tools in $(bin_dir)/tools, we still require some binaries # to be available on the system. The vendor-go MAKECMDGOALS trick prevents the # check for the presence of Go when 'make vendor-go' is run. # Gotcha warning: MAKECMDGOALS only contains what the _top level_ make invocation used, and doesn't look at target dependencies # i.e. if we have a target "abc: vendor-go test" and run "make abc", we'll get an error # about go being missing even though abc itself depends on vendor-go! # That means we need to pass vendor-go at the top level if go is not installed (i.e. "make vendor-go abc") missing=$(shell (command -v curl >/dev/null || echo curl) \ && (command -v sha256sum >/dev/null || command -v shasum >/dev/null || echo sha256sum) \ && (command -v git >/dev/null || echo git) \ && (command -v rsync >/dev/null || echo rsync) \ && (command -v bash >/dev/null || echo bash)) ifneq ($(missing),) $(error Missing required tools: $(missing)) endif .PHONY: tools ## Download and setup all tools ## @category [shared] Tools tools: $(tools_paths) 07070100000058000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002400000000cmctl-2.1.1/make/_shared/tools/util07070100000059000081ED00000000000000000000000166DFF09D00000662000000000000000000000000000000000000003100000000cmctl-2.1.1/make/_shared/tools/util/checkhash.sh#!/usr/bin/env bash # Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. set -o errexit set -o nounset set -o pipefail SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" # This script takes the hash of its first argument and verifies it against the # hex hash given in its second argument function usage_and_exit() { echo "usage: $0 <path-to-target> <expected-hash>" echo "or: LEARN_FILE=<path-to-learn-file> $0 <path-to-target> <old-hash>" exit 1 } HASH_TARGET=${1:-} EXPECTED_HASH=${2:-} if [[ -z $HASH_TARGET ]]; then usage_and_exit fi if [[ -z $EXPECTED_HASH ]]; then usage_and_exit fi SHASUM=$("${SCRIPT_DIR}/hash.sh" "$HASH_TARGET") if [[ "$SHASUM" == "$EXPECTED_HASH" ]]; then exit 0 fi # When running 'make learn-sha-tools', we don't want this script to fail. # Instead we log what sha values are wrong, so the make.mk file can be updated. if [ "${LEARN_FILE:-}" != "" ]; then echo "s/$EXPECTED_HASH/$SHASUM/g" >> "${LEARN_FILE:-}" exit 0 fi echo "invalid checksum for \"$HASH_TARGET\": wanted \"$EXPECTED_HASH\" but got \"$SHASUM\"" exit 1 0707010000005A000081ED00000000000000000000000166DFF09D00000373000000000000000000000000000000000000002C00000000cmctl-2.1.1/make/_shared/tools/util/hash.sh#!/usr/bin/env bash # Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. set -o errexit set -o nounset set -o pipefail # This script is a wrapper for outputting purely the sha256 hash of the input file, # ideally in a portable way. case "$(uname -s)" in Darwin*) shasum -a 256 "$1";; *) sha256sum "$1" esac | cut -d" " -f10707010000005B000081ED00000000000000000000000166DFF09D000008B2000000000000000000000000000000000000002C00000000cmctl-2.1.1/make/_shared/tools/util/lock.sh#!/usr/bin/env bash # Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. set -o errexit set -o nounset set -o pipefail # This script is used to lock a file while it is being downloaded. It prevents # multiple processes from downloading the same file at the same time or from reading # a half-downloaded file. # We need this solution because we have recursive $(MAKE) calls in our makefile # which each will try to download a set of tools. To prevent them from all downloading # the same files, we re-use the same downloads folder for all $(MAKE) invocations and # use this script to deduplicate the download processes. finalfile="$1" lockfile="$finalfile.lock" # On OSX, flock is not installed, we just skip locking in that case, # this means that running verify in parallel without downloading all # tools first will not work. flock_installed=$(command -v flock >/dev/null && echo "yes" || echo "no") if [[ "$flock_installed" == "yes" ]]; then mkdir -p "$(dirname "$lockfile")" touch "$lockfile" exec {FD}<>"$lockfile" # wait for the file to be unlocked if ! flock -x $FD; then echo "Failed to obtain a lock for $lockfile" exit 1 fi fi # now that we have the lock, check if file is already there if [[ -e "$finalfile" ]]; then exit 0 fi # use a temporary file to prevent Make from thinking the file is ready # while in reality is is only a partial download # shellcheck disable=SC2034 outfile="$finalfile.tmp" finish() { rv=$? if [[ $rv -eq 0 ]]; then mv "$outfile" "$finalfile" echo "[info]: downloaded $finalfile" else rm -rf "$outfile" || true rm -rf "$finalfile" || true fi rm -rf "$lockfile" || true } trap finish EXIT SIGINT 0707010000005C000081A400000000000000000000000166DFF09D000008ED000000000000000000000000000000000000002500000000cmctl-2.1.1/make/test-integration.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. .PHONY: generate-testgroup ## Generate code and crds for testgroup API ## @category Generate/ Verify generate-testgroup: | $(NEEDS_CONTROLLER-GEN) $(NEEDS_DEFAULTER-GEN) $(NEEDS_CONVERSION-GEN) rm -rf ./test/integration/testdata/apis/testgroup/crds/*.yaml rm -rf ./test/integration/testdata/apis/testgroup/**/zz_generated.* $(CONTROLLER-GEN) \ object:headerFile=$(go_header_file) \ paths=./test/integration/testdata/apis/testgroup/... $(CONTROLLER-GEN) \ crd \ paths=./test/integration/testdata/apis/testgroup/v{1,2}/... \ output:crd:dir=./test/integration/testdata/apis/testgroup/crds $(DEFAULTER-GEN) \ --go-header-file=$(go_header_file) \ --output-file=zz_generated.defaults.go \ ./test/integration/testdata/apis/testgroup/v{1,2}/... $(CONVERSION-GEN) \ --go-header-file=$(go_header_file) \ --output-file=zz_generated.conversion.go \ ./test/integration/testdata/apis/testgroup/v{1,2}/... shared_generate_targets += generate-testgroup .PHONY: test-integration ## Integration tests ## @category Testing test-integration: | $(cert_manager_crds) $(NEEDS_GO) $(NEEDS_GOTESTSUM) $(NEEDS_ETCD) $(NEEDS_KUBE-APISERVER) $(NEEDS_KUBECTL) $(NEEDS_HELM) $(ARTIFACTS) TEST_ASSET_ETCD=$(ETCD) \ TEST_ASSET_KUBE_APISERVER=$(KUBE-APISERVER) \ TEST_ASSET_KUBECTL=$(KUBECTL) \ TEST_CRDS=$(CURDIR)/test/integration/testdata/apis/testgroup \ CERT_MANAGER_CRDS=$(CURDIR)/$(cert_manager_crds) \ HELM_BIN=$(HELM) \ $(GOTESTSUM) \ --junitfile=$(ARTIFACTS)/junit-go-e2e.xml \ -- \ -coverprofile=$(ARTIFACTS)/filtered.cov \ ./test/integration/... \ -- \ -ldflags $(go_cmctl_ldflags) $(GO) tool cover -html=$(ARTIFACTS)/filtered.cov -o=$(ARTIFACTS)/filtered.html 0707010000005D000081A400000000000000000000000166DFF09D00000572000000000000000000000000000000000000001E00000000cmctl-2.1.1/make/test-unit.mk# Copyright 2023 The cert-manager Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. .PHONY: generate-versionchecker-testdata ## Generate versionchecker testdata ## @category Testing generate-versionchecker-testdata: | $(NEEDS_GO) cd ./internal/versionchecker/test/testdata/ && \ $(GO) run . \ $(CURDIR)/internal/versionchecker/test/testdata/test_manifests.yaml \ $(cert_manager_version) shared_generate_targets += generate-versionchecker-testdata .PHONY: test-unit ## Unit tests ## @category Testing test-unit: | $(NEEDS_GO) $(NEEDS_GOTESTSUM) $(ARTIFACTS) KUBEBUILDER_ASSETS=$(CURDIR)/$(bin_dir)/tools \ $(GOTESTSUM) \ --junitfile=$(ARTIFACTS)/junit-go-e2e.xml \ -- \ -coverprofile=$(ARTIFACTS)/filtered.cov \ ./cmd/... ./internal/... ./pkg/... \ -- \ -ldflags $(go_cmctl_ldflags) $(GO) tool cover -html=$(ARTIFACTS)/filtered.cov -o=$(ARTIFACTS)/filtered.html 0707010000005E000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001000000000cmctl-2.1.1/pkg0707010000005F000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001800000000cmctl-2.1.1/pkg/approve07070100000060000081A400000000000000000000000166DFF09D00001146000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/approve/approve.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package approve import ( "context" "errors" "fmt" apiutil "github.com/cert-manager/cert-manager/pkg/api/util" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/kubectl/pkg/util/templates" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/factory" ) // Options is a struct to support create certificaterequest command type Options struct { // Reason is the string that will be set on the Reason field of the Approved // condition. Reason string // Message is the string that will be set on the Message field of the // Approved condition. Message string genericclioptions.IOStreams *factory.Factory } // newOptions returns initialized Options func newOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } func NewCmdApprove(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := newOptions(ioStreams) cmd := &cobra.Command{ Use: "approve", Short: "Approve a CertificateRequest", Long: `Mark a CertificateRequest as Approved, so it may be signed by a configured Issuer.`, Example: templates.Examples(build.WithTemplate(setupCtx, ` # Approve a CertificateRequest with the name 'my-cr' {{.BuildName}} approve my-cr # Approve a CertificateRequest in namespace default {{.BuildName}} approve my-cr --namespace default # Approve a CertificateRequest giving a custom reason and message {{.BuildName}} approve my-cr --reason "ManualApproval" --reason "Approved by PKI department" `)), ValidArgsFunction: factory.ValidArgsListCertificateRequests(&o.Factory), PreRunE: func(cmd *cobra.Command, args []string) error { return o.Validate(args) }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context(), args) }, } cmd.Flags().StringVar(&o.Reason, "reason", "KubectlCertManager", "The reason to give as to what approved this CertificateRequest.") cmd.Flags().StringVar(&o.Message, "message", fmt.Sprintf("manually approved by %q", build.Name(setupCtx)), "The message to give as to why this CertificateRequest was approved.") o.Factory = factory.New(cmd) return cmd } // Validate validates the provided options func (o *Options) Validate(args []string) error { if len(args) < 1 { return errors.New("the name of the CertificateRequest to approve has to be provided as an argument") } if len(args) > 1 { return errors.New("only one argument can be passed: the name of the CertificateRequest") } if len(o.Reason) == 0 { return errors.New("a reason must be given as to who approved this CertificateRequest") } if len(o.Message) == 0 { return errors.New("a message must be given as to why this CertificateRequest is approved") } return nil } // Run executes approve command func (o *Options) Run(ctx context.Context, args []string) error { cr, err := o.CMClient.CertmanagerV1().CertificateRequests(o.Namespace).Get(ctx, args[0], metav1.GetOptions{}) if err != nil { return err } if apiutil.CertificateRequestIsApproved(cr) { return errors.New("CertificateRequest is already approved") } if apiutil.CertificateRequestIsDenied(cr) { return errors.New("CertificateRequest is already denied") } apiutil.SetCertificateRequestCondition(cr, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, o.Reason, o.Message) _, err = o.CMClient.CertmanagerV1().CertificateRequests(o.Namespace).UpdateStatus(ctx, cr, metav1.UpdateOptions{}) if err != nil { return err } fmt.Fprintf(o.Out, "Approved CertificateRequest '%s/%s'\n", cr.Namespace, cr.Name) return nil } 07070100000061000081A400000000000000000000000166DFF09D0000092D000000000000000000000000000000000000002800000000cmctl-2.1.1/pkg/approve/approve_test.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package approve import ( "testing" ) func TestValidate(t *testing.T) { tests := map[string]struct { args []string reason, message string expErr bool expErrMsg string }{ "CR name not passed as arg throws error": { args: []string{}, reason: "", message: "", expErr: true, expErrMsg: "the name of the CertificateRequest to approve has to be provided as an argument", }, "multiple CR names passed as arg throws error": { args: []string{"cr-1", "cr-1"}, reason: "", message: "", expErr: true, expErrMsg: "only one argument can be passed: the name of the CertificateRequest", }, "empty reason given should throw error": { args: []string{"cr-1"}, reason: "", message: "", expErr: true, expErrMsg: "a reason must be given as to who approved this CertificateRequest", }, "empty message given should throw error": { args: []string{"cr-1"}, reason: "foo", message: "", expErr: true, expErrMsg: "a message must be given as to why this CertificateRequest is approved", }, "all fields populated should not error": { args: []string{"cr-1"}, reason: "foo", message: "bar", expErr: false, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { opts := &Options{ Reason: test.reason, Message: test.message, } // Validating args and flags err := opts.Validate(test.args) if (err != nil) != test.expErr { t.Errorf("unexpected error, exp=%t got=%v", test.expErr, err) } if err != nil && err.Error() != test.expErrMsg { t.Errorf("got unexpected error when validating args and flags, expected: %v; actual: %v", test.expErrMsg, err) } }) } } 07070100000062000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001600000000cmctl-2.1.1/pkg/build07070100000063000081A400000000000000000000000166DFF09D0000093A000000000000000000000000000000000000001F00000000cmctl-2.1.1/pkg/build/build.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package build import ( "bytes" "context" "os" "path/filepath" "strings" "text/template" ) var defaultCtlName string = "cmctl" var defaultIsKubectlPlugin bool = false func DetectCtlInfo(args []string) (name string, isKubectlPlugin bool) { commandName := filepath.Base(os.Args[0]) if strings.HasPrefix(commandName, "kubectl-") || strings.HasPrefix(commandName, "kubectl_") { return "kubectl cert-manager", true } return commandName, false } // contextNameKey is how we find the ctl name in a context.Context. type contextNameKey struct{} // contextIsKubectlPluginKey is how we find if the ctl is a Kubectl plugin in a context.Context. type contextIsKubectlPluginKey struct{} func WithCtlInfo(ctx context.Context, name string, isKubectlPlugin bool) context.Context { ctx = context.WithValue(ctx, contextNameKey{}, name) ctx = context.WithValue(ctx, contextIsKubectlPluginKey{}, isKubectlPlugin) return ctx } func Name(ctx context.Context) string { name, ok := ctx.Value(contextNameKey{}).(string) if !ok { return defaultCtlName } return name } func IsKubectlPlugin(ctx context.Context) bool { isKubectlPlugin, ok := ctx.Value(contextIsKubectlPluginKey{}).(bool) if !ok { return defaultIsKubectlPlugin } return isKubectlPlugin } // WithTemplate returns a string that has the build name templated out with the // configured build name. Build name templates on '{{ .BuildName }}' variable. func WithTemplate(ctx context.Context, str string) string { buildName := Name(ctx) tmpl := template.Must(template.New("build-name").Parse(str)) var buf bytes.Buffer if err := tmpl.Execute(&buf, struct{ BuildName string }{buildName}); err != nil { // We panic here as it should never be possible that this template fails. panic(err) } return buf.String() } 07070100000064000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001F00000000cmctl-2.1.1/pkg/build/commands07070100000065000081A400000000000000000000000166DFF09D00000742000000000000000000000000000000000000002B00000000cmctl-2.1.1/pkg/build/commands/commands.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package commands import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/approve" "github.com/cert-manager/cmctl/v2/pkg/check" "github.com/cert-manager/cmctl/v2/pkg/completion" "github.com/cert-manager/cmctl/v2/pkg/convert" "github.com/cert-manager/cmctl/v2/pkg/create" "github.com/cert-manager/cmctl/v2/pkg/deny" "github.com/cert-manager/cmctl/v2/pkg/experimental" "github.com/cert-manager/cmctl/v2/pkg/inspect" "github.com/cert-manager/cmctl/v2/pkg/renew" "github.com/cert-manager/cmctl/v2/pkg/status" "github.com/cert-manager/cmctl/v2/pkg/upgrade" "github.com/cert-manager/cmctl/v2/pkg/version" ) type RegisterCommandFunc func(context.Context, genericclioptions.IOStreams) *cobra.Command // Commands returns the cobra Commands that should be registered for the CLI // build. func Commands() []RegisterCommandFunc { cmds := []RegisterCommandFunc{ version.NewCmdVersion, convert.NewCmdConvert, create.NewCmdCreate, renew.NewCmdRenew, status.NewCmdStatus, inspect.NewCmdInspect, approve.NewCmdApprove, deny.NewCmdDeny, check.NewCmdCheck, upgrade.NewCmdUpgrade, // Experimental features experimental.NewCmdExperimental, completion.NewCmdCompletion, } return cmds } 07070100000066000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001600000000cmctl-2.1.1/pkg/check07070100000067000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001A00000000cmctl-2.1.1/pkg/check/api07070100000068000081A400000000000000000000000166DFF09D00001074000000000000000000000000000000000000002100000000cmctl-2.1.1/pkg/check/api/api.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package api import ( "context" "errors" "fmt" "time" logf "github.com/cert-manager/cert-manager/pkg/logs" "github.com/cert-manager/cert-manager/pkg/util/cmapichecker" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/kubectl/pkg/util/templates" cmcmdutil "github.com/cert-manager/cmctl/v2/internal/util" "github.com/cert-manager/cmctl/v2/pkg/factory" ) // Options is a struct to support check api command type Options struct { // APIChecker is used to check that the cert-manager CRDs have been installed on the K8S // API server and that the cert-manager webhooks are all working APIChecker cmapichecker.Interface // Time before timeout when waiting Wait time.Duration // Time between checks when waiting Interval time.Duration genericclioptions.IOStreams *factory.Factory } var checkApiDesc = templates.LongDesc(` This check attempts to perform a dry-run create of a cert-manager *v1alpha2* Certificate resource in order to verify that CRDs are installed and all the required webhooks are reachable by the K8S API server. We use v1alpha2 API to ensure that the API server has also connected to the cert-manager conversion webhook.`) // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } // Complete takes the command arguments and factory and infers any remaining options. func (o *Options) Complete() error { var err error o.APIChecker, err = cmapichecker.New( o.RESTConfig, runtime.NewScheme(), o.Namespace, ) if err != nil { return err } return nil } // NewCmdCheckApi returns a cobra command for checking creating cert-manager resources against the K8S API server func NewCmdCheckApi(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "api", Short: "Check if the cert-manager API is ready", Long: checkApiDesc, PreRunE: func(cmd *cobra.Command, args []string) error { return o.Complete() }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context()) }, } cmd.Flags().DurationVar(&o.Wait, "wait", 0, "Wait until the cert-manager API is ready (default 0s = poll once)") cmd.Flags().DurationVar(&o.Interval, "interval", 5*time.Second, "Time between checks when waiting, must include unit, e.g. 1m or 10m") o.Factory = factory.New(cmd) return cmd } // Run executes check api command func (o *Options) Run(ctx context.Context) error { log := logf.FromContext(ctx, "checkAPI") start := time.Now() var lastError error pollErr := wait.PollUntilContextCancel(ctx, o.Interval, true, func(ctx context.Context) (bool, error) { if err := o.APIChecker.Check(ctx); err != nil { simpleError := cmapichecker.TranslateToSimpleError(err) if simpleError != nil { log.V(2).Info("Not ready", "err", simpleError, "underlyingError", err) lastError = simpleError } else { log.V(2).Info("Not ready", "err", err) lastError = err } if time.Since(start) > o.Wait { return false, context.DeadlineExceeded } return false, nil } return true, nil }) if pollErr != nil { if errors.Is(pollErr, context.DeadlineExceeded) && o.Wait > 0 { log.V(2).Info("Timed out", "after", o.Wait, "err", pollErr) cmcmdutil.SetExitCode(pollErr) } else { cmcmdutil.SetExitCode(lastError) } return lastError } fmt.Fprintln(o.Out, "The cert-manager API is ready") return nil } 07070100000069000081A400000000000000000000000166DFF09D000004F5000000000000000000000000000000000000001F00000000cmctl-2.1.1/pkg/check/check.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package check import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/check/api" ) // NewCmdCheck returns a cobra command for checking cert-manager components. func NewCmdCheck(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { cmds := NewCmdCreateBare() cmds.AddCommand(api.NewCmdCheckApi(setupCtx, ioStreams)) return cmds } // NewCmdCreateBare returns bare cobra command for checking cert-manager components. func NewCmdCreateBare() *cobra.Command { return &cobra.Command{ Use: "check", Short: "Check cert-manager components", Long: `Check cert-manager components`, } } 0707010000006A000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001B00000000cmctl-2.1.1/pkg/completion0707010000006B000081A400000000000000000000000166DFF09D000005AA000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/completion/bash.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package completion import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/build" ) func newCmdCompletionBash(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { return &cobra.Command{ Use: "bash", Short: "Generate cert-manager CLI scripts for a Bash shell", Long: build.WithTemplate(setupCtx, `To load completions: Bash: $ source <({{.BuildName}} completion bash) # To load completions for each session, execute once: # Linux: $ {{.BuildName}} completion bash > /etc/bash_completion.d/{{.BuildName}} # macOS: $ {{.BuildName}} completion bash > /usr/local/etc/bash_completion.d/{{.BuildName}} `), DisableFlagsInUseLine: true, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Root().GenBashCompletion(ioStreams.Out) }, } } 0707010000006C000081A400000000000000000000000166DFF09D000005AB000000000000000000000000000000000000002900000000cmctl-2.1.1/pkg/completion/completion.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package completion import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/build" ) func NewCmdCompletion(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { cmds := &cobra.Command{ Use: "completion", Short: "Generate completion scripts for the cert-manager CLI", Long: "Generate completion for the cert-manager CLI so arguments and flags can be suggested and auto-completed", } if build.IsKubectlPlugin(setupCtx) { cmds.AddCommand(newCmdCompletionKubectl(setupCtx, ioStreams)) } else { cmds.AddCommand(newCmdCompletionBash(setupCtx, ioStreams)) cmds.AddCommand(newCmdCompletionZSH(setupCtx, ioStreams)) cmds.AddCommand(newCmdCompletionFish(setupCtx, ioStreams)) cmds.AddCommand(newCmdCompletionPowerShell(setupCtx, ioStreams)) } return cmds } 0707010000006D000081A400000000000000000000000166DFF09D00000547000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/completion/fish.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package completion import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/build" ) func newCmdCompletionFish(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { return &cobra.Command{ Use: "fish", Short: "Generate cert-manager CLI scripts for a Fish shell", Long: build.WithTemplate(setupCtx, `To load completions: $ {{.BuildName}} completion fish | source # To load completions for each session, execute once: $ {{.BuildName}} completion fish > ~/.config/fish/completions/{{.BuildName}}.fish `), DisableFlagsInUseLine: true, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Root().GenFishCompletion(ioStreams.Out, true) }, } } 0707010000006E000081A400000000000000000000000166DFF09D0000054A000000000000000000000000000000000000002600000000cmctl-2.1.1/pkg/completion/kubectl.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package completion import ( "context" "fmt" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/build" ) func newCmdCompletionKubectl(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { return &cobra.Command{ Use: "kubectl", Short: "Generate cert-manager CLI scripts for Kubectl", Long: build.WithTemplate(setupCtx, `To load completions: $ {{.BuildName}} completion kubectl > kubectl_complete-cert_manager $ sudo install kubectl_complete-cert_manager /usr/local/bin `), DisableFlagsInUseLine: true, RunE: func(cmd *cobra.Command, args []string) error { _, err := fmt.Fprint(ioStreams.Out, `#!/usr/bin/env sh kubectl cert-manager __complete "$@" `) return err }, } } 0707010000006F000081A400000000000000000000000166DFF09D00000598000000000000000000000000000000000000002900000000cmctl-2.1.1/pkg/completion/powershell.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package completion import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/build" ) func newCmdCompletionPowerShell(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { return &cobra.Command{ Use: "powershell", Short: "Generate cert-manager CLI scripts for a PowerShell shell", Long: build.WithTemplate(setupCtx, `To load completions: PS> {{.BuildName}} completion powershell | Out-String | Invoke-Expression # To load completions for every new session, run: PS> {{.BuildName}} completion powershell > {{.BuildName}}.ps1 # and source this file from your PowerShell profile. `), DisableFlagsInUseLine: true, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Root().GenPowerShellCompletion(ioStreams.Out) }, } } 07070100000070000081A400000000000000000000000166DFF09D00000606000000000000000000000000000000000000002200000000cmctl-2.1.1/pkg/completion/zsh.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package completion import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/build" ) func newCmdCompletionZSH(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { return &cobra.Command{ Use: "zsh", Short: "Generation cert-manager CLI scripts for a ZSH shell", Long: build.WithTemplate(setupCtx, `To load completions: # If shell completion is not already enabled in your environment, # you will need to enable it. You can execute the following once: $ echo "autoload -U compinit; compinit" >> ~/.zshrc # To load completions for each session, execute once: $ {{.BuildName}} completion zsh > "${fpath[1]}/_{{.BuildName}}" # You will need to start a new shell for this setup to take effect. `), DisableFlagsInUseLine: true, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Root().GenZshCompletion(ioStreams.Out) }, } } 07070100000071000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001800000000cmctl-2.1.1/pkg/convert07070100000072000081A400000000000000000000000166DFF09D00002106000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/convert/convert.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package convert import ( "context" "fmt" "github.com/cert-manager/cert-manager/pkg/ctl" logf "github.com/cert-manager/cert-manager/pkg/logs" "github.com/spf13/cobra" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" apijson "k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/printers" "k8s.io/cli-runtime/pkg/resource" cmdutil "k8s.io/kubectl/pkg/cmd/util" "k8s.io/kubectl/pkg/util/templates" "github.com/cert-manager/cmctl/v2/pkg/build" ) var ( // Use this scheme as it has the internal cert-manager types // and their conversion functions registered. scheme = ctl.Scheme ) // Options is a struct to support convert command type Options struct { PrintFlags *genericclioptions.PrintFlags Printer printers.ResourcePrinter OutputVersion string resource.FilenameOptions genericclioptions.IOStreams } // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, PrintFlags: genericclioptions.NewPrintFlags("converted").WithDefaultOutput("yaml"), } } // NewCmdConvert returns a cobra command for converting cert-manager resources func NewCmdConvert(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "convert", Short: "Convert cert-manager config files between different API versions", Long: templates.LongDesc(` Convert cert-manager config files between different API versions. Both YAML and JSON formats are accepted. The command takes filename, directory, or URL as input, and converts into the format of the version specified by --output-version flag. If target version is not specified or not supported, it will convert to the latest version The default output will be printed to stdout in YAML format. One can use -o option to change to output destination.`), Example: templates.Examples(build.WithTemplate(setupCtx, ` # Convert 'cert.yaml' to latest version and print to stdout. {{.BuildName}} convert -f cert.yaml # Convert kustomize overlay under current directory to 'cert-manager.io/v1alpha3' {{.BuildName}} convert -k . --output-version cert-manager.io/v1alpha3`)), DisableFlagsInUseLine: true, PreRunE: func(cmd *cobra.Command, args []string) error { return o.Complete() }, RunE: func(cmd *cobra.Command, args []string) error { return o.Run() }, } cmd.Flags().StringVar(&o.OutputVersion, "output-version", o.OutputVersion, "Output the formatted object with the given group version (for ex: 'cert-manager.io/v1alpha3').") cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "Path to a file containing cert-manager resources to be converted.") o.PrintFlags.AddFlags(cmd) return cmd } // Complete collects information required to run Convert command from command line. func (o *Options) Complete() error { err := o.FilenameOptions.RequireFilenameOrKustomize() if err != nil { return err } // build the printer o.Printer, err = o.PrintFlags.ToPrinter() if err != nil { return err } return nil } // Run executes convert command func (o *Options) Run() error { builder := new(resource.Builder) r := builder. WithScheme(scheme). LocalParam(true).FilenameParam(false, &o.FilenameOptions).Flatten().Do() if err := r.Err(); err != nil { return err } singleItemImplied := false infos, err := r.IntoSingleItemImplied(&singleItemImplied).Infos() if err != nil { return err } if len(infos) == 0 { return fmt.Errorf("no objects passed to convert") } var specifiedOutputVersion schema.GroupVersion if len(o.OutputVersion) > 0 { specifiedOutputVersion, err = schema.ParseGroupVersion(o.OutputVersion) if err != nil { return err } } factory := serializer.NewCodecFactory(scheme) serializer := apijson.NewSerializerWithOptions(apijson.DefaultMetaFactory, scheme, scheme, apijson.SerializerOptions{}) encoder := factory.WithoutConversion().EncoderForVersion(serializer, nil) objects, err := asVersionedObject(infos, !singleItemImplied, specifiedOutputVersion, encoder) if err != nil { return err } return o.Printer.PrintObj(objects, o.Out) } // asVersionedObject converts a list of infos into a single object - either a List containing // the objects as children, or if only a single Object is present, as that object. The provided // version will be preferred as the conversion target, but the Object's mapping version will be // used if that version is not present. func asVersionedObject(infos []*resource.Info, forceList bool, specifiedOutputVersion schema.GroupVersion, encoder runtime.Encoder) (runtime.Object, error) { objects, err := asVersionedObjects(infos, specifiedOutputVersion, encoder) if err != nil { return nil, err } var object runtime.Object if len(objects) == 1 && !forceList { object = objects[0] } else { object = &metainternalversion.List{Items: objects} targetVersions := []schema.GroupVersion{} if !specifiedOutputVersion.Empty() { targetVersions = append(targetVersions, specifiedOutputVersion) } // This is needed so we are able to handle the List object when converting // multiple resources targetVersions = append(targetVersions, schema.GroupVersion{Group: "", Version: "v1"}) converted, err := tryConvert(object, targetVersions...) if err != nil { return nil, err } object = converted } actualVersion := object.GetObjectKind().GroupVersionKind() if actualVersion.Version != specifiedOutputVersion.Version { defaultVersionInfo := "" if len(actualVersion.Version) > 0 { defaultVersionInfo = fmt.Sprintf("Defaulting to %q", actualVersion.Version) } logf.V(logf.WarnLevel).Infof("info: the output version specified is invalid. %s\n", defaultVersionInfo) } return object, nil } // asVersionedObjects converts a list of infos into versioned objects. The provided // version will be preferred as the conversion target, but the Object's mapping version will be // used if that version is not present. func asVersionedObjects(infos []*resource.Info, specifiedOutputVersion schema.GroupVersion, encoder runtime.Encoder) ([]runtime.Object, error) { objects := []runtime.Object{} for _, info := range infos { if info.Object == nil { continue } targetVersions := []schema.GroupVersion{} // objects that are not part of api.Scheme must be converted to JSON if !specifiedOutputVersion.Empty() { _, _, err := scheme.ObjectKinds(info.Object) if err != nil { if runtime.IsNotRegisteredError(err) { data, err := runtime.Encode(encoder, info.Object) if err != nil { return nil, err } objects = append(objects, &runtime.Unknown{Raw: data}) continue } return nil, err } targetVersions = append(targetVersions, specifiedOutputVersion) } else { gvks, _, err := scheme.ObjectKinds(info.Object) if err == nil { for _, gvk := range gvks { targetVersions = append(targetVersions, scheme.PrioritizedVersionsForGroup(gvk.Group)...) } } } converted, err := tryConvert(info.Object, targetVersions...) if err != nil { return nil, err } objects = append(objects, converted) } return objects, nil } // tryConvert attempts to convert the given object to the provided versions in order. This function assumes // the object is in internal version. func tryConvert(object runtime.Object, versions ...schema.GroupVersion) (runtime.Object, error) { var last error for _, version := range versions { if version.Empty() { return object, nil } obj, err := scheme.ConvertToVersion(object, version) if err != nil { last = err continue } return obj, nil } return nil, last } 07070100000073000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001700000000cmctl-2.1.1/pkg/create07070100000074000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002A00000000cmctl-2.1.1/pkg/create/certificaterequest07070100000075000081A400000000000000000000000166DFF09D000031A2000000000000000000000000000000000000004000000000cmctl-2.1.1/pkg/create/certificaterequest/certificaterequest.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package certificaterequest import ( "context" "encoding/pem" "errors" "fmt" "os" "time" apiutil "github.com/cert-manager/cert-manager/pkg/api/util" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" "github.com/cert-manager/cert-manager/pkg/ctl" "github.com/cert-manager/cert-manager/pkg/util/pki" "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/resource" "k8s.io/kubectl/pkg/util/templates" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/factory" ) var ( // Dedicated scheme used by the ctl tool that has the internal cert-manager types, // and their conversion functions registered scheme = ctl.Scheme ) // Options is a struct to support create certificaterequest command type Options struct { // Name of file that the generated private key will be stored in // If not specified, the private key will be written to <NameOfCR>.key KeyFilename string // If true, will wait for CertificateRequest to be ready to store the x509 certificate in a file // Command will block until CertificateRequest is ready or timeout as specified by Timeout happens FetchCert bool // Name of file that the generated x509 certificate will be stored in if --fetch-certificate flag is set // If not specified, the private key will be written to <NameOfCR>.crt CertFileName string // Path to a file containing a Certificate resource used as a template // when generating the CertificateRequest resource // Required InputFilename string // Length of time the command blocks to wait on CertificateRequest to be ready if --fetch-certificate flag is set // If not specified, default value is 5 minutes Timeout time.Duration genericclioptions.IOStreams *factory.Factory } // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } // NewCmdCreateCR returns a cobra command for create CertificateRequest func NewCmdCreateCR(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "certificaterequest", Aliases: []string{"cr"}, Short: "Create a cert-manager CertificateRequest resource, using a Certificate resource as a template", Long: templates.LongDesc(` Create a new CertificateRequest resource based on a Certificate resource, by generating a private key locally and create a 'certificate signing request' to be submitted to a cert-manager Issuer.`), Example: templates.Examples(build.WithTemplate(setupCtx, ` # Create a CertificateRequest with the name 'my-cr', saving the private key in a file named 'my-cr.key'. {{.BuildName}} create certificaterequest my-cr --from-certificate-file my-certificate.yaml # Create a CertificateRequest in namespace default, provided no conflict with namespace defined in file. {{.BuildName}} create certificaterequest my-cr --namespace default --from-certificate-file my-certificate.yaml # Create a CertificateRequest and store private key in file 'new.key'. {{.BuildName}} create certificaterequest my-cr --from-certificate-file my-certificate.yaml --output-key-file new.key # Create a CertificateRequest, wait for it to be signed for up to 5 minutes (default) and store the x509 certificate in file 'new.crt'. {{.BuildName}} create certificaterequest my-cr --from-certificate-file my-certificate.yaml --fetch-certificate --output-cert-file new.crt # Create a CertificateRequest, wait for it to be signed for up to 20 minutes and store the x509 certificate in file 'my-cr.crt'. {{.BuildName}} create certificaterequest my-cr --from-certificate-file my-certificate.yaml --fetch-certificate --timeout 20m `)), ValidArgsFunction: factory.ValidArgsListCertificateRequests(&o.Factory), PreRunE: func(cmd *cobra.Command, args []string) error { return o.Validate(args) }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context(), args) }, } cmd.Flags().StringVar(&o.InputFilename, "from-certificate-file", o.InputFilename, "Path to a file containing a Certificate resource used as a template when generating the CertificateRequest resource") cmd.Flags().StringVar(&o.KeyFilename, "output-key-file", o.KeyFilename, "Name of file that the generated private key will be written to") cmd.Flags().StringVar(&o.CertFileName, "output-certificate-file", o.CertFileName, "Name of the file the certificate is to be stored in") cmd.Flags().BoolVar(&o.FetchCert, "fetch-certificate", o.FetchCert, "If set to true, command will wait for CertificateRequest to be signed to store x509 certificate in a file") cmd.Flags().DurationVar(&o.Timeout, "timeout", 5*time.Minute, "Time before timeout when waiting for CertificateRequest to be signed, must include unit, e.g. 10m or 1h") o.Factory = factory.New(cmd) return cmd } // Validate validates the provided options func (o *Options) Validate(args []string) error { if len(args) < 1 { return errors.New("the name of the CertificateRequest to be created has to be provided as argument") } if len(args) > 1 { return errors.New("only one argument can be passed in: the name of the CertificateRequest") } if o.InputFilename == "" { return errors.New("the path to a YAML manifest of a Certificate resource cannot be empty, please specify by using --from-certificate-file flag") } if o.KeyFilename != "" && o.CertFileName != "" && o.KeyFilename == o.CertFileName { return errors.New("the file to store private key cannot be the same as the file to store certificate") } if !o.FetchCert && o.CertFileName != "" { return errors.New("cannot specify file to store certificate if not waiting for and fetching certificate, please set --fetch-certificate flag") } return nil } // Run executes create certificaterequest command func (o *Options) Run(ctx context.Context, args []string) error { builder := new(resource.Builder) // Read file as internal API version r := builder. WithScheme(scheme, schema.GroupVersion{Group: cmapi.SchemeGroupVersion.Group, Version: runtime.APIVersionInternal}). LocalParam(true).ContinueOnError(). NamespaceParam(o.Namespace).DefaultNamespace(). FilenameParam(o.EnforceNamespace, &resource.FilenameOptions{Filenames: []string{o.InputFilename}}).Flatten().Do() if err := r.Err(); err != nil { return err } singleItemImplied := false infos, err := r.IntoSingleItemImplied(&singleItemImplied).Infos() if err != nil { return err } // Ensure only one object per command if len(infos) == 0 { return fmt.Errorf("no objects found in manifest file %q. Expected one Certificate object", o.InputFilename) } if len(infos) > 1 { return fmt.Errorf("multiple objects found in manifest file %q. Expected only one Certificate object", o.InputFilename) } info := infos[0] // Convert to v1 because that version is needed for functions that follow crtObj, err := scheme.ConvertToVersion(info.Object, cmapi.SchemeGroupVersion) if err != nil { return fmt.Errorf("failed to convert object into version v1: %w", err) } // Cast Object into Certificate crt, ok := crtObj.(*cmapi.Certificate) if !ok { return errors.New("decoded object is not a v1 Certificate") } crt = crt.DeepCopy() if crt.Spec.PrivateKey == nil { crt.Spec.PrivateKey = &cmapi.CertificatePrivateKey{} } signer, err := pki.GeneratePrivateKeyForCertificate(crt) if err != nil { return fmt.Errorf("error when generating new private key for CertificateRequest: %w", err) } keyData, err := pki.EncodePrivateKey(signer, crt.Spec.PrivateKey.Encoding) if err != nil { return fmt.Errorf("failed to encode new private key for CertificateRequest: %w", err) } crName := args[0] // Storing private key to file keyFileName := crName + ".key" if o.KeyFilename != "" { keyFileName = o.KeyFilename } if err := os.WriteFile(keyFileName, keyData, 0600); err != nil { return fmt.Errorf("error when writing private key to file: %w", err) } fmt.Fprintf(o.ErrOut, "Private key written to file %s\n", keyFileName) // Build CertificateRequest with name as specified by argument req, err := buildCertificateRequest(crt, keyData, crName) if err != nil { return fmt.Errorf("error when building CertificateRequest: %w", err) } ns := crt.Namespace if ns == "" { ns = o.Namespace } req, err = o.CMClient.CertmanagerV1().CertificateRequests(ns).Create(ctx, req, metav1.CreateOptions{}) if err != nil { return fmt.Errorf("error creating CertificateRequest: %w", err) } fmt.Fprintf(o.ErrOut, "CertificateRequest %s has been created in namespace %s\n", req.Name, req.Namespace) if o.FetchCert { fmt.Fprintf(o.ErrOut, "CertificateRequest %v in namespace %v has not been signed yet. Wait until it is signed...\n", req.Name, req.Namespace) err = wait.PollUntilContextTimeout(ctx, time.Second, o.Timeout, false, func(ctx context.Context) (done bool, err error) { req, err = o.CMClient.CertmanagerV1().CertificateRequests(req.Namespace).Get(ctx, req.Name, metav1.GetOptions{}) if err != nil { return false, nil // nolint: nilerr // Retry and keep polling until context is cancelled } return apiutil.CertificateRequestHasCondition(req, cmapi.CertificateRequestCondition{ Type: cmapi.CertificateRequestConditionReady, Status: cmmeta.ConditionTrue, }) && len(req.Status.Certificate) > 0, nil }) if err != nil { return fmt.Errorf("error when waiting for CertificateRequest to be signed: %w", err) } fmt.Fprintf(o.ErrOut, "CertificateRequest %v in namespace %v has been signed\n", req.Name, req.Namespace) // Fetch x509 certificate and store to file actualCertFileName := req.Name + ".crt" if o.CertFileName != "" { actualCertFileName = o.CertFileName } err = fetchCertificateFromCR(req, actualCertFileName) if err != nil { return fmt.Errorf("error when writing certificate to file: %w", err) } fmt.Fprintf(o.ErrOut, "Certificate written to file %s\n", actualCertFileName) } return nil } // Builds a CertificateRequest func buildCertificateRequest(crt *cmapi.Certificate, pk []byte, crName string) (*cmapi.CertificateRequest, error) { csrPEM, err := generateCSR(crt, pk) if err != nil { return nil, err } cr := &cmapi.CertificateRequest{ ObjectMeta: metav1.ObjectMeta{ Name: crName, Annotations: crt.Annotations, Labels: crt.Labels, }, Spec: cmapi.CertificateRequestSpec{ Request: csrPEM, Duration: crt.Spec.Duration, IssuerRef: crt.Spec.IssuerRef, IsCA: crt.Spec.IsCA, Usages: crt.Spec.Usages, }, } return cr, nil } func generateCSR(crt *cmapi.Certificate, pk []byte) ([]byte, error) { csr, err := pki.GenerateCSR(crt) if err != nil { return nil, err } signer, err := pki.DecodePrivateKeyBytes(pk) if err != nil { return nil, err } csrDER, err := pki.EncodeCSR(csr, signer) if err != nil { return nil, err } csrPEM := pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE REQUEST", Bytes: csrDER, }) return csrPEM, nil } // fetchCertificateFromCR fetches the x509 certificate from a CR and stores the // certificate in file specified by certFilename. Assumes CR is ready, // otherwise returns error. func fetchCertificateFromCR(req *cmapi.CertificateRequest, certFileName string) error { // If CR not ready yet, error if !apiutil.CertificateRequestHasCondition(req, cmapi.CertificateRequestCondition{ Type: cmapi.CertificateRequestConditionReady, Status: cmmeta.ConditionTrue, }) || len(req.Status.Certificate) == 0 { return errors.New("CertificateRequest is not ready yet, unable to fetch certificate") } // Store certificate to file err := os.WriteFile(certFileName, req.Status.Certificate, 0600) if err != nil { return fmt.Errorf("error when writing certificate to file: %w", err) } return nil } 07070100000076000081A400000000000000000000000166DFF09D00001AFE000000000000000000000000000000000000004500000000cmctl-2.1.1/pkg/create/certificaterequest/certificaterequest_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package certificaterequest import ( "context" "os" "testing" "github.com/cert-manager/cmctl/v2/pkg/factory" ) func TestValidate(t *testing.T) { tests := map[string]struct { inputFile string inputArgs []string keyFilename string certFilename string fetchCert bool expErr bool expErrMsg string }{ "CR name not passed as arg throws error": { inputFile: "example.yaml", inputArgs: []string{}, expErr: true, expErrMsg: "the name of the CertificateRequest to be created has to be provided as argument", }, "More than one arg throws error": { inputFile: "example.yaml", inputArgs: []string{"hello", "World"}, expErr: true, expErrMsg: "only one argument can be passed in: the name of the CertificateRequest", }, "not specifying path to yaml manifest throws error": { inputFile: "", inputArgs: []string{"hello"}, expErr: true, expErrMsg: "the path to a YAML manifest of a Certificate resource cannot be empty, please specify by using --from-certificate-file flag", }, "key filename and cert filename are optional flags": { inputFile: "example.yaml", inputArgs: []string{"hello"}, keyFilename: "", certFilename: "", expErr: false, }, "identical key filename and cert filename throws error": { inputFile: "example.yaml", inputArgs: []string{"hello"}, keyFilename: "same", certFilename: "same", expErr: true, expErrMsg: "the file to store private key cannot be the same as the file to store certificate", }, "cannot specify cert filename without fetch-certificate flag": { inputFile: "example.yaml", inputArgs: []string{"hello"}, certFilename: "cert.crt", fetchCert: false, expErr: true, expErrMsg: "cannot specify file to store certificate if not waiting for and fetching certificate, please set --fetch-certificate flag", }, } for name, test := range tests { t.Run(name, func(t *testing.T) { opts := &Options{ InputFilename: test.inputFile, KeyFilename: test.keyFilename, CertFileName: test.certFilename, FetchCert: test.fetchCert, } // Validating args and flags err := opts.Validate(test.inputArgs) if err != nil { if !test.expErr { t.Fatalf("got unexpected error when validating args and flags: %v", err) } if err.Error() != test.expErrMsg { t.Fatalf("got unexpected error when validating args and flags, expected: %v; actual: %v", test.expErrMsg, err) } } else if test.expErr { // got no error t.Errorf("expected but got no error validating args and flags") } }) } } // Test Run tests the Run function's error behaviour up where it fails before interacting with // other components, e.g. writing private key to file. func TestRun(t *testing.T) { const ( crName = "testcr-3" ns1 = "testns-1" ns2 = "testns-2" ) tests := map[string]struct { inputFileContent string inputArgs []string inputNamespace string keyFilename string certFilename string fetchCert bool expErr bool expErrMsg string }{ // Build clients "conflicting namespaces defined in flag and file": { inputFileContent: `--- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: testcert-1 namespace: testns-1 spec: isCA: true secretName: ca-key-pair commonName: my-csi-app issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io `, inputArgs: []string{crName}, inputNamespace: ns2, keyFilename: "", expErr: true, expErrMsg: "the namespace from the provided object \"testns-1\" does not match the namespace \"testns-2\". You must pass '--namespace=testns-1' to perform this operation.", }, "file passed in defines resource other than certificate": { inputFileContent: `--- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: ca-issuer namespace: testns-1 spec: ca: secretName: ca-key-pair `, inputArgs: []string{crName}, inputNamespace: ns1, keyFilename: "", expErr: true, expErrMsg: "decoded object is not a v1 Certificate", }, "empty manifest file throws error": { inputFileContent: ``, inputArgs: []string{crName}, inputNamespace: ns1, keyFilename: "", expErr: true, expErrMsg: "no objects found in manifest file \"testfile.yaml\". Expected one Certificate object", }, "manifest file with multiple objects throws error": { inputFileContent: `--- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: ca-issuer namespace: testns-1 spec: ca: secretName: ca-key-pair --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: testcert-1 namespace: testns-1 spec: isCA: true secretName: ca-key-pair commonName: my-csi-app issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io`, inputArgs: []string{crName}, inputNamespace: ns1, keyFilename: "", expErr: true, expErrMsg: "multiple objects found in manifest file \"testfile.yaml\". Expected only one Certificate object", }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if err := os.WriteFile("testfile.yaml", []byte(test.inputFileContent), 0600); err != nil { t.Fatalf("error creating test file %#v", err) } defer os.Remove("testfile.yaml") // Options to run create CR command opts := &Options{ InputFilename: "testfile.yaml", KeyFilename: test.keyFilename, CertFileName: test.certFilename, Factory: &factory.Factory{ Namespace: test.inputNamespace, EnforceNamespace: test.inputNamespace != "", }, } // Validating args and flags err := opts.Validate(test.inputArgs) if err != nil { t.Fatal(err) } // Create CR err = opts.Run(context.TODO(), test.inputArgs) if err != nil { if !test.expErr { t.Fatalf("got unexpected error when trying to create CR: %v", err) } if err.Error() != test.expErrMsg { t.Fatalf("got unexpected error when trying to create CR, expected: %v; actual: %v", test.expErrMsg, err) } } else if test.expErr { // got no error t.Errorf("expected but got no error when creating CR") } }) } } 07070100000077000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003100000000cmctl-2.1.1/pkg/create/certificatesigningrequest07070100000078000081A400000000000000000000000166DFF09D00003A84000000000000000000000000000000000000004E00000000cmctl-2.1.1/pkg/create/certificatesigningrequest/certificatesigningrequest.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package certificatesigningrequest import ( "context" "encoding/pem" "errors" "fmt" "os" "strconv" "time" apiutil "github.com/cert-manager/cert-manager/pkg/api/util" "github.com/cert-manager/cert-manager/pkg/apis/certmanager" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" experimentalapi "github.com/cert-manager/cert-manager/pkg/apis/experimental/v1alpha1" "github.com/cert-manager/cert-manager/pkg/ctl" "github.com/cert-manager/cert-manager/pkg/util/pki" "github.com/spf13/cobra" certificatesv1 "k8s.io/api/certificates/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/resource" "k8s.io/client-go/discovery" "k8s.io/kubectl/pkg/util/templates" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/factory" ) var ( // Dedicated scheme used by the ctl tool that has the internal cert-manager types, // and their conversion functions registered scheme = ctl.Scheme ) // Options is a struct to support create certificatesigningrequest command type Options struct { // Name of file that the generated private key will be stored in If not // specified, the private key will be written to '<NameOfCSR>.key'. KeyFilename string // If true, will wait for CertificateSigingRequest to be ready to store the // x509 certificate in a file. // Command will block until CertificateSigningRequest is ready or timeout as // specified by Timeout happens. FetchCert bool // Name of file that the generated x509 certificate will be stored in if // --fetch-certificate flag is set If not specified, the private key will be // written to '<NameOfCSR>.crt'. CertFileName string // Path to a file containing a Certificate resource used as a template when // generating the CertificateSigningRequest resource. // Required. InputFilename string // Length of time the command blocks to wait on CertificateSigningRequest to // be ready if --fetch-certificate flag is set If not specified, default // value is 5 minutes. Timeout time.Duration genericclioptions.IOStreams *factory.Factory } // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } // NewCmdCreateCSR returns a cobra command for create CertificateSigningRequest func NewCmdCreateCSR(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "certificatesigningrequest", Aliases: []string{"csr"}, Short: "Create a Kubernetes CertificateSigningRequest resource, using a Certificate resource as a template", Long: templates.LongDesc(` Experimental. Only supported for Kubernetes versions 1.19+. Requires cert-manager versions 1.4+ with experimental controllers enabled. Create a new CertificateSigningRequest resource based on a Certificate resource, by generating a private key locally and create a 'certificate signing request' to be submitted to a cert-manager Issuer.`), Example: templates.Examples(build.WithTemplate(setupCtx, ` # Create a CertificateSigningRequest with the name 'my-csr', saving the private key in a file named 'my-cr.key'. {{.BuildName}} x create certificatesigningrequest my-csr --from-certificate-file my-certificate.yaml # Create a CertificateSigningRequest and store private key in file 'new.key'. {{.BuildName}} x create certificatesigningrequest my-csr --from-certificate-file my-certificate.yaml --output-key-file new.key # Create a CertificateSigningRequest, wait for it to be signed for up to 5 minutes (default) and store the x509 certificate in file 'new.crt'. {{.BuildName}} x create csr my-cr -f my-certificate.yaml -c new.crt -w # Create a CertificateSigningRequest, wait for it to be signed for up to 20 minutes and store the x509 certificate in file 'my-cr.crt'. {{.BuildName}} x create csr my-cr --from-certificate-file my-certificate.yaml --fetch-certificate --timeout 20m `)), ValidArgsFunction: factory.ValidArgsListCertificateSigningRequests(&o.Factory), PreRunE: func(cmd *cobra.Command, args []string) error { return o.Validate(args) }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context(), args) }, } cmd.Flags().StringVarP(&o.InputFilename, "from-certificate-file", "f", o.InputFilename, "Path to a file containing a Certificate resource used as a template when generating the CertificateSigningRequest resource") cmd.Flags().StringVarP(&o.KeyFilename, "output-key-file", "k", o.KeyFilename, "Name of file that the generated private key will be written to") cmd.Flags().StringVarP(&o.CertFileName, "output-certificate-file", "c", o.CertFileName, "Name of the file the certificate is to be stored in") cmd.Flags().BoolVarP(&o.FetchCert, "fetch-certificate", "w", o.FetchCert, "If set to true, command will wait for CertificateSigningRequest to be signed to store x509 certificate in a file") cmd.Flags().DurationVar(&o.Timeout, "timeout", 5*time.Minute, "Time before timeout when waiting for CertificateSigningRequest to be signed, must include unit, e.g. 10m or 1h") o.Factory = factory.New(cmd) return cmd } // Validate validates the provided options func (o *Options) Validate(args []string) error { if len(args) < 1 { return errors.New("the name of the CertificateSigningRequest to be created has to be provided as argument") } if len(args) > 1 { return errors.New("only one argument can be passed in: the name of the CertificateSigningRequest") } if o.InputFilename == "" { return errors.New("the path to a YAML manifest of a Certificate resource cannot be empty, please specify by using --from-certificate-file or -f flag") } if o.KeyFilename != "" && o.CertFileName != "" && o.KeyFilename == o.CertFileName { return errors.New("the file to store private key cannot be the same as the file to store certificate") } if !o.FetchCert && o.CertFileName != "" { return errors.New("cannot specify file to store certificate if not waiting for and fetching certificate, please set --fetch-certificate or -w flag") } return nil } // Run executes create certificatesigningrequest command func (o *Options) Run(ctx context.Context, args []string) error { builder := new(resource.Builder) // Read file as internal API version r := builder. WithScheme(scheme, schema.GroupVersion{Group: cmapi.SchemeGroupVersion.Group, Version: runtime.APIVersionInternal}). LocalParam(true).ContinueOnError(). FilenameParam(false, &resource.FilenameOptions{Filenames: []string{o.InputFilename}}).Flatten().Do() if err := r.Err(); err != nil { return err } singleItemImplied := false infos, err := r.IntoSingleItemImplied(&singleItemImplied).Infos() if err != nil { return err } // Ensure only one object per command if len(infos) == 0 { return fmt.Errorf("no objects found in manifest file %q. Expected one Certificate object", o.InputFilename) } if len(infos) > 1 { return fmt.Errorf("multiple objects found in manifest file %q. Expected only one Certificate object", o.InputFilename) } info := infos[0] // Convert to v1 because that version is needed for functions that follow crtObj, err := scheme.ConvertToVersion(info.Object, cmapi.SchemeGroupVersion) if err != nil { return fmt.Errorf("failed to convert object into version v1: %s", err) } // Cast Object into Certificate crt, ok := crtObj.(*cmapi.Certificate) if !ok { return errors.New("decoded object is not a v1 Certificate") } crt = crt.DeepCopy() if crt.Spec.PrivateKey == nil { crt.Spec.PrivateKey = &cmapi.CertificatePrivateKey{} } if len(crt.Namespace) == 0 { // Default to the 'default' Namespace if no Namespaced defined on the // Certificate crt.Namespace = "default" } signer, err := pki.GeneratePrivateKeyForCertificate(crt) if err != nil { return fmt.Errorf("error when generating new private key for CertificateSigningRequest: %s", err) } keyPEM, err := pki.EncodePrivateKey(signer, crt.Spec.PrivateKey.Encoding) if err != nil { return fmt.Errorf("failed to encode new private key for CertificateSigningRequest: %s", err) } csrName := args[0] // Storing private key to file keyFileName := csrName + ".key" if o.KeyFilename != "" { keyFileName = o.KeyFilename } if err := os.WriteFile(keyFileName, keyPEM, 0600); err != nil { return fmt.Errorf("error when writing private key to file: %s", err) } fmt.Fprintf(o.Out, "Private key written to file %s\n", keyFileName) signerName, err := buildSignerName(o.KubeClient.Discovery(), crt) if err != nil { return fmt.Errorf("failed to build signerName from Certificate: %s", err) } // Build CertificateSigningRequest with name as specified by argument req, err := buildCertificateSigningRequest(crt, keyPEM, csrName, signerName) if err != nil { return fmt.Errorf("error when building CertificateSigningRequest: %s", err) } req, err = o.KubeClient.CertificatesV1().CertificateSigningRequests().Create(ctx, req, metav1.CreateOptions{}) if err != nil { return fmt.Errorf("error creating CertificateSigningRequest: %s", err) } fmt.Fprintf(o.Out, "CertificateSigningRequest %s has been created\n", req.Name) if o.FetchCert { fmt.Fprintf(o.Out, "CertificateSigningRequest %s has not been signed yet. Wait until it is signed...\n", req.Name) err = wait.PollUntilContextTimeout(ctx, time.Second, o.Timeout, false, func(ctx context.Context) (done bool, err error) { req, err = o.KubeClient.CertificatesV1().CertificateSigningRequests().Get(ctx, req.Name, metav1.GetOptions{}) if err != nil { return false, err } return len(req.Status.Certificate) > 0, nil }) if err != nil { return fmt.Errorf("error when waiting for CertificateSigningRequest to be signed: %s", err) } fmt.Fprintf(o.Out, "CertificateSigningRequest %s has been signed\n", req.Name) // Fetch x509 certificate and store to file actualCertFileName := req.Name + ".crt" if o.CertFileName != "" { actualCertFileName = o.CertFileName } err = storeCertificate(req, actualCertFileName) if err != nil { return fmt.Errorf("error when writing certificate to file: %s", err) } fmt.Fprintf(o.Out, "Certificate written to file %s\n", actualCertFileName) } return nil } // buildSignerName with generate a Kubernetes CertificateSigningRequest signer // name, based on the input Certificate's IssuerRef. This function will use the // Discovery API to fetch the resource definition of the referenced Issuer // Kind. // The signer name format follows that of cert-manager. func buildSignerName(client discovery.DiscoveryInterface, crt *cmapi.Certificate) (string, error) { targetGroup := crt.Spec.IssuerRef.Group if len(targetGroup) == 0 { targetGroup = certmanager.GroupName } targetKind := crt.Spec.IssuerRef.Kind if len(targetKind) == 0 { targetKind = cmapi.IssuerKind } grouplist, err := client.ServerGroups() if err != nil { return "", err } for _, group := range grouplist.Groups { if group.Name != targetGroup { continue } for _, version := range group.Versions { resources, err := client.ServerResourcesForGroupVersion(version.GroupVersion) if err != nil { return "", err } for _, resource := range resources.APIResources { if resource.Kind != targetKind { continue } if resource.Namespaced { return fmt.Sprintf("%s.%s/%s.%s", resource.Name, targetGroup, crt.Namespace, crt.Spec.IssuerRef.Name), nil } return fmt.Sprintf("%s.%s/%s", resource.Name, targetGroup, crt.Spec.IssuerRef.Name), nil } } } return "", fmt.Errorf("issuer references a resource definition which does not exist group=%s kind=%s", targetGroup, targetKind) } // Builds a CertificateSigningRequest func buildCertificateSigningRequest(crt *cmapi.Certificate, pk []byte, crName, signerName string) (*certificatesv1.CertificateSigningRequest, error) { csrPEM, err := generateCSR(crt, pk) if err != nil { return nil, err } ku, eku, err := pki.KeyUsagesForCertificateOrCertificateRequest(crt.Spec.Usages, crt.Spec.IsCA) if err != nil { return nil, err } csr := &certificatesv1.CertificateSigningRequest{ ObjectMeta: metav1.ObjectMeta{ Name: crName, Annotations: crt.Annotations, Labels: crt.Labels, }, Spec: certificatesv1.CertificateSigningRequestSpec{ Request: csrPEM, SignerName: signerName, Usages: append(apiutil.KubeKeyUsageStrings(ku), apiutil.KubeExtKeyUsageStrings(eku)...), }, } if csr.Annotations == nil { csr.Annotations = make(map[string]string) } csr.Annotations[experimentalapi.CertificateSigningRequestIsCAAnnotationKey] = strconv.FormatBool(crt.Spec.IsCA) if crt.Spec.Duration != nil { duration := crt.Spec.Duration.Duration csr.Annotations[experimentalapi.CertificateSigningRequestDurationAnnotationKey] = duration.String() seconds := int32(duration.Seconds()) // technically this could overflow but I do not think it matters csr.Spec.ExpirationSeconds = &seconds // if this is less than 600, the API server will fail the request } return csr, nil } func generateCSR(crt *cmapi.Certificate, pk []byte) ([]byte, error) { csr, err := pki.GenerateCSR(crt) if err != nil { return nil, err } signer, err := pki.DecodePrivateKeyBytes(pk) if err != nil { return nil, err } csrDER, err := pki.EncodeCSR(csr, signer) if err != nil { return nil, err } csrPEM := pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE REQUEST", Bytes: csrDER, }) return csrPEM, nil } // storeCertificate fetches the x509 certificate from a // CertificateSigningRequest and stores the certificate in file specified by // certFilename. Assumes request is signed, otherwise returns error. func storeCertificate(req *certificatesv1.CertificateSigningRequest, fileName string) error { // If request not signed yet, error if len(req.Status.Certificate) == 0 { return errors.New("CertificateSigningRequest is not ready yet, unable to fetch certificate") } // Store certificate to file err := os.WriteFile(fileName, req.Status.Certificate, 0600) if err != nil { return fmt.Errorf("error when writing certificate to file: %s", err) } return nil } 07070100000079000081A400000000000000000000000166DFF09D00000C79000000000000000000000000000000000000005300000000cmctl-2.1.1/pkg/create/certificatesigningrequest/certificatesigningrequest_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package certificatesigningrequest import ( "testing" ) func Test_Validate(t *testing.T) { tests := map[string]struct { inputFile string inputArgs []string keyFilename string certFilename string fetchCert bool expErr bool expErrMsg string }{ "CSR name not passed as arg throws error": { inputFile: "example.yaml", inputArgs: []string{}, expErr: true, expErrMsg: "the name of the CertificateSigningRequest to be created has to be provided as argument", }, "More than one arg throws error": { inputFile: "example.yaml", inputArgs: []string{"hello", "World"}, expErr: true, expErrMsg: "only one argument can be passed in: the name of the CertificateSigningRequest", }, "not specifying path to yaml manifest throws error": { inputFile: "", inputArgs: []string{"hello"}, expErr: true, expErrMsg: "the path to a YAML manifest of a Certificate resource cannot be empty, please specify by using --from-certificate-file or -f flag", }, "key filename and cert filename are optional flags": { inputFile: "example.yaml", inputArgs: []string{"hello"}, keyFilename: "", certFilename: "", expErr: false, }, "identical key filename and cert filename throws error": { inputFile: "example.yaml", inputArgs: []string{"hello"}, keyFilename: "same", certFilename: "same", expErr: true, expErrMsg: "the file to store private key cannot be the same as the file to store certificate", }, "cannot specify cert filename without fetch-certificate flag": { inputFile: "example.yaml", inputArgs: []string{"hello"}, certFilename: "cert.crt", fetchCert: false, expErr: true, expErrMsg: "cannot specify file to store certificate if not waiting for and fetching certificate, please set --fetch-certificate or -w flag", }, } for name, test := range tests { t.Run(name, func(t *testing.T) { opts := &Options{ InputFilename: test.inputFile, KeyFilename: test.keyFilename, CertFileName: test.certFilename, FetchCert: test.fetchCert, } // Validating args and flags err := opts.Validate(test.inputArgs) if err != nil { if !test.expErr { t.Fatalf("got unexpected error when validating args and flags: %v", err) } if err.Error() != test.expErrMsg { t.Fatalf("got unexpected error when validating args and flags, expected: %v; actual: %v", test.expErrMsg, err) } } else if test.expErr { // got no error t.Errorf("expected but got no error validating args and flags") } }) } } 0707010000007A000081A400000000000000000000000166DFF09D000004DA000000000000000000000000000000000000002100000000cmctl-2.1.1/pkg/create/create.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package create import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/create/certificaterequest" ) func NewCmdCreate(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { cmds := NewCmdCreateBare() cmds.AddCommand(certificaterequest.NewCmdCreateCR(setupCtx, ioStreams)) return cmds } // NewCmdCreateBare creates a bare Create Command, without any subcommands func NewCmdCreateBare() *cobra.Command { return &cobra.Command{ Use: "create", Short: "Create cert-manager resources", Long: `Create cert-manager resources e.g. a CertificateRequest`, } } 0707010000007B000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001500000000cmctl-2.1.1/pkg/deny0707010000007C000081A400000000000000000000000166DFF09D00001110000000000000000000000000000000000000001D00000000cmctl-2.1.1/pkg/deny/deny.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package deny import ( "context" "errors" "fmt" apiutil "github.com/cert-manager/cert-manager/pkg/api/util" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/kubectl/pkg/util/templates" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/factory" ) // Options is a struct to support create certificaterequest command type Options struct { // Reason is the string that will be set on the Reason field of the Denied // condition. Reason string // Message is the string that will be set on the Message field of the // Denied condition. Message string genericclioptions.IOStreams *factory.Factory } // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } func NewCmdDeny(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "deny", Short: "Deny a CertificateRequest", Long: `Mark a CertificateRequest as Denied, so it may never be signed by a configured Issuer.`, Example: templates.Examples(build.WithTemplate(setupCtx, ` # Deny a CertificateRequest with the name 'my-cr' {{.BuildName}} deny my-cr # Deny a CertificateRequest in namespace default {{.BuildName}} deny my-cr --namespace default # Deny a CertificateRequest giving a custom reason and message {{.BuildName}} deny my-cr --reason "ManualDenial" --reason "Denied by PKI department" `)), ValidArgsFunction: factory.ValidArgsListCertificateRequests(&o.Factory), PreRunE: func(cmd *cobra.Command, args []string) error { return o.Validate(args) }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context(), args) }, } cmd.Flags().StringVar(&o.Reason, "reason", "KubectlCertManager", "The reason to give as to what denied this CertificateRequest.") cmd.Flags().StringVar(&o.Message, "message", fmt.Sprintf("manually denied by %q", build.Name(setupCtx)), "The message to give as to why this CertificateRequest was denied.") o.Factory = factory.New(cmd) return cmd } // Validate validates the provided options func (o *Options) Validate(args []string) error { if len(args) < 1 { return errors.New("the name of the CertificateRequest to deny has to be provided as an argument") } if len(args) > 1 { return errors.New("only one argument can be passed: the name of the CertificateRequest") } if len(o.Reason) == 0 { return errors.New("a reason must be given as to who denied this CertificateRequest") } if len(o.Message) == 0 { return errors.New("a message must be given as to why this CertificateRequest is denied") } return nil } // Run executes deny command func (o *Options) Run(ctx context.Context, args []string) error { cr, err := o.CMClient.CertmanagerV1().CertificateRequests(o.Namespace).Get(ctx, args[0], metav1.GetOptions{}) if err != nil { return err } if apiutil.CertificateRequestIsApproved(cr) { return errors.New("CertificateRequest is already approved") } if apiutil.CertificateRequestIsDenied(cr) { return errors.New("CertificateRequest is already denied") } apiutil.SetCertificateRequestCondition(cr, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, o.Reason, o.Message) _, err = o.CMClient.CertmanagerV1().CertificateRequests(o.Namespace).UpdateStatus(ctx, cr, metav1.UpdateOptions{}) if err != nil { return err } fmt.Fprintf(o.Out, "Denied CertificateRequest '%s/%s'\n", cr.Namespace, cr.Name) return nil } 0707010000007D000081A400000000000000000000000166DFF09D00000923000000000000000000000000000000000000002200000000cmctl-2.1.1/pkg/deny/deny_test.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package deny import ( "testing" ) func TestValidate(t *testing.T) { tests := map[string]struct { args []string reason, message string expErr bool expErrMsg string }{ "CR name not passed as arg throws error": { args: []string{}, reason: "", message: "", expErr: true, expErrMsg: "the name of the CertificateRequest to deny has to be provided as an argument", }, "multiple CR names passed as arg throws error": { args: []string{"cr-1", "cr-1"}, reason: "", message: "", expErr: true, expErrMsg: "only one argument can be passed: the name of the CertificateRequest", }, "empty reason given should throw error": { args: []string{"cr-1"}, reason: "", message: "", expErr: true, expErrMsg: "a reason must be given as to who denied this CertificateRequest", }, "empty message given should throw error": { args: []string{"cr-1"}, reason: "foo", message: "", expErr: true, expErrMsg: "a message must be given as to why this CertificateRequest is denied", }, "all fields populated should not error": { args: []string{"cr-1"}, reason: "foo", message: "bar", expErr: false, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { opts := &Options{ Reason: test.reason, Message: test.message, } // Validating args and flags err := opts.Validate(test.args) if (err != nil) != test.expErr { t.Errorf("unexpected error, exp=%t got=%v", test.expErr, err) } if err != nil && err.Error() != test.expErrMsg { t.Errorf("got unexpected error when validating args and flags, expected: %v; actual: %v", test.expErrMsg, err) } }) } } 0707010000007E000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001D00000000cmctl-2.1.1/pkg/experimental0707010000007F000081A400000000000000000000000166DFF09D000005C2000000000000000000000000000000000000002D00000000cmctl-2.1.1/pkg/experimental/experimental.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package experimental import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/create" "github.com/cert-manager/cmctl/v2/pkg/create/certificatesigningrequest" "github.com/cert-manager/cmctl/v2/pkg/install" "github.com/cert-manager/cmctl/v2/pkg/uninstall" ) func NewCmdExperimental(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { cmds := &cobra.Command{ Use: "experimental", Aliases: []string{"x"}, Short: "Interact with experimental features", Long: "Interact with experimental features", } create := create.NewCmdCreateBare() create.AddCommand(certificatesigningrequest.NewCmdCreateCSR(setupCtx, ioStreams)) cmds.AddCommand(create) cmds.AddCommand(install.NewCmdInstall(setupCtx, ioStreams)) cmds.AddCommand(uninstall.NewCmd(setupCtx, ioStreams)) return cmds } 07070100000080000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001800000000cmctl-2.1.1/pkg/factory07070100000081000081A400000000000000000000000166DFF09D00000E5B000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/factory/factory.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package factory import ( cmclient "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/kubectl/pkg/cmd/util" // Load all auth plugins _ "k8s.io/client-go/plugin/pkg/client/auth" ) // Factory provides a set of clients and configurations to authenticate and // access a target Kubernetes cluster. Factory will ensure that its fields are // populated and valid during command execution. type Factory struct { factory util.Factory // Namespace is the namespace that the user has requested with the // "--namespace" / "-n" flag. Defaults to "default" if the flag was not // provided. Namespace string // EnforceNamespace will be true if the user provided the namespace flag. EnforceNamespace bool // RESTConfig is a Kubernetes REST config that contains the user's // authentication and access configuration. RESTConfig *rest.Config // CMClient is a Kubernetes clientset for interacting with cert-manager APIs. CMClient cmclient.Interface // KubeClient is a Kubernetes clientset for interacting with the base // Kubernetes APIs. KubeClient kubernetes.Interface // RESTClientGetter is used to get RESTConfig, DiscoveryClients and // RESTMapper implementations RESTClientGetter genericclioptions.RESTClientGetter } // New returns a new Factory. The supplied command will have flags registered // for interacting with the Kubernetes access options. Factory will be // populated when the command is executed using the cobra PreRunE. If a PreRunE // is already defined, it will be executed _after_ Factory has been populated, // making it available. func New(cmd *cobra.Command) *Factory { f := new(Factory) kubeConfigFlags := genericclioptions.NewConfigFlags(true) f.factory = util.NewFactory(kubeConfigFlags) kubeConfigFlags.AddFlags(cmd.Flags()) if err := cmd.RegisterFlagCompletionFunc("namespace", validArgsListNamespaces(f)); err != nil { panic(err) } // Setup a PreRunE to populate the Factory. Catch the existing PreRunE command // if one was defined, and execute it second. // WARNING: Do not set PreRun on the command as cobra will not execute PreRun when // PreRunE is set. existingPreRunE := cmd.PreRunE cmd.PreRunE = func(cmd *cobra.Command, args []string) error { if err := f.complete(); err != nil { return err } if existingPreRunE != nil { return existingPreRunE(cmd, args) } return nil } return f } // complete will populate the Factory with values using the shared Kubernetes // CLI factory. func (f *Factory) complete() error { var err error f.Namespace, f.EnforceNamespace, err = f.factory.ToRawKubeConfigLoader().Namespace() if err != nil { return err } f.RESTConfig, err = f.factory.ToRESTConfig() if err != nil { return err } f.KubeClient, err = kubernetes.NewForConfig(f.RESTConfig) if err != nil { return err } f.CMClient, err = cmclient.NewForConfig(f.RESTConfig) if err != nil { return err } f.RESTClientGetter = f.factory return nil } 07070100000082000081A400000000000000000000000166DFF09D0000133C000000000000000000000000000000000000002500000000cmctl-2.1.1/pkg/factory/validargs.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package factory import ( "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // ValidArgsListCertificates returns a cobra ValidArgsFunction for listing Certificates. func ValidArgsListCertificates(factory **Factory) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) { if len(args) > 0 { return nil, cobra.ShellCompDirectiveNoFileComp } f := *factory if err := f.complete(); err != nil { return nil, cobra.ShellCompDirectiveNoFileComp } certList, err := f.CMClient.CertmanagerV1().Certificates(f.Namespace).List(cmd.Context(), metav1.ListOptions{}) if err != nil { return nil, cobra.ShellCompDirectiveError } var names []string for _, cert := range certList.Items { names = append(names, cert.Name) } return names, cobra.ShellCompDirectiveNoFileComp } } // ValidArgsListSecrets returns a cobra ValidArgsFunction for listing Secrets. func ValidArgsListSecrets(factory **Factory) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) { if len(args) > 0 { return nil, cobra.ShellCompDirectiveNoFileComp } f := *factory if err := f.complete(); err != nil { return nil, cobra.ShellCompDirectiveNoFileComp } secretsList, err := f.KubeClient.CoreV1().Secrets(f.Namespace).List(cmd.Context(), metav1.ListOptions{}) if err != nil { return nil, cobra.ShellCompDirectiveError } var names []string for _, secret := range secretsList.Items { names = append(names, secret.Name) } return names, cobra.ShellCompDirectiveNoFileComp } } // ValidArgsListCertificateSigningRequests returns a cobra ValidArgsFunction for // listing CertificateSigningRequests. func ValidArgsListCertificateSigningRequests(factory **Factory) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) { if len(args) > 0 { return nil, cobra.ShellCompDirectiveNoFileComp } f := *factory if err := f.complete(); err != nil { return nil, cobra.ShellCompDirectiveNoFileComp } csrList, err := f.KubeClient.CertificatesV1().CertificateSigningRequests().List(cmd.Context(), metav1.ListOptions{}) if err != nil { return nil, cobra.ShellCompDirectiveError } var names []string for _, csr := range csrList.Items { names = append(names, csr.Name) } return names, cobra.ShellCompDirectiveNoFileComp } } // ValidArgsListCertificateRequests returns a cobra ValidArgsFunction for listing // CertificateRequests. func ValidArgsListCertificateRequests(factory **Factory) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) { if len(args) > 0 { return nil, cobra.ShellCompDirectiveNoFileComp } f := *factory if err := f.complete(); err != nil { return nil, cobra.ShellCompDirectiveNoFileComp } crList, err := f.CMClient.CertmanagerV1().CertificateRequests(f.Namespace).List(cmd.Context(), metav1.ListOptions{}) if err != nil { return nil, cobra.ShellCompDirectiveError } var names []string for _, cr := range crList.Items { names = append(names, cr.Name) } return names, cobra.ShellCompDirectiveNoFileComp } } // validArgsListNamespaces returns a cobra ValidArgsFunction for listing // namespaces. func validArgsListNamespaces(factory *Factory) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) { if len(args) > 0 { return nil, cobra.ShellCompDirectiveNoFileComp } if err := factory.complete(); err != nil { return nil, cobra.ShellCompDirectiveNoFileComp } namespaceList, err := factory.KubeClient.CoreV1().Namespaces().List(cmd.Context(), metav1.ListOptions{}) if err != nil { return nil, cobra.ShellCompDirectiveError } var names []string for _, namespace := range namespaceList.Items { names = append(names, namespace.Name) } return names, cobra.ShellCompDirectiveNoFileComp } } 07070100000083000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001800000000cmctl-2.1.1/pkg/inspect07070100000084000081A400000000000000000000000166DFF09D0000044C000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/inspect/inspect.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package inspect import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/inspect/secret" ) func NewCmdInspect(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { cmds := &cobra.Command{ Use: "inspect", Short: "Get details on certificate related resources", Long: `Get details on certificate related resources, e.g. secrets`, } cmds.AddCommand(secret.NewCmdInspectSecret(setupCtx, ioStreams)) return cmds } 07070100000085000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001F00000000cmctl-2.1.1/pkg/inspect/secret07070100000086000081A400000000000000000000000166DFF09D00002BEA000000000000000000000000000000000000002900000000cmctl-2.1.1/pkg/inspect/secret/secret.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package secret import ( "bytes" "context" "crypto/x509" "errors" "fmt" "io" "net/url" "strings" "text/template" "time" apiutil "github.com/cert-manager/cert-manager/pkg/api/util" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" "github.com/cert-manager/cert-manager/pkg/util/pki" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/kubectl/pkg/util/templates" k8sclock "k8s.io/utils/clock" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/factory" ) var clock k8sclock.Clock = k8sclock.RealClock{} const validForTemplate = `Valid for: DNS Names: {{ .DNSNames }} URIs: {{ .URIs }} IP Addresses: {{ .IPAddresses }} Email Addresses: {{ .EmailAddresses }} Usages: {{ .KeyUsage }}` const validityPeriodTemplate = `Validity period: Not Before: {{ .NotBefore }} Not After: {{ .NotAfter }}` const issuedByTemplate = `Issued By: Common Name: {{ .CommonName }} Organization: {{ .Organization }} OrganizationalUnit: {{ .OrganizationalUnit }} Country: {{ .Country }}` const issuedForTemplate = `Issued For: Common Name: {{ .CommonName }} Organization: {{ .Organization }} OrganizationalUnit: {{ .OrganizationalUnit }} Country: {{ .Country }}` const certificateTemplate = `Certificate: Signing Algorithm: {{ .SigningAlgorithm }} Public Key Algorithm: {{ .PublicKeyAlgorithm }} Serial Number: {{ .SerialNumber }} Fingerprints: {{ .Fingerprints }} Is a CA certificate: {{ .IsCACertificate }} CRL: {{ .CRL }} OCSP: {{ .OCSP }}` const debuggingTemplate = `Debugging: Trusted by this computer: {{ .TrustedByThisComputer }} CRL Status: {{ .CRLStatus }} OCSP Status: {{ .OCSPStatus }}` // Options is a struct to support status certificate command type Options struct { genericclioptions.IOStreams *factory.Factory } // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } // NewCmdInspectSecret returns a cobra command for status certificate func NewCmdInspectSecret(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "secret", Short: "Get details about a kubernetes.io/tls typed secret", Long: templates.LongDesc(` Get details about a kubernetes.io/tls typed secret`), Example: templates.Examples(build.WithTemplate(setupCtx, ` # Query information about a secret with name 'my-crt' in namespace 'my-namespace' {{.BuildName}} inspect secret my-crt --namespace my-namespace `)), ValidArgsFunction: factory.ValidArgsListSecrets(&o.Factory), PreRunE: func(cmd *cobra.Command, args []string) error { return o.Validate(args) }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context(), args, ioStreams.Out) }, } o.Factory = factory.New(cmd) return cmd } // Validate validates the provided options func (o *Options) Validate(args []string) error { if len(args) < 1 { return errors.New("the name of the Secret has to be provided as argument") } if len(args) > 1 { return errors.New("only one argument can be passed in: the name of the Secret") } return nil } // Run executes status certificate command func (o *Options) Run(ctx context.Context, args []string, stdout io.Writer) error { secret, err := o.KubeClient.CoreV1().Secrets(o.Namespace).Get(ctx, args[0], metav1.GetOptions{}) if err != nil { return fmt.Errorf("error when finding Secret %q: %w\n", args[0], err) } certData := secret.Data[corev1.TLSCertKey] certs, err := splitPEMs(certData) if err != nil { return err } if len(certs) < 1 { return errors.New("no PEM data found in secret") } intermediates := [][]byte(nil) if len(certs) > 1 { intermediates = certs[1:] } // we only want to inspect the leaf certificate x509Cert, err := pki.DecodeX509CertificateBytes(certs[0]) if err != nil { return fmt.Errorf("error when parsing 'tls.crt': %w", err) } var out []string for _, describeFn := range []func(*x509.Certificate) (string, error){ describeValidFor, describeValidityPeriod, describeIssuedBy, describeIssuedFor, describeCertificate, } { desc, err := describeFn(x509Cert) if err != nil { return err } out = append(out, desc) } if desc, err := describeDebugging(ctx, x509Cert, intermediates, secret.Data[cmmeta.TLSCAKey]); err != nil { return err } else { out = append(out, desc) } fmt.Fprintln(stdout, strings.Join(out, "\n\n")) return nil } func describeValidFor(cert *x509.Certificate) (string, error) { tmpl, err := template.New("validForTemplate").Parse(validForTemplate) if err != nil { return "", err } var b bytes.Buffer err = tmpl.Execute(&b, struct { DNSNames string URIs string IPAddresses string EmailAddresses string KeyUsage string }{ DNSNames: printSlice(cert.DNSNames), URIs: printSlice(pki.URLsToString(cert.URIs)), IPAddresses: printSlice(pki.IPAddressesToString(cert.IPAddresses)), EmailAddresses: printSlice(cert.EmailAddresses), KeyUsage: printKeyUsage(buildCertManagerKeyUsages(cert.KeyUsage, cert.ExtKeyUsage)), }) return b.String(), err } func buildCertManagerKeyUsages(ku x509.KeyUsage, eku []x509.ExtKeyUsage) []cmapi.KeyUsage { var usages []cmapi.KeyUsage usages = append(usages, apiutil.KeyUsageStrings(ku)...) usages = append(usages, apiutil.ExtKeyUsageStrings(eku)...) return usages } func describeValidityPeriod(cert *x509.Certificate) (string, error) { tmpl, err := template.New("validityPeriodTemplate").Parse(validityPeriodTemplate) if err != nil { return "", err } var b bytes.Buffer err = tmpl.Execute(&b, struct { NotBefore string NotAfter string }{ NotBefore: cert.NotBefore.Format(time.RFC1123), NotAfter: cert.NotAfter.Format(time.RFC1123), }) return b.String(), err } func describeIssuedBy(cert *x509.Certificate) (string, error) { tmpl, err := template.New("issuedByTemplate").Parse(issuedByTemplate) if err != nil { return "", err } var b bytes.Buffer err = tmpl.Execute(&b, struct { CommonName string Organization string OrganizationalUnit string Country string }{ CommonName: printOrNone(cert.Issuer.CommonName), Organization: printSliceOrOne(cert.Issuer.Organization), OrganizationalUnit: printSliceOrOne(cert.Issuer.OrganizationalUnit), Country: printSliceOrOne(cert.Issuer.Country), }) return b.String(), err } func describeIssuedFor(cert *x509.Certificate) (string, error) { tmpl, err := template.New("issuedForTemplate").Parse(issuedForTemplate) if err != nil { return "", err } var b bytes.Buffer err = tmpl.Execute(&b, struct { CommonName string Organization string OrganizationalUnit string Country string }{ CommonName: printOrNone(cert.Subject.CommonName), Organization: printSliceOrOne(cert.Subject.Organization), OrganizationalUnit: printSliceOrOne(cert.Subject.OrganizationalUnit), Country: printSliceOrOne(cert.Subject.Country), }) return b.String(), err } func describeCertificate(cert *x509.Certificate) (string, error) { tmpl, err := template.New("certificateTemplate").Parse(certificateTemplate) if err != nil { return "", err } var b bytes.Buffer err = tmpl.Execute(&b, struct { SigningAlgorithm string PublicKeyAlgorithm string SerialNumber string Fingerprints string IsCACertificate bool CRL string OCSP string }{ SigningAlgorithm: cert.SignatureAlgorithm.String(), PublicKeyAlgorithm: cert.PublicKeyAlgorithm.String(), SerialNumber: cert.SerialNumber.String(), Fingerprints: fingerprintCert(cert), IsCACertificate: cert.IsCA, CRL: printSliceOrOne(cert.CRLDistributionPoints), OCSP: printSliceOrOne(cert.OCSPServer), }) return b.String(), err } func describeDebugging(ctx context.Context, cert *x509.Certificate, intermediates [][]byte, ca []byte) (string, error) { tmpl, err := template.New("debuggingTemplate").Parse(debuggingTemplate) if err != nil { return "", err } var b bytes.Buffer err = tmpl.Execute(&b, struct { TrustedByThisComputer string CRLStatus string OCSPStatus string }{ TrustedByThisComputer: describeTrusted(cert, intermediates), CRLStatus: describeCRL(ctx, cert), OCSPStatus: describeOCSP(ctx, cert, intermediates, ca), }) return b.String(), err } func describeCRL(ctx context.Context, cert *x509.Certificate) string { if len(cert.CRLDistributionPoints) < 1 { return "No CRL endpoints set" } hasChecked := false for _, crlURL := range cert.CRLDistributionPoints { u, err := url.Parse(crlURL) if err != nil { return fmt.Sprintf("Invalid CRL URL: %v", err) } if u.Scheme != "ldap" && u.Scheme != "https" { continue } hasChecked = true valid, err := checkCRLValidCert(ctx, cert, crlURL) if err != nil { return fmt.Sprintf("Cannot check CRL: %s", err.Error()) } if !valid { return fmt.Sprintf("Revoked by %s", crlURL) } } if !hasChecked { return "No CRL endpoints we support found" } return "Valid" } func describeOCSP(ctx context.Context, cert *x509.Certificate, intermediates [][]byte, ca []byte) string { if len(ca) > 1 { intermediates = append([][]byte{ca}, intermediates...) } if len(intermediates) < 1 { return "Cannot check OCSP, does not have a CA or intermediate certificate provided" } issuerCert, err := pki.DecodeX509CertificateBytes(intermediates[len(intermediates)-1]) if err != nil { return fmt.Sprintf("Cannot parse intermediate certificate: %s", err.Error()) } valid, err := checkOCSPValidCert(ctx, cert, issuerCert) if err != nil { return fmt.Sprintf("Cannot check OCSP: %s", err.Error()) } if !valid { return "Marked as revoked" } return "valid" } func describeTrusted(cert *x509.Certificate, intermediates [][]byte) string { systemPool, err := x509.SystemCertPool() if err != nil { return fmt.Sprintf("Error getting system CA store: %s", err.Error()) } for _, intermediate := range intermediates { systemPool.AppendCertsFromPEM(intermediate) } _, err = cert.Verify(x509.VerifyOptions{ Roots: systemPool, CurrentTime: clock.Now(), }) if err == nil { return "yes" } return fmt.Sprintf("no: %s", err.Error()) } 07070100000087000081A400000000000000000000000166DFF09D000029B8000000000000000000000000000000000000002E00000000cmctl-2.1.1/pkg/inspect/secret/secret_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package secret import ( "context" "crypto/x509" "strings" "testing" "time" v1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "github.com/cert-manager/cert-manager/pkg/util/pki" "github.com/cert-manager/cert-manager/test/unit/gen" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var ( testCert string testCertSerial string testCertFingerprint string testNotBefore string testNotAfter string ) func init() { caKey, err := pki.GenerateECPrivateKey(256) if err != nil { panic(err) } caCertificateTemplate := gen.Certificate( "ca", gen.SetCertificateCommonName("testing-ca"), gen.SetCertificateIsCA(true), gen.SetCertificateKeyAlgorithm(v1.ECDSAKeyAlgorithm), gen.SetCertificateKeySize(256), gen.SetCertificateKeyUsages( v1.UsageDigitalSignature, v1.UsageKeyEncipherment, v1.UsageCertSign, ), gen.SetCertificateNotBefore(metav1.Time{Time: time.Now().Add(-time.Hour)}), gen.SetCertificateNotAfter(metav1.Time{Time: time.Now().Add(time.Hour)}), ) caCertificateTemplate.Spec.Subject = &v1.X509Subject{ Organizations: []string{"Internet Widgets, Inc."}, Countries: []string{"US"}, OrganizationalUnits: []string{"WWW"}, Localities: []string{"San Francisco"}, Provinces: []string{"California"}, } caX509Cert, err := pki.CertificateTemplateFromCertificate(caCertificateTemplate) if err != nil { panic(err) } _, caCert, err := pki.SignCertificate(caX509Cert, caX509Cert, caKey.Public(), caKey) if err != nil { panic(err) } testCertKey, err := pki.GenerateECPrivateKey(256) if err != nil { panic(err) } testCertTemplate := gen.Certificate( "testing-cert", gen.SetCertificateDNSNames("cert-manager.test"), gen.SetCertificateIPs("10.0.0.1"), gen.SetCertificateURIs("spiffe://cert-manager.test"), gen.SetCertificateEmails("test@cert-manager.io"), gen.SetCertificateKeyAlgorithm(v1.ECDSAKeyAlgorithm), gen.SetCertificateIsCA(false), gen.SetCertificateKeySize(256), gen.SetCertificateKeyUsages( v1.UsageDigitalSignature, v1.UsageKeyEncipherment, v1.UsageServerAuth, v1.UsageClientAuth, ), gen.SetCertificateNotBefore(metav1.Time{Time: time.Now().Add(-30 * time.Minute)}), gen.SetCertificateNotAfter(metav1.Time{Time: time.Now().Add(30 * time.Minute)}), ) testCertTemplate.Spec.Subject = &v1.X509Subject{ Organizations: []string{"cncf"}, Countries: []string{"GB"}, OrganizationalUnits: []string{"cert-manager"}, } testX509Cert, err := pki.CertificateTemplateFromCertificate(testCertTemplate) if err != nil { panic(err) } testCertPEM, testCertGo, err := pki.SignCertificate(testX509Cert, caCert, testCertKey.Public(), caKey) if err != nil { panic(err) } testCert = string(testCertPEM) testCertSerial = testCertGo.SerialNumber.String() testCertFingerprint = fingerprintCert(testCertGo) testNotBefore = testCertGo.NotBefore.Format(time.RFC1123) testNotAfter = testCertGo.NotAfter.Format(time.RFC1123) } func MustParseCertificate(t *testing.T, certData string) *x509.Certificate { x509Cert, err := pki.DecodeX509CertificateBytes([]byte(certData)) if err != nil { t.Fatalf("error when parsing crt: %v", err) } return x509Cert } func Test_describeCRL(t *testing.T) { tests := []struct { name string cert *x509.Certificate want string }{ { name: "Print cert without CRL", cert: MustParseCertificate(t, testCert), want: "No CRL endpoints set", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := describeCRL(context.TODO(), tt.cert); got != tt.want { t.Errorf("describeCRL() = %v, want %v", makeInvisibleVisible(got), makeInvisibleVisible(tt.want)) } }) } } func Test_describeCertificate(t *testing.T) { tests := []struct { name string cert *x509.Certificate want string }{ { name: "Describe test certificate", cert: MustParseCertificate(t, testCert), want: `Certificate: Signing Algorithm: ECDSA-SHA256 Public Key Algorithm: ECDSA Serial Number: ` + testCertSerial + ` Fingerprints: ` + testCertFingerprint + ` Is a CA certificate: false CRL: <none> OCSP: <none>`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := describeCertificate(tt.cert) if got != tt.want { t.Errorf("describeCertificate() = %v, want %v", makeInvisibleVisible(got), makeInvisibleVisible(tt.want)) } if err != nil { t.Errorf("describeCertificate() error = %v", err) } }) } } func Test_describeDebugging(t *testing.T) { type args struct { cert *x509.Certificate intermediates [][]byte ca []byte } tests := []struct { name string args args want string }{ { name: "Debug test cert without trusting CA", args: args{ cert: MustParseCertificate(t, testCert), intermediates: nil, ca: nil, }, want: `Debugging: Trusted by this computer: no: x509: certificate signed by unknown authority CRL Status: No CRL endpoints set OCSP Status: Cannot check OCSP, does not have a CA or intermediate certificate provided`, }, // TODO: add fake clock and test with trusting CA } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := describeDebugging(context.TODO(), tt.args.cert, tt.args.intermediates, tt.args.ca) if got != tt.want { t.Errorf("describeDebugging() = %v, want %v", makeInvisibleVisible(got), makeInvisibleVisible(tt.want)) } if err != nil { t.Errorf("describeCertificate() error = %v", err) } }) } } func Test_describeIssuedBy(t *testing.T) { tests := []struct { name string cert *x509.Certificate want string }{ { name: "Describe test certificate", cert: MustParseCertificate(t, testCert), want: `Issued By: Common Name: testing-ca Organization: Internet Widgets, Inc. OrganizationalUnit: WWW Country: US`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := describeIssuedBy(tt.cert) if got != tt.want { t.Errorf("describeIssuedBy() = %v, want %v", makeInvisibleVisible(got), makeInvisibleVisible(tt.want)) } if err != nil { t.Errorf("describeIssuedBy() error = %v", err) } }) } } func Test_describeIssuedFor(t *testing.T) { tests := []struct { name string cert *x509.Certificate want string }{ { name: "Describe test cert", cert: MustParseCertificate(t, testCert), want: `Issued For: Common Name: <none> Organization: cncf OrganizationalUnit: cert-manager Country: GB`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := describeIssuedFor(tt.cert) if got != tt.want { t.Errorf("describeIssuedFor() = %v, want %v", makeInvisibleVisible(got), makeInvisibleVisible(tt.want)) } if err != nil { t.Errorf("describeCertificate() error = %v", err) } }) } } func Test_describeOCSP(t *testing.T) { type args struct { cert *x509.Certificate intermediates [][]byte ca []byte } tests := []struct { name string args args want string }{ { name: "Describe cert with no OCSP", args: args{ cert: MustParseCertificate(t, testCert), }, want: "Cannot check OCSP, does not have a CA or intermediate certificate provided", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := describeOCSP(context.TODO(), tt.args.cert, tt.args.intermediates, tt.args.ca); got != tt.want { t.Errorf("describeOCSP() = %v, want %v", makeInvisibleVisible(got), makeInvisibleVisible(tt.want)) } }) } } func Test_describeTrusted(t *testing.T) { type args struct { cert *x509.Certificate intermediates [][]byte } tests := []struct { name string args args want string }{ { name: "Describe test certificate", args: args{ cert: MustParseCertificate(t, testCert), intermediates: nil, }, want: "no: x509: certificate signed by unknown authority", }, { name: "Describe test certificate with adding it to the trust store", args: args{ cert: MustParseCertificate(t, testCert), intermediates: [][]byte{[]byte(testCert)}, }, want: "yes", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := describeTrusted(tt.args.cert, tt.args.intermediates); got != tt.want { t.Errorf("describeTrusted() = %v, want %v", makeInvisibleVisible(got), makeInvisibleVisible(tt.want)) } }) } } func Test_describeValidFor(t *testing.T) { tests := []struct { name string cert *x509.Certificate want string }{ { name: "Describe test certificate", cert: MustParseCertificate(t, testCert), want: `Valid for: DNS Names: - cert-manager.test URIs: - spiffe://cert-manager.test IP Addresses: - 10.0.0.1 Email Addresses: - test@cert-manager.io Usages: - digital signature - key encipherment - server auth - client auth`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := describeValidFor(tt.cert) if got != tt.want { t.Errorf("describeValidFor() = %v, want %v", makeInvisibleVisible(got), makeInvisibleVisible(tt.want)) } if err != nil { t.Errorf("describeIssuedBy() error = %v", err) } }) } } func Test_describeValidityPeriod(t *testing.T) { tests := []struct { name string cert *x509.Certificate want string }{ { name: "Describe test certificate", cert: MustParseCertificate(t, testCert), want: `Validity period: Not Before: ` + testNotBefore + ` Not After: ` + testNotAfter, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := describeValidityPeriod(tt.cert) if got != tt.want { t.Errorf("describeValidityPeriod() = %v, want %v", makeInvisibleVisible(got), makeInvisibleVisible(tt.want)) } if err != nil { t.Errorf("describeValidityPeriod() error = %v", err) } }) } } func makeInvisibleVisible(in string) string { in = strings.ReplaceAll(in, "\n", "\\n\n") in = strings.ReplaceAll(in, "\t", "\\t") return in } 07070100000088000081A400000000000000000000000166DFF09D0000123F000000000000000000000000000000000000002700000000cmctl-2.1.1/pkg/inspect/secret/util.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package secret import ( "bytes" "context" "crypto" "crypto/sha256" "crypto/x509" "encoding/pem" "errors" "fmt" "io" "net/http" "net/url" "strings" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "golang.org/x/crypto/ocsp" ) func fingerprintCert(cert *x509.Certificate) string { if cert == nil { return "" } fingerprint := sha256.Sum256(cert.Raw) var buf bytes.Buffer for i, f := range fingerprint { if i > 0 { fmt.Fprintf(&buf, ":") } fmt.Fprintf(&buf, "%02X", f) } return buf.String() } func checkOCSPValidCert(ctx context.Context, leafCert, issuerCert *x509.Certificate) (bool, error) { if len(leafCert.OCSPServer) < 1 { return false, errors.New("No OCSP Server set") } buffer, err := ocsp.CreateRequest(leafCert, issuerCert, &ocsp.RequestOptions{Hash: crypto.SHA1}) if err != nil { return false, fmt.Errorf("error creating OCSP request: %w", err) } for _, ocspServer := range leafCert.OCSPServer { httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, ocspServer, bytes.NewBuffer(buffer)) if err != nil { return false, fmt.Errorf("error creating HTTP request: %w", err) } ocspUrl, err := url.Parse(ocspServer) if err != nil { return false, fmt.Errorf("error parsing OCSP URL: %w", err) } httpRequest.Header.Add("Content-Type", "application/ocsp-request") httpRequest.Header.Add("Accept", "application/ocsp-response") httpRequest.Header.Add("Host", ocspUrl.Host) httpClient := &http.Client{} httpResponse, err := httpClient.Do(httpRequest) if err != nil { return false, fmt.Errorf("error making HTTP request: %w", err) } defer httpResponse.Body.Close() output, err := io.ReadAll(httpResponse.Body) if err != nil { return false, fmt.Errorf("error reading HTTP body: %w", err) } ocspResponse, err := ocsp.ParseResponse(output, issuerCert) if err != nil { return false, fmt.Errorf("error reading OCSP response: %w", err) } if ocspResponse.Status == ocsp.Revoked { // one OCSP revoked it do not trust return false, nil } } return true, nil } func checkCRLValidCert(ctx context.Context, cert *x509.Certificate, url string) (bool, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return false, fmt.Errorf("error creating HTTP request: %w", err) } resp, err := http.DefaultClient.Do(req) if err != nil { return false, fmt.Errorf("error getting HTTP response: %w", err) } body, err := io.ReadAll(resp.Body) if err != nil { return false, fmt.Errorf("error reading HTTP body: %w", err) } resp.Body.Close() crl, err := x509.ParseRevocationList(body) if err != nil { return false, fmt.Errorf("error parsing HTTP body: %w", err) } // TODO: check CRL signature for _, revoked := range crl.RevokedCertificateEntries { if cert.SerialNumber.Cmp(revoked.SerialNumber) == 0 { return false, nil } } return true, nil } func printSlice(in []string) string { if len(in) < 1 { return "<none>" } return "\n\t\t- " + strings.Trim(strings.Join(in, "\n\t\t- "), " ") } func printSliceOrOne(in []string) string { if len(in) < 1 { return "<none>" } else if len(in) == 1 { return in[0] } return printSlice(in) } func printOrNone(in string) string { if in == "" { return "<none>" } return in } func printKeyUsage(in []cmapi.KeyUsage) string { if len(in) < 1 { return " <none>" } var usageStrings []string for _, usage := range in { usageStrings = append(usageStrings, string(usage)) } return "\n\t\t- " + strings.Trim(strings.Join(usageStrings, "\n\t\t- "), " ") } func splitPEMs(certData []byte) ([][]byte, error) { certs := [][]byte(nil) for { block, rest := pem.Decode(certData) if block == nil { break // got no more certs to decode } // ignore private key data if block.Type == "CERTIFICATE" { buf := bytes.NewBuffer(nil) err := pem.Encode(buf, block) if err != nil { return nil, fmt.Errorf("error when reencoding PEM: %s", err) } certs = append(certs, buf.Bytes()) } certData = rest } return certs, nil } 07070100000089000081A400000000000000000000000166DFF09D00001625000000000000000000000000000000000000002C00000000cmctl-2.1.1/pkg/inspect/secret/util_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package secret import ( "crypto/x509" "reflect" "testing" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" ) const testCertForFingerprinting = `-----BEGIN CERTIFICATE----- MIICljCCAhugAwIBAgIUNAQr779ga/BNXyCpK7ddFbjAK98wCgYIKoZIzj0EAwMw aTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK BgNVBAsTA1dXVzAeFw0yMTAyMjYxMDM1MDBaFw0yMjAyMjYxMDM1MDBaMDMxCzAJ BgNVBAYTAkdCMQ0wCwYDVQQKEwRjbmNmMRUwEwYDVQQLEwxjZXJ0LW1hbmFnZXIw WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATd5gWH2rkzWBGrr1jCR6JDB0dZOizZ jCt2gnzNfzZmEg3rqxPvIakfT1lsjL2HrQyBRMQGGZhj7RkN7/VUM+VUo4HWMIHT MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUCUEeUFyT7U3e6zP4q4VYEr2x0KcwHwYD VR0jBBgwFoAUFkKAaJ18Vg9xFx3K7d5b7HjoSSMwVAYDVR0RBE0wS4IRY2VydC1t YW5hZ2VyLnRlc3SBFHRlc3RAY2VydC1tYW5hZ2VyLmlvhwQKAAABhhpzcGlmZmU6 Ly9jZXJ0LW1hbmFnZXIudGVzdDAKBggqhkjOPQQDAwNpADBmAjEA3Fv1aP+dBtBh +DThW0QQO/Xl0CHQRKnJmJ8JjnleaMYFVdHf7dcf0ZeyOC26aUkdAjEA/fvxvhcz Dtj+gY2rewoeJv5Pslli+SEObUslRaVtUMGxwUbmPU2fKuZHWBfe2FfA -----END CERTIFICATE----- ` func Test_fingerprintCert(t *testing.T) { tests := []struct { name string cert *x509.Certificate want string }{ { name: "Fingerprint a valid cert", cert: MustParseCertificate(t, testCertForFingerprinting), want: "FF:D0:A8:85:0B:A4:5A:E1:FC:55:40:E1:FC:07:09:F1:02:AE:B9:EB:28:C4:01:23:B9:4F:C8:FA:9B:EF:F4:C1", }, { name: "Fingerprint nil", cert: nil, want: "", }, { name: "Fingerprint invalid cert", cert: &x509.Certificate{Raw: []byte("fake")}, want: "B5:D5:4C:39:E6:66:71:C9:73:1B:9F:47:1E:58:5D:82:62:CD:4F:54:96:3F:0C:93:08:2D:8D:CF:33:4D:4C:78", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := fingerprintCert(tt.cert); got != tt.want { t.Errorf("fingerprintCert() = %v, want %v", got, tt.want) } }) } } func Test_printKeyUsage(t *testing.T) { type args struct { in []cmapi.KeyUsage } tests := []struct { name string args args want string }{ // TODO: Add test cases. } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := printKeyUsage(tt.args.in); got != tt.want { t.Errorf("printKeyUsage() = %v, want %v", got, tt.want) } }) } } func Test_printOrNone(t *testing.T) { tests := []struct { name string in string want string }{ { name: "Print none on empty", in: "", want: "<none>", }, { name: "Print value on not empty", in: "ok", want: "ok", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := printOrNone(tt.in); got != tt.want { t.Errorf("printOrNone() = %v, want %v", got, tt.want) } }) } } func Test_printSlice(t *testing.T) { tests := []struct { name string in []string want string }{ { name: "Print test slice multiple objects", in: []string{"test", "ok"}, want: ` - test - ok`, }, { name: "Print test slice one object", in: []string{"test"}, want: "\n\t\t- test", }, { name: "Print nil slice", in: nil, want: "<none>", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := printSlice(tt.in); got != tt.want { t.Errorf("printSlice() = %v, want %v", got, tt.want) } }) } } func Test_printSliceOrOne(t *testing.T) { tests := []struct { name string in []string want string }{ { name: "Print test slice multiple objects", in: []string{"test", "ok"}, want: ` - test - ok`, }, { name: "Print test slice one object", in: []string{"test"}, want: "test", }, { name: "Print nil slice", in: nil, want: "<none>", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := printSliceOrOne(tt.in); got != tt.want { t.Errorf("printSliceOrOne() = %v, want %v", got, tt.want) } }) } } func Test_splitPEMs(t *testing.T) { tests := []struct { name string certData []byte want [][]byte wantErr bool }{ { name: "Single PEM in file", certData: []byte(testCert), want: [][]byte{[]byte(testCert)}, wantErr: false, }, { name: "2 PEMs in file", certData: []byte(testCert + "\n" + testCert), want: [][]byte{[]byte(testCert), []byte(testCert)}, wantErr: false, }, { name: "Invalid input after a valid PEM", certData: []byte(testCert + "\n\ninvalid"), want: [][]byte{[]byte(testCert)}, wantErr: false, }, { name: "Invalid input without PEM block", certData: []byte("invalid"), want: nil, wantErr: false, }, // TODO: somehow find an error case the PEM encoder/decoder is quite error resistant } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := splitPEMs(tt.certData) if (err != nil) != tt.wantErr { t.Errorf("splitPEMs() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { t.Errorf("splitPEMs() got = %v, want %v", got, tt.want) } }) } } 0707010000008A000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001800000000cmctl-2.1.1/pkg/install0707010000008B000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001D00000000cmctl-2.1.1/pkg/install/helm0707010000008C000081A400000000000000000000000166DFF09D0000066C000000000000000000000000000000000000002900000000cmctl-2.1.1/pkg/install/helm/applycrd.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package helm import ( "time" logf "github.com/cert-manager/cert-manager/pkg/logs" "helm.sh/helm/v3/pkg/action" "k8s.io/cli-runtime/pkg/resource" ) // CreateCRDs creates cert manager CRDs. Before calling this function, we // made sure that the CRDs are not yet installed on the cluster. func CreateCRDs(allCRDs []*resource.Info, cfg *action.Configuration) error { logf.Log.Info("Creating the cert-manager CRDs") // Create all CRDs rr, err := cfg.KubeClient.Create(allCRDs) if err != nil { return err } createdCRDs := rr.Created // Invalidate the local cache, since it will not have the new CRDs // present. discoveryClient, err := cfg.RESTClientGetter.ToDiscoveryClient() if err != nil { return err } logf.Log.Info("Clearing discovery cache") discoveryClient.Invalidate() // Give time for the CRD to be recognized. if err := cfg.KubeClient.Wait(createdCRDs, 60*time.Second); err != nil { return err } // Make sure to force a rebuild of the cache. if _, err := discoveryClient.ServerGroups(); err != nil { return err } return nil } 0707010000008D000081A400000000000000000000000166DFF09D0000051A000000000000000000000000000000000000002600000000cmctl-2.1.1/pkg/install/helm/flags.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package helm import ( "time" "github.com/spf13/pflag" ) // Flags that are shared between the Install and the Uninstall command func AddInstallUninstallFlags(f *pflag.FlagSet, timeout *time.Duration, wait *bool) { f.DurationVar(timeout, "timeout", 300*time.Second, "Time to wait for any individual Kubernetes operation (like Jobs for hooks)") if err := f.MarkHidden("timeout"); err != nil { panic(err) } f.BoolVar(wait, "wait", true, "If set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment, StatefulSet, or ReplicaSet are in a ready state before marking the release as successful. It will wait for as long as --timeout") if err := f.MarkHidden("wait"); err != nil { panic(err) } } 0707010000008E000081A400000000000000000000000166DFF09D000009D3000000000000000000000000000000000000002900000000cmctl-2.1.1/pkg/install/helm/resource.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package helm import ( "bytes" "fmt" "helm.sh/helm/v3/pkg/kube" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/cli-runtime/pkg/resource" ) const ( customResourceDefinitionGroup = "apiextensions.k8s.io" customResourceDefinitionKind = "CustomResourceDefinition" ) // Build a list of resource.Info objects from a rendered manifest. func ParseMultiDocumentYAML(manifest string, kubeClient kube.Interface) ([]*resource.Info, error) { resources := make([]*resource.Info, 0) res, err := kubeClient.Build(bytes.NewBufferString(manifest), false) if err != nil { return nil, fmt.Errorf("Parsing the CRDs from the rendered manifest was not successful: %w", err) } resources = append(resources, res...) return resources, nil } func filterResources(resources []*resource.Info, filter func(*resource.Info) bool) []*resource.Info { filtered := make([]*resource.Info, 0) for _, res := range resources { if filter(res) { filtered = append(filtered, res) } } return filtered } // Retrieve the latest version of the resources from the kubernetes cluster. func FetchResources(resources []*resource.Info, kubeClient kube.Interface) ([]*resource.Info, error) { detected := make([]*resource.Info, 0) for _, info := range resources { helper := resource.NewHelper(info.Client, info.Mapping) obj, err := helper.Get(info.Namespace, info.Name) if err != nil { if apierrors.IsNotFound(err) { continue } return nil, err } info.Object = obj detected = append(detected, info) } return detected, nil } // Filter resources that are Custom Resource Definitions. func FilterCrdResources(resources []*resource.Info) []*resource.Info { return filterResources(resources, func(res *resource.Info) bool { groupVersionKind := res.Object.GetObjectKind().GroupVersionKind() return (groupVersionKind.Group == customResourceDefinitionGroup) && (groupVersionKind.Kind == customResourceDefinitionKind) }) } 0707010000008F000081A400000000000000000000000166DFF09D00000C8F000000000000000000000000000000000000002900000000cmctl-2.1.1/pkg/install/helm/settings.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package helm import ( "context" "fmt" "os" logf "github.com/cert-manager/cert-manager/pkg/logs" "github.com/go-logr/logr" "github.com/spf13/cobra" "github.com/spf13/pflag" "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/cli" "github.com/cert-manager/cmctl/v2/pkg/factory" ) const defaultCertManagerNamespace = "cert-manager" const debugLogLevel = 3 type NormalisedEnvSettings struct { logger logr.Logger EnvSettings *cli.EnvSettings ActionConfiguration *action.Configuration Factory *factory.Factory } func NewNormalisedEnvSettings() *NormalisedEnvSettings { return &NormalisedEnvSettings{ EnvSettings: cli.New(), ActionConfiguration: &action.Configuration{}, } } func (n *NormalisedEnvSettings) Namespace() string { return n.Factory.Namespace } func (n *NormalisedEnvSettings) Setup(ctx context.Context, cmd *cobra.Command) { log := logf.FromContext(ctx) n.logger = log n.Factory = factory.New(cmd) n.setupEnvSettings(cmd) { // Add a PreRunE hook to initialise the action configuration. existingPreRunE := cmd.PreRunE cmd.PreRunE = func(cmd *cobra.Command, args []string) error { if existingPreRunE != nil { if err := existingPreRunE(cmd, args); err != nil { return err } } return n.InitActionConfiguration() } } // Fix the default namespace to be cert-manager cmd.Flag("namespace").DefValue = defaultCertManagerNamespace if err := cmd.Flag("namespace").Value.Set(defaultCertManagerNamespace); err != nil { panic(err) } } func (n *NormalisedEnvSettings) setupEnvSettings(cmd *cobra.Command) { { // Create a tempoary flag set to add the EnvSettings flags to, this // can then be iterated over to copy the flags we want to the command var tmpFlagSet pflag.FlagSet n.EnvSettings.AddFlags(&tmpFlagSet) tmpFlagSet.VisitAll(func(f *pflag.Flag) { switch f.Name { case "registry-config", "repository-config", "repository-cache": cmd.Flags().AddFlag(f) } }) } { // Add a PreRun hook to set the debug value to true if the log level is // >= 3. existingPreRunE := cmd.PreRunE cmd.PreRunE = func(cmd *cobra.Command, args []string) error { if n.logger.V(debugLogLevel).Enabled() { n.EnvSettings.Debug = true } if existingPreRunE != nil { return existingPreRunE(cmd, args) } return nil } } } func (n *NormalisedEnvSettings) InitActionConfiguration() error { return n.ActionConfiguration.Init( n.Factory.RESTClientGetter, n.Factory.Namespace, os.Getenv("HELM_DRIVER"), func(format string, v ...interface{}) { n.logger.Info(fmt.Sprintf(format, v...)) }, ) } 07070100000090000081A400000000000000000000000166DFF09D0000246B000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/install/install.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package install import ( "context" "fmt" "io" "strings" "time" logf "github.com/cert-manager/cert-manager/pkg/logs" "github.com/spf13/cobra" "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/cli/values" "helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/release" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/install/helm" ) type InstallOptions struct { settings *helm.NormalisedEnvSettings client *action.Install valueOpts *values.Options ChartName string DryRun bool Wait bool genericclioptions.IOStreams } const ( installCRDsFlagName = "installCRDs" ) func installDesc(ctx context.Context) string { return build.WithTemplate(ctx, `This command installs cert-manager. It uses the Helm libraries to do so. The latest published cert-manager chart in the "https://charts.jetstack.io" repo is used. Most of the features supported by 'helm install' are also supported by this command. In addition, this command will always correctly install the required CRD resources. Some example uses: $ {{.BuildName}} x install or $ {{.BuildName}} x install -n new-cert-manager or $ {{.BuildName}} x install --version v1.4.0 or $ {{.BuildName}} x install --set prometheus.enabled=false To override values in the cert-manager chart, use either the '--values' flag and pass in a file or use the '--set' flag and pass configuration from the command line. `) } func NewCmdInstall(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { settings := helm.NewNormalisedEnvSettings() options := &InstallOptions{ settings: settings, client: action.NewInstall(settings.ActionConfiguration), valueOpts: &values.Options{}, IOStreams: ioStreams, } cmd := &cobra.Command{ Use: "install", Short: "Install cert-manager", Long: installDesc(setupCtx), // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { options.client.Namespace = settings.Namespace() rel, err := options.runInstall(cmd.Context()) if err != nil { return err } if options.DryRun { fmt.Fprintf(ioStreams.Out, "%s", rel.Manifest) return nil } printReleaseSummary(ioStreams.Out, rel) return nil }, } settings.Setup(setupCtx, cmd) helm.AddInstallUninstallFlags(cmd.Flags(), &options.client.Timeout, &options.Wait) addInstallFlags(cmd.Flags(), options.client) addValueOptionsFlags(cmd.Flags(), options.valueOpts) addChartPathOptionsFlags(cmd.Flags(), &options.client.ChartPathOptions) cmd.Flags().BoolVar(&options.client.CreateNamespace, "create-namespace", true, "Create the release namespace if not present") if err := cmd.Flags().MarkHidden("create-namespace"); err != nil { panic(err) } cmd.Flags().StringVar(&options.ChartName, "chart-name", "cert-manager", "Name of the chart to install") if err := cmd.Flags().MarkHidden("chart-name"); err != nil { panic(err) } cmd.Flags().BoolVar(&options.DryRun, "dry-run", false, "Simulate install and output manifest") return cmd } // The overall strategy is to install the CRDs first, and not as part of a Helm // release, and then to install a Helm release without the CRDs. This is to // ensure that CRDs are not removed by a subsequent helm uninstall or by a // future cmctl uninstall. We want the removal of CRDs to only be performed by // an administrator who understands that the consequences of removing CRDs will // be the garbage collection of all the related CRs in the cluster. We first // do a dry-run install of the chart (effectively helm template // --validate=false) to render the CRDs from the CRD templates in the Chart. // The ClientOnly option is required, otherwise Helm will return an error in // case the CRDs are already installed in the cluster. We then extract the // CRDs from the resulting dry-run manifests and install those first. Finally, // we perform a helm install to install the remaining non-CRD resources and // wait for those to be "Ready". // This creates a Helm "release" artifact in a Secret in the target namespace, which contains // a record of all the resources installed by Helm (except the CRDs). func (o *InstallOptions) runInstall(ctx context.Context) (*release.Release, error) { log := logf.FromContext(ctx, "install") // Find chart cp, err := o.client.ChartPathOptions.LocateChart(o.ChartName, o.settings.EnvSettings) if err != nil { return nil, err } chart, err := loader.Load(cp) if err != nil { return nil, err } // Check if chart is installable if err := checkIfInstallable(chart); err != nil { return nil, err } // Console print if chart is deprecated if chart.Metadata.Deprecated { log.Error(fmt.Errorf("chart.Metadata.Deprecated is true"), "This chart is deprecated") } // Merge all values flags p := getter.All(o.settings.EnvSettings) chartValues, err := o.valueOpts.MergeValues(p) if err != nil { return nil, err } // Dryrun template generation (used for rendering the CRDs in /templates) o.client.DryRun = true // Do not apply install o.client.ClientOnly = true // Do not validate against cluster (otherwise double CRDs can cause error) // Kube version to be used in dry run template generation which does not // talk to kube apiserver. This is to ensure that template generation // does not fail because our Kubernetes minimum version requirement is // higher than that hardcoded in Helm codebase for client-only runs o.client.KubeVersion = &chartutil.KubeVersion{ Version: "v999.999.999", Major: "999", Minor: "999", } chartValues[installCRDsFlagName] = true // Make sure to render CRDs dryRunResult, err := o.client.Run(chart, chartValues) if err != nil { return nil, err } if o.DryRun { return dryRunResult, nil } // The o.client.Run() call above will have altered the settings.ActionConfiguration // object, so we need to re-initialise it. if err := o.settings.InitActionConfiguration(); err != nil { return nil, err } // Extract the resource.Info objects from the manifest resources, err := helm.ParseMultiDocumentYAML(dryRunResult.Manifest, o.settings.ActionConfiguration.KubeClient) if err != nil { return nil, err } // Filter resource.Info objects and only keep the CRDs crds := helm.FilterCrdResources(resources) // Abort in case CRDs were not found in chart if len(crds) == 0 { return nil, fmt.Errorf("Found no CRDs in provided cert-manager chart.") } // Make sure that no CRDs are currently installed originalCRDs, err := helm.FetchResources(crds, o.settings.ActionConfiguration.KubeClient) if err != nil { return nil, err } if len(originalCRDs) > 0 { return nil, fmt.Errorf("Found existing installed cert-manager CRDs! Cannot continue with installation.") } // Install CRDs if err := helm.CreateCRDs(crds, o.settings.ActionConfiguration); err != nil { return nil, err } // Install chart o.client.DryRun = false // Apply DryRun cli flags o.client.ClientOnly = false // Perform install against cluster o.client.KubeVersion = nil o.client.Wait = o.Wait // Wait for resources to be ready // If part of the install fails and the Atomic option is set to True, // all resource installs are reverted. Atomic cannot be enabled without // waiting (if Atomic=True is set, the value for Wait is overwritten with True), // so only enable Atomic if we are waiting. o.client.Atomic = o.Wait // The cert-manager chart currently has only a startupapicheck hook, // if waiting is disabled, this hook should be disabled too; otherwise // the hook will still wait for the installation to succeed. o.client.DisableHooks = !o.Wait chartValues[installCRDsFlagName] = false // Do not render CRDs, as this might cause problems when uninstalling using helm return o.client.Run(chart, chartValues) } func printReleaseSummary(out io.Writer, rel *release.Release) { fmt.Fprintf(out, "NAME: %s\n", rel.Name) if !rel.Info.LastDeployed.IsZero() { fmt.Fprintf(out, "LAST DEPLOYED: %s\n", rel.Info.LastDeployed.Format(time.ANSIC)) } fmt.Fprintf(out, "NAMESPACE: %s\n", rel.Namespace) fmt.Fprintf(out, "STATUS: %s\n", rel.Info.Status.String()) fmt.Fprintf(out, "REVISION: %d\n", rel.Version) fmt.Fprintf(out, "DESCRIPTION: %s\n", rel.Info.Description) if len(rel.Info.Notes) > 0 { fmt.Fprintf(out, "NOTES:\n%s\n", strings.TrimSpace(rel.Info.Notes)) } } // Only Application chart type are installable. func checkIfInstallable(ch *chart.Chart) error { switch ch.Metadata.Type { case "", "application": return nil } return fmt.Errorf("%s charts are not installable", ch.Metadata.Type) } 07070100000091000081A400000000000000000000000166DFF09D00000C12000000000000000000000000000000000000002000000000cmctl-2.1.1/pkg/install/util.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package install import ( "os" "path/filepath" "github.com/spf13/pflag" "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/cli/values" "k8s.io/client-go/util/homedir" ) func addInstallFlags(f *pflag.FlagSet, client *action.Install) { f.StringVar(&client.ReleaseName, "release-name", "cert-manager", "Name of the helm release") if err := f.MarkHidden("release-name"); err != nil { panic(err) } f.BoolVarP(&client.GenerateName, "generate-name", "g", false, "Generate the name (instead of using the default 'cert-manager' value)") if err := f.MarkHidden("generate-name"); err != nil { panic(err) } f.StringVar(&client.NameTemplate, "name-template", "", "Specify template used to name the release") if err := f.MarkHidden("name-template"); err != nil { panic(err) } f.StringVar(&client.Description, "description", "cert-manager was installed using the cert-manager CLI", "Add a custom description") if err := f.MarkHidden("description"); err != nil { panic(err) } } func addValueOptionsFlags(f *pflag.FlagSet, v *values.Options) { f.StringSliceVarP(&v.ValueFiles, "values", "f", []string{}, "Specify values in a YAML file or a URL (can specify multiple)") f.StringArrayVar(&v.Values, "set", []string{}, "Set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") f.StringArrayVar(&v.StringValues, "set-string", []string{}, "Set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") if err := f.MarkHidden("set-string"); err != nil { panic(err) } f.StringArrayVar(&v.FileValues, "set-file", []string{}, "Set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)") if err := f.MarkHidden("set-file"); err != nil { panic(err) } } // defaultKeyring returns the expanded path to the default keyring. func defaultKeyring() string { if v, ok := os.LookupEnv("GNUPGHOME"); ok { return filepath.Join(v, "pubring.gpg") } return filepath.Join(homedir.HomeDir(), ".gnupg", "pubring.gpg") } func addChartPathOptionsFlags(f *pflag.FlagSet, c *action.ChartPathOptions) { c.Keyring = defaultKeyring() c.RepoURL = "https://charts.jetstack.io" f.StringVar(&c.Version, "version", "", "specify a version constraint for the chart version to use. This constraint can be a specific tag (e.g. 1.1.1) or it may reference a valid range (e.g. ^2.0.0). If this is not specified, the latest version is used") } 07070100000092000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001600000000cmctl-2.1.1/pkg/renew07070100000093000081A400000000000000000000000166DFF09D00001BD2000000000000000000000000000000000000001F00000000cmctl-2.1.1/pkg/renew/renew.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package renew import ( "context" "errors" "fmt" "strings" apiutil "github.com/cert-manager/cert-manager/pkg/api/util" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" cmclient "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/kubernetes" cmdutil "k8s.io/kubectl/pkg/cmd/util" "k8s.io/kubectl/pkg/util/templates" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/factory" ) // Options is a struct to support renew command type Options struct { LabelSelector string All bool AllNamespaces bool genericclioptions.IOStreams *factory.Factory } // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } // NewCmdRenew returns a cobra command for renewing Certificates func NewCmdRenew(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "renew", Short: "Mark a Certificate for manual renewal", Long: templates.LongDesc(` Mark cert-manager Certificate resources for manual renewal.`), Example: templates.Examples(build.WithTemplate(setupCtx, ` # Renew the Certificates named 'my-app' and 'vault' in the current context namespace. {{.BuildName}} renew my-app vault # Renew all Certificates in the 'kube-system' namespace. {{.BuildName}} renew --namespace kube-system --all # Renew all Certificates in all namespaces, provided those Certificates have the label 'app=my-service' {{.BuildName}} renew --all-namespaces -l app=my-service`)), ValidArgsFunction: factory.ValidArgsListCertificates(&o.Factory), PreRunE: func(cmd *cobra.Command, args []string) error { return o.Validate(cmd, args) }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context(), args) }, } cmd.Flags().StringVarP(&o.LabelSelector, "selector", "l", o.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If present, mark Certificates across namespaces for manual renewal. Namespace in current context is ignored even if specified with --namespace.") cmd.Flags().BoolVar(&o.All, "all", o.All, "Renew all Certificates in the given Namespace, or all namespaces with --all-namespaces enabled.") o.Factory = factory.New(cmd) return cmd } // Validate validates the provided options func (o *Options) Validate(cmd *cobra.Command, args []string) error { // The --all, --selector and args are mutually exclusive. // - --all is equivalent to a match-all label selector // - --selector filters by label selector // - args are an explicit list of Certificate names // However, there must always be one of the three specified. var flags []string if len(args) > 0 { flags = append(flags, fmt.Sprintf("the Certificate resource names %q", args)) } if o.All { flags = append(flags, "the --all flag") } if len(o.LabelSelector) > 0 { flags = append(flags, "a label selector") } // Ensure that only one of the three flags are specified if len(flags) > 1 { return fmt.Errorf("cannot specify %s in conjunction with %s", flags[0], strings.Join(flags[1:], " and ")) } if len(flags) == 0 { return errors.New("please either supply one or more Certificate resource names, label selectors, or use the --all flag to renew all Certificate resources") } // The --all-namespaces flag overrides the --namespace flag. // Additionally, we can only use --all-namespaces when not specifying a list of Certificate names if o.AllNamespaces && len(args) > 0 { return errors.New("cannot specify Certificate names in conjunction with --all-namespaces flag") } return nil } // Complete takes the command arguments and factory and infers any remaining options. func (o *Options) Complete(f cmdutil.Factory) error { var err error o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } o.RESTConfig, err = f.ToRESTConfig() if err != nil { return err } o.CMClient, err = cmclient.NewForConfig(o.RESTConfig) if err != nil { return err } return nil } // Run executes renew command func (o *Options) Run(ctx context.Context, args []string) error { nss := []corev1.Namespace{{ObjectMeta: metav1.ObjectMeta{Name: o.Namespace}}} if o.AllNamespaces { kubeClient, err := kubernetes.NewForConfig(o.RESTConfig) if err != nil { return err } nsList, err := kubeClient.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) if err != nil { return err } nss = nsList.Items } var crts []cmapi.Certificate for _, ns := range nss { switch { case o.All, len(o.LabelSelector) > 0: crtsList, err := o.CMClient.CertmanagerV1().Certificates(ns.Name).List(ctx, metav1.ListOptions{ LabelSelector: o.LabelSelector, }) if err != nil { return err } crts = append(crts, crtsList.Items...) default: for _, crtName := range args { crt, err := o.CMClient.CertmanagerV1().Certificates(ns.Name).Get(ctx, crtName, metav1.GetOptions{}) if err != nil { return err } crts = append(crts, *crt) } } } if len(crts) == 0 { if o.AllNamespaces { fmt.Fprintln(o.ErrOut, "No Certificates found") } else { fmt.Fprintf(o.ErrOut, "No Certificates found in %s namespace.\n", o.Namespace) } return nil } for _, crt := range crts { if err := o.renewCertificate(ctx, &crt); /* #nosec G601 -- Pointer does not outlive function scope */ err != nil { return err } } return nil } func (o *Options) renewCertificate(ctx context.Context, crt *cmapi.Certificate) error { apiutil.SetCertificateCondition(crt, crt.Generation, cmapi.CertificateConditionIssuing, cmmeta.ConditionTrue, "ManuallyTriggered", "Certificate re-issuance manually triggered") _, err := o.CMClient.CertmanagerV1().Certificates(crt.Namespace).UpdateStatus(ctx, crt, metav1.UpdateOptions{}) if err != nil { return fmt.Errorf("failed to trigger issuance of Certificate %s/%s: %v", crt.Namespace, crt.Name, err) } fmt.Fprintf(o.Out, "Manually triggered issuance of Certificate %s/%s\n", crt.Namespace, crt.Name) return nil } 07070100000094000081A400000000000000000000000166DFF09D00000F1B000000000000000000000000000000000000002400000000cmctl-2.1.1/pkg/renew/renew_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package renew import ( "context" "testing" "k8s.io/cli-runtime/pkg/genericclioptions" ) type stringFlag struct { name, value string } func TestValidate(t *testing.T) { tests := map[string]struct { options *Options args []string setStringFlags []stringFlag expErr bool }{ "If there are arguments, as well as label selector, error": { options: &Options{ LabelSelector: "foo=bar", }, args: []string{"abc"}, expErr: true, }, "If there are arguments, as well as --all-namespaces, error": { options: &Options{ AllNamespaces: true, }, args: []string{"abc"}, expErr: true, }, "If there are all certificates selected, as well as label selector, error": { options: &Options{ LabelSelector: "foo=bar", All: true, }, expErr: true, }, "If there are all certificates selected, as well as arguments, error": { options: &Options{ All: true, }, args: []string{"abc"}, expErr: true, }, "If all certificates in all namespaces selected, don't error": { options: &Options{ All: true, AllNamespaces: true, }, expErr: false, }, "If --namespace and --all specified, don't error": { options: &Options{ All: true, }, setStringFlags: []stringFlag{ {name: "namespace", value: "foo"}, }, expErr: false, }, "If --namespace specified without arguments, error": { options: &Options{}, setStringFlags: []stringFlag{ {name: "namespace", value: "foo"}, }, expErr: true, }, "If --namespace specified and at least one argument, don't error": { options: &Options{}, args: []string{"bar"}, setStringFlags: []stringFlag{ {name: "namespace", value: "foo"}, }, expErr: false, }, "If --namespace specified with multiple arguments, don't error": { options: &Options{}, args: []string{"bar", "abc"}, setStringFlags: []stringFlag{ {name: "namespace", value: "foo"}, }, expErr: false, }, "If --label-selector specified with --all, error": { options: &Options{ LabelSelector: "foo=bar", All: true, }, expErr: true, }, "If --label-selector specified with --all-namespaces, don't error": { options: &Options{ AllNamespaces: true, LabelSelector: "foo=bar", }, expErr: false, }, "If --label-selector specified with --namespace, don't error": { options: &Options{ LabelSelector: "foo=bar", }, setStringFlags: []stringFlag{ {name: "namespace", value: "foo"}, }, expErr: false, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { cmd := NewCmdRenew(context.TODO(), genericclioptions.IOStreams{}) // This is normally registered in the main func. We add here to test // against flags normally inherited. kubeConfigFlags := genericclioptions.NewConfigFlags(true) kubeConfigFlags.AddFlags(cmd.PersistentFlags()) if test.setStringFlags != nil { for _, s := range test.setStringFlags { if err := cmd.PersistentFlags().Set(s.name, s.value); err != nil { t.Fatal(err) } } } err := test.options.Validate(cmd, test.args) if test.expErr != (err != nil) { t.Errorf("expected error=%t got=%v", test.expErr, err) } }) } } 07070100000095000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001700000000cmctl-2.1.1/pkg/status07070100000096000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/status/certificate07070100000097000081A400000000000000000000000166DFF09D00003563000000000000000000000000000000000000003200000000cmctl-2.1.1/pkg/status/certificate/certificate.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package certificate import ( "context" "errors" "fmt" "time" cmacme "github.com/cert-manager/cert-manager/pkg/apis/acme/v1" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmclient "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned" "github.com/cert-manager/cert-manager/pkg/ctl" "github.com/cert-manager/cert-manager/pkg/util/predicate" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/reference" "k8s.io/kubectl/pkg/util/templates" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/factory" ) // Options is a struct to support status certificate command type Options struct { genericclioptions.IOStreams *factory.Factory } // Data is a struct containing the information to build a CertificateStatus type Data struct { Certificate *cmapi.Certificate CrtEvents *corev1.EventList Issuer cmapi.GenericIssuer IssuerKind string IssuerError error IssuerEvents *corev1.EventList Secret *corev1.Secret SecretError error SecretEvents *corev1.EventList Req *cmapi.CertificateRequest ReqError error ReqEvents *corev1.EventList Order *cmacme.Order OrderError error Challenges []*cmacme.Challenge ChallengeErr error } // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } // NewCmdStatusCert returns a cobra command for status certificate func NewCmdStatusCert(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "certificate", Short: "Get details about the current status of a cert-manager Certificate resource", Long: templates.LongDesc(` Get details about the current status of a cert-manager Certificate resource, including information on related resources like CertificateRequest or Order.`), Example: templates.Examples(build.WithTemplate(setupCtx, ` # Query status of Certificate with name 'my-crt' in namespace 'my-namespace' {{.BuildName}} status certificate my-crt --namespace my-namespace `)), ValidArgsFunction: factory.ValidArgsListCertificates(&o.Factory), PreRunE: func(cmd *cobra.Command, args []string) error { return o.Validate(args) }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context(), args) }, } o.Factory = factory.New(cmd) return cmd } // Validate validates the provided options func (o *Options) Validate(args []string) error { if len(args) < 1 { return errors.New("the name of the Certificate has to be provided as argument") } if len(args) > 1 { return errors.New("only one argument can be passed in: the name of the Certificate") } return nil } // Run executes status certificate command func (o *Options) Run(ctx context.Context, args []string) error { data, err := o.GetResources(ctx, args[0]) if err != nil { return err } // Build status of Certificate with data gathered status := StatusFromResources(data) fmt.Fprint(o.Out, status.String()) return nil } // GetResources collects all related resources of the Certificate and any errors while doing so // in a Data struct and returns it. // Returns error if error occurs when finding Certificate resource or while preparing to find other resources, // e.g. when creating clientSet func (o *Options) GetResources(ctx context.Context, crtName string) (*Data, error) { clientSet, err := kubernetes.NewForConfig(o.RESTConfig) if err != nil { return nil, err } crt, err := o.CMClient.CertmanagerV1().Certificates(o.Namespace).Get(ctx, crtName, metav1.GetOptions{}) if err != nil { return nil, fmt.Errorf("error when getting Certificate resource: %v", err) } crtRef, err := reference.GetReference(ctl.Scheme, crt) if err != nil { return nil, err } // If no events found, crtEvents would be nil and handled down the line in DescribeEvents crtEvents, err := clientSet.CoreV1().Events(crt.Namespace).Search(ctl.Scheme, crtRef) if err != nil { return nil, err } issuer, issuerKind, issuerError := getGenericIssuer(o.CMClient, ctx, crt) var issuerEvents *corev1.EventList if issuer != nil { issuerRef, err := reference.GetReference(ctl.Scheme, issuer) if err != nil { return nil, err } // If no events found, issuerEvents would be nil and handled down the line in DescribeEvents issuerEvents, err = clientSet.CoreV1().Events(issuer.GetNamespace()).Search(ctl.Scheme, issuerRef) if err != nil { return nil, err } } secret, secretErr := clientSet.CoreV1().Secrets(crt.Namespace).Get(ctx, crt.Spec.SecretName, metav1.GetOptions{}) if secretErr != nil { secretErr = fmt.Errorf("error when finding Secret %q: %w\n", crt.Spec.SecretName, secretErr) } var secretEvents *corev1.EventList if secret != nil { secretRef, err := reference.GetReference(ctl.Scheme, secret) if err != nil { return nil, err } // If no events found, secretEvents would be nil and handled down the line in DescribeEvents secretEvents, err = clientSet.CoreV1().Events(secret.Namespace).Search(ctl.Scheme, secretRef) if err != nil { return nil, err } } // TODO: What about timing issues? When I query condition it's not ready yet, but then looking for cr it's finished and deleted // Try find the CertificateRequest that is owned by crt and has the correct revision req, reqErr := findMatchingCR(o.CMClient, ctx, crt) if reqErr != nil { reqErr = fmt.Errorf("error when finding CertificateRequest: %w\n", reqErr) } else if req == nil { reqErr = errors.New("No CertificateRequest found for this Certificate\n") } var reqEvents *corev1.EventList if req != nil { reqRef, err := reference.GetReference(ctl.Scheme, req) if err != nil { return nil, err } // If no events found, reqEvents would be nil and handled down the line in DescribeEvents reqEvents, err = clientSet.CoreV1().Events(req.Namespace).Search(ctl.Scheme, reqRef) if err != nil { return nil, err } } var ( order *cmacme.Order orderErr error challenges []*cmacme.Challenge challengeErr error ) // Nothing to output about Order and Challenge if no CR or not ACME Issuer if req != nil && issuer != nil && issuer.GetSpec().ACME != nil { // Get Order order, orderErr = findMatchingOrder(o.CMClient, ctx, req) if orderErr != nil { orderErr = fmt.Errorf("error when finding Order: %w\n", orderErr) } else if order == nil { orderErr = errors.New("No Order found for this Certificate\n") } if order != nil { challenges, challengeErr = findMatchingChallenges(o.CMClient, ctx, order) if challengeErr != nil { challengeErr = fmt.Errorf("error when finding Challenges: %w\n", challengeErr) } else if len(challenges) == 0 { challengeErr = errors.New("No Challenges found for this Certificate\n") } } } return &Data{ Certificate: crt, CrtEvents: crtEvents, Issuer: issuer, IssuerKind: issuerKind, IssuerError: issuerError, IssuerEvents: issuerEvents, Secret: secret, SecretError: secretErr, SecretEvents: secretEvents, Req: req, ReqError: reqErr, ReqEvents: reqEvents, Order: order, OrderError: orderErr, Challenges: challenges, ChallengeErr: challengeErr, }, nil } // StatusFromResources takes in a Data struct and returns a CertificateStatus built using // the information in data. func StatusFromResources(data *Data) *CertificateStatus { return newCertificateStatusFromCert(data.Certificate). withEvents(data.CrtEvents). withGenericIssuer(data.Issuer, data.IssuerKind, data.IssuerEvents, data.IssuerError). withSecret(data.Secret, data.SecretEvents, data.SecretError). withCR(data.Req, data.ReqEvents, data.ReqError). withOrder(data.Order, data.OrderError). withChallenges(data.Challenges, data.ChallengeErr) } // formatStringSlice takes in a string slice and formats the contents of the slice // into a single string where each element of the slice is prefixed with "- " and on a new line func formatStringSlice(strings []string) string { result := "" for _, str := range strings { result += "- " + str + "\n" } return result } // formatTimeString returns the time as a string // If nil, return "<none>" func formatTimeString(t *metav1.Time) string { if t == nil { return "<none>" } return t.Time.Format(time.RFC3339) } // findMatchingCR tries to find a CertificateRequest that is owned by crt and has the correct revision annotated from reqs. // If none found returns nil // If one found returns the CR // If multiple found or error occurs when listing CRs, returns error func findMatchingCR(cmClient cmclient.Interface, ctx context.Context, crt *cmapi.Certificate) (*cmapi.CertificateRequest, error) { reqs, err := cmClient.CertmanagerV1().CertificateRequests(crt.Namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, fmt.Errorf("error when listing CertificateRequest resources: %w", err) } possibleMatches := []*cmapi.CertificateRequest{} // CertificateRequest revisions begin from 1. // If no revision is set on the Certificate then assume the revision on the CertificateRequest should be 1. // If revision is set on the Certificate then revision on the CertificateRequest should be crt.Status.Revision + 1. nextRevision := 1 if crt.Status.Revision != nil { nextRevision = *crt.Status.Revision + 1 } for _, req := range reqs.Items { if predicate.CertificateRequestRevision(nextRevision)(&req) && /* #nosec G601 -- Pointer does not outlive function scope */ predicate.ResourceOwnedBy(crt)(&req) /* #nosec G601 -- Pointer does not outlive function scope */ { possibleMatches = append(possibleMatches, req.DeepCopy()) } } switch { case len(possibleMatches) < 1: return nil, nil case len(possibleMatches) == 1: return possibleMatches[0], nil default: return nil, errors.New("found multiple certificate requests with expected revision and owner") } } // findMatchingOrder tries to find an Order that is owned by req. // If none found returns nil // If one found returns the Order // If multiple found or error occurs when listing Orders, returns error func findMatchingOrder(cmClient cmclient.Interface, ctx context.Context, req *cmapi.CertificateRequest) (*cmacme.Order, error) { orders, err := cmClient.AcmeV1().Orders(req.Namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, err } possibleMatches := []*cmacme.Order{} for _, order := range orders.Items { if predicate.ResourceOwnedBy(req)(&order) /* #nosec G601 -- Pointer does not outlive function scope */ { possibleMatches = append(possibleMatches, order.DeepCopy()) } } switch { case len(possibleMatches) < 1: return nil, nil case len(possibleMatches) == 1: return possibleMatches[0], nil default: return nil, fmt.Errorf("found multiple orders owned by CertificateRequest %s", req.Name) } } func getGenericIssuer(cmClient cmclient.Interface, ctx context.Context, crt *cmapi.Certificate) (cmapi.GenericIssuer, string, error) { issuerKind := crt.Spec.IssuerRef.Kind if issuerKind == "" { issuerKind = "Issuer" } switch { case crt.Spec.IssuerRef.Group != "cert-manager.io" && crt.Spec.IssuerRef.Group != "": // TODO: Support Issuers/ClusterIssuers from other groups as well return nil, "", fmt.Errorf("The %s %q is not of the group cert-manager.io, this command currently does not support third party issuers.\nTo get more information about %q, try 'kubectl describe'\n", issuerKind, crt.Spec.IssuerRef.Name, crt.Spec.IssuerRef.Name) case issuerKind == "Issuer": issuer, issuerErr := cmClient.CertmanagerV1().Issuers(crt.Namespace).Get(ctx, crt.Spec.IssuerRef.Name, metav1.GetOptions{}) if issuerErr != nil { issuerErr = fmt.Errorf("error when getting Issuer: %v\n", issuerErr) } return issuer, issuerKind, issuerErr default: // ClusterIssuer clusterIssuer, issuerErr := cmClient.CertmanagerV1().ClusterIssuers().Get(ctx, crt.Spec.IssuerRef.Name, metav1.GetOptions{}) if issuerErr != nil { issuerErr = fmt.Errorf("error when getting ClusterIssuer: %v\n", issuerErr) } return clusterIssuer, issuerKind, issuerErr } } // findMatchingChallenges tries to find Challenges that are owned by order. // If none found returns empty slice. func findMatchingChallenges(cmClient cmclient.Interface, ctx context.Context, order *cmacme.Order) ([]*cmacme.Challenge, error) { challenges, err := cmClient.AcmeV1().Challenges(order.Namespace).List(ctx, metav1.ListOptions{}) if err != nil { return nil, err } possibleMatches := []*cmacme.Challenge{} for _, challenge := range challenges.Items { if predicate.ResourceOwnedBy(order)(&challenge) /* #nosec G601 -- Pointer does not outlive function scope */ { possibleMatches = append(possibleMatches, challenge.DeepCopy()) } } return possibleMatches, nil } 07070100000098000081A400000000000000000000000166DFF09D00003E19000000000000000000000000000000000000003700000000cmctl-2.1.1/pkg/status/certificate/certificate_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package certificate import ( "crypto/x509" "errors" "math/big" "strings" "testing" "time" cmacme "github.com/cert-manager/cert-manager/pkg/apis/acme/v1" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" "github.com/cert-manager/cert-manager/test/unit/gen" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestFormatStringSlice(t *testing.T) { tests := map[string]struct { slice []string expOutput string }{ // Newlines are part of the expected output "Empty slice returns empty string": { slice: []string{}, expOutput: ``, }, "Slice with one element returns string with one line": { slice: []string{"hello"}, expOutput: `- hello `, }, "Slice with multiple elements returns string with multiple lines": { slice: []string{"hello", "World", "another line"}, expOutput: `- hello - World - another line `, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if actualOutput := formatStringSlice(test.slice); actualOutput != test.expOutput { t.Errorf("Unexpected output; expected: \n%s\nactual: \n%s", test.expOutput, actualOutput) } }) } } func TestCRInfoString(t *testing.T) { tests := map[string]struct { cr *cmapi.CertificateRequest err error expOutput string }{ // Newlines are part of the expected output "Nil pointer output correct": { cr: nil, err: errors.New("No CertificateRequest found for this Certificate\n"), expOutput: `No CertificateRequest found for this Certificate `, }, "CR with no condition output correct": { cr: &cmapi.CertificateRequest{Status: cmapi.CertificateRequestStatus{Conditions: []cmapi.CertificateRequestCondition{}}}, expOutput: `CertificateRequest: Name: Namespace: Conditions: No Conditions set Events: <none> `, }, "CR with conditions output correct": { cr: &cmapi.CertificateRequest{ Status: cmapi.CertificateRequestStatus{ Conditions: []cmapi.CertificateRequestCondition{ {Type: cmapi.CertificateRequestConditionReady, Status: cmmeta.ConditionTrue, Message: "example"}, }}}, expOutput: `CertificateRequest: Name: Namespace: Conditions: Ready: True, Reason: , Message: example Events: <none> `, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { actualOutput := (&CertificateStatus{}).withCR(test.cr, nil, test.err).CRStatus.String() if strings.ReplaceAll(actualOutput, " \n", "\n") != strings.ReplaceAll(test.expOutput, " \n", "\n") { t.Errorf("Unexpected output; expected: \n%s\nactual: \n%s", test.expOutput, actualOutput) } }) } } func TestKeyUsageToString(t *testing.T) { tests := map[string]struct { usage x509.KeyUsage expOutput string }{ "no key usage set": { usage: x509.KeyUsage(0), expOutput: "", }, "key usage Digital Signature": { usage: x509.KeyUsageDigitalSignature, expOutput: "Digital Signature", }, "key usage Digital Signature and Data Encipherment": { usage: x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment, expOutput: "Digital Signature, Data Encipherment", }, "key usage with three usages is ordered": { usage: x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment | x509.KeyUsageContentCommitment, expOutput: "Digital Signature, Content Commitment, Data Encipherment", }, } for name, test := range tests { t.Run(name, func(t *testing.T) { if actualOutput := keyUsageToString(test.usage); actualOutput != test.expOutput { t.Errorf("Unexpected output; expected: \n%s\nactual: \n%s", test.expOutput, actualOutput) } }) } } func TestExtKeyUsageToString(t *testing.T) { tests := map[string]struct { extUsage []x509.ExtKeyUsage expOutput string expError bool expErrorOutput string }{ "no extended key usage": { extUsage: []x509.ExtKeyUsage{}, expOutput: "", }, "extended key usage Any": { extUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, expOutput: "Any", }, "multiple extended key usages": { extUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageEmailProtection}, expOutput: "Client Authentication, Email Protection", }, "undefined extended key usage": { extUsage: []x509.ExtKeyUsage{x509.ExtKeyUsage(42)}, expOutput: "", expError: true, expErrorOutput: "error when converting Extended Usages to string: encountered unknown Extended Usage with code 42", }, } for name, test := range tests { t.Run(name, func(t *testing.T) { actualOutput, err := extKeyUsageToString(test.extUsage) if err != nil { if !test.expError || test.expErrorOutput != err.Error() { t.Errorf("got unexpected error. This test expects an error: %t. expected error: %q, actual error: %q", test.expError, test.expErrorOutput, err.Error()) } } else if test.expError { t.Errorf("expects error: %q, but did not get any", test.expErrorOutput) } if actualOutput != test.expOutput { t.Errorf("Unexpected output; expected: \n%s\nactual: \n%s", test.expOutput, actualOutput) } }) } } func TestStatusFromResources(t *testing.T) { timestamp, err := time.Parse(time.RFC3339, "2020-09-16T09:26:18Z") if err != nil { t.Fatal(err) } tlsCrt := []byte(`-----BEGIN CERTIFICATE----- MIICyTCCAbGgAwIBAgIRAOL4jtyULBSEYyGdqQn9YzowDQYJKoZIhvcNAQELBQAw DzENMAsGA1UEAxMEdGVzdDAeFw0yMDA3MzAxNjExNDNaFw0yMDEwMjgxNjExNDNa MA8xDTALBgNVBAMTBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQDdfNmjh5ag7f6U1hj1OAx/dEN9kQzPsSlBMXGb/Ho4k5iegrFd6w8JkYdCthFv lfg3bIhw5tCKaw1o57HnWKBKKGt7XpeIu1mEcv8pveMIPO7TZ4+oElgX880NfJmL DkjEcctEo/+FurudO1aEbNfbNWpzudYKj7gGtYshBytqaYt4/APqWARJBFCYVVys wexZ0fLi5cBD8H1bQ1Ec3OCr5Mrq9thAGkj+rVlgYR0AZVGa9+SCOj27t6YCmyzR AJSEQ35v58Zfxp5tNyYd6wcAswJ9YipnUXvwahF95PNlRmMhp3Eo15m9FxehcVXU BOfxykMwZN7onMhuHiiwiB+NAgMBAAGjIDAeMA4GA1UdDwEB/wQEAwIFoDAMBgNV HRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQALrnldWjTBTvV5WKapUHUG0rhA vp2Cf+5FsPw8vKScXp4L+wKGdPOjhHz6NOiw5wu8A0HxlVUFawRpagkjFkeTL78O 9ghBHLiqn9xNPIKC6ID3WpnN5terwQxQeO/M54sVMslUWCcZm9Pu4Eb//2e6wEdu eMmpfeISQmCsBC1CTmpxUjeUg5DEQ0X1TQykXq+bG2iso6RYPxZTFTHJFzXiDYEc /X7H+bOmpo/dMrXapwfvp2gD+BEq96iVpf/DBzGYNs/657LAHJ4YtxtAZCa1CK9G MA6koCR/K23HZfML8vT6lcHvQJp9XXaHRIe9NX/M/2f6VpfO7JjKWLou5k5a -----END CERTIFICATE-----`) serialNum, _ := new(big.Int).SetString("301696114246524167282555582613204853562", 10) ns := "ns1" dummyEventList := &corev1.EventList{ Items: []corev1.Event{{ Type: "type", Reason: "reason", Message: "message", }}, } tests := map[string]struct { inputData *Data expOutput *CertificateStatus }{ "Correct information extracted from Certificate resource": { inputData: &Data{ Certificate: gen.Certificate("test-crt", gen.SetCertificateNamespace(ns), gen.SetCertificateNotAfter(metav1.Time{Time: timestamp}), gen.SetCertificateNotBefore(metav1.Time{Time: timestamp}), gen.SetCertificateRenewalTime(metav1.Time{Time: timestamp}), gen.SetCertificateStatusCondition(cmapi.CertificateCondition{Type: cmapi.CertificateConditionReady, Status: cmmeta.ConditionTrue, Message: "Certificate is up to date and has not expired"}), gen.SetCertificateDNSNames("example.com"), ), CrtEvents: dummyEventList, }, expOutput: &CertificateStatus{ Name: "test-crt", Namespace: ns, CreationTime: metav1.Time{}, Conditions: []cmapi.CertificateCondition{{Type: cmapi.CertificateConditionReady, Status: cmmeta.ConditionTrue, Message: "Certificate is up to date and has not expired"}}, DNSNames: []string{"example.com"}, Events: dummyEventList, NotBefore: &metav1.Time{Time: timestamp}, NotAfter: &metav1.Time{Time: timestamp}, RenewalTime: &metav1.Time{Time: timestamp}, }, }, "Issuer correctly with Kind Issuer": { inputData: &Data{ Certificate: gen.Certificate("test-crt", gen.SetCertificateNamespace(ns)), Issuer: gen.Issuer("test-issuer"), IssuerKind: "Issuer", IssuerError: nil, IssuerEvents: dummyEventList, }, expOutput: &CertificateStatus{ Name: "test-crt", Namespace: ns, CreationTime: metav1.Time{}, IssuerStatus: &IssuerStatus{ Name: "test-issuer", Kind: "Issuer", Events: dummyEventList, }, }, }, "Issuer correctly with Kind ClusterIssuer": { inputData: &Data{ Certificate: gen.Certificate("test-crt", gen.SetCertificateNamespace(ns)), Issuer: gen.Issuer("test-clusterissuer"), IssuerKind: "ClusterIssuer", IssuerError: nil, IssuerEvents: dummyEventList, }, expOutput: &CertificateStatus{ Name: "test-crt", Namespace: ns, CreationTime: metav1.Time{}, IssuerStatus: &IssuerStatus{ Name: "test-clusterissuer", Kind: "ClusterIssuer", Events: dummyEventList, }, }, }, "Correct information extracted from Secret resource": { inputData: &Data{ Certificate: gen.Certificate("test-crt", gen.SetCertificateNamespace(ns)), Secret: gen.Secret("existing-tls-secret", gen.SetSecretNamespace(ns), gen.SetSecretData(map[string][]byte{"tls.crt": tlsCrt})), SecretError: nil, SecretEvents: dummyEventList, }, expOutput: &CertificateStatus{ Name: "test-crt", Namespace: ns, CreationTime: metav1.Time{}, SecretStatus: &SecretStatus{ Error: nil, Name: "existing-tls-secret", IssuerCountry: nil, IssuerOrganisation: nil, IssuerCommonName: "test", KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: nil, PublicKeyAlgorithm: x509.RSA, SignatureAlgorithm: x509.SHA256WithRSA, SubjectKeyId: nil, AuthorityKeyId: nil, SerialNumber: serialNum, Events: dummyEventList, }, }, }, "Correct information extracted from CR resource": { inputData: &Data{ Certificate: gen.Certificate("test-crt", gen.SetCertificateNamespace(ns)), Req: gen.CertificateRequest("test-req", gen.SetCertificateRequestNamespace(ns), gen.SetCertificateRequestStatusCondition(cmapi.CertificateRequestCondition{Type: cmapi.CertificateRequestConditionReady, Status: cmmeta.ConditionFalse, Reason: "Pending", Message: "Waiting on certificate issuance from order default/example-order: \"pending\""})), ReqError: nil, ReqEvents: dummyEventList, }, expOutput: &CertificateStatus{ Name: "test-crt", Namespace: ns, CreationTime: metav1.Time{}, CRStatus: &CRStatus{ Error: nil, Name: "test-req", Namespace: ns, Conditions: []cmapi.CertificateRequestCondition{{Type: cmapi.CertificateRequestConditionReady, Status: cmmeta.ConditionFalse, Reason: "Pending", Message: "Waiting on certificate issuance from order default/example-order: \"pending\""}}, Events: dummyEventList, }, }, }, "Correct information extracted from Order resource": { inputData: &Data{ Certificate: gen.Certificate("test-crt", gen.SetCertificateNamespace(ns)), Order: &cmacme.Order{ TypeMeta: metav1.TypeMeta{}, ObjectMeta: metav1.ObjectMeta{Name: "example-order", Namespace: ns}, Spec: cmacme.OrderSpec{Request: []byte("dummyCSR"), DNSNames: []string{"www.example.com"}}, Status: cmacme.OrderStatus{}, }, OrderError: nil, }, expOutput: &CertificateStatus{ Name: "test-crt", Namespace: ns, CreationTime: metav1.Time{}, OrderStatus: &OrderStatus{ Error: nil, Name: "example-order", State: "", Reason: "", Authorizations: nil, FailureTime: nil, }, }, }, "Correct information extracted from Challenge resources": { inputData: &Data{ Certificate: gen.Certificate("test-crt", gen.SetCertificateNamespace(ns)), Challenges: []*cmacme.Challenge{ { TypeMeta: metav1.TypeMeta{}, ObjectMeta: metav1.ObjectMeta{Name: "test-challenge1", Namespace: ns}, Spec: cmacme.ChallengeSpec{ Type: "HTTP-01", Token: "token", Key: "key", }, Status: cmacme.ChallengeStatus{ Processing: false, Presented: false, Reason: "reason", State: "state", }, }, { TypeMeta: metav1.TypeMeta{}, ObjectMeta: metav1.ObjectMeta{Name: "test-challenge2", Namespace: ns}, Spec: cmacme.ChallengeSpec{ Type: "HTTP-01", Token: "token", Key: "key", }, Status: cmacme.ChallengeStatus{ Processing: false, Presented: false, Reason: "reason", State: "state", }, }, }, ChallengeErr: nil, }, expOutput: &CertificateStatus{ Name: "test-crt", Namespace: ns, CreationTime: metav1.Time{}, ChallengeStatusList: &ChallengeStatusList{ ChallengeStatuses: []*ChallengeStatus{ { Name: "test-challenge1", Type: "HTTP-01", Token: "token", Key: "key", State: "state", Reason: "reason", Processing: false, Presented: false, }, { Name: "test-challenge2", Type: "HTTP-01", Token: "token", Key: "key", State: "state", Reason: "reason", Processing: false, Presented: false, }, }, }, }, }, "When error, ignore rest of the info about the resource": { inputData: &Data{ Certificate: gen.Certificate("test-crt", gen.SetCertificateNamespace(ns)), CrtEvents: nil, Issuer: gen.Issuer("test-issuer"), IssuerKind: "", IssuerError: errors.New("dummy error"), IssuerEvents: dummyEventList, Secret: gen.Secret("test-secret"), SecretError: errors.New("dummy error"), SecretEvents: dummyEventList, Req: gen.CertificateRequest("test-req"), ReqError: errors.New("dummy error"), ReqEvents: dummyEventList, Order: &cmacme.Order{ ObjectMeta: metav1.ObjectMeta{Name: "test-order"}, }, OrderError: errors.New("dummy error"), Challenges: []*cmacme.Challenge{{ObjectMeta: metav1.ObjectMeta{Name: "test-challenge"}}}, ChallengeErr: errors.New("dummy error"), }, expOutput: &CertificateStatus{ Name: "test-crt", Namespace: ns, CreationTime: metav1.Time{}, IssuerStatus: &IssuerStatus{Error: errors.New("dummy error")}, SecretStatus: &SecretStatus{Error: errors.New("dummy error")}, CRStatus: &CRStatus{Error: errors.New("dummy error")}, OrderStatus: &OrderStatus{Error: errors.New("dummy error")}, ChallengeStatusList: &ChallengeStatusList{Error: errors.New("dummy error")}, }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { got := StatusFromResources(test.inputData) assert.Equal(t, test.expOutput, got) }) } } 07070100000099000081A400000000000000000000000166DFF09D00004125000000000000000000000000000000000000002C00000000cmctl-2.1.1/pkg/status/certificate/types.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package certificate import ( "bytes" "crypto/x509" "encoding/hex" "fmt" "math/big" "strings" cmacme "github.com/cert-manager/cert-manager/pkg/apis/acme/v1" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "github.com/cert-manager/cert-manager/pkg/util/pki" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubectl/pkg/describe" "github.com/cert-manager/cmctl/v2/pkg/status/util" ) type CertificateStatus struct { // Name of the Certificate resource Name string // Namespace of the Certificate resource Namespace string // Creation Time of Certificate resource CreationTime metav1.Time // Conditions of Certificate resource Conditions []cmapi.CertificateCondition // DNS Names of Certificate resource DNSNames []string // Events of Certificate resource Events *v1.EventList // Not Before of Certificate resource NotBefore *metav1.Time // Not After of Certificate resource NotAfter *metav1.Time // Renewal Time of Certificate resource RenewalTime *metav1.Time IssuerStatus *IssuerStatus SecretStatus *SecretStatus CRStatus *CRStatus OrderStatus *OrderStatus ChallengeStatusList *ChallengeStatusList } type IssuerStatus struct { // If Error is not nil, there was a problem getting the status of the Issuer/ClusterIssuer resource, // so the rest of the fields is unusable Error error // Name of the Issuer/ClusterIssuer resource Name string // Kind of the resource, can be Issuer or ClusterIssuer Kind string // Conditions of Issuer/ClusterIssuer resource Conditions []cmapi.IssuerCondition // Events of Issuer/ClusterIssuer resource Events *v1.EventList } type SecretStatus struct { // If Error is not nil, there was a problem getting the status of the Secret resource, // so the rest of the fields is unusable Error error // Name of the Secret resource Name string // Issuer Countries of the x509 certificate in the Secret IssuerCountry []string // Issuer Organisations of the x509 certificate in the Secret IssuerOrganisation []string // Issuer Common Name of the x509 certificate in the Secret IssuerCommonName string // Key Usage of the x509 certificate in the Secret KeyUsage x509.KeyUsage // Extended Key Usage of the x509 certificate in the Secret ExtKeyUsage []x509.ExtKeyUsage // Public Key Algorithm of the x509 certificate in the Secret PublicKeyAlgorithm x509.PublicKeyAlgorithm // Signature Algorithm of the x509 certificate in the Secret SignatureAlgorithm x509.SignatureAlgorithm // Subject Key Id of the x509 certificate in the Secret SubjectKeyId []byte // Authority Key Id of the x509 certificate in the Secret AuthorityKeyId []byte // Serial Number of the x509 certificate in the Secret SerialNumber *big.Int // Events of Secret resource Events *v1.EventList } type CRStatus struct { // If Error is not nil, there was a problem getting the status of the CertificateRequest resource, // so the rest of the fields is unusable Error error // Name of the CertificateRequest resource Name string // Namespace of the CertificateRequest resource Namespace string // Conditions of CertificateRequest resource Conditions []cmapi.CertificateRequestCondition // Events of CertificateRequest resource Events *v1.EventList } type OrderStatus struct { // If Error is not nil, there was a problem getting the status of the Order resource, // so the rest of the fields is unusable Error error // Name of the Order resource Name string // State of Order resource State cmacme.State // Reason why the Order resource is in its State Reason string // What authorizations must be completed to validate the DNS names specified on the Order Authorizations []cmacme.ACMEAuthorization // Time the Order failed FailureTime *metav1.Time } type ChallengeStatusList struct { // If Error is not nil, there was a problem getting the status of the Order resource, // so the rest of the fields is unusable Error error ChallengeStatuses []*ChallengeStatus } type ChallengeStatus struct { Name string Type cmacme.ACMEChallengeType Token string Key string State cmacme.State Reason string Processing bool Presented bool } func newCertificateStatusFromCert(crt *cmapi.Certificate) *CertificateStatus { if crt == nil { return nil } return &CertificateStatus{ Name: crt.Name, Namespace: crt.Namespace, CreationTime: crt.CreationTimestamp, Conditions: crt.Status.Conditions, DNSNames: crt.Spec.DNSNames, NotBefore: crt.Status.NotBefore, NotAfter: crt.Status.NotAfter, RenewalTime: crt.Status.RenewalTime} } func (status *CertificateStatus) withEvents(events *v1.EventList) *CertificateStatus { status.Events = events return status } func (status *CertificateStatus) withGenericIssuer(genericIssuer cmapi.GenericIssuer, issuerKind string, issuerEvents *v1.EventList, err error) *CertificateStatus { if err != nil { status.IssuerStatus = &IssuerStatus{Error: err} return status } if genericIssuer == nil { return status } if issuerKind == "ClusterIssuer" { status.IssuerStatus = &IssuerStatus{Name: genericIssuer.GetName(), Kind: "ClusterIssuer", Conditions: genericIssuer.GetStatus().Conditions, Events: issuerEvents} return status } status.IssuerStatus = &IssuerStatus{Name: genericIssuer.GetName(), Kind: "Issuer", Conditions: genericIssuer.GetStatus().Conditions, Events: issuerEvents} return status } func (status *CertificateStatus) withSecret(secret *v1.Secret, secretEvents *v1.EventList, err error) *CertificateStatus { if err != nil { status.SecretStatus = &SecretStatus{Error: err} return status } if secret == nil { return status } certData := secret.Data["tls.crt"] if len(certData) == 0 { status.SecretStatus = &SecretStatus{Error: fmt.Errorf("error: 'tls.crt' of Secret %q is not set\n", secret.Name)} return status } x509Cert, err := pki.DecodeX509CertificateBytes(certData) if err != nil { status.SecretStatus = &SecretStatus{Error: fmt.Errorf("error when parsing 'tls.crt' of Secret %q: %s\n", secret.Name, err)} return status } status.SecretStatus = &SecretStatus{Error: nil, Name: secret.Name, IssuerCountry: x509Cert.Issuer.Country, IssuerOrganisation: x509Cert.Issuer.Organization, IssuerCommonName: x509Cert.Issuer.CommonName, KeyUsage: x509Cert.KeyUsage, ExtKeyUsage: x509Cert.ExtKeyUsage, PublicKeyAlgorithm: x509Cert.PublicKeyAlgorithm, SignatureAlgorithm: x509Cert.SignatureAlgorithm, SubjectKeyId: x509Cert.SubjectKeyId, AuthorityKeyId: x509Cert.AuthorityKeyId, SerialNumber: x509Cert.SerialNumber, Events: secretEvents} return status } func (status *CertificateStatus) withCR(req *cmapi.CertificateRequest, events *v1.EventList, err error) *CertificateStatus { if err != nil { status.CRStatus = &CRStatus{Error: err} return status } if req == nil { return status } status.CRStatus = &CRStatus{Name: req.Name, Namespace: req.Namespace, Conditions: req.Status.Conditions, Events: events} return status } func (status *CertificateStatus) withOrder(order *cmacme.Order, err error) *CertificateStatus { if err != nil { status.OrderStatus = &OrderStatus{Error: err} return status } if order == nil { return status } status.OrderStatus = &OrderStatus{Name: order.Name, State: order.Status.State, Reason: order.Status.Reason, Authorizations: order.Status.Authorizations, FailureTime: order.Status.FailureTime} return status } func (status *CertificateStatus) withChallenges(challenges []*cmacme.Challenge, err error) *CertificateStatus { if err != nil { status.ChallengeStatusList = &ChallengeStatusList{Error: err} return status } if len(challenges) == 0 { return status } var list []*ChallengeStatus for _, challenge := range challenges { list = append(list, &ChallengeStatus{ Name: challenge.Name, Type: challenge.Spec.Type, Token: challenge.Spec.Token, Key: challenge.Spec.Key, State: challenge.Status.State, Reason: challenge.Status.Reason, Processing: challenge.Status.Processing, Presented: challenge.Status.Presented, }) } status.ChallengeStatusList = &ChallengeStatusList{ChallengeStatuses: list} return status } func (status *CertificateStatus) String() string { output := "" output += fmt.Sprintf("Name: %s\n", status.Name) output += fmt.Sprintf("Namespace: %s\n", status.Namespace) output += fmt.Sprintf("Created at: %s\n", formatTimeString(&status.CreationTime)) // Output one line about each type of Condition that is set. // Certificate can have multiple Conditions of different types set, e.g. "Ready" or "Issuing" conditionMsg := "" for _, con := range status.Conditions { conditionMsg += fmt.Sprintf(" %s: %s, Reason: %s, Message: %s\n", con.Type, con.Status, con.Reason, con.Message) } if conditionMsg == "" { conditionMsg = " No Conditions set\n" } output += fmt.Sprintf("Conditions:\n%s", conditionMsg) output += fmt.Sprintf("DNS Names:\n%s", formatStringSlice(status.DNSNames)) output += eventsToString(status.Events, 0) output += status.IssuerStatus.String() output += status.SecretStatus.String() output += fmt.Sprintf("Not Before: %s\n", formatTimeString(status.NotBefore)) output += fmt.Sprintf("Not After: %s\n", formatTimeString(status.NotAfter)) output += fmt.Sprintf("Renewal Time: %s\n", formatTimeString(status.RenewalTime)) output += status.CRStatus.String() // OrderStatus is nil is not found or Issuer/ClusterIssuer is not ACME Issuer if status.OrderStatus != nil { output += status.OrderStatus.String() } if status.ChallengeStatusList != nil { output += status.ChallengeStatusList.String() } return output } // String returns the information about the status of a Issuer/ClusterIssuer as a string to be printed as output func (issuerStatus *IssuerStatus) String() string { if issuerStatus.Error != nil { return issuerStatus.Error.Error() } issuerFormat := `Issuer: Name: %s Kind: %s Conditions: %s` conditionMsg := "" for _, con := range issuerStatus.Conditions { conditionMsg += fmt.Sprintf(" %s: %s, Reason: %s, Message: %s\n", con.Type, con.Status, con.Reason, con.Message) } if conditionMsg == "" { conditionMsg = " No Conditions set\n" } output := fmt.Sprintf(issuerFormat, issuerStatus.Name, issuerStatus.Kind, conditionMsg) output += eventsToString(issuerStatus.Events, 1) return output } // String returns the information about the status of a Secret as a string to be printed as output func (secretStatus *SecretStatus) String() string { if secretStatus.Error != nil { return secretStatus.Error.Error() } detailsFormat := `Secret: Name: %s Issuer Country: %s Issuer Organisation: %s Issuer Common Name: %s Key Usage: %s Extended Key Usages: %s Public Key Algorithm: %s Signature Algorithm: %s Subject Key ID: %s Authority Key ID: %s Serial Number: %s ` extKeyUsageString, err := extKeyUsageToString(secretStatus.ExtKeyUsage) if err != nil { extKeyUsageString = err.Error() } output := fmt.Sprintf(detailsFormat, secretStatus.Name, strings.Join(secretStatus.IssuerCountry, ", "), strings.Join(secretStatus.IssuerOrganisation, ", "), secretStatus.IssuerCommonName, keyUsageToString(secretStatus.KeyUsage), extKeyUsageString, secretStatus.PublicKeyAlgorithm, secretStatus.SignatureAlgorithm, hex.EncodeToString(secretStatus.SubjectKeyId), hex.EncodeToString(secretStatus.AuthorityKeyId), hex.EncodeToString(secretStatus.SerialNumber.Bytes())) output += eventsToString(secretStatus.Events, 1) return output } var ( keyUsageToStringMap = map[int]string{ 1: "Digital Signature", 2: "Content Commitment", 4: "Key Encipherment", 8: "Data Encipherment", 16: "Key Agreement", 32: "Cert Sign", 64: "CRL Sign", 128: "Encipher Only", 256: "Decipher Only", } keyUsagePossibleValues = []int{256, 128, 64, 32, 16, 8, 4, 2, 1} extKeyUsageStringValues = []string{"Any", "Server Authentication", "Client Authentication", "Code Signing", "Email Protection", "IPSEC End System", "IPSEC Tunnel", "IPSEC User", "Time Stamping", "OCSP Signing", "Microsoft Server Gated Crypto", "Netscape Server Gated Crypto", "Microsoft Commercial Code Signing", "Microsoft Kernel Code Signing", } ) func keyUsageToString(usage x509.KeyUsage) string { usageInt := int(usage) var usageStrings []string for _, val := range keyUsagePossibleValues { if usageInt >= val { usageInt -= val usageStrings = append(usageStrings, keyUsageToStringMap[val]) } if usageInt == 0 { break } } // Reversing because that's usually the order the usages are printed for i := 0; i < len(usageStrings)/2; i++ { opp := len(usageStrings) - 1 - i usageStrings[i], usageStrings[opp] = usageStrings[opp], usageStrings[i] } return strings.Join(usageStrings, ", ") } func extKeyUsageToString(extUsages []x509.ExtKeyUsage) (string, error) { var extUsageStrings []string for _, extUsage := range extUsages { if extUsage < 0 || int(extUsage) >= len(extKeyUsageStringValues) { return "", fmt.Errorf("error when converting Extended Usages to string: encountered unknown Extended Usage with code %d", extUsage) } extUsageStrings = append(extUsageStrings, extKeyUsageStringValues[extUsage]) } return strings.Join(extUsageStrings, ", "), nil } // String returns the information about the status of a CR as a string to be printed as output func (crStatus *CRStatus) String() string { if crStatus.Error != nil { return crStatus.Error.Error() } crFormat := ` Name: %s Namespace: %s Conditions: %s` conditionMsg := "" for _, con := range crStatus.Conditions { conditionMsg += fmt.Sprintf(" %s: %s, Reason: %s, Message: %s\n", con.Type, con.Status, con.Reason, con.Message) } if conditionMsg == "" { conditionMsg = " No Conditions set\n" } infos := fmt.Sprintf(crFormat, crStatus.Name, crStatus.Namespace, conditionMsg) infos = fmt.Sprintf("CertificateRequest:%s", infos) infos += eventsToString(crStatus.Events, 1) return infos } // String returns the information about the status of a CR as a string to be printed as output func (orderStatus *OrderStatus) String() string { if orderStatus.Error != nil { return orderStatus.Error.Error() } output := "Order:\n" output += fmt.Sprintf(" Name: %s\n", orderStatus.Name) output += fmt.Sprintf(" State: %s, Reason: %s\n", orderStatus.State, orderStatus.Reason) authString := "" for _, auth := range orderStatus.Authorizations { wildcardString := "nil (bool pointer not set)" if auth.Wildcard != nil { wildcardString = fmt.Sprintf("%t", *auth.Wildcard) } authString += fmt.Sprintf(" URL: %s, Identifier: %s, Initial State: %s, Wildcard: %s\n", auth.URL, auth.Identifier, auth.InitialState, wildcardString) } if authString == "" { output += " No Authorizations for this Order\n" } else { output += " Authorizations:\n" output += authString } if orderStatus.FailureTime != nil { output += fmt.Sprintf(" FailureTime: %s\n", formatTimeString(orderStatus.FailureTime)) } return output } func (c *ChallengeStatusList) String() string { if c.Error != nil { return c.Error.Error() } challengeStrings := []string{} for _, challengeStatus := range c.ChallengeStatuses { challengeStrings = append(challengeStrings, challengeStatus.String()) } output := "Challenges:\n" output += formatStringSlice(challengeStrings) return output } func (challengeStatus *ChallengeStatus) String() string { return fmt.Sprintf("Name: %s, Type: %s, Token: %s, Key: %s, State: %s, Reason: %s, Processing: %t, Presented: %t", challengeStatus.Name, challengeStatus.Type, challengeStatus.Token, challengeStatus.Key, challengeStatus.State, challengeStatus.Reason, challengeStatus.Processing, challengeStatus.Presented) } func eventsToString(events *v1.EventList, baseLevel int) string { var buf bytes.Buffer defer buf.Reset() tabWriter := util.NewTabWriter(&buf) prefixWriter := describe.NewPrefixWriter(tabWriter) util.DescribeEvents(events, prefixWriter, baseLevel) tabWriter.Flush() return buf.String() } 0707010000009A000081A400000000000000000000000166DFF09D00000469000000000000000000000000000000000000002100000000cmctl-2.1.1/pkg/status/status.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package status import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/status/certificate" ) func NewCmdStatus(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { cmds := &cobra.Command{ Use: "status", Short: "Get details on current status of cert-manager resources", Long: `Get details on current status of cert-manager resources, e.g. Certificate`, } cmds.AddCommand(certificate.NewCmdStatusCert(setupCtx, ioStreams)) return cmds } 0707010000009B000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001C00000000cmctl-2.1.1/pkg/status/util0707010000009C000081A400000000000000000000000166DFF09D00000C43000000000000000000000000000000000000002400000000cmctl-2.1.1/pkg/status/util/util.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package util import ( "fmt" "io" "sort" "strings" "text/tabwriter" "time" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/duration" "k8s.io/kubectl/pkg/describe" "k8s.io/kubectl/pkg/util/event" ) // This file contains functions that are copied from "k8s.io/kubectl/pkg/describe". // DescribeEvents was slightly modified. The other functions are copied over. // The purpose of this is to be able to reuse the PrefixWriter interface defined in the describe package, // and because we need to indent certain lines differently than the original function. // DescribeEvents writes a formatted string of the Events in el with PrefixWriter. // The intended use is for w to be created with a *tabWriter.Writer underneath, and the caller // of DescribeEvents would need to call Flush() on that *tabWriter.Writer to actually print the output. func DescribeEvents(el *corev1.EventList, w describe.PrefixWriter, baseLevel int) { if el == nil || len(el.Items) == 0 { w.Write(baseLevel, "Events:\t<none>\n") w.Flush() return } w.Flush() sort.Sort(event.SortableEvents(el.Items)) w.Write(baseLevel, "Events:\n") w.Write(baseLevel+1, "Type\tReason\tAge\tFrom\tMessage\n") w.Write(baseLevel+1, "----\t------\t----\t----\t-------\n") for _, e := range el.Items { var interval string if e.Count > 1 { interval = fmt.Sprintf("%s (x%d over %s)", translateTimestampSince(e.LastTimestamp), e.Count, translateTimestampSince(e.FirstTimestamp)) } else { interval = translateTimestampSince(e.FirstTimestamp) } w.Write(baseLevel+1, "%v\t%v\t%s\t%v\t%v\n", e.Type, e.Reason, interval, formatEventSource(e.Source), strings.TrimSpace(e.Message), ) } w.Flush() } // NewTabWriter returns a *tabwriter.Writer with fixed parameters to be used in the status command func NewTabWriter(writer io.Writer) *tabwriter.Writer { return tabwriter.NewWriter(writer, 0, 8, 2, ' ', 0) } // formatEventSource formats EventSource as a comma separated string excluding Host when empty func formatEventSource(es corev1.EventSource) string { EventSourceString := []string{es.Component} if len(es.Host) > 0 { EventSourceString = append(EventSourceString, es.Host) } return strings.Join(EventSourceString, ", ") } // translateTimestampSince returns the elapsed time since timestamp in // human-readable approximation. func translateTimestampSince(timestamp metav1.Time) string { if timestamp.IsZero() { return "<unknown>" } return duration.HumanDuration(time.Since(timestamp.Time)) } 0707010000009D000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001A00000000cmctl-2.1.1/pkg/uninstall0707010000009E000081A400000000000000000000000166DFF09D00001BD9000000000000000000000000000000000000002700000000cmctl-2.1.1/pkg/uninstall/uninstall.go/* Copyright 2022 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package uninstall import ( "context" "errors" "fmt" "sort" "strings" "github.com/spf13/cobra" "golang.org/x/exp/maps" "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/releaseutil" "helm.sh/helm/v3/pkg/storage/driver" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/cli-runtime/pkg/genericclioptions" "sigs.k8s.io/yaml" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/install/helm" ) type options struct { settings *helm.NormalisedEnvSettings client *action.Uninstall releaseName string dryRun bool wait bool genericclioptions.IOStreams } const ( releaseName = "cert-manager" ) func description(ctx context.Context) string { return build.WithTemplate(ctx, `This command safely uninstalls any Helm-managed release of cert-manager. This command is safe because it will not delete any of the cert-manager CRDs even if they were installed as part of the Helm release. This is to avoid accidentally deleting CRDs and custom resources. This feature is why this command should always be used instead of 'helm uninstall'. Most of the features supported by 'helm uninstall' are also supported by this command. Some example uses: $ {{.BuildName}} x uninstall or $ {{.BuildName}} x uninstall --namespace my-cert-manager or $ {{.BuildName}} x uninstall --dry-run or $ {{.BuildName}} x uninstall --no-hooks `) } func NewCmd(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { settings := helm.NewNormalisedEnvSettings() options := options{ settings: settings, client: action.NewUninstall(settings.ActionConfiguration), IOStreams: ioStreams, } cmd := &cobra.Command{ Use: "uninstall", Short: "Uninstall cert-manager", Long: description(setupCtx), // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { res, err := run(cmd.Context(), options) if err != nil { return err } if options.dryRun { fmt.Fprintf(ioStreams.Out, "%s", res.Release.Manifest) return nil } if res != nil && res.Info != "" { fmt.Fprintln(ioStreams.Out, res.Info) } fmt.Fprintf(ioStreams.Out, "release \"%s\" uninstalled\n", options.releaseName) return nil }, } settings.Setup(setupCtx, cmd) helm.AddInstallUninstallFlags(cmd.Flags(), &options.client.Timeout, &options.wait) cmd.Flags().StringVar(&options.releaseName, "release-name", releaseName, "name of the helm release to uninstall") cmd.Flags().BoolVar(&options.dryRun, "dry-run", false, "simulate uninstall and output manifests to be deleted") return cmd } // run assumes cert-manager was installed as a Helm release named cert-manager. // this is not configurable to avoid uninstalling non-cert-manager releases. func run(ctx context.Context, o options) (*release.UninstallReleaseResponse, error) { // The cert-manager Helm chart currently does not have any uninstall hooks. o.client.DisableHooks = false o.client.DryRun = o.dryRun o.client.Wait = o.wait if o.client.Wait { o.client.DeletionPropagation = "foreground" } else { o.client.DeletionPropagation = "background" } o.client.KeepHistory = false o.client.IgnoreNotFound = true if !o.client.DryRun { if err := addCRDAnnotations(ctx, o); err != nil { return nil, err } } res, err := o.client.Run(o.releaseName) if errors.Is(err, driver.ErrReleaseNotFound) { return nil, fmt.Errorf("release %v not found in namespace %v, did you use the correct namespace?", releaseName, o.settings.Namespace()) } return res, nil } func addCRDAnnotations(_ context.Context, o options) error { if err := o.settings.ActionConfiguration.KubeClient.IsReachable(); err != nil { return err } if err := chartutil.ValidateReleaseName(o.releaseName); err != nil { return fmt.Errorf("uninstall: %v", err) } lastRelease, err := o.settings.ActionConfiguration.Releases.Last(o.releaseName) if err != nil { return fmt.Errorf("uninstall: %v", err) } if lastRelease.Info.Status != release.StatusDeployed { return fmt.Errorf("release %v is in a non-deployed state: %v", o.releaseName, lastRelease.Info.Status) } const ( customResourceDefinitionApiVersionV1 = "apiextensions.k8s.io/v1" customResourceDefinitionApiVersionV1Beta1 = "apiextensions.k8s.io/v1beta1" customResourceDefinitionKind = "CustomResourceDefinition" ) // Check if the release manifest contains CRDs. If it does, we need to modify the // release manifest to add the "helm.sh/resource-policy: keep" annotation to the CRDs. manifests := releaseutil.SplitManifests(lastRelease.Manifest) foundNonAnnotatedCRD := false for key, manifest := range manifests { var entry releaseutil.SimpleHead if err := yaml.Unmarshal([]byte(manifest), &entry); err != nil { return fmt.Errorf("failed to unmarshal manifest: %v", err) } if entry.Kind != customResourceDefinitionKind || (entry.Version != customResourceDefinitionApiVersionV1 && entry.Version != customResourceDefinitionApiVersionV1Beta1) { continue } if entry.Metadata != nil && entry.Metadata.Annotations != nil && entry.Metadata.Annotations["helm.sh/resource-policy"] == "keep" { continue } foundNonAnnotatedCRD = true var object unstructured.Unstructured if err := yaml.Unmarshal([]byte(manifest), &object); err != nil { return fmt.Errorf("failed to unmarshal manifest: %v", err) } annotations := object.GetAnnotations() if annotations == nil { annotations = make(map[string]string) } annotations["helm.sh/resource-policy"] = "keep" object.SetAnnotations(annotations) updatedManifestJSON, err := object.MarshalJSON() if err != nil { return fmt.Errorf("failed to marshal manifest: %v", err) } updatedManifest, err := yaml.JSONToYAML(updatedManifestJSON) if err != nil { return fmt.Errorf("failed to convert manifest to YAML: %v", err) } manifests[key] = string(updatedManifest) } if foundNonAnnotatedCRD { manifestNames := releaseutil.BySplitManifestsOrder(maps.Keys(manifests)) sort.Sort(manifestNames) var fullManifest strings.Builder for _, manifest := range manifestNames { fullManifest.WriteString(manifests[manifest]) fullManifest.WriteString("\n---\n") } lastRelease.Manifest = fullManifest.String() if err := o.settings.ActionConfiguration.Releases.Update(lastRelease); err != nil { o.settings.ActionConfiguration.Log("uninstall: Failed to store updated release: %s", err) } } return nil } 0707010000009F000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001800000000cmctl-2.1.1/pkg/upgrade070701000000A0000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002A00000000cmctl-2.1.1/pkg/upgrade/migrateapiversion070701000000A1000081A400000000000000000000000166DFF09D00001232000000000000000000000000000000000000003500000000cmctl-2.1.1/pkg/upgrade/migrateapiversion/command.go/* Copyright 2022 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package migrateapiversion import ( "context" "github.com/spf13/cobra" apiextinstall "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install" "k8s.io/apimachinery/pkg/runtime" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/kubectl/pkg/util/templates" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/factory" ) // Options is a struct to support renew command type Options struct { genericclioptions.IOStreams *factory.Factory client client.Client skipStoredVersionCheck bool qps float32 burst int } // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } // NewCmdMigrate returns a cobra command for updating resources in an apiserver // to force a new storage version to be used. func NewCmdMigrate(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "migrate-api-version", Short: "Migrate all existing persisted cert-manager resources to the v1 API version", Long: templates.LongDesc(` Ensures resources in your Kubernetes cluster are persisted in the v1 API version. This must be run prior to upgrading to ensure your cluster is ready to upgrade to cert-manager v1.7 and beyond. This command must be run with a cluster running cert-manager v1.0 or greater.`), Example: templates.Examples(build.WithTemplate(setupCtx, ` # Check the cert-manager installation is ready to be upgraded to v1.7 and perform necessary migrations # to ensure that the kube-apiserver has stored only v1 API versions. {{.BuildName}} upgrade migrate-api-version # Force migrations to be run, even if the 'status.storedVersion' field on the CRDs does not contain # old, deprecated API versions. # This should only be used if you have manually edited/patched the CRDs already. # It will force a read and a write of ALL cert-manager resources unconditionally. {{.BuildName}} upgrade migrate-api-version --skip-stored-version-check `)), PreRunE: func(cmd *cobra.Command, args []string) error { if err := o.Validate(args); err != nil { return err } return o.Complete() }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context(), args) }, } cmd.Flags().BoolVar(&o.skipStoredVersionCheck, "skip-stored-version-check", o.skipStoredVersionCheck, ""+ "If true, all resources will be read and written regardless of the 'status.storedVersions' on the CRD resource. "+ "Use this mode if you have previously manually modified the 'status.storedVersions' field on CRD resources.") cmd.Flags().Float32Var(&o.qps, "qps", 5, "Indicates the maximum QPS to the apiserver from the client.") cmd.Flags().IntVar(&o.burst, "burst", 10, "Maximum burst value for queries set to the apiserver from the client.") o.Factory = factory.New(cmd) return cmd } // Validate validates the provided options func (o *Options) Validate(_ []string) error { return nil } // Complete takes the command arguments and factory and infers any remaining options. func (o *Options) Complete() error { var err error scheme := runtime.NewScheme() apiextinstall.Install(scheme) // cminstall.Install(scheme) // acmeinstall.Install(scheme) if o.qps != 0 { o.RESTConfig.QPS = o.qps } if o.burst != 0 { o.RESTConfig.Burst = o.burst } o.client, err = client.New(o.RESTConfig, client.Options{Scheme: scheme}) if err != nil { return err } return nil } // Run executes renew command func (o *Options) Run(ctx context.Context, args []string) error { _, err := NewMigrator(o.client, o.skipStoredVersionCheck, o.Out, o.ErrOut).Run(ctx, "v1", []string{ "certificates.cert-manager.io", "certificaterequests.cert-manager.io", "issuers.cert-manager.io", "clusterissuers.cert-manager.io", "orders.acme.cert-manager.io", "challenges.acme.cert-manager.io", }) return err } 070701000000A2000081A400000000000000000000000166DFF09D00002E03000000000000000000000000000000000000003600000000cmctl-2.1.1/pkg/upgrade/migrateapiversion/migrator.go/* Copyright 2022 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package migrateapiversion import ( "context" "fmt" "io" "time" apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/util/retry" "sigs.k8s.io/controller-runtime/pkg/client" ) type Migrator struct { // Client used for API interactions Client client.Client // If true, skip checking the 'status.storedVersion' before running the migration. // By default, migration will only be run if the CRD contains storedVersions other // than the desired target version. SkipStoredVersionCheck bool // Writers to write informational & error messages to Out, ErrOut io.Writer } // NewMigrator creates a new migrator with the given API client. // If either of out or errOut are nil, log messages will be discarded. func NewMigrator(client client.Client, skipStoredVersionCheck bool, out, errOut io.Writer) *Migrator { if out == nil { out = io.Discard } if errOut == nil { errOut = io.Discard } return &Migrator{ Client: client, SkipStoredVersionCheck: skipStoredVersionCheck, Out: out, ErrOut: errOut, } } // Run begins the migration of all the named CRDs. // It will attempt to migrate all resources defined as part of these CRDs to the // given 'targetVersion', and after completion will update the `status.storedVersions` // field on the corresponding CRD version to only contain the given targetVersion. // Returns 'true' if a migration was actually performed, and false if migration was not required. func (m *Migrator) Run(ctx context.Context, targetVersion string, names []string) (bool, error) { fmt.Fprintf(m.Out, "Checking all CustomResourceDefinitions have storage version set to \"%s\"\n", targetVersion) allTargetVersion, allCRDs, err := m.ensureCRDStorageVersionEquals(ctx, targetVersion, names) if err != nil { return false, err } if !allTargetVersion { fmt.Fprintf(m.ErrOut, "It looks like you are running a version of cert-manager that does not set the storage version of CRDs to %q. You MUST upgrade to cert-manager v1.0-v1.6 before migrating resources for v1.7.\n", targetVersion) return false, fmt.Errorf("preflight checks failed") } fmt.Fprintf(m.Out, "All CustomResourceDefinitions have %q configured as the storage version.\n", targetVersion) crdsRequiringMigration := allCRDs if !m.SkipStoredVersionCheck { fmt.Fprintf(m.Out, "Looking for CRDs that contain resources that require migrating to %q...\n", targetVersion) crdsRequiringMigration, err = m.discoverCRDsRequiringMigration(ctx, targetVersion, names) if err != nil { fmt.Fprintf(m.ErrOut, "Failed to determine resource types that require migration: %v\n", err) return false, err } if len(crdsRequiringMigration) == 0 { fmt.Fprintln(m.Out, "Nothing to do. cert-manager CRDs do not have \"status.storedVersions\" containing old API versions. You may proceed to upgrade to cert-manager v1.7.") return false, nil } } else { fmt.Fprintln(m.Out, "Forcing migration of all CRD resources as --skip-stored-version-check=true") } fmt.Fprintf(m.Out, "Found %d resource types that require migration:\n", len(crdsRequiringMigration)) for _, crd := range crdsRequiringMigration { fmt.Fprintf(m.Out, " - %s (%s)\n", crd.Name, crd.Spec.Names.Kind) } for _, crd := range crdsRequiringMigration { if err := m.migrateResourcesForCRD(ctx, crd); err != nil { fmt.Fprintf(m.ErrOut, "Failed to migrate resource: %v\n", err) return false, err } } fmt.Fprintf(m.Out, "Patching CRD resources to set \"status.storedVersions\" to %q...\n", targetVersion) if err := m.patchCRDStoredVersions(ctx, crdsRequiringMigration); err != nil { fmt.Fprintf(m.ErrOut, "Failed to patch \"status.storedVersions\" field: %v\n", err) return false, err } fmt.Fprintln(m.Out, "Successfully migrated all cert-manager resource types. It is now safe to upgrade to cert-manager v1.7.") return true, nil } func (m *Migrator) ensureCRDStorageVersionEquals(ctx context.Context, vers string, names []string) (bool, []*apiext.CustomResourceDefinition, error) { var crds []*apiext.CustomResourceDefinition for _, crdName := range names { crd := &apiext.CustomResourceDefinition{} if err := m.Client.Get(ctx, client.ObjectKey{Name: crdName}, crd); err != nil { return false, nil, err } // Discover the storage version storageVersion := storageVersionForCRD(crd) if storageVersion != vers { fmt.Fprintf(m.Out, "CustomResourceDefinition object %q has storage version set to %q.\n", crdName, storageVersion) return false, nil, nil } crds = append(crds, crd) } return true, crds, nil } func (m *Migrator) discoverCRDsRequiringMigration(ctx context.Context, desiredStorageVersion string, names []string) ([]*apiext.CustomResourceDefinition, error) { var requireMigration []*apiext.CustomResourceDefinition for _, name := range names { crd := &apiext.CustomResourceDefinition{} if err := m.Client.Get(ctx, client.ObjectKey{Name: name}, crd); err != nil { return nil, err } // If no versions are stored, there's nothing to migrate. if len(crd.Status.StoredVersions) == 0 { continue } // If more than one entry exists in `storedVersions` OR if the only element in there is not // the desired version, perform a migration. if len(crd.Status.StoredVersions) > 1 || crd.Status.StoredVersions[0] != desiredStorageVersion { requireMigration = append(requireMigration, crd) } } return requireMigration, nil } func (m *Migrator) migrateResourcesForCRD(ctx context.Context, crd *apiext.CustomResourceDefinition) error { startTime := time.Now() timeFormat := "15:04:05" fmt.Fprintf(m.Out, "Migrating %q objects in group %q - this may take a while (started at %s)...\n", crd.Spec.Names.Kind, crd.Spec.Group, startTime.Format(timeFormat)) list := &unstructured.UnstructuredList{} list.SetGroupVersionKind(schema.GroupVersionKind{ Group: crd.Spec.Group, Version: storageVersionForCRD(crd), Kind: crd.Spec.Names.ListKind, }) if err := m.Client.List(ctx, list); err != nil { return err } fmt.Fprintf(m.Out, " %d resources to migrate...\n", len(list.Items)) for _, obj := range list.Items { // retry on any kind of error to handle cases where e.g. the network connection to the apiserver fails if err := retry.OnError(wait.Backoff{ Duration: time.Second, // wait 1s between attempts Steps: 3, // allow up to 3 attempts per object }, func(err error) bool { // Retry on any errors that are not otherwise skipped/ignored return handleUpdateErr(err) != nil }, func() error { return m.Client.Update(ctx, &obj) // #nosec G601 -- False positive. See https://github.com/golang/go/discussions/56010 }); handleUpdateErr(err) != nil { return err } } // add 500ms to the duration to ensure we always round up duration := time.Since(startTime) + (time.Millisecond * 500) fmt.Fprintf(m.Out, " Successfully migrated %d %s objects in %s\n", len(list.Items), crd.Spec.Names.Kind, duration.Round(time.Second)) return nil } // patchCRDStoredVersions will patch the `status.storedVersions` field of all passed in CRDs to be // set to an array containing JUST the current storage version. // This is only safe to run after a successful migration (i.e. a read/write of all resources of the given CRD type). func (m *Migrator) patchCRDStoredVersions(ctx context.Context, crds []*apiext.CustomResourceDefinition) error { for _, crd := range crds { // fetch a fresh copy of the CRD to avoid any conflict errors freshCRD := &apiext.CustomResourceDefinition{} if err := m.Client.Get(ctx, client.ObjectKey{Name: crd.Name}, freshCRD); err != nil { return err } // Check the latest copy of the CRD to ensure that: // 1) the storage version is the same as it was at the start of the migration // 2) the status.storedVersion field has not changed, and if it has, it has only added the new/desired storage version // This helps to avoid cases where the storage version was changed by a third-party midway through the migration, // which could lead to corrupted apiservers when we patch the status.storedVersions field below. expectedStorageVersion := storageVersionForCRD(crd) if storageVersionForCRD(freshCRD) != expectedStorageVersion { return newUnexpectedChangeError(crd) } newlyAddedVersions := storedVersionsAdded(crd, freshCRD) if newlyAddedVersions.Len() != 0 && !newlyAddedVersions.Equal(sets.New[string](expectedStorageVersion)) { return newUnexpectedChangeError(crd) } // Set the `status.storedVersions` field to the target storage version freshCRD.Status.StoredVersions = []string{storageVersionForCRD(crd)} if err := m.Client.Status().Update(ctx, freshCRD); err != nil { return err } } return nil } // storageVersionForCRD discovers the storage version for a given CRD. func storageVersionForCRD(crd *apiext.CustomResourceDefinition) string { storageVersion := "" for _, v := range crd.Spec.Versions { if v.Storage { storageVersion = v.Name break } } return storageVersion } // storedVersionsAdded returns a list of any versions added to the `status.storedVersions` field on // a CRD resource. func storedVersionsAdded(oldCRD, newCRD *apiext.CustomResourceDefinition) sets.Set[string] { oldStoredVersions := sets.New[string](oldCRD.Status.StoredVersions...) newStoredVersions := sets.New[string](newCRD.Status.StoredVersions...) return newStoredVersions.Difference(oldStoredVersions) } // newUnexpectedChangeError creates a new 'error' that informs users that a change to the CRDs // was detected during the migration process and so the migration must be re-run. func newUnexpectedChangeError(crd *apiext.CustomResourceDefinition) error { errorFmt := "" + "The CRD %q unexpectedly changed during the migration. " + "This means that either an object was persisted in a non-storage version during the migration, " + "or the storage version was changed by someone else (or some automated deployment tooling) whilst the migration " + "was in progress.\n\n" + "All automated deployment tooling should be in a stable state (i.e. no upgrades to cert-manager CRDs should be" + "in progress whilst the migration is running).\n\n" + "Please ensure no changes to the CRDs are made during the migration process and re-run the migration until you" + "no longer see this message." return fmt.Errorf(errorFmt, crd.Name) } // handleUpdateErr will absorb certain types of errors that we know can be skipped/passed on // during a migration of a particular object. func handleUpdateErr(err error) error { if err == nil { return nil } // If the resource no longer exists, don't return the error as the object no longer // needs updating to the new API version. if apierrors.IsNotFound(err) { return nil } // If there was a conflict, another client must have written the object already which // means we don't need to force an update. if apierrors.IsConflict(err) { return nil } return err } 070701000000A3000081A400000000000000000000000166DFF09D00000468000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/upgrade/upgrade.go/* Copyright 2022 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package upgrade import ( "context" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/upgrade/migrateapiversion" ) func NewCmdUpgrade(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { cmds := &cobra.Command{ Use: "upgrade", Short: "Tools that assist in upgrading cert-manager", Long: `Note: this command does NOT actually upgrade cert-manager installations`, } cmds.AddCommand(migrateapiversion.NewCmdMigrate(setupCtx, ioStreams)) return cmds } 070701000000A4000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001800000000cmctl-2.1.1/pkg/version070701000000A5000081A400000000000000000000000166DFF09D00001665000000000000000000000000000000000000002300000000cmctl-2.1.1/pkg/version/version.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package version import ( "context" "encoding/json" "errors" "fmt" "github.com/cert-manager/cert-manager/pkg/util" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/runtime" "k8s.io/cli-runtime/pkg/genericclioptions" "sigs.k8s.io/yaml" "github.com/cert-manager/cmctl/v2/internal/versionchecker" "github.com/cert-manager/cmctl/v2/pkg/build" "github.com/cert-manager/cmctl/v2/pkg/factory" ) // Version is a struct for version information type Version struct { ClientVersion *util.Version `json:"clientVersion,omitempty"` ServerVersion *versionchecker.Version `json:"serverVersion,omitempty"` } // Options is a struct to support version command type Options struct { // If true, don't try to retrieve the installed version ClientOnly bool // If true, only prints the version number. Short bool // Output is the target output format for the version string. This may be of // value "", "json" or "yaml". Output string VersionChecker versionchecker.Interface genericclioptions.IOStreams *factory.Factory } // NewOptions returns initialized Options func NewOptions(ioStreams genericclioptions.IOStreams) *Options { return &Options{ IOStreams: ioStreams, } } func versionLong(ctx context.Context) string { return build.WithTemplate(ctx, `Print the cert-manager CLI version and the deployed cert-manager version. The CLI version is embedded in the binary and directly displayed. Determining the deployed cert-manager version is done by querying the cert-manger resources. First, the tool looks at the labels of the cert-manager CRD resources. Then, it searches for the labels of the resources related the cert-manager webhook linked in the CRDs. It also tries to derive the version from the docker image tag of that webhook service. After gathering all this version information, the tool checks if all versions are the same and returns that version. If no version information is found or the found versions differ, an error will be displayed. The '--client' flag can be used to disable the logic that tries to determine the installed cert-manager version. Some example uses: $ {{.BuildName}} version or $ {{.BuildName}} version --client or $ {{.BuildName}} version --short or $ {{.BuildName}} version -o yaml `) } // NewCmdVersion returns a cobra command for fetching versions func NewCmdVersion(setupCtx context.Context, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewOptions(ioStreams) cmd := &cobra.Command{ Use: "version", Short: "Print the cert-manager CLI version and the deployed cert-manager version", Long: versionLong(setupCtx), PreRunE: func(cmd *cobra.Command, args []string) error { if err := o.Validate(); err != nil { return err } return o.Complete() }, // nolint:contextcheck // False positive RunE: func(cmd *cobra.Command, args []string) error { return o.Run(cmd.Context()) }, } cmd.Flags().BoolVar(&o.ClientOnly, "client", o.ClientOnly, "If true, shows client version only (no server required).") cmd.Flags().BoolVar(&o.Short, "short", o.Short, "If true, print just the version number.") cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, "One of 'yaml' or 'json'.") o.Factory = factory.New(cmd) return cmd } // Validate validates the provided options func (o *Options) Validate() error { switch o.Output { case "", "yaml", "json": return nil default: return errors.New(`--output must be '', 'yaml' or 'json'`) } } // Complete takes the command arguments and factory and infers any remaining options. func (o *Options) Complete() error { if o.ClientOnly { return nil } versionChecker, err := versionchecker.New( o.RESTConfig, runtime.NewScheme(), ) if err != nil { return err } o.VersionChecker = versionChecker return nil } // Run executes version command func (o *Options) Run(ctx context.Context) error { var ( serverVersion *versionchecker.Version serverErr error versionInfo Version ) clientVersion := util.VersionInfo() versionInfo.ClientVersion = &clientVersion if !o.ClientOnly { serverVersion, serverErr = o.VersionChecker.Version(ctx) versionInfo.ServerVersion = serverVersion } switch o.Output { case "": if o.Short { fmt.Fprintf(o.Out, "Client Version: %s\n", clientVersion.GitVersion) if serverVersion != nil { fmt.Fprintf(o.Out, "Server Version: %s\n", serverVersion.Detected) } } else { fmt.Fprintf(o.Out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion)) if serverVersion != nil { fmt.Fprintf(o.Out, "Server Version: %s\n", fmt.Sprintf("%#v", serverVersion)) } } case "yaml": marshalled, err := yaml.Marshal(&versionInfo) if err != nil { return err } fmt.Fprint(o.Out, string(marshalled)) case "json": marshalled, err := json.MarshalIndent(&versionInfo, "", " ") if err != nil { return err } fmt.Fprintln(o.Out, string(marshalled)) default: // There is a bug in the program if we hit this case. // However, we follow a policy of never panicking. return fmt.Errorf("VersionOptions were not validated: --output=%q should have been rejected", o.Output) } return serverErr } 070701000000A6000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001100000000cmctl-2.1.1/test070701000000A7000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000001D00000000cmctl-2.1.1/test/integration070701000000A8000081A400000000000000000000000166DFF09D00001C11000000000000000000000000000000000000003100000000cmctl-2.1.1/test/integration/ctl_convert_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package ctl import ( "bytes" "os" "testing" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/convert" ) const ( testdataResource1 = "./testdata/convert/input/resource1.yaml" testdataResource2 = "./testdata/convert/input/resource2.yaml" testdataResource3 = "./testdata/convert/input/resource3.yaml" testdataResourceWithOrganizationV1alpha2 = "./testdata/convert/input/resource_with_organization_v1alpha2.yaml" testdataResourcesAsListV1alpha2 = "./testdata/convert/input/resources_as_list_v1alpha2.yaml" testdataNoOutputError = "./testdata/convert/output/no_output_error.yaml" testdataResource1V1 = "./testdata/convert/output/resource1_v1.yaml" testdataResource1V1alpha2 = "./testdata/convert/output/resource1_v1alpha2.yaml" testdataResource1V1alpha3 = "./testdata/convert/output/resource1_v1alpha3.yaml" testdataResource2V1 = "./testdata/convert/output/resource2_v1.yaml" testdataResource2V1alpha2 = "./testdata/convert/output/resource2_v1alpha2.yaml" testdataResource2V1alpha3 = "./testdata/convert/output/resource2_v1alpha3.yaml" testdataResourceWithOrganizationV1alpha3 = "./testdata/convert/output/resource_with_organization_v1alpha3.yaml" testdataResourceWithOrganizationV1beta1 = "./testdata/convert/output/resource_with_organization_v1beta1.yaml" testdataResourceWithOrganizationV1 = "./testdata/convert/output/resource_with_organization_v1.yaml" testdataResourcesOutAsListV1alpha2 = "./testdata/convert/output/resources_as_list_v1alpha2.yaml" testdataResourcesOutAsListV1alpha3 = "./testdata/convert/output/resources_as_list_v1alpha3.yaml" testdataResourcesOutAsListV1beta1 = "./testdata/convert/output/resources_as_list_v1beta1.yaml" testdataResourcesOutAsListV1 = "./testdata/convert/output/resources_as_list_v1.yaml" targetv1alpha2 = "cert-manager.io/v1alpha2" targetv1alpha3 = "cert-manager.io/v1alpha3" targetv1beta1 = "cert-manager.io/v1beta1" targetv1 = "cert-manager.io/v1" ) func TestCtlConvert(t *testing.T) { tests := map[string]struct { input, expOutputFile string targetVersion string expErr bool }{ "a single cert-manager resource should convert to v1 with no target": { input: testdataResource1, expOutputFile: testdataResource1V1, }, "a single cert-manager resource should convert to v1alpha2 with target v1alpha2": { input: testdataResource1, targetVersion: targetv1alpha2, expOutputFile: testdataResource1V1alpha2, }, "a single cert-manager resource should convert to v1alpha3 with target v1alpha3": { input: testdataResource1, targetVersion: targetv1alpha3, expOutputFile: testdataResource1V1alpha3, }, "a list of cert-manager resources should convert to v1 with no target": { input: testdataResource2, expOutputFile: testdataResource2V1, }, "a list of cert-manager resources should convert to v1alpha2 with target v1alpha2": { input: testdataResource2, targetVersion: targetv1alpha2, expOutputFile: testdataResource2V1alpha2, }, "a list of cert-manager resources should convert to v1alpha3 with target v1alpha3": { input: testdataResource2, targetVersion: targetv1alpha3, expOutputFile: testdataResource2V1alpha3, }, "a list of a mix of cert-manager and non cert-manager resources should error with no target": { input: testdataResource3, expOutputFile: testdataNoOutputError, expErr: true, }, "a list of a mix of cert-manager and non cert-manager resources should error with target v1alpha2": { input: testdataResource3, targetVersion: targetv1alpha2, expOutputFile: testdataNoOutputError, expErr: true, }, "a list of a mix of cert-manager and non cert-manager resources should error with target v1alpha3": { input: testdataResource3, targetVersion: targetv1alpha3, expOutputFile: testdataNoOutputError, expErr: true, }, "an object in v1alpha2 that uses a field that has been renamed in v1alpha3 should be converted properly": { input: testdataResourceWithOrganizationV1alpha2, targetVersion: targetv1alpha3, expOutputFile: testdataResourceWithOrganizationV1alpha3, }, "an object in v1alpha2 that uses a field that has been renamed in v1beta1 should be converted properly": { input: testdataResourceWithOrganizationV1alpha2, targetVersion: targetv1beta1, expOutputFile: testdataResourceWithOrganizationV1beta1, }, "an object in v1alpha2 that uses a field that has been renamed in v1 should be converted properly": { input: testdataResourceWithOrganizationV1alpha2, targetVersion: targetv1, expOutputFile: testdataResourceWithOrganizationV1, }, "a list in v1alpha2 should parsed": { input: testdataResourcesAsListV1alpha2, targetVersion: targetv1alpha2, expOutputFile: testdataResourcesOutAsListV1alpha2, }, "a list in v1alpha2 should be converted to v1alpha3": { input: testdataResourcesAsListV1alpha2, targetVersion: targetv1alpha3, expOutputFile: testdataResourcesOutAsListV1alpha3, }, "a list in v1alpha2 should be converted to v1beta1": { input: testdataResourcesAsListV1alpha2, targetVersion: targetv1beta1, expOutputFile: testdataResourcesOutAsListV1beta1, }, "a list in v1alpha2 should be converted to v1": { input: testdataResourcesAsListV1alpha2, targetVersion: targetv1, expOutputFile: testdataResourcesOutAsListV1, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { expOutput, err := os.ReadFile(test.expOutputFile) if err != nil { t.Fatalf("%s: %s", test.expOutputFile, err) } // Run ctl convert command with input options streams, _, outBuf, _ := genericclioptions.NewTestIOStreams() opts := convert.NewOptions(streams) opts.OutputVersion = test.targetVersion opts.Filenames = []string{test.input} if err := opts.Complete(); err != nil { t.Fatal(err) } err = opts.Run() if test.expErr != (err != nil) { t.Errorf("got unexpected error, exp=%t got=%v", test.expErr, err) } if !bytes.Equal(bytes.TrimSpace(expOutput), bytes.TrimSpace(outBuf.Bytes())) { t.Errorf("got unexpected output, exp=%s\n got=%s", bytes.TrimSpace(expOutput), bytes.TrimSpace(outBuf.Bytes())) } }) } } 070701000000A9000081A400000000000000000000000166DFF09D00004823000000000000000000000000000000000000003300000000cmctl-2.1.1/test/integration/ctl_create_cr_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package ctl import ( "bytes" "context" "fmt" "os" "path" "testing" "time" cmapiv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" "github.com/cert-manager/cert-manager/pkg/util/pki" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/create/certificaterequest" "github.com/cert-manager/cmctl/v2/pkg/factory" "github.com/cert-manager/cmctl/v2/test/integration/framework" ) type CreateCRTest struct { inputFile string inputArgs []string inputNamespace string keyFilename string certFilename string fetchCert bool timeout time.Duration crStatus cmapiv1.CertificateRequestStatus expRunErr bool expErrMsg string expNamespace string expName string expKeyFilename string expCertFilename string expCertFileContent []byte } // TestCtlCreateCRBeforeCRIsCreated tests the behaviour in the case where the command fails // after the private key has been written to file and before the CR is successfully created. // Achieved by trying to create two CRs with the same name, storing the private key to two different files. func TestCtlCreateCRBeforeCRIsCreated(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*40) defer cancel() config, stopFn := framework.RunControlPlane(t, ctx) defer stopFn() // Build clients kubernetesCl, cmCl, _, _ := framework.NewClients(t, config) testdataPath := getTestDataDir(t) const ( cr5Name = "testcr-5" ns1 = "testns-1" ) // Create Namespace ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns1}} _, err := kubernetesCl.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } tests := map[string]CreateCRTest{ "path to file to store private key provided": { inputFile: path.Join(testdataPath, "create_cr_cert_with_ns1.yaml"), inputArgs: []string{cr5Name}, inputNamespace: ns1, keyFilename: "test.key", expRunErr: true, expErrMsg: fmt.Sprintf("error creating CertificateRequest: certificaterequests.cert-manager.io %q already exists", cr5Name), expKeyFilename: "test.key", }, } for name, test := range tests { t.Run(name, func(t *testing.T) { streams, _, _, _ := genericclioptions.NewTestIOStreams() cleanUpFunc := setupPathForTest(t) defer cleanUpFunc() // Options to run create CR command opts := &certificaterequest.Options{ InputFilename: test.inputFile, CertFileName: test.certFilename, Factory: &factory.Factory{ CMClient: cmCl, RESTConfig: config, Namespace: test.inputNamespace, EnforceNamespace: test.inputNamespace != "", }, IOStreams: streams, } err := opts.Run(ctx, test.inputArgs) if err != nil { t.Fatal("failed to set up test to fail after writing private key to file and during creating CR") } // By now we have created a CR already // Now we try to create another CR with the same name, but storing the private key somewhere else // This should break after writing private key to file and during creating CR opts.KeyFilename = test.keyFilename // Validating args and flags err = opts.Validate(test.inputArgs) if err != nil { t.Fatal(err) } // Run ctl create cr command with input options err = opts.Run(ctx, test.inputArgs) if err != nil { if !test.expRunErr { t.Errorf("got unexpected error when trying to create CR: %v", err) } else if err.Error() != test.expErrMsg { t.Errorf("got unexpected error when trying to create CR, expected: %v; actual: %v", test.expErrMsg, err) } } else { // got no error if test.expRunErr { t.Errorf("expected but got no error when creating CR") } } // Check the file where the private key is stored keyData, err := os.ReadFile(test.expKeyFilename) if err != nil { t.Errorf("error when reading file storing private key: %v", err) } _, err = pki.DecodePrivateKeyBytes(keyData) if err != nil { t.Errorf("invalid private key: %v", err) } }) } } // TestCtlCreateCRSuccessful tests the behaviour in the case where the command successfully // creates the CR, including the --fetch-certificate logic. func TestCtlCreateCRSuccessful(t *testing.T) { rootCtx, cancelRoot := context.WithTimeout(context.Background(), time.Second*200) defer cancelRoot() config, stopFn := framework.RunControlPlane(t, rootCtx) defer stopFn() // Build clients kubernetesCl, cmCl, _, _ := framework.NewClients(t, config) testdataPath := getTestDataDir(t) const ( cr1Name = "testcr-1" cr2Name = "testcr-2" cr5Name = "testcr-5" cr6Name = "testcr-6" cr7Name = "testcr-7" ns1 = "testns-1" ) exampleCertificate := []byte(`LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZUekNDQkRlZ0F3SUJBZ0lUQVBwOWhMUit2ODF2UTdpZSt6emxTMWY5MFRBTkJna3Foa2lHOXcwQkFRc0YKQURBaU1TQXdIZ1lEVlFRRERCZEdZV3RsSUV4RklFbHVkR1Z5YldWa2FXRjBaU0JZTVRBZUZ3MHlNREEyTXpBeApNelUyTkRoYUZ3MHlNREE1TWpneE16VTJORGhhTUNZeEpEQWlCZ05WQkFNVEcyaGhiM2hwWVc1bkxXZGpjQzVxClpYUnpkR0ZqYTJWeUxtNWxkRENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFOTjIKTS9zZGtPazgvenJLbXNvMEE1SmxoUjRTQU9pTVhiWGZleEpvUzZ3b3krakszNVBCOUFDUDFQcllXR0diZjNYRwo1VngvZmRBSlNmdVFmL0NoZlRsa0kwQUYxUCsxUThhQU9BUXhKdU4ySVJxT0ErNlEwUTg2Vy9oZVFXbUdOUkI4CmxMcHQvWU9IV3NreHRqRDNmN3p1QXZZUkI1czFCZ3o2K2s1REF6d1pGNnlMMEtja1JpY3dFMHh3aisrZkcyeCsKdEpQb1AwdmliM0EzU0xySFhsRW5HbFdEL3ZSbkkrNkc1dFI2ZHJWbGcrcjhSRkFiYTJDc1VpTGFiM252Q2JqUQpDNG9xZWd1NklUNzk4R0thenBXbGw2b3M0SndQdFJnQzlvYS9FeklVanlWeStuRWhHU3pwSmlNQ0NZOS96b0daCmV1TGJ0M1lSdVVIaStiemludnNDQXdFQUFhT0NBbmd3Z2dKME1BNEdBMVVkRHdFQi93UUVBd0lGb0RBZEJnTlYKSFNVRUZqQVVCZ2dyQmdFRkJRY0RBUVlJS3dZQkJRVUhBd0l3REFZRFZSMFRBUUgvQkFJd0FEQWRCZ05WSFE0RQpGZ1FVRGZKNml2NlNoRlhzLzFrUTh5bmR1NGhTUEtrd0h3WURWUjBqQkJnd0ZvQVV3TXdEUnJsWUlNeGNjbkR6CjRTN0xJS2IxYURvd2R3WUlLd1lCQlFVSEFRRUVhekJwTURJR0NDc0dBUVVGQnpBQmhpWm9kSFJ3T2k4dmIyTnoKY0M1emRHY3RhVzUwTFhneExteGxkSE5sYm1OeWVYQjBMbTl5WnpBekJnZ3JCZ0VGQlFjd0FvWW5hSFIwY0RvdgpMMk5sY25RdWMzUm5MV2x1ZEMxNE1TNXNaWFJ6Wlc1amNubHdkQzV2Y21jdk1DWUdBMVVkRVFRZk1CMkNHMmhoCmIzaHBZVzVuTFdkamNDNXFaWFJ6ZEdGamEyVnlMbTVsZERCTUJnTlZIU0FFUlRCRE1BZ0dCbWVCREFFQ0FUQTMKQmdzckJnRUVBWUxmRXdFQkFUQW9NQ1lHQ0NzR0FRVUZCd0lCRmhwb2RIUndPaTh2WTNCekxteGxkSE5sYm1OeQplWEIwTG05eVp6Q0NBUVFHQ2lzR0FRUUIxbmtDQkFJRWdmVUVnZklBOEFCMkFMRE1nK1dsK1gxcnIzd0p6Q2hKCkJJY3F4K2lMRXl4alVMZkcvU2JoYkd4M0FBQUJjd1c3QXB3QUFBUURBRWN3UlFJaEFPai9nNm9ONjNTRnBqa00Ka3FmcjRDUlVzb0dWamZqQzN4MkRFdmR0RVZzNEFpQm05OTFzTHFHUzFJYksrM1VoemZzUDUvNTVjU2FpWkVPcwpwQmdVb1plb0l3QjJBTjJaTlB5bDV5U0F5VlpvZllFMG1RaEpza24zdFduWXg3eXJQMXpCODI1a0FBQUJjd1c3CkJJb0FBQVFEQUVjd1JRSWdVbTRDbW9hdDBIdTZaMUExcFRKbTc4WTRYaHZWcmJIQ3RYUUZaa0QweHZzQ0lRQ0IKbVBSTFFZS2RObUMyMXJLRW5hUjBBRjBZbS9ENEp6NjlhWTJUbEcwM1hqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQwpBUUVBZHZoNFJuUGVaWEliazc3b2xjaTM0K0tZRmxCSUtDbFdUTkl3dXB5NlpGM0NYSlBzSjRQQWUvMGMzTVpaCkZSbDl4SHN2LzNESXZOaU5udkJSblRjdHJFMGp1V0cxYVlrWWIzaGRJMFVNcWlqUHNmc0doZW9LQnpRVDBoREcKRDFET0hPNXB5czQvNnp3NXk2TVMrdkoyVXY3aHlWem1PdldqaFp1c0xvUUZBcmpYY0ROY0puN3N2SkdOMXRFSgpZeUxHSk42SFpMV0xSeU8zdTBHYU9HQkk4SGRmc3JzbGVKaUk4b1ROaXdjaFZuekR1UUlLZFo0M040N0R5QlgwClpjTmplbElzeGtPSlhCUHJQVWJOaGltK1dNWjlicWxpUFZLamlhRUJFQ1BIaVRFK0Y2a3dkRkpkTktJZUVtL3UKR0JTRW5Zdmp2RWRJMzh4U1JWMXZDdDgxUUE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlFcXpDQ0FwT2dBd0lCQWdJUkFJdmhLZzVaUk8wOFZHUXg4SmRoVCtVd0RRWUpLb1pJaHZjTkFRRUxCUUF3CkdqRVlNQllHQTFVRUF3d1BSbUZyWlNCTVJTQlNiMjkwSUZneE1CNFhEVEUyTURVeU16SXlNRGMxT1ZvWERUTTIKTURVeU16SXlNRGMxT1Zvd0lqRWdNQjRHQTFVRUF3d1hSbUZyWlNCTVJTQkpiblJsY20xbFpHbGhkR1VnV0RFdwpnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEdFdLeVNEbjdyV1pjNWdnanozWkIwCjhqTzR4dGkzdXpJTmZENXNRN0xqN2h6ZXRVVCt3UW9iK2lYU1praG52eCtJdmRiWEY1L3l0OGFXUHBVS25QeW0Kb0x4c1lpSTVnUUJMeE5EekllYzBPSWFmbFdxQXIyOW03SjgrTk50QXBFTjhuWkZuZjNiaGVoWlc3QXhtUzFtMApablNzZEh3MEZ3K2JnaXhQZzJNUTlrOW9lZkZlcWErN0txZGx6NWJiclVZVjJ2b2x4aERGdG5JNE1oOEJpV0NOCnhESDFIaXpxK0dLQ2NIc2luRFpXdXJDcWRlci9hZkpCblFzK1NCU0w2TVZBcEh0K2QzNXpqQkQ5MmZPMkplNTYKZGhNZnpDZ09LWGVKMzQwV2hXM1RqRDF6cUxaWGVhQ3lVTlJuZk9tV1pWOG5FaHRIT0ZiVUNVN3IvS2tqTVpPOQpBZ01CQUFHamdlTXdnZUF3RGdZRFZSMFBBUUgvQkFRREFnR0dNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUF3CkhRWURWUjBPQkJZRUZNRE1BMGE1V0NETVhISnc4K0V1eXlDbTlXZzZNSG9HQ0NzR0FRVUZCd0VCQkc0d2JEQTAKQmdnckJnRUZCUWN3QVlZb2FIUjBjRG92TDI5amMzQXVjM1JuTFhKdmIzUXRlREV1YkdWMGMyVnVZM0o1Y0hRdQpiM0puTHpBMEJnZ3JCZ0VGQlFjd0FvWW9hSFIwY0RvdkwyTmxjblF1YzNSbkxYSnZiM1F0ZURFdWJHVjBjMlZ1ClkzSjVjSFF1YjNKbkx6QWZCZ05WSFNNRUdEQVdnQlRCSm5Ta2lrU2c1dm9nS05oY0k1cEZpQmg1NERBTkJna3EKaGtpRzl3MEJBUXNGQUFPQ0FnRUFCWVN1NElsK2ZJME1ZVTQyT1RtRWorMUhxUTVEdnlBZXlDQTZzR3VaZHdqRgpVR2VWT3YzTm5MeWZvZnVVT2pFYlk1aXJGQ0R0bnYrMGNrdWtVWk45bHo0UTJZaldHVXBXNFRUdTNpZVRzYUM5CkFGdkNTZ05ISnlXU1Z0V3ZCNVhEeHNxYXdsMUt6SHp6d3IxMzJiRjJydEd0YXpTcVZxSzlFMDdzR0hNQ2YrenAKRFFWRFZWR3RxWlBId1gzS3FVdGVmRTYyMWI4Ukk2VkNsNG9EMzBPbGY4cGp1ekc0SktCRlJGY2x6TFJqby9oNwpJa2tmalo4d0RhN2ZhT2pWWHg2bitlVVEyOWNJTUN6cjgvck5XSFM5cFlHR1FLSmlZMnhtVkM5aDEySDk5WHlmCnpXRTl2YjV6S1AzTVZHNm5lWDFoU2RvN1BFQWI5ZnFSaEhrcVZzcVV2SmxJUm12WHZWS1R3TkNQM2VDalJDQ0kKUFRBdmpWKzRuaTc4NmlYd3dGWU56OGwzUG1QTEN5UVhXR29obko4aUJtKzVuazdPMnluYVBWVzBVMlcrcHQydwpTVnV2ZERNNXpHdjJmOWx0TldVaVlaSEoxbW1POTdqU1kvNllmZE9VSDY2aVJ0UXREa0hCUmRrTkJzTWJEK0VtCjJUZ0JsZHRITlNKQmZCM3BtOUZibGdPY0owRlNXY1VEV0o3dk8wK05UWGxnclJvZlJUNnBWeXd6eFZvNmRORDAKV3pZbFRXZVVWc080MHhKcWhnVVFSRVI5WUxPTHhKME82QzhpMHhGeEFNS090U2RvZE1CM1JJd3Q3UkZRMHV5dApuNVo1TXFrWWhsTUkzSjF0UFJUcDFuRXQ5ZnlHc3BCT08wNWdpMTQ4UWFzcCszTitzdnFLb21vUWdsTm9BeFU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K`) // Create Namespace _, err := kubernetesCl.CoreV1().Namespaces().Create(rootCtx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns1}}, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } tests := map[string]CreateCRTest{ "v1 Certificate given": { inputFile: path.Join(testdataPath, "create_cr_cert_with_ns1.yaml"), inputArgs: []string{cr1Name}, inputNamespace: ns1, keyFilename: "", expRunErr: false, expNamespace: ns1, expName: cr1Name, expKeyFilename: cr1Name + ".key", }, "v1alpha3 Certificate given": { inputFile: path.Join(testdataPath, "create_cr_v1alpha3_cert_with_ns1.yaml"), inputArgs: []string{cr2Name}, inputNamespace: ns1, keyFilename: "", expRunErr: false, expNamespace: ns1, expName: cr2Name, expKeyFilename: cr2Name + ".key", }, "path to file to store private key provided": { inputFile: path.Join(testdataPath, "create_cr_cert_with_ns1.yaml"), inputArgs: []string{cr5Name}, inputNamespace: ns1, keyFilename: "test.key", expRunErr: false, expNamespace: ns1, expName: cr5Name, expKeyFilename: "test.key", }, "fetch flag set and CR will be ready and status.certificate set": { inputFile: path.Join(testdataPath, "create_cr_cert_with_ns1.yaml"), inputArgs: []string{cr6Name}, inputNamespace: ns1, keyFilename: "", fetchCert: true, timeout: 5 * time.Minute, crStatus: cmapiv1.CertificateRequestStatus{ Conditions: []cmapiv1.CertificateRequestCondition{ {Type: cmapiv1.CertificateRequestConditionReady, Status: cmmeta.ConditionTrue}, }, Certificate: exampleCertificate, }, expRunErr: false, expNamespace: ns1, expName: cr6Name, expKeyFilename: cr6Name + ".key", expCertFilename: cr6Name + ".crt", expCertFileContent: exampleCertificate, }, "fetch flag set and CR will be ready but status.certificate empty": { inputFile: path.Join(testdataPath, "create_cr_cert_with_ns1.yaml"), inputArgs: []string{cr7Name}, inputNamespace: ns1, keyFilename: "", fetchCert: true, timeout: 5 * time.Second, crStatus: cmapiv1.CertificateRequestStatus{ Conditions: []cmapiv1.CertificateRequestCondition{ {Type: cmapiv1.CertificateRequestConditionReady, Status: cmmeta.ConditionTrue}, }, }, expRunErr: true, expErrMsg: "error when waiting for CertificateRequest to be signed: context deadline exceeded", expNamespace: ns1, expName: cr7Name, expKeyFilename: cr7Name + ".key", expCertFilename: cr7Name + ".crt", expCertFileContent: exampleCertificate, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { ctx, cancel := context.WithTimeout(rootCtx, time.Second*20) defer cancel() streams, _, _, _ := genericclioptions.NewTestIOStreams() cleanUpFunc := setupPathForTest(t) defer cleanUpFunc() // Options to run create CR command opts := &certificaterequest.Options{ Factory: &factory.Factory{ CMClient: cmCl, RESTConfig: config, Namespace: test.inputNamespace, EnforceNamespace: test.inputNamespace != "", }, IOStreams: streams, InputFilename: test.inputFile, KeyFilename: test.keyFilename, CertFileName: test.certFilename, FetchCert: test.fetchCert, Timeout: test.timeout, } // Validating args and flags err := opts.Validate(test.inputArgs) if err != nil { t.Fatal(err) } if test.fetchCert { req := &cmapiv1.CertificateRequest{} // Start a goroutine that will periodically check whether the CertificateRequest has been created // by the CLI command yet. // Once it has been created, set the `status.certificate` and `Ready` condition so that the `--fetch-certificate` // part of the command is able to proceed. errCh := make(chan error) pollCtx, cancelPoll := context.WithCancel(ctx) defer func() { cancelPoll() err := <-errCh if err != nil { t.Fatal(err) } }() go func() { defer close(errCh) err = wait.PollUntilContextCancel(pollCtx, time.Second, true, func(ctx context.Context) (done bool, err error) { req, err = cmCl.CertmanagerV1().CertificateRequests(test.inputNamespace).Get(ctx, test.inputArgs[0], metav1.GetOptions{}) if err != nil { return false, nil // nolint: nilerr // Retry and keep polling until context is cancelled } return true, nil }) if err != nil { errCh <- fmt.Errorf("timeout when waiting for CertificateRequest to be created, error: %v", err) return } // CR has been created, try update status req.Status.Conditions = test.crStatus.Conditions req.Status.Certificate = test.crStatus.Certificate req, err = cmCl.CertmanagerV1().CertificateRequests(test.inputNamespace).UpdateStatus(pollCtx, req, metav1.UpdateOptions{}) if err != nil { errCh <- err } }() } // Run ctl create cr command with input options err = opts.Run(ctx, test.inputArgs) if err != nil { if !test.expRunErr { t.Errorf("got unexpected error when trying to create CR: %v", err) } else if err.Error() != test.expErrMsg { t.Errorf("got unexpected error when trying to create CR, expected: %v; actual: %v", test.expErrMsg, err) } } else { // got no error if test.expRunErr { t.Errorf("expected but got no error when creating CR") } } // Check the file where the private key is stored keyData, err := os.ReadFile(test.expKeyFilename) if err != nil { t.Errorf("error when reading file storing private key: %v", err) } _, err = pki.DecodePrivateKeyBytes(keyData) if err != nil { t.Errorf("invalid private key: %v", err) } // Finished creating CR, check if everything is expected crName := test.inputArgs[0] gotCr, err := cmCl.CertmanagerV1().CertificateRequests(test.inputNamespace).Get(ctx, crName, metav1.GetOptions{}) if err != nil { t.Fatal(err) } if gotCr.Name != test.expName { t.Errorf("CR created has unexpected Name, expected: %s, actual: %s", test.expName, gotCr.Name) } if gotCr.Namespace != test.expNamespace { t.Errorf("CR created in unexpected Namespace, expected: %s, actual: %s", test.expNamespace, gotCr.Namespace) } // If applicable, check the file where the certificate is stored // If the expected error message is the one below, we skip checking // because no certificate will have been written to file if test.fetchCert && test.expErrMsg != "error when waiting for CertificateRequest to be signed: context deadline exceeded" { certData, err := os.ReadFile(test.expCertFilename) if err != nil { t.Errorf("error when reading file storing private key: %v", err) } if !bytes.Equal(test.expCertFileContent, certData) { t.Errorf("certificate written to file is wrong, expected: %s,\nactual: %s", test.expCertFileContent, certData) } } }) } } func getTestDataDir(t *testing.T) string { testWorkingDirectory, err := os.Getwd() if err != nil { t.Fatal(err) } return path.Join(testWorkingDirectory, "testdata") } // setupPathForTest sets up a tmp directory and cd into it for tests as the command being tested creates files // in the local directory. // Returns a cleanup function which will change cd back to original working directory and remove the tmp directory. func setupPathForTest(t *testing.T) func() { workingDirectoryBeforeTest, err := os.Getwd() if err != nil { t.Fatal(err) } // Create tmp directory and cd into it to store private key files tmpDir, err := os.MkdirTemp("", "tmp-ctl-test-*") if err != nil { t.Fatal(err) } if err := os.Chdir(tmpDir); err != nil { t.Fatal(err) } return func() { if err := os.Chdir(workingDirectoryBeforeTest); err != nil { t.Fatal(err) } if err := os.RemoveAll(tmpDir); err != nil { t.Fatal(err) } } } 070701000000AA000081A400000000000000000000000166DFF09D0000101E000000000000000000000000000000000000003100000000cmctl-2.1.1/test/integration/ctl_install_test.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package ctl import ( "bytes" "context" "fmt" "io" "regexp" "strings" "testing" "time" "github.com/sergi/go-diff/diffmatchpatch" logsapi "k8s.io/component-base/logs/api/v1" "github.com/cert-manager/cmctl/v2/cmd" "github.com/cert-manager/cmctl/v2/test/integration/install_framework" ) func TestCtlInstall(t *testing.T) { tests := map[string]struct { prerun bool preInputArgs []string preExpErr bool preExpOutput string inputArgs []string expErr bool expOutput string }{ "install cert-manager": { inputArgs: []string{"x", "install", "--wait=false"}, expErr: false, expOutput: `STATUS: deployed`, }, "install cert-manager (already installed)": { prerun: true, preInputArgs: []string{"x", "install", "--wait=false"}, preExpErr: false, preExpOutput: `STATUS: deployed`, inputArgs: []string{"x", "install", "--wait=false"}, expErr: true, expOutput: `^Found existing installed cert-manager CRDs! Cannot continue with installation.$`, }, "install cert-manager (already installed, in other namespace)": { prerun: true, preInputArgs: []string{"x", "install", "--wait=false", "--namespace=test"}, preExpErr: false, preExpOutput: `STATUS: deployed`, inputArgs: []string{"x", "install", "--wait=false"}, expErr: true, expOutput: `^Found existing installed cert-manager CRDs! Cannot continue with installation.$`, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { testApiServer, cleanup := install_framework.NewTestInstallApiServer(t) defer cleanup() ctx, cancel := context.WithTimeout(context.Background(), time.Second*40) defer cancel() if test.prerun { executeCmctlAndCheckOutput( t, ctx, testApiServer.KubeConfigFilePath(), test.preInputArgs, test.preExpErr, test.preExpOutput, ) } executeCmctlAndCheckOutput( t, ctx, testApiServer.KubeConfigFilePath(), test.inputArgs, test.expErr, test.expOutput, ) }) } } func executeAndCheckOutput( t *testing.T, f func(io.Reader, io.Writer) error, expErr bool, expOutput string, ) { stdin := bytes.NewBufferString("") stdout := bytes.NewBufferString("") err := f(stdin, stdout) if err != nil { fmt.Fprintf(stdout, "%s\n", err) if !expErr { t.Errorf("got unexpected error: %v", err) } else { t.Logf("got an error, which was expected, details: %v", err) } } else if expErr { // expected error but error is nil t.Errorf("expected but got no error") } match, err := regexp.MatchString(strings.TrimSpace(expOutput), strings.TrimSpace(stdout.String())) if err != nil { t.Error(err) } dmp := diffmatchpatch.New() if !match { diffs := dmp.DiffMain(strings.TrimSpace(expOutput), strings.TrimSpace(stdout.String()), false) t.Errorf( "got unexpected output, diff (ignoring line anchors ^ and $ and regex for creation time):\n"+ "diff: %s\n\n"+ " exp: %s\n\n"+ " got: %s", dmp.DiffPrettyText(diffs), expOutput, stdout.String(), ) } } func executeCmctlAndCheckOutput( t *testing.T, ctx context.Context, kubeConfig string, inputArgs []string, expErr bool, expOutput string, ) { if err := logsapi.ResetForTest(nil); err != nil { t.Fatal(err) } executeAndCheckOutput(t, func(stdin io.Reader, stdout io.Writer) error { cmd := cmd.NewCertManagerCtlCommand(ctx, stdin, stdout, stdout) cmd.SetArgs(append([]string{fmt.Sprintf("--kubeconfig=%s", kubeConfig)}, inputArgs...)) return cmd.Execute() }, expErr, expOutput) } 070701000000AB000081A400000000000000000000000166DFF09D000016FB000000000000000000000000000000000000002F00000000cmctl-2.1.1/test/integration/ctl_renew_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package ctl import ( "context" "testing" "time" apiutil "github.com/cert-manager/cert-manager/pkg/api/util" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" "github.com/cert-manager/cert-manager/test/unit/gen" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/cert-manager/cmctl/v2/pkg/factory" "github.com/cert-manager/cmctl/v2/pkg/renew" "github.com/cert-manager/cmctl/v2/test/integration/framework" ) // TestCtlRenew tests the renewal logic of the ctl CLI command against the // cert-manager Issuing controller. func TestCtlRenew(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*40) defer cancel() config, stopFn := framework.RunControlPlane(t, ctx) defer stopFn() // Build clients kubeClient, cmCl, _, _ := framework.NewClients(t, config) var ( crt1Name = "testcrt-1" crt2Name = "testcrt-2" crt3Name = "testcrt-3" crt4Name = "testcrt-4" ns1 = "testns-1" ns2 = "testns-2" ) // Create Namespaces for _, ns := range []string{ns1, ns2} { _, err := kubeClient.CoreV1().Namespaces().Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}}, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } } crt1 := gen.Certificate(crt1Name, gen.SetCertificateNamespace(ns1), gen.SetCertificateIssuer(cmmeta.ObjectReference{Kind: "Issuer", Name: "test-issuer"}), gen.SetCertificateSecretName("crt1"), gen.SetCertificateCommonName("crt1"), ) crt2 := gen.Certificate(crt2Name, gen.SetCertificateNamespace(ns1), gen.SetCertificateIssuer(cmmeta.ObjectReference{Kind: "Issuer", Name: "test-issuer"}), gen.SetCertificateSecretName("crt2"), gen.SetCertificateCommonName("crt2"), gen.AddCertificateLabels(map[string]string{ "foo": "bar", }), ) crt3 := gen.Certificate(crt3Name, gen.SetCertificateNamespace(ns2), gen.SetCertificateIssuer(cmmeta.ObjectReference{Kind: "Issuer", Name: "test-issuer"}), gen.SetCertificateSecretName("crt3"), gen.SetCertificateCommonName("crt3"), gen.AddCertificateLabels(map[string]string{ "foo": "bar", }), ) crt4 := gen.Certificate(crt4Name, gen.SetCertificateIssuer(cmmeta.ObjectReference{Kind: "Issuer", Name: "test-issuer"}), gen.SetCertificateSecretName("crt4"), gen.SetCertificateCommonName("crt5"), gen.SetCertificateNamespace(ns2), ) tests := map[string]struct { inputArgs []string inputLabels string inputNamespace string inputAll bool inputAllNamespaces bool crtsWithIssuing map[*cmapi.Certificate]bool }{ "certificate name and namespace given": { inputArgs: []string{crt1Name, crt2Name}, inputNamespace: ns1, crtsWithIssuing: map[*cmapi.Certificate]bool{ crt1: true, crt2: true, crt3: false, crt4: false, }, }, "--all and namespace given": { inputAll: true, inputNamespace: ns2, crtsWithIssuing: map[*cmapi.Certificate]bool{ crt1: false, crt2: false, crt3: true, crt4: true, }, }, "--all and --all-namespaces given": { inputAll: true, inputAllNamespaces: true, crtsWithIssuing: map[*cmapi.Certificate]bool{ crt1: true, crt2: true, crt3: true, crt4: true, }, }, "--all-namespaces and -l foo=bar given": { inputAllNamespaces: true, inputLabels: "foo=bar", crtsWithIssuing: map[*cmapi.Certificate]bool{ crt1: false, crt2: true, crt3: true, crt4: false, }, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { // Create Certificates for _, crt := range []*cmapi.Certificate{crt1, crt2, crt3, crt4} { _, err := cmCl.CertmanagerV1().Certificates(crt.Namespace).Create(ctx, crt, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } } // Run ctl renew command with input options streams, _, _, _ := genericclioptions.NewTestIOStreams() cmd := &renew.Options{ LabelSelector: test.inputLabels, All: test.inputAll, AllNamespaces: test.inputAllNamespaces, Factory: &factory.Factory{ CMClient: cmCl, RESTConfig: config, Namespace: test.inputNamespace, }, IOStreams: streams, } if err := cmd.Run(ctx, test.inputArgs); err != nil { t.Fatal(err) } // Check issuing condition against Certificates for crt, shouldIssue := range test.crtsWithIssuing { gotCrt, err := cmCl.CertmanagerV1().Certificates(crt.Namespace).Get(ctx, crt.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } hasCondition := true if cond := apiutil.GetCertificateCondition(gotCrt, cmapi.CertificateConditionIssuing); cond == nil || cond.Status != cmmeta.ConditionTrue { hasCondition = false } if shouldIssue != hasCondition { t.Errorf("%s/%s expected to have issuing condition=%t got=%t", crt.Namespace, crt.Name, shouldIssue, hasCondition) } } // Clean up Certificates for _, crt := range []*cmapi.Certificate{crt1, crt2, crt3, crt4} { err := cmCl.CertmanagerV1().Certificates(crt.Namespace).Delete(ctx, crt.Name, metav1.DeleteOptions{}) if err != nil { t.Fatal(err) } } }) } } 070701000000AC000081A400000000000000000000000166DFF09D00005E5F000000000000000000000000000000000000003C00000000cmctl-2.1.1/test/integration/ctl_status_certificate_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package ctl import ( "context" "fmt" "regexp" "strings" "testing" "time" apiutil "github.com/cert-manager/cert-manager/pkg/api/util" cmacme "github.com/cert-manager/cert-manager/pkg/apis/acme/v1" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned" "github.com/cert-manager/cert-manager/pkg/ctl" "github.com/cert-manager/cert-manager/pkg/util/pki" "github.com/cert-manager/cert-manager/test/unit/gen" "github.com/sergi/go-diff/diffmatchpatch" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/reference" "github.com/cert-manager/cmctl/v2/pkg/factory" statuscertcmd "github.com/cert-manager/cmctl/v2/pkg/status/certificate" "github.com/cert-manager/cmctl/v2/test/integration/framework" ) func generateCSR(t *testing.T) []byte { skRSA, err := pki.GenerateRSAPrivateKey(2048) if err != nil { t.Fatal(err) } csr, err := gen.CSRWithSigner(skRSA, gen.SetCSRCommonName("test"), ) if err != nil { t.Fatal(err) } return csr } func TestCtlStatusCert(t *testing.T) { testCSR := generateCSR(t) ctx, cancel := context.WithTimeout(context.Background(), time.Second*40) defer cancel() config, stopFn := framework.RunControlPlane(t, ctx) defer stopFn() // Build clients kubernetesCl, cmCl, _, _ := framework.NewClients(t, config) var ( crt1Name = "testcrt-1" crt2Name = "testcrt-2" crt3Name = "testcrt-3" crt4Name = "testcrt-4" ns1 = "testns-1" req1Name = "testreq-1" req2Name = "testreq-2" req3Name = "testreq-3" revision1 = 1 revision2 = 2 crtReadyAndUpToDateCond = cmapi.CertificateCondition{Type: cmapi.CertificateConditionReady, Status: cmmeta.ConditionTrue, Message: "Certificate is up to date and has not expired"} crtIssuingCond = cmapi.CertificateCondition{Type: cmapi.CertificateConditionIssuing, Status: cmmeta.ConditionTrue, Message: "Issuance of a new Certificate is in Progress"} reqNotReadyCond = cmapi.CertificateRequestCondition{Type: cmapi.CertificateRequestConditionReady, Status: cmmeta.ConditionFalse, Reason: "Pending", Message: "Waiting on certificate issuance from order default/example-order: \"pending\""} tlsCrt = []byte(`-----BEGIN CERTIFICATE----- MIICyTCCAbGgAwIBAgIRAOL4jtyULBSEYyGdqQn9YzowDQYJKoZIhvcNAQELBQAw DzENMAsGA1UEAxMEdGVzdDAeFw0yMDA3MzAxNjExNDNaFw0yMDEwMjgxNjExNDNa MA8xDTALBgNVBAMTBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQDdfNmjh5ag7f6U1hj1OAx/dEN9kQzPsSlBMXGb/Ho4k5iegrFd6w8JkYdCthFv lfg3bIhw5tCKaw1o57HnWKBKKGt7XpeIu1mEcv8pveMIPO7TZ4+oElgX880NfJmL DkjEcctEo/+FurudO1aEbNfbNWpzudYKj7gGtYshBytqaYt4/APqWARJBFCYVVys wexZ0fLi5cBD8H1bQ1Ec3OCr5Mrq9thAGkj+rVlgYR0AZVGa9+SCOj27t6YCmyzR AJSEQ35v58Zfxp5tNyYd6wcAswJ9YipnUXvwahF95PNlRmMhp3Eo15m9FxehcVXU BOfxykMwZN7onMhuHiiwiB+NAgMBAAGjIDAeMA4GA1UdDwEB/wQEAwIFoDAMBgNV HRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQALrnldWjTBTvV5WKapUHUG0rhA vp2Cf+5FsPw8vKScXp4L+wKGdPOjhHz6NOiw5wu8A0HxlVUFawRpagkjFkeTL78O 9ghBHLiqn9xNPIKC6ID3WpnN5terwQxQeO/M54sVMslUWCcZm9Pu4Eb//2e6wEdu eMmpfeISQmCsBC1CTmpxUjeUg5DEQ0X1TQykXq+bG2iso6RYPxZTFTHJFzXiDYEc /X7H+bOmpo/dMrXapwfvp2gD+BEq96iVpf/DBzGYNs/657LAHJ4YtxtAZCa1CK9G MA6koCR/K23HZfML8vT6lcHvQJp9XXaHRIe9NX/M/2f6VpfO7JjKWLou5k5a -----END CERTIFICATE-----`) ) certIsValidTime, err := time.Parse(time.RFC3339, "2020-09-16T09:26:18Z") if err != nil { t.Fatal(err) } // Create Namespace _, err = kubernetesCl.CoreV1().Namespaces().Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns1}}, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } tests := map[string]struct { certificate *cmapi.Certificate certificateStatus *cmapi.CertificateStatus inputArgs []string inputNamespace string req *cmapi.CertificateRequest reqStatus *cmapi.CertificateRequestStatus // At most one of issuer and clusterIssuer is not nil issuer *cmapi.Issuer clusterIssuer *cmapi.ClusterIssuer secret *corev1.Secret order *cmacme.Order challenges []*cmacme.Challenge crtEvents *corev1.EventList issuerEvents *corev1.EventList secretEvents *corev1.EventList reqEvents *corev1.EventList expErr bool expOutput string }{ "certificate issued and up-to-date with clusterIssuer": { certificate: gen.Certificate(crt1Name, gen.SetCertificateNamespace(ns1), gen.SetCertificateDNSNames("www.example.com"), gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "letsencrypt-prod", Kind: "ClusterIssuer"}), gen.SetCertificateSecretName("example-tls")), certificateStatus: &cmapi.CertificateStatus{Conditions: []cmapi.CertificateCondition{crtReadyAndUpToDateCond}, NotAfter: &metav1.Time{Time: certIsValidTime}, Revision: &revision1}, crtEvents: &corev1.EventList{ Items: []corev1.Event{{ ObjectMeta: metav1.ObjectMeta{ Name: "crtEvent", Namespace: ns1, }, Type: "type", Reason: "reason", Message: "message", }}, }, inputArgs: []string{crt1Name}, inputNamespace: ns1, clusterIssuer: gen.ClusterIssuer("letsencrypt-prod", gen.SetIssuerSelfSigned(cmapi.SelfSignedIssuer{})), expErr: false, expOutput: `^Name: testcrt-1 Namespace: testns-1 Created at: .* Conditions: Ready: True, Reason: , Message: Certificate is up to date and has not expired DNS Names: - www.example.com Events: Type Reason Age From Message ---- ------ ---- ---- ------- type reason <unknown> message Issuer: Name: letsencrypt-prod Kind: ClusterIssuer Conditions: No Conditions set Events: <none> error when finding Secret "example-tls": secrets "example-tls" not found Not Before: <none> Not After: .* Renewal Time: <none> No CertificateRequest found for this Certificate$`, }, "certificate issued and renewal in progress with Issuer": { certificate: gen.Certificate(crt2Name, gen.SetCertificateNamespace(ns1), gen.SetCertificateDNSNames("www.example.com"), gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "letsencrypt-prod", Kind: "Issuer"}), gen.SetCertificateSecretName("existing-tls-secret")), certificateStatus: &cmapi.CertificateStatus{Conditions: []cmapi.CertificateCondition{crtReadyAndUpToDateCond, crtIssuingCond}, NotAfter: &metav1.Time{Time: certIsValidTime}, Revision: &revision1}, inputArgs: []string{crt2Name}, inputNamespace: ns1, req: gen.CertificateRequest(req1Name, gen.SetCertificateRequestNamespace(ns1), gen.SetCertificateRequestAnnotations(map[string]string{cmapi.CertificateRequestRevisionAnnotationKey: fmt.Sprintf("%d", revision2)}), gen.SetCertificateRequestIssuer(cmmeta.ObjectReference{Name: "letsencrypt-prod", Kind: "Issuer"}), gen.SetCertificateRequestCSR(testCSR)), reqStatus: &cmapi.CertificateRequestStatus{Conditions: []cmapi.CertificateRequestCondition{reqNotReadyCond}}, issuer: gen.Issuer("letsencrypt-prod", gen.SetIssuerNamespace(ns1), gen.SetIssuerACME(cmacme.ACMEIssuer{ Server: "https://dummy.acme.local/", PrivateKey: cmmeta.SecretKeySelector{ LocalObjectReference: cmmeta.LocalObjectReference{ Name: "test", }, Key: "test", }, })), issuerEvents: &corev1.EventList{ Items: []corev1.Event{{ ObjectMeta: metav1.ObjectMeta{ Name: "issuerEvent", }, Type: "type", Reason: "reason", Message: "message", }}, }, secret: gen.Secret("existing-tls-secret", gen.SetSecretNamespace(ns1), gen.SetSecretData(map[string][]byte{"tls.crt": tlsCrt})), secretEvents: &corev1.EventList{ Items: []corev1.Event{{ ObjectMeta: metav1.ObjectMeta{ Name: "secretEvent", Namespace: ns1, }, Type: "type", Reason: "reason", Message: "message", }}, }, order: gen.Order("example-order", gen.SetOrderNamespace(ns1), gen.SetOrderCsr(testCSR), gen.SetOrderIssuer(cmmeta.ObjectReference{Name: "letsencrypt-prod", Kind: "Issuer"}), gen.SetOrderDNSNames("www.example.com")), challenges: []*cmacme.Challenge{ gen.Challenge("test-challenge1", gen.SetChallengeNamespace(ns1), gen.SetChallengeType(cmacme.ACMEChallengeTypeHTTP01), gen.SetChallengeToken("dummy-token1"), gen.SetChallengePresented(false), gen.SetChallengeProcessing(false), ), gen.Challenge("test-challenge2", gen.SetChallengeNamespace(ns1), gen.SetChallengeType(cmacme.ACMEChallengeTypeDNS01), gen.SetChallengeToken("dummy-token2"), gen.SetChallengePresented(false), gen.SetChallengeProcessing(false), ), }, expErr: false, expOutput: `^Name: testcrt-2 Namespace: testns-1 Created at: .* Conditions: Ready: True, Reason: , Message: Certificate is up to date and has not expired Issuing: True, Reason: , Message: Issuance of a new Certificate is in Progress DNS Names: - www.example.com Events: <none> Issuer: Name: letsencrypt-prod Kind: Issuer Conditions: No Conditions set Events: Type Reason Age From Message ---- ------ ---- ---- ------- type reason <unknown> message Secret: Name: existing-tls-secret Issuer Country: Issuer Organisation: Issuer Common Name: test Key Usage: Digital Signature, Key Encipherment Extended Key Usages: Public Key Algorithm: RSA Signature Algorithm: SHA256-RSA Subject Key ID: Authority Key ID: Serial Number: e2f88edc942c148463219da909fd633a Events: Type Reason Age From Message ---- ------ ---- ---- ------- type reason <unknown> message Not Before: <none> Not After: .* Renewal Time: <none> CertificateRequest: Name: testreq-1 Namespace: testns-1 Conditions: Ready: False, Reason: Pending, Message: Waiting on certificate issuance from order default/example-order: "pending" Events: <none> Order: Name: example-order State: , Reason: No Authorizations for this Order Challenges: - Name: test-challenge1, Type: HTTP-01, Token: dummy-token1, Key: , State: , Reason: , Processing: false, Presented: false - Name: test-challenge2, Type: DNS-01, Token: dummy-token2, Key: , State: , Reason: , Processing: false, Presented: false$`, }, "certificate issued and renewal in progress without Issuer": { certificate: gen.Certificate(crt3Name, gen.SetCertificateNamespace(ns1), gen.SetCertificateDNSNames("www.example.com"), gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "non-existing-issuer", Kind: "Issuer"}), gen.SetCertificateSecretName("example-tls")), certificateStatus: &cmapi.CertificateStatus{Conditions: []cmapi.CertificateCondition{crtReadyAndUpToDateCond, crtIssuingCond}, NotAfter: &metav1.Time{Time: certIsValidTime}, Revision: &revision1}, inputArgs: []string{crt3Name}, inputNamespace: ns1, req: gen.CertificateRequest(req2Name, gen.SetCertificateRequestNamespace(ns1), gen.SetCertificateRequestAnnotations(map[string]string{cmapi.CertificateRequestRevisionAnnotationKey: fmt.Sprintf("%d", revision2)}), gen.SetCertificateRequestIssuer(cmmeta.ObjectReference{Name: "non-existing-issuer", Kind: "Issuer"}), gen.SetCertificateRequestCSR(testCSR)), reqStatus: &cmapi.CertificateRequestStatus{Conditions: []cmapi.CertificateRequestCondition{reqNotReadyCond}}, reqEvents: &corev1.EventList{ Items: []corev1.Event{{ ObjectMeta: metav1.ObjectMeta{ Name: "reqEvent", Namespace: ns1, }, Type: "type", Reason: "reason", Message: "message", }}, }, issuer: nil, expErr: false, expOutput: `^Name: testcrt-3 Namespace: testns-1 Created at: .* Conditions: Ready: True, Reason: , Message: Certificate is up to date and has not expired Issuing: True, Reason: , Message: Issuance of a new Certificate is in Progress DNS Names: - www.example.com Events: <none> error when getting Issuer: issuers.cert-manager.io "non-existing-issuer" not found error when finding Secret "example-tls": secrets "example-tls" not found Not Before: <none> Not After: .* Renewal Time: <none> CertificateRequest: Name: testreq-2 Namespace: testns-1 Conditions: Ready: False, Reason: Pending, Message: Waiting on certificate issuance from order default/example-order: "pending" Events: Type Reason Age From Message ---- ------ ---- ---- ------- type reason <unknown> message$`, }, "certificate issued and renewal in progress without ClusterIssuer": { certificate: gen.Certificate(crt4Name, gen.SetCertificateNamespace(ns1), gen.SetCertificateDNSNames("www.example.com"), gen.SetCertificateIssuer(cmmeta.ObjectReference{Name: "non-existing-clusterissuer", Kind: "ClusterIssuer"}), gen.SetCertificateSecretName("example-tls")), certificateStatus: &cmapi.CertificateStatus{Conditions: []cmapi.CertificateCondition{crtReadyAndUpToDateCond, crtIssuingCond}, NotAfter: &metav1.Time{Time: certIsValidTime}, Revision: &revision1}, inputArgs: []string{crt4Name}, inputNamespace: ns1, req: gen.CertificateRequest(req3Name, gen.SetCertificateRequestNamespace(ns1), gen.SetCertificateRequestIssuer(cmmeta.ObjectReference{Name: "non-existing-clusterissuer", Kind: "ClusterIssuer"}), gen.SetCertificateRequestAnnotations(map[string]string{cmapi.CertificateRequestRevisionAnnotationKey: fmt.Sprintf("%d", revision2)}), gen.SetCertificateRequestCSR(testCSR)), reqStatus: &cmapi.CertificateRequestStatus{Conditions: []cmapi.CertificateRequestCondition{reqNotReadyCond}}, issuer: nil, expErr: false, expOutput: `^Name: testcrt-4 Namespace: testns-1 Created at: .* Conditions: Ready: True, Reason: , Message: Certificate is up to date and has not expired Issuing: True, Reason: , Message: Issuance of a new Certificate is in Progress DNS Names: - www.example.com Events: <none> error when getting ClusterIssuer: clusterissuers.cert-manager.io "non-existing-clusterissuer" not found error when finding Secret "example-tls": secrets "example-tls" not found Not Before: <none> Not After: .* Renewal Time: <none> CertificateRequest: Name: testreq-3 Namespace: testns-1 Conditions: Ready: False, Reason: Pending, Message: Waiting on certificate issuance from order default/example-order: "pending" Events: <none>$`, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { // Create Certificate resource crt, err := cmCl.CertmanagerV1().Certificates(test.inputNamespace).Create(ctx, test.certificate, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } crt, err = setCertificateStatus(cmCl, crt, test.certificateStatus, ctx) if err != nil { t.Fatal(err) } if test.crtEvents != nil { crtRef, err := reference.GetReference(ctl.Scheme, crt) if err != nil { t.Fatalf("error when getting ObjectReference: %v", err) } err = createEventsOwnedByRef(kubernetesCl, ctx, test.crtEvents, crtRef, crt.Namespace) if err != nil { t.Fatal(err) } } // Set up related resources if test.req != nil { req, err := createCROwnedByCrt(cmCl, ctx, crt, test.req, test.reqStatus) if err != nil { t.Fatal(err) } if test.reqEvents != nil { reqRef, err := reference.GetReference(ctl.Scheme, req) if err != nil { t.Fatalf("error when getting ObjectReference: %v", err) } err = createEventsOwnedByRef(kubernetesCl, ctx, test.reqEvents, reqRef, req.Namespace) if err != nil { t.Fatal(err) } } } if test.issuer != nil { issuer, err := cmCl.CertmanagerV1().Issuers(crt.Namespace).Create(ctx, test.issuer, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } if test.issuerEvents != nil { issuerRef, err := reference.GetReference(ctl.Scheme, issuer) if err != nil { t.Fatalf("error when getting ObjectReference: %v", err) } err = createEventsOwnedByRef(kubernetesCl, ctx, test.issuerEvents, issuerRef, issuer.Namespace) if err != nil { t.Fatal(err) } } } if test.clusterIssuer != nil { clusterIssuer, err := cmCl.CertmanagerV1().ClusterIssuers().Create(ctx, test.clusterIssuer, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } if test.issuerEvents != nil { issuerRef, err := reference.GetReference(ctl.Scheme, clusterIssuer) if err != nil { t.Fatalf("error when getting ObjectReference: %v", err) } err = createEventsOwnedByRef(kubernetesCl, ctx, test.issuerEvents, issuerRef, clusterIssuer.Namespace) if err != nil { t.Fatal(err) } } } if test.secret != nil { secret, err := kubernetesCl.CoreV1().Secrets(test.inputNamespace).Create(ctx, test.secret, metav1.CreateOptions{}) if err != nil { t.Fatal(err) } if test.secretEvents != nil { secretRef, err := reference.GetReference(ctl.Scheme, secret) if err != nil { t.Fatalf("error when getting ObjectReference: %v", err) } err = createEventsOwnedByRef(kubernetesCl, ctx, test.secretEvents, secretRef, secret.Namespace) if err != nil { t.Fatal(err) } } } if test.order != nil { createdReq, err := cmCl.CertmanagerV1().CertificateRequests(test.req.Namespace).Get(ctx, test.req.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } err = createOrderOwnedByCR(cmCl, ctx, createdReq, test.order) if err != nil { t.Fatal(err) } } if len(test.challenges) > 0 { createdOrder, err := cmCl.AcmeV1().Orders(test.req.Namespace).Get(ctx, test.order.Name, metav1.GetOptions{}) if err != nil { t.Fatal(err) } err = createChallengesOwnedByOrder(cmCl, ctx, createdOrder, test.challenges) if err != nil { t.Fatal(err) } } // Options to run status command streams, _, outBuf, _ := genericclioptions.NewTestIOStreams() opts := &statuscertcmd.Options{ Factory: &factory.Factory{ CMClient: cmCl, RESTConfig: config, Namespace: test.inputNamespace, }, IOStreams: streams, } err = opts.Run(ctx, test.inputArgs) if err != nil { if !test.expErr { t.Errorf("got unexpected error: %v", err) } else { t.Logf("got an error, which was expected, details: %v", err) } return } else if test.expErr { // expected error but error is nil t.Error("got no error but expected one") return } expectedOutput := strings.TrimSpace(test.expOutput) commandOutput := strings.TrimSpace(outBuf.String()) match, err := regexp.MatchString(expectedOutput, commandOutput) if err != nil { t.Errorf("failed to match regex for output: %s", err) } if !match { dmp := diffmatchpatch.New() diffs := dmp.DiffMain(expectedOutput, commandOutput, false) t.Errorf("got unexpected output, diff (ignoring line anchors ^ and $ and regex for creation time):\n%s\n\n expected: \n%s\n\n got: \n%s", dmp.DiffPrettyText(diffs), test.expOutput, outBuf.String()) } err = validateOutputTimes(commandOutput, certIsValidTime) if err != nil { t.Errorf("couldn't validate times in output: %s", err) } }) } } func setCertificateStatus(cmCl versioned.Interface, crt *cmapi.Certificate, status *cmapi.CertificateStatus, ctx context.Context) (*cmapi.Certificate, error) { for _, cond := range status.Conditions { apiutil.SetCertificateCondition(crt, crt.Generation, cond.Type, cond.Status, cond.Reason, cond.Message) } crt.Status.NotAfter = status.NotAfter crt.Status.Revision = status.Revision crt, err := cmCl.CertmanagerV1().Certificates(crt.Namespace).UpdateStatus(ctx, crt, metav1.UpdateOptions{}) return crt, err } func createCROwnedByCrt(cmCl versioned.Interface, ctx context.Context, crt *cmapi.Certificate, req *cmapi.CertificateRequest, reqStatus *cmapi.CertificateRequestStatus) (*cmapi.CertificateRequest, error) { req, err := cmCl.CertmanagerV1().CertificateRequests(crt.Namespace).Create(ctx, req, metav1.CreateOptions{}) if err != nil { return nil, err } req.OwnerReferences = append(req.OwnerReferences, *metav1.NewControllerRef(crt, cmapi.SchemeGroupVersion.WithKind("Certificate"))) req, err = cmCl.CertmanagerV1().CertificateRequests(crt.Namespace).Update(ctx, req, metav1.UpdateOptions{}) if err != nil { return nil, fmt.Errorf("Update Err: %v", err) } if reqStatus != nil { req.Status.Conditions = reqStatus.Conditions req, err = cmCl.CertmanagerV1().CertificateRequests(crt.Namespace).UpdateStatus(ctx, req, metav1.UpdateOptions{}) if err != nil { return nil, fmt.Errorf("Update Err: %v", err) } } return req, nil } func createOrderOwnedByCR(cmCl versioned.Interface, ctx context.Context, req *cmapi.CertificateRequest, order *cmacme.Order) error { order, err := cmCl.AcmeV1().Orders(req.Namespace).Create(ctx, order, metav1.CreateOptions{}) if err != nil { return err } order.OwnerReferences = append(order.OwnerReferences, *metav1.NewControllerRef(req, cmapi.SchemeGroupVersion.WithKind("CertificateRequest"))) _, err = cmCl.AcmeV1().Orders(req.Namespace).Update(ctx, order, metav1.UpdateOptions{}) if err != nil { return fmt.Errorf("Update Err: %v", err) } return nil } func createChallengesOwnedByOrder(cmCl versioned.Interface, ctx context.Context, order *cmacme.Order, challenges []*cmacme.Challenge) error { for _, c := range challenges { challenge, err := cmCl.AcmeV1().Challenges(order.Namespace).Create(ctx, c, metav1.CreateOptions{}) if err != nil { return err } challenge.OwnerReferences = append(challenge.OwnerReferences, *metav1.NewControllerRef(order, cmacme.SchemeGroupVersion.WithKind("Order"))) _, err = cmCl.AcmeV1().Challenges(order.Namespace).Update(ctx, challenge, metav1.UpdateOptions{}) if err != nil { return fmt.Errorf("Update Err: %v", err) } } return nil } func createEventsOwnedByRef(kubernetesCl kubernetes.Interface, ctx context.Context, eventList *corev1.EventList, objRef *corev1.ObjectReference, ns string) error { for _, event := range eventList.Items { event.InvolvedObject = *objRef _, err := kubernetesCl.CoreV1().Events(ns).Create(ctx, &event, metav1.CreateOptions{}) // #nosec G601 -- False positive. See https://github.com/golang/go/discussions/56010 if err != nil { return fmt.Errorf("Create Err: %v", err) } } return nil } func validateOutputTimes(output string, expectedNotAfter time.Time) error { for _, line := range strings.Split(output, "\n") { rawParts := strings.Split(strings.TrimSpace(line), ":") if len(rawParts) == 1 { continue } partType := strings.ToLower(rawParts[0]) rest := strings.TrimSpace(strings.Join(rawParts[1:], ":")) if partType == "created at" { _, err := time.Parse(time.RFC3339, rest) if err != nil { return fmt.Errorf("couldn't parse 'created at' as an RFC3339 timestamp: %s", err) } } else if partType == "not after" { notAfter, err := time.Parse(time.RFC3339, rest) if err != nil { return fmt.Errorf("couldn't parse 'not after' as an RFC3339 timestamp: %s", err) } if !notAfter.Equal(expectedNotAfter) { return fmt.Errorf("got unexpected 'not after' (note that time zone differences could be a red herring) - wanted %q but got %q", expectedNotAfter.Format(time.RFC3339), notAfter.Format(time.RFC3339)) } } } return nil } 070701000000AD000081A400000000000000000000000166DFF09D00000F48000000000000000000000000000000000000003300000000cmctl-2.1.1/test/integration/ctl_uninstall_test.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package ctl import ( "context" "io" "os" "os/exec" "testing" "time" "github.com/stretchr/testify/require" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/cert-manager/cmctl/v2/test/integration/install_framework" ) func TestCtlUninstall(t *testing.T) { tests := map[string]struct { prerun bool prehelm bool preInputArgs []string preExpErr bool preExpOutput string inputArgs []string expErr bool expOutput string didInstallCRDs bool }{ "install and uninstall cert-manager": { prerun: true, preInputArgs: []string{"x", "install", "--wait=false"}, preExpErr: false, preExpOutput: `STATUS: deployed`, inputArgs: []string{"x", "uninstall", "--wait=false"}, expErr: false, expOutput: `release "cert-manager" uninstalled`, didInstallCRDs: true, }, "uninstall cert-manager installed by helm": { prehelm: true, preInputArgs: []string{ "install", "cert-manager", "cert-manager", "--repo=https://charts.jetstack.io", "--namespace=cert-manager", "--create-namespace", "--version=v1.12.0", "--set=installCRDs=true", "--wait=false", "--no-hooks", }, preExpErr: false, preExpOutput: `STATUS: deployed`, inputArgs: []string{"x", "uninstall", "--wait=false"}, expErr: false, expOutput: `These resources were kept due to the resource policy:`, didInstallCRDs: true, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { testApiServer, cleanup := install_framework.NewTestInstallApiServer(t) defer cleanup() ctx, cancel := context.WithTimeout(context.Background(), time.Second*40) defer cancel() if test.prerun { executeCmctlAndCheckOutput( t, ctx, testApiServer.KubeConfigFilePath(), test.preInputArgs, test.preExpErr, test.preExpOutput, ) } else if test.prehelm { executeHelmAndCheckOutput( t, ctx, testApiServer.KubeConfigFilePath(), test.preInputArgs, test.preExpErr, test.preExpOutput, ) } executeCmctlAndCheckOutput( t, ctx, testApiServer.KubeConfigFilePath(), test.inputArgs, test.expErr, test.expOutput, ) // if we installed CRDs, check that they were not deleted if test.didInstallCRDs { clientset, err := apiextensionsv1.NewForConfig(testApiServer.RestConfig()) require.NoError(t, err) _, err = clientset.CustomResourceDefinitions().Get(ctx, "certificates.cert-manager.io", metav1.GetOptions{}) require.NoError(t, err) } }) } } func executeHelmAndCheckOutput( t *testing.T, ctx context.Context, kubeConfig string, inputArgs []string, expErr bool, expOutput string, ) { // find Helm binary helmBinPath, ok := os.LookupEnv("HELM_BIN") if !ok { t.Fatal("HELM_BIN environment variable not set") } cmd := exec.CommandContext(ctx, helmBinPath, inputArgs...) // Set empty environment variables except for KUBECONFIG and HOME environment variable cmd.Env = []string{"KUBECONFIG=" + kubeConfig, "HOME=" + os.Getenv("HOME")} executeAndCheckOutput(t, func(stdin io.Reader, stdout io.Writer) error { cmd.Stdin = stdin cmd.Stdout = stdout cmd.Stderr = stdout return cmd.Run() }, expErr, expOutput) } 070701000000AE000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002700000000cmctl-2.1.1/test/integration/framework070701000000AF000081A400000000000000000000000166DFF09D00002042000000000000000000000000000000000000003400000000cmctl-2.1.1/test/integration/framework/apiserver.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package framework import ( "context" "fmt" "os" "path/filepath" "strings" "testing" "github.com/cert-manager/cert-manager/test/apiserver" webhooktesting "github.com/cert-manager/cert-manager/test/webhook" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" apiextensionsinstall "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" jsonserializer "k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/apimachinery/pkg/runtime/serializer/versioning" utilruntime "k8s.io/apimachinery/pkg/util/runtime" kscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" ) type StopFunc func() // controlPlaneOptions has parameters for the control plane of the integration // test framework which can be overridden in tests. type controlPlaneOptions struct { crdsDir *string } type RunControlPlaneOption func(*controlPlaneOptions) // WithCRDDirectory allows alternative CRDs to be loaded into the test API // server in tests. func WithCRDDirectory(directory string) RunControlPlaneOption { return func(o *controlPlaneOptions) { o.crdsDir = ptr.To(directory) } } func RunControlPlane(t *testing.T, ctx context.Context, optionFunctions ...RunControlPlaneOption) (*rest.Config, StopFunc) { options := &controlPlaneOptions{} for _, f := range optionFunctions { f(options) } if options.crdsDir == nil { path, ok := os.LookupEnv("CERT_MANAGER_CRDS") if !ok { t.Fatal("CERT_MANAGER_CRDS environment variable must be set to the path of the CRDs to load") } options.crdsDir = ptr.To(path) } env, stopControlPlane := apiserver.RunBareControlPlane(t) testuser, err := env.ControlPlane.AddUser(envtest.User{Name: "test-user", Groups: []string{"cluster-admin"}}, env.Config) if err != nil { t.Fatal(err) } kubeconfig, err := testuser.KubeConfig() if err != nil { t.Fatal(err) } f, err := os.CreateTemp("", "integration-") if err != nil { t.Fatal(err) } defer f.Close() defer func() { os.Remove(f.Name()) }() if _, err := f.Write(kubeconfig); err != nil { t.Fatal(err) } webhookOpts, stopWebhook := webhooktesting.StartWebhookServer( t, ctx, []string{"--kubeconfig", f.Name()}, ) crds := readCustomResourcesAtPath(t, *options.crdsDir) for _, crd := range crds { t.Logf("Found CRD with name %q", crd.Name) } if _, err := envtest.InstallCRDs(env.Config, envtest.CRDInstallOptions{ CRDs: crds, }); err != nil { t.Fatal(err) } cl, err := client.New(env.Config, client.Options{Scheme: kscheme.Scheme}) if err != nil { t.Fatal(err) } // installing the validating webhooks, not using WebhookInstallOptions as it patches the CA to be it's own err = cl.Create(ctx, getValidatingWebhookConfig(webhookOpts.URL, webhookOpts.CAPEM)) if err != nil { t.Fatal(err) } // installing the mutating webhooks, not using WebhookInstallOptions as it patches the CA to be it's own err = cl.Create(ctx, getMutatingWebhookConfig(webhookOpts.URL, webhookOpts.CAPEM)) if err != nil { t.Fatal(err) } return env.Config, func() { defer stopWebhook() stopControlPlane() } } var ( internalScheme = runtime.NewScheme() ) func init() { utilruntime.Must(metav1.AddMetaToScheme(internalScheme)) apiextensionsinstall.Install(internalScheme) } func readCustomResourcesAtPath(t *testing.T, path string) []*apiextensionsv1.CustomResourceDefinition { serializer := jsonserializer.NewSerializerWithOptions(jsonserializer.DefaultMetaFactory, internalScheme, internalScheme, jsonserializer.SerializerOptions{ Yaml: true, }) converter := runtime.UnsafeObjectConvertor(internalScheme) codec := versioning.NewCodec(serializer, serializer, converter, internalScheme, internalScheme, internalScheme, runtime.InternalGroupVersioner, runtime.InternalGroupVersioner, internalScheme.Name()) var crds []*apiextensionsv1.CustomResourceDefinition if err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if filepath.Ext(path) != ".yaml" { return nil } crd, err := readCRDsAtPath(codec, converter, path) if err != nil { return fmt.Errorf("failed reading CRDs at path %s: %w", path, err) } crds = append(crds, crd...) return nil }); err != nil { t.Fatal(err) } return crds } func readCRDsAtPath(codec runtime.Codec, converter runtime.ObjectConvertor, path string) ([]*apiextensionsv1.CustomResourceDefinition, error) { data, err := os.ReadFile(path) if err != nil { return nil, err } var crds []*apiextensionsv1.CustomResourceDefinition for _, d := range strings.Split(string(data), "\n---\n") { // skip empty YAML documents if strings.TrimSpace(d) == "" { continue } internalCRD := &apiextensions.CustomResourceDefinition{} if _, _, err := codec.Decode([]byte(d), nil, internalCRD); err != nil { return nil, err } out := apiextensionsv1.CustomResourceDefinition{} if err := converter.Convert(internalCRD, &out, nil); err != nil { return nil, err } crds = append(crds, &out) } return crds, nil } func getValidatingWebhookConfig(url string, caPEM []byte) client.Object { failurePolicy := admissionregistrationv1.Fail sideEffects := admissionregistrationv1.SideEffectClassNone validateURL := fmt.Sprintf("%s/validate", url) webhook := admissionregistrationv1.ValidatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{ Name: "cert-manager-webhook", }, Webhooks: []admissionregistrationv1.ValidatingWebhook{ { Name: "webhook.cert-manager.io", ClientConfig: admissionregistrationv1.WebhookClientConfig{ URL: &validateURL, CABundle: caPEM, }, Rules: []admissionregistrationv1.RuleWithOperations{ { Operations: []admissionregistrationv1.OperationType{ admissionregistrationv1.Create, admissionregistrationv1.Update, }, Rule: admissionregistrationv1.Rule{ APIGroups: []string{"cert-manager.io", "acme.cert-manager.io"}, APIVersions: []string{"*"}, Resources: []string{"*/*"}, }, }, }, FailurePolicy: &failurePolicy, SideEffects: &sideEffects, AdmissionReviewVersions: []string{"v1"}, }, }, } return &webhook } func getMutatingWebhookConfig(url string, caPEM []byte) client.Object { failurePolicy := admissionregistrationv1.Fail sideEffects := admissionregistrationv1.SideEffectClassNone validateURL := fmt.Sprintf("%s/mutate", url) webhook := admissionregistrationv1.MutatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{ Name: "cert-manager-webhook", }, Webhooks: []admissionregistrationv1.MutatingWebhook{ { Name: "webhook.cert-manager.io", ClientConfig: admissionregistrationv1.WebhookClientConfig{ URL: &validateURL, CABundle: caPEM, }, Rules: []admissionregistrationv1.RuleWithOperations{ { Operations: []admissionregistrationv1.OperationType{ admissionregistrationv1.Create, admissionregistrationv1.Update, }, Rule: admissionregistrationv1.Rule{ APIGroups: []string{"cert-manager.io", "acme.cert-manager.io"}, APIVersions: []string{"*"}, Resources: []string{"*/*"}, }, }, }, FailurePolicy: &failurePolicy, SideEffects: &sideEffects, AdmissionReviewVersions: []string{"v1"}, }, }, } return &webhook } 070701000000B0000081A400000000000000000000000166DFF09D00000FC3000000000000000000000000000000000000003200000000cmctl-2.1.1/test/integration/framework/helpers.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package framework import ( "context" "testing" "time" cmclient "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned" certmgrscheme "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned/scheme" cminformers "github.com/cert-manager/cert-manager/pkg/client/informers/externalversions" controllerpkg "github.com/cert-manager/cert-manager/pkg/controller" "golang.org/x/sync/errgroup" corev1 "k8s.io/api/core/v1" apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/discovery" "k8s.io/client-go/kubernetes" kscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" "k8s.io/client-go/tools/record" apireg "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" "k8s.io/kubectl/pkg/util/openapi" gwapi "sigs.k8s.io/gateway-api/apis/v1" ) func NewEventRecorder(t *testing.T, scheme *runtime.Scheme) record.EventRecorder { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(t.Logf) return eventBroadcaster.NewRecorder(scheme, corev1.EventSource{Component: t.Name()}) } func NewClients(t *testing.T, config *rest.Config) (kubernetes.Interface, cmclient.Interface, cminformers.SharedInformerFactory, *runtime.Scheme) { httpClient, err := rest.HTTPClientFor(config) if err != nil { t.Fatal(err) } cl, err := kubernetes.NewForConfigAndClient(config, httpClient) if err != nil { t.Fatal(err) } cmCl, err := cmclient.NewForConfigAndClient(config, httpClient) if err != nil { t.Fatal(err) } cmFactory := cminformers.NewSharedInformerFactory(cmCl, 0) scheme := runtime.NewScheme() for _, err := range []error{ kscheme.AddToScheme(scheme), certmgrscheme.AddToScheme(scheme), apiext.AddToScheme(scheme), apireg.AddToScheme(scheme), gwapi.Install(scheme), } { if err != nil { t.Fatal(err) } } return cl, cmCl, cmFactory, scheme } func StartInformersAndController(t *testing.T, cmFactory cminformers.SharedInformerFactory, c controllerpkg.Interface) StopFunc { return StartInformersAndControllers(t, cmFactory, c) } func StartInformersAndControllers(t *testing.T, cmFactory cminformers.SharedInformerFactory, cs ...controllerpkg.Interface) StopFunc { rootCtx, cancel := context.WithCancel(context.Background()) errCh := make(chan error) cmFactory.Start(rootCtx.Done()) group, _ := errgroup.WithContext(context.Background()) go func() { defer close(errCh) for _, c := range cs { func(c controllerpkg.Interface) { group.Go(func() error { return c.Run(1, rootCtx) }) }(c) } errCh <- group.Wait() }() return func() { cancel() err := <-errCh if err != nil { t.Fatal(err) } } } func WaitForOpenAPIResourcesToBeLoaded(t *testing.T, ctx context.Context, config *rest.Config, gvk schema.GroupVersionKind) { dc, err := discovery.NewDiscoveryClientForConfig(config) if err != nil { t.Fatal(err) } err = wait.PollUntilContextCancel(ctx, time.Second, true, func(ctx context.Context) (done bool, err error) { og := openapi.NewOpenAPIGetter(dc) oapiResource, err := openapi.NewOpenAPIParser(og).Parse() if err != nil { return false, err } if oapiResource.LookupResource(gvk) != nil { return true, nil } return false, nil }) if err != nil { t.Fatal("Our GVK isn't loaded into the OpenAPI resources API after waiting for 2 minutes", err) } } 070701000000B1000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002F00000000cmctl-2.1.1/test/integration/install_framework070701000000B2000081A400000000000000000000000166DFF09D00000A1B000000000000000000000000000000000000003C00000000cmctl-2.1.1/test/integration/install_framework/framework.go/* Copyright 2021 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package install_framework import ( "os" "testing" "github.com/cert-manager/cert-manager/test/apiserver" "github.com/go-logr/logr/testr" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/log" ) type TestInstallApiServer struct { environment *envtest.Environment testUser *envtest.AuthenticatedUser kubeClient kubernetes.Interface kubeConfig string } type CleanupFunction func() func NewTestInstallApiServer(t *testing.T) (*TestInstallApiServer, CleanupFunction) { log.SetLogger(testr.New(t)) env, stopFn := apiserver.RunBareControlPlane(t) testUser, err := env.ControlPlane.AddUser( envtest.User{ Name: "test", Groups: []string{"system:masters"}, }, &rest.Config{ // gotta go fast during tests -- we don't really care about overwhelming our test API server QPS: 1000.0, Burst: 2000.0, }, ) if err != nil { t.Error(err) } kubeConfig, removeFile := createKubeConfigFile(t, testUser) kubeClientset, err := kubernetes.NewForConfig(env.Config) if err != nil { t.Error(err) } return &TestInstallApiServer{ environment: env, testUser: testUser, kubeClient: kubeClientset, kubeConfig: kubeConfig, }, func() { defer removeFile() stopFn() } } func createKubeConfigFile(t *testing.T, user *envtest.AuthenticatedUser) (string, CleanupFunction) { tmpfile, err := os.CreateTemp("", "config") if err != nil { t.Fatal(err) } path := tmpfile.Name() contents, err := user.KubeConfig() if err != nil { os.Remove(path) t.Fatal(err) } if _, err := tmpfile.Write(contents); err != nil { tmpfile.Close() os.Remove(path) t.Fatal(err) } if err := tmpfile.Close(); err != nil { os.Remove(path) t.Fatal(err) } return path, func() { os.Remove(path) } } func (s *TestInstallApiServer) RestConfig() *rest.Config { return s.testUser.Config() } func (s *TestInstallApiServer) KubeConfigFilePath() string { return s.kubeConfig } 070701000000B3000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002500000000cmctl-2.1.1/test/integration/migrate070701000000B4000081A400000000000000000000000166DFF09D0000347B000000000000000000000000000000000000004100000000cmctl-2.1.1/test/integration/migrate/ctl_upgrade_migrate_test.go/* Copyright 2022 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package migrate import ( "context" "os" "testing" "time" apiextinstall "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install" apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/cert-manager/cmctl/v2/pkg/upgrade/migrateapiversion" "github.com/cert-manager/cmctl/v2/test/integration/framework" "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup/install" v1 "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup/v1" v2 "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup/v2" ) // Create a test resource at a given version. func newResourceAtVersion(t *testing.T, version string) client.Object { switch version { case "v1": return &v1.TestType{ ObjectMeta: metav1.ObjectMeta{ Name: "object", Namespace: "default", }, TestField: "abc", TestFieldImmutable: "def", } case "v2": return &v2.TestType{ ObjectMeta: metav1.ObjectMeta{ Name: "object", Namespace: "default", }, TestField: "abc", TestFieldImmutable: "def", } default: t.Fatalf("unknown version %q", version) } return nil } func crdFolder(t *testing.T) string { val, ok := os.LookupEnv("TEST_CRDS") if !ok { t.Fatal("TEST_CRDS environment variable must be set") } return val } func newScheme() *runtime.Scheme { scheme := runtime.NewScheme() apiextinstall.Install(scheme) install.Install(scheme) return scheme } func TestCtlUpgradeMigrate(t *testing.T) { // This test takes about 25 seconds to run. Let's give it enough time. ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() // Create the control plane with the TestType conversion handlers registered scheme := newScheme() // name of the testtype CRD resource crdName := "testtypes.testgroup.testing.cert-manager.io" restCfg, stop := framework.RunControlPlane(t, context.Background(), framework.WithCRDDirectory(crdFolder(t))) defer stop() // Ensure the OpenAPI endpoint has been updated with the TestType CRD framework.WaitForOpenAPIResourcesToBeLoaded(t, ctx, restCfg, schema.GroupVersionKind{ Group: "testgroup.testing.cert-manager.io", Version: "v1", Kind: "TestType", }) // Create an API client cl, err := client.New(restCfg, client.Options{Scheme: scheme}) if err != nil { t.Fatal(err) } // Fetch a copy of the recently created TestType CRD crd := &apiext.CustomResourceDefinition{} if err := cl.Get(ctx, client.ObjectKey{Name: crdName}, crd); err != nil { t.Fatal(err) } // Identify the current storage version and one non-storage version for this CRD. // We'll be creating objects and then changing the storage version on the CRD to // the 'nonStorageVersion' and ensuring the migration/upgrade is successful. storageVersion, nonStorageVersion := versionsForCRD(crd) if storageVersion == "" || nonStorageVersion == "" { t.Fatal("this test requires testdata with both a storage and non-storage version set") } // Ensure the original storage version is the only one on the CRD if len(crd.Status.StoredVersions) != 1 || crd.Status.StoredVersions[0] != storageVersion { t.Errorf("Expected status.storedVersions to only contain the storage version %q but it was: %v", storageVersion, crd.Status.StoredVersions) } // Create a resource obj := newResourceAtVersion(t, storageVersion) if err := cl.Create(ctx, obj); err != nil { t.Errorf("Failed to create test resource: %v", err) } // Set the storage version to the 'nonStorageVersion' setStorageVersion(crd, nonStorageVersion) if err := cl.Update(ctx, crd); err != nil { t.Fatalf("Failed to update CRD storage version: %v", err) } if len(crd.Status.StoredVersions) != 2 || crd.Status.StoredVersions[0] != storageVersion || crd.Status.StoredVersions[1] != nonStorageVersion { t.Fatalf("Expected status.storedVersions to contain [%s, %s] but it was: %v", storageVersion, nonStorageVersion, crd.Status.StoredVersions) } // Run the migrator and migrate all objects to the 'nonStorageVersion' (which is now the new storage version) migrator := migrateapiversion.NewMigrator(cl, false, os.Stdout, os.Stderr) migrated, err := migrator.Run(ctx, nonStorageVersion, []string{crdName}) if err != nil { t.Errorf("migrator failed to run: %v", err) } if !migrated { t.Errorf("migrator didn't actually perform a migration") } // Check the status.storedVersions field to ensure it only contains one element crd = &apiext.CustomResourceDefinition{} if err := cl.Get(ctx, client.ObjectKey{Name: crdName}, crd); err != nil { t.Fatal(err) } if len(crd.Status.StoredVersions) != 1 || crd.Status.StoredVersions[0] != nonStorageVersion { t.Fatalf("Expected status.storedVersions to be %q but it was: %v", nonStorageVersion, crd.Status.StoredVersions) } // Remove the previous storage version from the CRD and update it removeAPIVersion(crd, storageVersion) if err := cl.Update(ctx, crd); err != nil { t.Fatalf("Failed to remove old API version: %v", err) } // Attempt to read a resource list in the new API version objList := &unstructured.UnstructuredList{} objList.SetGroupVersionKind(schema.GroupVersionKind{ Group: crd.Spec.Group, Version: nonStorageVersion, Kind: crd.Spec.Names.ListKind, }) if err := cl.List(ctx, objList); err != nil { t.Fatalf("Failed to list objects (gvk %v): %v", objList.GroupVersionKind(), err) } if len(objList.Items) != 1 { t.Fatalf("Expected a single TestType resource to exist") } } func TestCtlUpgradeMigrate_FailsIfStorageVersionDoesNotEqualTargetVersion(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() // Create the control plane with the TestType conversion handlers registered scheme := newScheme() // name of the testtype CRD resource crdName := "testtypes.testgroup.testing.cert-manager.io" restCfg, stop := framework.RunControlPlane(t, context.Background(), framework.WithCRDDirectory(crdFolder(t))) defer stop() // Ensure the OpenAPI endpoint has been updated with the TestType CRD framework.WaitForOpenAPIResourcesToBeLoaded(t, ctx, restCfg, schema.GroupVersionKind{ Group: "testgroup.testing.cert-manager.io", Version: "v1", Kind: "TestType", }) // Create an API client cl, err := client.New(restCfg, client.Options{Scheme: scheme}) if err != nil { t.Fatal(err) } // Fetch a copy of the recently created TestType CRD crd := &apiext.CustomResourceDefinition{} if err := cl.Get(ctx, client.ObjectKey{Name: crdName}, crd); err != nil { t.Fatal(err) } // Identify the current storage version and one non-storage version for this CRD. storageVersion, nonStorageVersion := versionsForCRD(crd) if storageVersion == "" || nonStorageVersion == "" { t.Fatal("this test requires testdata with both a storage and non-storage version set") } // We expect this to fail, as we are attempting to migrate to the 'nonStorageVersion'. migrator := migrateapiversion.NewMigrator(cl, false, os.Stdout, os.Stderr) migrated, err := migrator.Run(ctx, nonStorageVersion, []string{crdName}) if err == nil { t.Errorf("expected an error to be returned but we got none") } if err.Error() != "preflight checks failed" { t.Errorf("unexpected error: %v", err) } if migrated { t.Errorf("migrator ran but it should not have") } } func TestCtlUpgradeMigrate_SkipsMigrationIfNothingToDo(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() // Create the control plane with the TestType conversion handlers registered scheme := newScheme() // name of the testtype CRD resource crdName := "testtypes.testgroup.testing.cert-manager.io" restCfg, stop := framework.RunControlPlane(t, context.Background(), framework.WithCRDDirectory(crdFolder(t))) defer stop() // Ensure the OpenAPI endpoint has been updated with the TestType CRD framework.WaitForOpenAPIResourcesToBeLoaded(t, ctx, restCfg, schema.GroupVersionKind{ Group: "testgroup.testing.cert-manager.io", Version: "v1", Kind: "TestType", }) // Create an API client cl, err := client.New(restCfg, client.Options{Scheme: scheme}) if err != nil { t.Fatal(err) } // Fetch a copy of the recently created TestType CRD crd := &apiext.CustomResourceDefinition{} if err := cl.Get(ctx, client.ObjectKey{Name: crdName}, crd); err != nil { t.Fatal(err) } // Identify the current storage version and one non-storage version for this CRD. storageVersion, nonStorageVersion := versionsForCRD(crd) if storageVersion == "" || nonStorageVersion == "" { t.Fatal("this test requires testdata with both a storage and non-storage version set") } // Ensure the original storage version is the only one on the CRD if len(crd.Status.StoredVersions) != 1 || crd.Status.StoredVersions[0] != storageVersion { t.Errorf("Expected status.storedVersions to only contain the storage version %q but it was: %v", storageVersion, crd.Status.StoredVersions) } // Create a resource obj := newResourceAtVersion(t, storageVersion) if err := cl.Create(ctx, obj); err != nil { t.Errorf("Failed to create test resource: %v", err) } // We expect this to succeed and for the migration to not be run migrator := migrateapiversion.NewMigrator(cl, false, os.Stdout, os.Stderr) migrated, err := migrator.Run(ctx, storageVersion, []string{crdName}) if err != nil { t.Errorf("unexpected error: %v", err) } if migrated { t.Errorf("migrator ran but it should not have") } } func TestCtlUpgradeMigrate_ForcesMigrationIfSkipStoredVersionCheckIsEnabled(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() // Create the control plane with the TestType conversion handlers registered scheme := newScheme() // name of the testtype CRD resource crdName := "testtypes.testgroup.testing.cert-manager.io" restCfg, stop := framework.RunControlPlane(t, context.Background(), framework.WithCRDDirectory(crdFolder(t))) defer stop() // Ensure the OpenAPI endpoint has been updated with the TestType CRD framework.WaitForOpenAPIResourcesToBeLoaded(t, ctx, restCfg, schema.GroupVersionKind{ Group: "testgroup.testing.cert-manager.io", Version: "v1", Kind: "TestType", }) // Create an API client cl, err := client.New(restCfg, client.Options{Scheme: scheme}) if err != nil { t.Fatal(err) } // Fetch a copy of the recently created TestType CRD crd := &apiext.CustomResourceDefinition{} if err := cl.Get(ctx, client.ObjectKey{Name: crdName}, crd); err != nil { t.Fatal(err) } // Identify the current storage version and one non-storage version for this CRD. storageVersion, nonStorageVersion := versionsForCRD(crd) if storageVersion == "" || nonStorageVersion == "" { t.Fatal("this test requires testdata with both a storage and non-storage version set") } // Ensure the original storage version is the only one on the CRD if len(crd.Status.StoredVersions) != 1 || crd.Status.StoredVersions[0] != storageVersion { t.Errorf("Expected status.storedVersions to only contain the storage version %q but it was: %v", storageVersion, crd.Status.StoredVersions) } // Create a resource obj := newResourceAtVersion(t, storageVersion) if err := cl.Create(ctx, obj); err != nil { t.Errorf("Failed to create test resource: %v", err) } // We expect this to force a migration migrator := migrateapiversion.NewMigrator(cl, true, os.Stdout, os.Stderr) migrated, err := migrator.Run(ctx, storageVersion, []string{crdName}) if err != nil { t.Errorf("unexpected error: %v", err) } if !migrated { t.Errorf("expected migrator to run due to skip flag being set") } } func versionsForCRD(crd *apiext.CustomResourceDefinition) (storage, nonstorage string) { storageVersion := "" nonStorageVersion := "" for _, v := range crd.Spec.Versions { if v.Storage { storageVersion = v.Name } else { nonStorageVersion = v.Name } if storageVersion != "" && nonStorageVersion != "" { break } } return storageVersion, nonStorageVersion } func setStorageVersion(crd *apiext.CustomResourceDefinition, newStorageVersion string) { for i, v := range crd.Spec.Versions { if v.Name == newStorageVersion { v.Storage = true } else if v.Storage { v.Storage = false } crd.Spec.Versions[i] = v } } func removeAPIVersion(crd *apiext.CustomResourceDefinition, version string) { var newVersions []apiext.CustomResourceDefinitionVersion for _, v := range crd.Spec.Versions { if v.Name != version { newVersions = append(newVersions, v) } } crd.Spec.Versions = newVersions } 070701000000B5000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002600000000cmctl-2.1.1/test/integration/testdata070701000000B6000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002B00000000cmctl-2.1.1/test/integration/testdata/apis070701000000B7000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003500000000cmctl-2.1.1/test/integration/testdata/apis/testgroup070701000000B8000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003A00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/crds070701000000B9000081A400000000000000000000000166DFF09D00000047000000000000000000000000000000000000004400000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/crds/README.md# README These CRDs are auto generated by `make/test-integration.mk`. 070701000000BA000081A400000000000000000000000166DFF09D00000FFE000000000000000000000000000000000000006B00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/crds/testgroup.testing.cert-manager.io_testtypes.yaml--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.1 name: testtypes.testgroup.testing.cert-manager.io spec: group: testgroup.testing.cert-manager.io names: kind: TestType listKind: TestTypeList plural: testtypes singular: testtype scope: Namespaced versions: - name: v1 schema: openAPIV3Schema: properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object testDefaultingField: description: |- TestDefaultingField is used to test defaulting. In the v1 API, it defaults to `set-in-v1`. In the v2 API, it defaults to `set-in-v2`. type: string testField: description: |- TestField is used in tests. Validation doesn't allow this to be set to the value of TestFieldValueNotAllowed. type: string testFieldImmutable: description: TestFieldImmutable cannot be changed after being set to a non-zero value type: string testFieldPtr: type: string required: - metadata - testField - testFieldImmutable type: object served: true storage: false - name: v2 schema: openAPIV3Schema: description: TestType in v2 is identical to v1, except TestFieldPtr has been renamed to TestFieldPtrAlt properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object testDefaultingField: description: |- TestDefaultingField is used to test defaulting. In the v1 API, it defaults to `set-in-v1`. In the v2 API, it defaults to `set-in-v2`. type: string testField: description: |- TestField is used in tests. Validation doesn't allow this to be set to the value of TestFieldValueNotAllowed. type: string testFieldImmutable: description: TestFieldImmutable cannot be changed after being set to a non-zero value type: string testFieldPtrAlt: type: string required: - metadata - testField - testFieldImmutable type: object served: true storage: true 070701000000BB000081A400000000000000000000000166DFF09D000002DD000000000000000000000000000000000000003C00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/doc.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // +k8s:deepcopy-gen=package,register // +groupName=testgroup.testing.cert-manager.io package testgroup const GroupName = "testgroup.testing.cert-manager.io" 070701000000BC000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003C00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/fuzzer070701000000BD000081A400000000000000000000000166DFF09D00000485000000000000000000000000000000000000004600000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/fuzzer/fuzzer.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package fuzzer import ( fuzz "github.com/google/gofuzz" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/utils/ptr" "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup" ) // Funcs returns the fuzzer functions for the apps api group. var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ func(s *testgroup.TestType, c fuzz.Continue) { c.FuzzNoCustom(s) // fuzz self without calling this function again if s.TestFieldPtr == nil { s.TestFieldPtr = ptr.To("teststr") } }, } } 070701000000BE000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003D00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/install070701000000BF000081A400000000000000000000000166DFF09D0000050F000000000000000000000000000000000000004800000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/install/install.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Package install installs the API group, making it available as an option to // all of the API encoding/decoding machinery. package install import ( "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup" v1 "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup/v1" v2 "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup/v2" ) // Install registers the API group and adds types to a scheme func Install(scheme *runtime.Scheme) { utilruntime.Must(testgroup.AddToScheme(scheme)) utilruntime.Must(v1.AddToScheme(scheme)) utilruntime.Must(v2.AddToScheme(scheme)) } 070701000000C0000081A400000000000000000000000166DFF09D00000357000000000000000000000000000000000000004F00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/install/roundtrip_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package install import ( "testing" "k8s.io/apimachinery/pkg/api/apitesting/roundtrip" "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup/fuzzer" ) func TestRoundTripTypes(t *testing.T) { roundtrip.RoundTripTestForAPIGroup(t, Install, fuzzer.Funcs) } 070701000000C1000081A400000000000000000000000166DFF09D0000053E000000000000000000000000000000000000004100000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/register.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package testgroup import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) var ( SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) AddToScheme = SchemeBuilder.AddToScheme ) // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} // Resource takes an unqualified resource and returns a Group qualified GroupResource func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() } // Adds the list of known types to api.Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TestType{}, ) return nil } 070701000000C2000081A400000000000000000000000166DFF09D0000046C000000000000000000000000000000000000003E00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/types.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package testgroup import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type TestType struct { metav1.TypeMeta metav1.ObjectMeta // TestField is used in tests. // Validation doesn't allow this to be set to the value of TestFieldValueNotAllowed. TestField string TestFieldPtr *string // TestFieldImmutable cannot be changed after being set to a non-zero value TestFieldImmutable string // TestDefaultingField is used to test defaulting. TestDefaultingField string } 070701000000C3000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003800000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v1070701000000C4000081A400000000000000000000000166DFF09D000003AC000000000000000000000000000000000000004400000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v1/defaults.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v1 import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/utils/ptr" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { return RegisterDefaults(scheme) } func SetDefaults_TestType(obj *TestType) { if obj.TestFieldPtr == nil { obj.TestFieldPtr = ptr.To("teststr") } if obj.TestDefaultingField == "" { obj.TestDefaultingField = "set-in-v1" } } 070701000000C5000081A400000000000000000000000166DFF09D0000031F000000000000000000000000000000000000003F00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v1/doc.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // +k8s:conversion-gen=github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup // +k8s:deepcopy-gen=package,register // +k8s:defaulter-gen=TypeMeta // +groupName=testgroup.testing.cert-manager.io package v1 070701000000C6000081A400000000000000000000000166DFF09D0000072E000000000000000000000000000000000000004400000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v1/register.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup" ) // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: testgroup.GroupName, Version: "v1"} // Resource takes an unqualified resource and returns a Group qualified GroupResource func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() } var ( SchemeBuilder runtime.SchemeBuilder localSchemeBuilder = &SchemeBuilder AddToScheme = localSchemeBuilder.AddToScheme ) func init() { // We only register manually written functions here. The registration of the // generated functions takes place in the generated files. The separation // makes the code compile even when the generated files are missing. localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs) } // Adds the list of known types to api.Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TestType{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil } 070701000000C7000081A400000000000000000000000166DFF09D0000059A000000000000000000000000000000000000004100000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v1/types.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type TestType struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` // TestField is used in tests. // Validation doesn't allow this to be set to the value of TestFieldValueNotAllowed. TestField string `json:"testField"` TestFieldPtr *string `json:"testFieldPtr,omitempty"` // TestFieldImmutable cannot be changed after being set to a non-zero value TestFieldImmutable string `json:"testFieldImmutable"` // TestDefaultingField is used to test defaulting. // In the v1 API, it defaults to `set-in-v1`. // In the v2 API, it defaults to `set-in-v2`. TestDefaultingField string `json:"testDefaultingField,omitempty"` } const ( TestFieldValueNotAllowed = "not-allowed-value" ) 070701000000C8000081A400000000000000000000000166DFF09D00000B87000000000000000000000000000000000000005300000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v1/zz_generated.conversion.go//go:build !ignore_autogenerated // +build !ignore_autogenerated /* Copyright The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Code generated by conversion-gen. DO NOT EDIT. package v1 import ( unsafe "unsafe" testgroup "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" ) func init() { localSchemeBuilder.Register(RegisterConversions) } // RegisterConversions adds conversion functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterConversions(s *runtime.Scheme) error { if err := s.AddGeneratedConversionFunc((*TestType)(nil), (*testgroup.TestType)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1_TestType_To_testgroup_TestType(a.(*TestType), b.(*testgroup.TestType), scope) }); err != nil { return err } if err := s.AddGeneratedConversionFunc((*testgroup.TestType)(nil), (*TestType)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_testgroup_TestType_To_v1_TestType(a.(*testgroup.TestType), b.(*TestType), scope) }); err != nil { return err } return nil } func autoConvert_v1_TestType_To_testgroup_TestType(in *TestType, out *testgroup.TestType, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta out.TestField = in.TestField out.TestFieldPtr = (*string)(unsafe.Pointer(in.TestFieldPtr)) out.TestFieldImmutable = in.TestFieldImmutable out.TestDefaultingField = in.TestDefaultingField return nil } // Convert_v1_TestType_To_testgroup_TestType is an autogenerated conversion function. func Convert_v1_TestType_To_testgroup_TestType(in *TestType, out *testgroup.TestType, s conversion.Scope) error { return autoConvert_v1_TestType_To_testgroup_TestType(in, out, s) } func autoConvert_testgroup_TestType_To_v1_TestType(in *testgroup.TestType, out *TestType, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta out.TestField = in.TestField out.TestFieldPtr = (*string)(unsafe.Pointer(in.TestFieldPtr)) out.TestFieldImmutable = in.TestFieldImmutable out.TestDefaultingField = in.TestDefaultingField return nil } // Convert_testgroup_TestType_To_v1_TestType is an autogenerated conversion function. func Convert_testgroup_TestType_To_v1_TestType(in *testgroup.TestType, out *TestType, s conversion.Scope) error { return autoConvert_testgroup_TestType_To_v1_TestType(in, out, s) } 070701000000C9000081A400000000000000000000000166DFF09D00000605000000000000000000000000000000000000005100000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v1/zz_generated.deepcopy.go//go:build !ignore_autogenerated /* Copyright The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Code generated by controller-gen. DO NOT EDIT. package v1 import ( "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestType) DeepCopyInto(out *TestType) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) if in.TestFieldPtr != nil { in, out := &in.TestFieldPtr, &out.TestFieldPtr *out = new(string) **out = **in } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestType. func (in *TestType) DeepCopy() *TestType { if in == nil { return nil } out := new(TestType) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *TestType) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } 070701000000CA000081A400000000000000000000000166DFF09D000004AF000000000000000000000000000000000000005100000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v1/zz_generated.defaults.go//go:build !ignore_autogenerated // +build !ignore_autogenerated /* Copyright The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Code generated by defaulter-gen. DO NOT EDIT. package v1 import ( runtime "k8s.io/apimachinery/pkg/runtime" ) // RegisterDefaults adds defaulters functions to the given scheme. // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { scheme.AddTypeDefaultingFunc(&TestType{}, func(obj interface{}) { SetObjectDefaults_TestType(obj.(*TestType)) }) return nil } func SetObjectDefaults_TestType(in *TestType) { SetDefaults_TestType(in) } 070701000000CB000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003800000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2070701000000CC000081A400000000000000000000000166DFF09D0000051F000000000000000000000000000000000000004300000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2/convert.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v2 import ( "unsafe" "k8s.io/apimachinery/pkg/conversion" "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup" ) func Convert_v2_TestType_To_testgroup_TestType(in *TestType, out *testgroup.TestType, s conversion.Scope) error { if err := autoConvert_v2_TestType_To_testgroup_TestType(in, out, s); err != nil { return err } out.TestFieldPtr = (*string)(unsafe.Pointer(in.TestFieldPtrAlt)) return nil } func Convert_testgroup_TestType_To_v2_TestType(in *testgroup.TestType, out *TestType, s conversion.Scope) error { if err := autoConvert_testgroup_TestType_To_v2_TestType(in, out, s); err != nil { return err } out.TestFieldPtrAlt = (*string)(unsafe.Pointer(in.TestFieldPtr)) return nil } 070701000000CD000081A400000000000000000000000166DFF09D000003B2000000000000000000000000000000000000004400000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2/defaults.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v2 import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/utils/ptr" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { return RegisterDefaults(scheme) } func SetDefaults_TestType(obj *TestType) { if obj.TestFieldPtrAlt == nil { obj.TestFieldPtrAlt = ptr.To("teststr") } if obj.TestDefaultingField == "" { obj.TestDefaultingField = "set-in-v2" } } 070701000000CE000081A400000000000000000000000166DFF09D0000031F000000000000000000000000000000000000003F00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2/doc.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // +k8s:conversion-gen=github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup // +k8s:deepcopy-gen=package,register // +k8s:defaulter-gen=TypeMeta // +groupName=testgroup.testing.cert-manager.io package v2 070701000000CF000081A400000000000000000000000166DFF09D0000072E000000000000000000000000000000000000004400000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2/register.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup" ) // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: testgroup.GroupName, Version: "v2"} // Resource takes an unqualified resource and returns a Group qualified GroupResource func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() } var ( SchemeBuilder runtime.SchemeBuilder localSchemeBuilder = &SchemeBuilder AddToScheme = localSchemeBuilder.AddToScheme ) func init() { // We only register manually written functions here. The registration of the // generated functions takes place in the generated files. The separation // makes the code compile even when the generated files are missing. localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs) } // Adds the list of known types to api.Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TestType{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil } 070701000000D0000081A400000000000000000000000166DFF09D00000627000000000000000000000000000000000000004100000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2/types.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +kubebuilder:storageversion // TestType in v2 is identical to v1, except TestFieldPtr has been renamed to TestFieldPtrAlt type TestType struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` // TestField is used in tests. // Validation doesn't allow this to be set to the value of TestFieldValueNotAllowed. TestField string `json:"testField"` // +optional TestFieldPtrAlt *string `json:"testFieldPtrAlt,omitempty"` // TestFieldImmutable cannot be changed after being set to a non-zero value TestFieldImmutable string `json:"testFieldImmutable"` // TestDefaultingField is used to test defaulting. // In the v1 API, it defaults to `set-in-v1`. // In the v2 API, it defaults to `set-in-v2`. TestDefaultingField string `json:"testDefaultingField,omitempty"` } const ( DisallowedTestFieldValue = "not-allowed-in-v2" ) 070701000000D1000081A400000000000000000000000166DFF09D0000040D000000000000000000000000000000000000004600000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2/validation.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v2 import ( admissionv1 "k8s.io/api/admission/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" ) func ValidateTestType(_ *admissionv1.AdmissionRequest, obj runtime.Object) (field.ErrorList, []string) { el := field.ErrorList{} tt := obj.(*TestType) if tt.TestField == DisallowedTestFieldValue { el = append(el, field.Invalid(field.NewPath("testField"), tt.TestField, "value not allowed")) } return el, nil } 070701000000D2000081A400000000000000000000000166DFF09D00000978000000000000000000000000000000000000005300000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2/zz_generated.conversion.go//go:build !ignore_autogenerated // +build !ignore_autogenerated /* Copyright The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Code generated by conversion-gen. DO NOT EDIT. package v2 import ( testgroup "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup" conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" ) func init() { localSchemeBuilder.Register(RegisterConversions) } // RegisterConversions adds conversion functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterConversions(s *runtime.Scheme) error { if err := s.AddConversionFunc((*testgroup.TestType)(nil), (*TestType)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_testgroup_TestType_To_v2_TestType(a.(*testgroup.TestType), b.(*TestType), scope) }); err != nil { return err } if err := s.AddConversionFunc((*TestType)(nil), (*testgroup.TestType)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v2_TestType_To_testgroup_TestType(a.(*TestType), b.(*testgroup.TestType), scope) }); err != nil { return err } return nil } func autoConvert_v2_TestType_To_testgroup_TestType(in *TestType, out *testgroup.TestType, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta out.TestField = in.TestField // WARNING: in.TestFieldPtrAlt requires manual conversion: does not exist in peer-type out.TestFieldImmutable = in.TestFieldImmutable out.TestDefaultingField = in.TestDefaultingField return nil } func autoConvert_testgroup_TestType_To_v2_TestType(in *testgroup.TestType, out *TestType, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta out.TestField = in.TestField // WARNING: in.TestFieldPtr requires manual conversion: does not exist in peer-type out.TestFieldImmutable = in.TestFieldImmutable out.TestDefaultingField = in.TestDefaultingField return nil } 070701000000D3000081A400000000000000000000000166DFF09D0000060E000000000000000000000000000000000000005100000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2/zz_generated.deepcopy.go//go:build !ignore_autogenerated /* Copyright The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Code generated by controller-gen. DO NOT EDIT. package v2 import ( "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestType) DeepCopyInto(out *TestType) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) if in.TestFieldPtrAlt != nil { in, out := &in.TestFieldPtrAlt, &out.TestFieldPtrAlt *out = new(string) **out = **in } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestType. func (in *TestType) DeepCopy() *TestType { if in == nil { return nil } out := new(TestType) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *TestType) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } 070701000000D4000081A400000000000000000000000166DFF09D000004AF000000000000000000000000000000000000005100000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/v2/zz_generated.defaults.go//go:build !ignore_autogenerated // +build !ignore_autogenerated /* Copyright The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Code generated by defaulter-gen. DO NOT EDIT. package v2 import ( runtime "k8s.io/apimachinery/pkg/runtime" ) // RegisterDefaults adds defaulters functions to the given scheme. // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { scheme.AddTypeDefaultingFunc(&TestType{}, func(obj interface{}) { SetObjectDefaults_TestType(obj.(*TestType)) }) return nil } func SetObjectDefaults_TestType(in *TestType) { SetDefaults_TestType(in) } 070701000000D5000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000004000000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/validation070701000000D6000081A400000000000000000000000166DFF09D000006F3000000000000000000000000000000000000004E00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/validation/validation.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package validation import ( admissionv1 "k8s.io/api/admission/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup" v1 "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup/v1" ) func ValidateTestType(_ *admissionv1.AdmissionRequest, obj runtime.Object) (field.ErrorList, []string) { testType := obj.(*testgroup.TestType) el := field.ErrorList{} if testType.TestField == v1.TestFieldValueNotAllowed { el = append(el, field.Invalid(field.NewPath("testField"), testType.TestField, "invalid value")) } return el, nil } func ValidateTestTypeUpdate(_ *admissionv1.AdmissionRequest, oldObj, newObj runtime.Object) (field.ErrorList, []string) { old, ok := oldObj.(*testgroup.TestType) new := newObj.(*testgroup.TestType) // if oldObj is not set, the Update operation is always valid. if !ok || old == nil { return nil, nil } el := field.ErrorList{} if old.TestFieldImmutable != "" && old.TestFieldImmutable != new.TestFieldImmutable { el = append(el, field.Forbidden(field.NewPath("testFieldImmutable"), "field is immutable once set")) } return el, nil } 070701000000D7000081A400000000000000000000000166DFF09D000012AA000000000000000000000000000000000000005300000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/validation/validation_test.go/* Copyright 2020 The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package validation import ( "reflect" "testing" "k8s.io/apimachinery/pkg/util/validation/field" "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup" v1 "github.com/cert-manager/cmctl/v2/test/integration/testdata/apis/testgroup/v1" ) func TestValidateTestType(t *testing.T) { scenarios := map[string]struct { obj *testgroup.TestType errs []*field.Error warnings []string }{ "does not allow testField to be TestFieldValueNotAllowed": { obj: &testgroup.TestType{ TestField: v1.TestFieldValueNotAllowed, }, errs: []*field.Error{ field.Invalid(field.NewPath("testField"), v1.TestFieldValueNotAllowed, "invalid value"), }, }, } for n, s := range scenarios { t.Run(n, func(t *testing.T) { errs, warnings := ValidateTestType(nil, s.obj) if len(errs) != len(s.errs) { t.Errorf("Expected errors %v but got %v", s.errs, errs) return } for i, e := range errs { expectedErr := s.errs[i] if !reflect.DeepEqual(e, expectedErr) { t.Errorf("Expected error %v but got %v", expectedErr, e) } } if !reflect.DeepEqual(warnings, s.warnings) { t.Errorf("Expected warnings %+#v but got %+#v", s.warnings, warnings) } }) } } func TestValidateTestTypeUpdate(t *testing.T) { testImmutableTestTypeField(t, field.NewPath("testFieldImmutable"), func(obj *testgroup.TestType, s testValue) { obj.TestFieldImmutable = string(s) }) scenarios := map[string]struct { old, new *testgroup.TestType errs []*field.Error warnings []string }{ "allows all updates if old is nil": { new: &testgroup.TestType{ TestFieldImmutable: "abc", }, }, } for n, s := range scenarios { t.Run(n, func(t *testing.T) { errs, warnings := ValidateTestTypeUpdate(nil, s.old, s.new) if len(errs) != len(s.errs) { t.Errorf("Expected errors %v but got %v", s.errs, errs) return } for i, e := range errs { expectedErr := s.errs[i] if !reflect.DeepEqual(e, expectedErr) { t.Errorf("Expected error %v but got %v", expectedErr, e) } } if !reflect.DeepEqual(warnings, s.warnings) { t.Errorf("Expected warnings %+#v but got %+#v", s.warnings, warnings) } }) } } type testValue string const ( testValueNone = "" testValueOptionOne = "one" testValueOptionTwo = "two" ) // testImmutableOrderField will test that the field at path fldPath does // not allow changes after being set, but does allow changes if the old field // is not set. func testImmutableTestTypeField(t *testing.T, fldPath *field.Path, setter func(*testgroup.TestType, testValue)) { t.Run("should reject updates to "+fldPath.String(), func(t *testing.T) { var expectedWarnings []string expectedErrs := []*field.Error{ field.Forbidden(fldPath, "field is immutable once set"), } old := &testgroup.TestType{} new := &testgroup.TestType{} setter(old, testValueOptionOne) setter(new, testValueOptionTwo) errs, warnings := ValidateTestTypeUpdate(nil, old, new) if len(errs) != len(expectedErrs) { t.Errorf("Expected errors %v but got %v", expectedErrs, errs) return } for i, e := range errs { expectedErr := expectedErrs[i] if !reflect.DeepEqual(e, expectedErr) { t.Errorf("Expected error %v but got %v", expectedErr, e) } } if !reflect.DeepEqual(warnings, expectedWarnings) { t.Errorf("Expected warnings %+#v got %+#v", expectedWarnings, warnings) } }) t.Run("should allow updates to "+fldPath.String()+" if not already set", func(t *testing.T) { var expectedWarnings []string expectedErrs := []*field.Error{} old := &testgroup.TestType{} new := &testgroup.TestType{} setter(old, testValueNone) setter(new, testValueOptionOne) errs, warnings := ValidateTestTypeUpdate(nil, old, new) if len(errs) != len(expectedErrs) { t.Errorf("Expected errors %v but got %v", expectedErrs, errs) return } for i, e := range errs { expectedErr := expectedErrs[i] if !reflect.DeepEqual(e, expectedErr) { t.Errorf("Expected error %v but got %v", expectedErr, e) } } if !reflect.DeepEqual(warnings, expectedWarnings) { t.Errorf("Expected warnings %+#v but got %+#v", expectedWarnings, warnings) } }) } 070701000000D8000081A400000000000000000000000166DFF09D0000060C000000000000000000000000000000000000004E00000000cmctl-2.1.1/test/integration/testdata/apis/testgroup/zz_generated.deepcopy.go//go:build !ignore_autogenerated /* Copyright The cert-manager Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Code generated by controller-gen. DO NOT EDIT. package testgroup import ( "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestType) DeepCopyInto(out *TestType) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) if in.TestFieldPtr != nil { in, out := &in.TestFieldPtr, &out.TestFieldPtr *out = new(string) **out = **in } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestType. func (in *TestType) DeepCopy() *TestType { if in == nil { return nil } out := new(TestType) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. func (in *TestType) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } 070701000000D9000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000002E00000000cmctl-2.1.1/test/integration/testdata/convert070701000000DA000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003400000000cmctl-2.1.1/test/integration/testdata/convert/input070701000000DB000081A400000000000000000000000166DFF09D00000103000000000000000000000000000000000000004300000000cmctl-2.1.1/test/integration/testdata/convert/input/resource1.yamlapiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: name: ca-issuer namespace: sandbox spec: isCA: true secretName: ca-key-pair commonName: my-csi-app issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io 070701000000DC000081A400000000000000000000000166DFF09D000002A8000000000000000000000000000000000000004300000000cmctl-2.1.1/test/integration/testdata/convert/input/resource2.yaml--- # my comment apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: name: ca-issuer namespace: sandbox spec: isCA: true secretName: ca-key-pair commonName: my-csi-app issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io --- apiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: name: ca-issuer namespace: sandbox spec: ca: secretName: ca-key-pair --- apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: name: ca-issuer-2 namespace: sandbox spec: isCA: true secretName: ca-key-pair commonName: my-csi-app issuerRef: name: ca-issuer kind: Issuer group: cert-manager.io --- 070701000000DD000081A400000000000000000000000166DFF09D000000BF000000000000000000000000000000000000004300000000cmctl-2.1.1/test/integration/testdata/convert/input/resource3.yamlapiVersion: v1 kind: Namespace metadata: name: sandbox --- apiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: name: selfsigned-issuer namespace: sandbox spec: selfSigned: {} 070701000000DE000081A400000000000000000000000166DFF09D00000125000000000000000000000000000000000000005D00000000cmctl-2.1.1/test/integration/testdata/convert/input/resource_with_organization_v1alpha2.yamlapiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: name: ca-issuer namespace: sandbox spec: isCA: true secretName: ca-key-pair organization: - "hello world" commonName: my-csi-app issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io 070701000000DF000081A400000000000000000000000166DFF09D00000318000000000000000000000000000000000000005400000000cmctl-2.1.1/test/integration/testdata/convert/input/resources_as_list_v1alpha2.yamlapiVersion: v1 kind: List items: - apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.1 duration: 24h issuerRef: name: cert-manager-test-1 secretName: cert-manager-test-1 - apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.2 duration: 24h issuerRef: name: cert-manager-test-2 secretName: cert-manager-test-2 - apiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: name: ca-issuer namespace: sandbox spec: ca: secretName: ca-key-pair 070701000000E0000041ED00000000000000000000000266DFF09D00000000000000000000000000000000000000000000003500000000cmctl-2.1.1/test/integration/testdata/convert/output070701000000E1000081A400000000000000000000000166DFF09D00000000000000000000000000000000000000000000004A00000000cmctl-2.1.1/test/integration/testdata/convert/output/no_output_error.yaml070701000000E2000081A400000000000000000000000166DFF09D00000122000000000000000000000000000000000000004700000000cmctl-2.1.1/test/integration/testdata/convert/output/resource1_v1.yamlapiVersion: cert-manager.io/v1 kind: Certificate metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: selfsigned-issuer secretName: ca-key-pair status: {} 070701000000E3000081A400000000000000000000000166DFF09D00000128000000000000000000000000000000000000004D00000000cmctl-2.1.1/test/integration/testdata/convert/output/resource1_v1alpha2.yamlapiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: selfsigned-issuer secretName: ca-key-pair status: {} 070701000000E4000081A400000000000000000000000166DFF09D00000128000000000000000000000000000000000000004D00000000cmctl-2.1.1/test/integration/testdata/convert/output/resource1_v1alpha3.yamlapiVersion: cert-manager.io/v1alpha3 kind: Certificate metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: selfsigned-issuer secretName: ca-key-pair status: {} 070701000000E5000081A400000000000000000000000166DFF09D00000366000000000000000000000000000000000000004700000000cmctl-2.1.1/test/integration/testdata/convert/output/resource2_v1.yamlapiVersion: v1 items: - apiVersion: cert-manager.io/v1 kind: Certificate metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: selfsigned-issuer secretName: ca-key-pair status: {} - apiVersion: cert-manager.io/v1 kind: Issuer metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: ca: secretName: ca-key-pair status: {} - apiVersion: cert-manager.io/v1 kind: Certificate metadata: creationTimestamp: null name: ca-issuer-2 namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: ca-issuer secretName: ca-key-pair status: {} kind: List metadata: {} 070701000000E6000081A400000000000000000000000166DFF09D00000378000000000000000000000000000000000000004D00000000cmctl-2.1.1/test/integration/testdata/convert/output/resource2_v1alpha2.yamlapiVersion: v1 items: - apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: selfsigned-issuer secretName: ca-key-pair status: {} - apiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: ca: secretName: ca-key-pair status: {} - apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: creationTimestamp: null name: ca-issuer-2 namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: ca-issuer secretName: ca-key-pair status: {} kind: List metadata: {} 070701000000E7000081A400000000000000000000000166DFF09D00000378000000000000000000000000000000000000004D00000000cmctl-2.1.1/test/integration/testdata/convert/output/resource2_v1alpha3.yamlapiVersion: v1 items: - apiVersion: cert-manager.io/v1alpha3 kind: Certificate metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: selfsigned-issuer secretName: ca-key-pair status: {} - apiVersion: cert-manager.io/v1alpha3 kind: Issuer metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: ca: secretName: ca-key-pair status: {} - apiVersion: cert-manager.io/v1alpha3 kind: Certificate metadata: creationTimestamp: null name: ca-issuer-2 namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: ca-issuer secretName: ca-key-pair status: {} kind: List metadata: {} 070701000000E8000081A400000000000000000000000166DFF09D00000152000000000000000000000000000000000000005800000000cmctl-2.1.1/test/integration/testdata/convert/output/resource_with_organization_v1.yamlapiVersion: cert-manager.io/v1 kind: Certificate metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: selfsigned-issuer secretName: ca-key-pair subject: organizations: - hello world status: {} 070701000000E9000081A400000000000000000000000166DFF09D00000158000000000000000000000000000000000000005E00000000cmctl-2.1.1/test/integration/testdata/convert/output/resource_with_organization_v1alpha3.yamlapiVersion: cert-manager.io/v1alpha3 kind: Certificate metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: selfsigned-issuer secretName: ca-key-pair subject: organizations: - hello world status: {} 070701000000EA000081A400000000000000000000000166DFF09D00000157000000000000000000000000000000000000005D00000000cmctl-2.1.1/test/integration/testdata/convert/output/resource_with_organization_v1beta1.yamlapiVersion: cert-manager.io/v1beta1 kind: Certificate metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: commonName: my-csi-app isCA: true issuerRef: group: cert-manager.io kind: Issuer name: selfsigned-issuer secretName: ca-key-pair subject: organizations: - hello world status: {} 070701000000EB000081A400000000000000000000000166DFF09D00000352000000000000000000000000000000000000004F00000000cmctl-2.1.1/test/integration/testdata/convert/output/resources_as_list_v1.yamlapiVersion: v1 items: - apiVersion: cert-manager.io/v1 kind: Certificate metadata: creationTimestamp: null name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.1 duration: 24h0m0s issuerRef: name: cert-manager-test-1 secretName: cert-manager-test-1 status: {} - apiVersion: cert-manager.io/v1 kind: Certificate metadata: creationTimestamp: null name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.2 duration: 24h0m0s issuerRef: name: cert-manager-test-2 secretName: cert-manager-test-2 status: {} - apiVersion: cert-manager.io/v1 kind: Issuer metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: ca: secretName: ca-key-pair status: {} kind: List metadata: {} 070701000000EC000081A400000000000000000000000166DFF09D00000364000000000000000000000000000000000000005500000000cmctl-2.1.1/test/integration/testdata/convert/output/resources_as_list_v1alpha2.yamlapiVersion: v1 items: - apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: creationTimestamp: null name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.1 duration: 24h0m0s issuerRef: name: cert-manager-test-1 secretName: cert-manager-test-1 status: {} - apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: creationTimestamp: null name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.2 duration: 24h0m0s issuerRef: name: cert-manager-test-2 secretName: cert-manager-test-2 status: {} - apiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: ca: secretName: ca-key-pair status: {} kind: List metadata: {} 070701000000ED000081A400000000000000000000000166DFF09D00000364000000000000000000000000000000000000005500000000cmctl-2.1.1/test/integration/testdata/convert/output/resources_as_list_v1alpha3.yamlapiVersion: v1 items: - apiVersion: cert-manager.io/v1alpha3 kind: Certificate metadata: creationTimestamp: null name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.1 duration: 24h0m0s issuerRef: name: cert-manager-test-1 secretName: cert-manager-test-1 status: {} - apiVersion: cert-manager.io/v1alpha3 kind: Certificate metadata: creationTimestamp: null name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.2 duration: 24h0m0s issuerRef: name: cert-manager-test-2 secretName: cert-manager-test-2 status: {} - apiVersion: cert-manager.io/v1alpha3 kind: Issuer metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: ca: secretName: ca-key-pair status: {} kind: List metadata: {} 070701000000EE000081A400000000000000000000000166DFF09D00000361000000000000000000000000000000000000005400000000cmctl-2.1.1/test/integration/testdata/convert/output/resources_as_list_v1beta1.yamlapiVersion: v1 items: - apiVersion: cert-manager.io/v1beta1 kind: Certificate metadata: creationTimestamp: null name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.1 duration: 24h0m0s issuerRef: name: cert-manager-test-1 secretName: cert-manager-test-1 status: {} - apiVersion: cert-manager.io/v1beta1 kind: Certificate metadata: creationTimestamp: null name: list-test-1 namespace: default spec: dnsNames: - example.cert-manager.2 duration: 24h0m0s issuerRef: name: cert-manager-test-2 secretName: cert-manager-test-2 status: {} - apiVersion: cert-manager.io/v1beta1 kind: Issuer metadata: creationTimestamp: null name: ca-issuer namespace: sandbox spec: ca: secretName: ca-key-pair status: {} kind: List metadata: {} 070701000000EF000081A400000000000000000000000166DFF09D00000109000000000000000000000000000000000000004300000000cmctl-2.1.1/test/integration/testdata/create_cr_cert_with_ns1.yaml--- apiVersion: cert-manager.io/v1alpha2 kind: Certificate metadata: name: testcert-1 namespace: testns-1 spec: isCA: true secretName: ca-key-pair commonName: my-csi-app issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io 070701000000F0000081A400000000000000000000000166DFF09D0000008C000000000000000000000000000000000000003C00000000cmctl-2.1.1/test/integration/testdata/create_cr_issuer.yamlapiVersion: cert-manager.io/v1alpha2 kind: Issuer metadata: name: ca-issuer namespace: testns-1 spec: ca: secretName: ca-key-pair 070701000000F1000081A400000000000000000000000166DFF09D00000142000000000000000000000000000000000000004C00000000cmctl-2.1.1/test/integration/testdata/create_cr_v1alpha3_cert_with_ns1.yaml--- apiVersion: cert-manager.io/v1alpha3 kind: Certificate metadata: name: testcert-v1alpha3 namespace: testns-1 spec: isCA: true secretName: ca-key-pair commonName: my-csi-app issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io subject: organizations: - hello world 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!1830 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor