diff --git a/.github/*.instructions.md b/.github/*.instructions.md new file mode 100644 index 00000000000..b37eb3af2e3 --- /dev/null +++ b/.github/*.instructions.md @@ -0,0 +1 @@ +See [AGENTS.md](../AGENTS.md) for AI agent guidelines. \ No newline at end of file diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 00000000000..7fb00f820b5 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,42 @@ +# Security Policy + +## Security Announcements + +Join the [kubernetes-security-announce] group for security and vulnerability announcements related to the Kubernetes ecosystem. + +You can also subscribe to an RSS feed of these announcements using [this link][kubernetes-security-announce-rss]. + +## Reporting a Vulnerability + +Instructions for reporting a vulnerability can be found on the [Kubernetes Security and Disclosure Information] page. + +## Supported Versions + +Kubebuilder is tested against the latest three Kubernetes releases, in alignment with the [Kubernetes version and version skew support policy](https://kubernetes.io/docs/setup/release/version-skew-policy/). + +However, each version is only tested with the dependencies used for its release. For detailed information, please refer to the [compatibility and support policy on GitHub][compatibility-policy]. + +## Release Policy + +Kubebuilder maintains a policy of releasing updates for the latest CLI version (currently v4). Older versions (v1, v2, v3) are no longer supported, and no releases will be produced for them. It is recommended to ensure that any project scaffolded by Kubebuilder remains aligned with the latest release. + +## Automated Vulnerability Scanning + +Kubebuilder employs automated scanning via Dependabot and GitHub Actions within its CI/CD pipeline. This process detects vulnerabilities in dependencies and configurations, generating daily or weekly reports prioritized for the latest supported versions. + +- **Dependabot Configuration**: You can review the setup in `.github/dependabot.yml`. +- **Security Checks**: Security checks are enabled in the Kubebuilder repository settings. +- **Code Scanning**: The `.github/workflows/codeql.yml` workflow scans the `master` and `book-v4` branches, which typically contain the latest release code. Other release branches may not be scanned. + +## Production-Grade Security + +Projects generated by Kubebuilder are designed for ease of development and are **not** configured with production-grade security settings. For example, default configurations do not enable cert-manager or perform proper certificate validation, which may not be suitable for production environments. Ensure that you make the necessary adjustments to security settings before releasing your solution for production. + +[kubernetes-security-announce]: https://groups.google.com/forum/#!forum/kubernetes-security-announce +[kubernetes-security-announce-rss]: https://groups.google.com/forum/feed/kubernetes-security-announce/msgs/rss_v2_0.xml?num=50 +[Kubernetes version and version skew support policy]: https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions +[Kubernetes Security and Disclosure Information]: https://kubernetes.io/docs/reference/issues-security/security/#report-a-vulnerability +[compatibility-policy]: ./../README.md#versions-compatibility-and-supportability +[project-upgrade-assistant]: https://book.kubebuilder.io/reference/rescaffold +[testdata-directory]: https://github.com/kubernetes-sigs/kubebuilder/tree/master/testdata +[kubebuilder-releases]: https://github.com/kubernetes-sigs/kubebuilder/releases diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 99a0002983e..3a27eeb1829 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,14 +5,13 @@ version: 2 updates: - # Maintain dependencies for GitHub Actions - package-ecosystem: "github-actions" # Workflow files stored in the # default location of `.github/workflows` directory: "/" schedule: - interval: "weekly" + interval: "daily" commit-message: prefix: ":seedling:" labels: @@ -22,28 +21,36 @@ updates: - package-ecosystem: "gomod" directory: "/" schedule: - interval: "weekly" + interval: "daily" + commit-message: + prefix: ":seedling:" labels: - "ok-to-test" - # Maintain dependencies for dockerfile in the branches - - package-ecosystem: docker - directory: "/build/thirdparty/darwin" - target-branch: "tools-releases" - schedule: - interval: daily - - package-ecosystem: docker - directory: "/build/thirdparty/linux" - target-branch: "tools-releases" + # Maintain dependencies for go + - package-ecosystem: "gomod" + directory: "/testdata/project-v4" schedule: - interval: "weekly" + interval: "daily" + commit-message: + prefix: ":seedling:" + labels: + - "ok-to-test" # Maintain dependencies for dockerfile scaffold in the projects - package-ecosystem: docker - directory: "testdata/project-v3" + directory: "testdata/project-v4" schedule: interval: daily - - package-ecosystem: docker - directory: "testdata/project-v4" + commit-message: + prefix: ":seedling:" + + # Maintain dependencies for go in external plugin sample + - package-ecosystem: "gomod" + directory: "docs/book/src/simple-external-plugin-tutorial/testdata/sampleexternalplugin/v1" schedule: - interval: "weekly" + interval: "daily" + commit-message: + prefix: ":book:" + labels: + - "ok-to-test" diff --git a/.github/workflows/apidiff.yml b/.github/workflows/apidiff.yml index 691a138379b..0d4897bd75d 100644 --- a/.github/workflows/apidiff.yml +++ b/.github/workflows/apidiff.yml @@ -1,54 +1,30 @@ name: APIDiff -# Trigger the workflow on pull requests and direct pushes to any branch on: push: + paths-ignore: + - '**/*.md' pull_request: + paths-ignore: + - '**/*.md' jobs: - check_docs_only: - name: check_docs_only - runs-on: ubuntu-18.04 - outputs: - skip: ${{ steps.check_docs_only.outputs.skip }} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: check_docs_only - # Since PR's are squashed prior to merging to the branch checked out (default branch), - # HEAD^ will resolve to the previous point in history. - run: | - REF="HEAD^" - [[ -z "${{ github.base_ref }}" ]] || REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2) - echo "::set-output name=skip::$(test/check-docs-only.sh $REF)" - go-apidiff: name: Verify API differences runs-on: ubuntu-latest - needs: check_docs_only # Pull requests from different repository only trigger this checks - if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && needs.check_docs_only.outputs.skip != 'true' + if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) steps: - name: Clone the code - uses: actions/checkout@v3 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v6 with: - go-version: "1.19" + go-version-file: go.mod - name: Execute go-apidiff - uses: joelanford/go-apidiff@v0.4.0 + uses: joelanford/go-apidiff@v0.8.3 with: compare-imports: true print-compatible: true - - name: Report failure - uses: nashmaniac/create-issue-action@v1.1 - # Only report failures of pushes (PRs have are visible through the Checks section) to the default branch - if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/master' - with: - title: 🐛 go-apidiff failed for ${{ github.sha }} - token: ${{ secrets.GITHUB_TOKEN }} - labels: kind/bug - body: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..1a20167e1aa --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,54 @@ +name: "CodeQL Advanced" + +on: + # We are checking both `master` and `book-v4` branches: + # - `master` represents the latest development work. + # - `book-v4` is the latest stable release branch, which contains the latest published code, + # ensuring that any issues in production are identified and addressed promptly. + schedule: + - cron: '30 20 * * 1' # Runs every Monday at 8:30 PM + +jobs: + analyze: + name: Analyze Go + runs-on: ubuntu-latest + permissions: + security-events: write + packages: read + actions: read + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Build and install Kubebuilder CLI + run: make install + + # Preparing the project-v4 sample for CodeQL analysis: + # - `go mod tidy` ensures dependencies are fully resolved. + # - `make manifests` generates required manifests for a complete project structure. + # - `make build` builds the project code, ensuring all components are ready for CodeQL analysis. + - name: Build project-v4 sample project + run: | + cd testdata/project-v4 + go mod tidy + echo 'Running build commands for Go in project-v4' + make manifests + make build + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: go + build-mode: autobuild + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:go" diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000000..954f211c131 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,31 @@ +name: Coverage + +on: + push: + paths-ignore: ['**/*.md'] + pull_request: + paths-ignore: ['**/*.md'] + +jobs: + coverage: + runs-on: ubuntu-latest + if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Remove pre-installed kustomize + run: sudo rm -f /usr/local/bin/kustomize + + - name: Run tests with coverage + run: make test-coverage + + - name: Upload coverage to Coveralls + uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: coverage-all.out diff --git a/.github/workflows/cross-platform-tests.yml b/.github/workflows/cross-platform-tests.yml new file mode 100644 index 00000000000..80fc47d9055 --- /dev/null +++ b/.github/workflows/cross-platform-tests.yml @@ -0,0 +1,43 @@ +name: Cross-Platform Tests + +# Trigger the workflow on pull requests and direct pushes to any branch +on: + push: + paths-ignore: + - '**/*.md' + pull_request: + paths-ignore: + - '**/*.md' + +jobs: + test: + name: ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - ubuntu-latest + - macos-latest + # Pull requests from the same repository won't trigger this checks as they were already triggered by the push + if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) + steps: + - name: Clone the code + uses: actions/checkout@v5 + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + # This step is needed as the following one tries to remove + # kustomize for each test but has no permission to do so + - name: Remove pre-installed kustomize + run: sudo rm -f /usr/local/bin/kustomize + + - name: Unit Tests + run: make test-unit + + - name: Run Testdata + run: make test-testdata + + - name: Run Integration Tests + run: make test-integration + diff --git a/.github/workflows/external-plugin.yml b/.github/workflows/external-plugin.yml new file mode 100644 index 00000000000..cafd8c241b0 --- /dev/null +++ b/.github/workflows/external-plugin.yml @@ -0,0 +1,31 @@ +name: External Plugin + +on: + push: + paths: + - 'pkg/' + - 'docs/book/src/simple-external-plugin-tutorial/testdata/sampleexternalplugin' + - '.github/workflows/external-plugin.yml' + pull_request: + paths: + - 'pkg/' + - 'docs/book/src/simple-external-plugin-tutorial/testdata/sampleexternalplugin' + - '.github/workflows/external-plugin.yml' + +jobs: + external: + name: Verify external plugin + runs-on: ubuntu-latest + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Run tests + run: make test-external-plugin + diff --git a/.github/workflows/legacy-webhook-path.yml b/.github/workflows/legacy-webhook-path.yml new file mode 100644 index 00000000000..f0a1632aaf5 --- /dev/null +++ b/.github/workflows/legacy-webhook-path.yml @@ -0,0 +1,32 @@ +# This test ensure that the legacy webhook path +# still working. The option is deprecated +# and should be removed when we no longer need +# to support go/v4 plugin. +name: Legacy Webhook Path + +on: + push: + paths: + - 'testdata/**' + - '.github/workflows/legacy-webhook-path.yml' + pull_request: + paths: + - 'testdata/**' + - '.github/workflows/legacy-webhook-path.yml' + +jobs: + webhook-legacy-path: + name: Verify Legacy Webhook Path + runs-on: ubuntu-latest + # Pull requests from the same repository won't trigger this checks as they were already triggered by the push + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Clone the code + uses: actions/checkout@v5 + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + - name: Run make test-legacy + run: make test-legacy + diff --git a/.github/workflows/lint-sample.yml b/.github/workflows/lint-sample.yml new file mode 100644 index 00000000000..910e47ae211 --- /dev/null +++ b/.github/workflows/lint-sample.yml @@ -0,0 +1,51 @@ +name: Lint Samples + +on: + push: + paths: + - 'testdata/**' + - 'docs/book/src/**/testdata/**' + - '.github/workflows/lint-sample.yml' + pull_request: + paths: + - 'testdata/**' + - 'docs/book/src/**/testdata/**' + - '.github/workflows/lint-sample.yml' + +jobs: + lint-samples: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + folder: [ + "testdata/project-v4", + "testdata/project-v4-with-plugins", + "testdata/project-v4-multigroup", + "docs/book/src/cronjob-tutorial/testdata/project", + "docs/book/src/getting-started/testdata/project", + "docs/book/src/multiversion-tutorial/testdata/project" + ] + if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) + steps: + - name: Clone the code + uses: actions/checkout@v5 + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + - name: Prepare ${{ matrix.folder }} + working-directory: ${{ matrix.folder }} + run: go mod tidy + - name: Check linter configuration + working-directory: ${{ matrix.folder }} + run: make lint-config + - name: Run linter + uses: golangci/golangci-lint-action@v8 + with: + version: v2.5.0 + working-directory: ${{ matrix.folder }} + - name: Run linter via makefile target + working-directory: ${{ matrix.folder }} + run: make lint + diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index bd071310451..ea30b1729e2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,52 +1,43 @@ name: Lint -# Trigger the workflow on pull requests and direct pushes to any branch on: push: + paths-ignore: + - '**/*.md' pull_request: + paths-ignore: + - '**/*.md' jobs: - check_docs_only: - name: check_docs_only - runs-on: ubuntu-18.04 - outputs: - skip: ${{ steps.check_docs_only.outputs.skip }} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: check_docs_only - # Since PR's are squashed prior to merging to the branch checked out (default branch), - # HEAD^ will resolve to the previous point in history. - run: | - REF="HEAD^" - [[ -z "${{ github.base_ref }}" ]] || REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2) - echo "::set-output name=skip::$(test/check-docs-only.sh $REF)" - lint: name: golangci-lint runs-on: ubuntu-latest - needs: check_docs_only # Pull requests from the same repository won't trigger this checks as they were already triggered by the push - if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) && needs.check_docs_only.outputs.skip != 'true' + if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) steps: + - name: Clone the code + uses: actions/checkout@v5 - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v6 with: - go-version: 1.19 - - name: Clone the code - uses: actions/checkout@v3 + go-version-file: go.mod + - name: Check linter configuration + run: make lint-config - name: Run linter - uses: golangci/golangci-lint-action@v3 - with: - version: v1.49 # Always uses the latest patch version. - only-new-issues: true # Show only new issues if it's a pull request - - name: Report failure - uses: nashmaniac/create-issue-action@v1.1 - # Only report failures of pushes (PRs have are visible through the Checks section) to the default branch - if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/master' + uses: golangci/golangci-lint-action@v8 with: - title: 🐛 Lint failed for ${{ github.sha }} - token: ${{ secrets.GITHUB_TOKEN }} - labels: kind/bug - body: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + version: v2.5.0 + + yamllint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: Run yamllint make target + run: make yamllint + + license: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: Run license check + run: make test-license diff --git a/.github/workflows/release-version-ci.yml b/.github/workflows/release-version-ci.yml new file mode 100644 index 00000000000..4838d0e9243 --- /dev/null +++ b/.github/workflows/release-version-ci.yml @@ -0,0 +1,61 @@ +name: Test GoReleaser and CLI Version + +on: + push: + paths: + - 'pkg/**' + - 'cmd/**' + - 'build/.goreleaser.yml' + - '.github/workflows/release-version-ci.yml' + pull_request: + paths: + - 'pkg/**' + - 'cmd/**' + - 'build/.goreleaser.yml' + - '.github/workflows/release-version-ci.yml' + +jobs: + go-releaser-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Clean dist directory + run: rm -rf dist || true + + - name: Create temporary git tag + run: | + git tag v4.5.3-rc.1 + + - name: Install Syft to generate SBOMs + run: | + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b $HOME/bin + echo "$HOME/bin" >> $GITHUB_PATH + + - name: Run GoReleaser in mock mode using tag + uses: goreleaser/goreleaser-action@v6 + with: + version: v2.7.0 + args: release --skip=publish --clean -f ./build/.goreleaser.yml + + - name: Init project using built kubebuilder binary and check cliVersion + run: | + mkdir test-operator && cd test-operator + go mod init test-operator + chmod +x ../dist/kubebuilder_linux_$(go env GOARCH)_v1/kubebuilder + ../dist/kubebuilder_linux_$(go env GOARCH)_v1/kubebuilder init --domain example.com + + echo "PROJECT file content:" + cat PROJECT + + echo "Verifying cliVersion value..." + grep '^cliVersion: 4.5.3-rc.1$' PROJECT diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6651f6225b1..9012009c117 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,29 +4,39 @@ on: tags: - '*' +permissions: + contents: write + jobs: goreleaser: runs-on: ubuntu-latest + steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Fetch all tags run: git fetch --force --tags - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v6 with: - go-version: '~1.19' + go-version-file: go.mod + - name: Clean dist directory + run: rm -rf dist || true + - name: Install Syft to generate SBOMs + run: | + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b $HOME/bin + echo "$HOME/bin" >> $GITHUB_PATH - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v3 + uses: goreleaser/goreleaser-action@v6 with: - version: v1.11.2 - args: release -f ./build/.goreleaser.yml --rm-dist + version: v2.7.0 + args: release -f ./build/.goreleaser.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload assets - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v5 with: name: kubebuilder path: dist/* diff --git a/.github/workflows/spaces.yml b/.github/workflows/spaces.yml new file mode 100644 index 00000000000..88d57762567 --- /dev/null +++ b/.github/workflows/spaces.yml @@ -0,0 +1,21 @@ +name: Trailing + +on: + push: + paths: + - '**/*.md' + pull_request: + paths: + - '**/*.md' + +jobs: + lint: + name: "Check Trailing" + runs-on: ubuntu-latest + # Pull requests from the same repository won't trigger this checks as they were already triggered by the push + if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) + steps: + - name: Clone the code + uses: actions/checkout@v5 + - name: Run check + run: make test-spaces diff --git a/.github/workflows/test-alpha-generate.yml b/.github/workflows/test-alpha-generate.yml new file mode 100644 index 00000000000..03ea301ae2b --- /dev/null +++ b/.github/workflows/test-alpha-generate.yml @@ -0,0 +1,53 @@ +name: Test Alpha Generate + +on: + push: + paths: + - 'pkg/cli/alpha/**' + - '.github/workflows/test-alpha-generate.yml' + pull_request: + paths: + - 'pkg/cli/alpha/**' + - '.github/workflows/test-alpha-generate.yml' + +jobs: + unsupported: + runs-on: ubuntu-latest + strategy: + fail-fast: true + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Install dependencies and generate binary + run: make install + + - name: Navigate to testdata/project-v4 + run: cd testdata/project-v4 + + - name: Update PROJECT file + run: | + sed -i 's#go.kubebuilder.io/v4#go.kubebuilder.io/v3#g' testdata/project-v4/PROJECT + + # Validate if help output is working and workaround to + # update the PROJECT file in memory to allow upgrade + # no longer supported layouts did not break the command options + - name: Validate help output for alpha generate + run: | + if kubebuilder alpha generate --help | grep -q "kubebuilder alpha generate \[flags\]"; then + echo "Help output validated" + else + echo "Help output missing or invalid" + exit 1 + fi + + - name: Run kubebuilder alpha generate + run: | + cd testdata/project-v4 && kubebuilder alpha generate + diff --git a/.github/workflows/test-book.yml b/.github/workflows/test-book.yml new file mode 100644 index 00000000000..98155248896 --- /dev/null +++ b/.github/workflows/test-book.yml @@ -0,0 +1,56 @@ +name: E2E Book Samples + +on: + push: + paths: + - 'docs/book/src/getting-started/testdata/project/**' + - 'docs/book/src/cronjob-tutorial/testdata/project/**' + - 'docs/book/src/multiversion-tutorial/testdata/project/**' + - '.github/workflows/test-e2e-book.yml' + pull_request: + paths: + - 'docs/book/src/getting-started/testdata/project/**' + - 'docs/book/src/cronjob-tutorial/testdata/project/**' + - 'docs/book/src/multiversion-tutorial/testdata/project/**' + - '.github/workflows/test-e2e-book.yml' + +jobs: + e2e: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + folder: [ + "docs/book/src/getting-started/testdata/project", + "docs/book/src/cronjob-tutorial/testdata/project", + "docs/book/src/multiversion-tutorial/testdata/project" + ] + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Install the latest version of kind + run: | + curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-$(go env GOARCH) + chmod +x ./kind + sudo mv ./kind /usr/local/bin/kind + + - name: Verify kind installation + run: kind version + + - name: Create kind cluster + run: kind create cluster + + - name: Running make test for ${{ matrix.folder }} + working-directory: ${{ matrix.folder }} + run: make test + + - name: Running make test-e2e for ${{ matrix.folder }} + working-directory: ${{ matrix.folder }} + run: make test-e2e diff --git a/.github/workflows/test-devcontainer.yml b/.github/workflows/test-devcontainer.yml new file mode 100644 index 00000000000..e8323ce6d5f --- /dev/null +++ b/.github/workflows/test-devcontainer.yml @@ -0,0 +1,46 @@ +name: Test DevContainer Image + +on: + push: + - 'testdata/**' + - '.github/workflows/test-devcontainer.yml' + pull_request: + paths: + - 'testdata/**' + - '.github/workflows/test-devcontainer.yml' + +jobs: + test-devcontainer: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Setup NodeJS 20.x + uses: actions/setup-node@v6 + with: + node-version: "20.x" + + - name: Setup Devcontainer CLI + run: | + npm install -g @devcontainers/cli + + - name: Build and Validate DevContainer + run: | + cd testdata/project-v4 + + OUTPUT=$(devcontainer up --workspace-folder=./) + STATUS=$(echo "$OUTPUT" | jq -r '.outcome') + + if [[ "$STATUS" == "success" ]]; then + echo "Devcontainer setup was successful." + exit 0 + else + echo "Devcontainer setup failed." + exit 1 + fi diff --git a/.github/workflows/test-e2e-samples.yml b/.github/workflows/test-e2e-samples.yml new file mode 100644 index 00000000000..974cdc49602 --- /dev/null +++ b/.github/workflows/test-e2e-samples.yml @@ -0,0 +1,163 @@ +name: E2E Testdata Sample + +on: + push: + paths: + - 'testdata/**' + - '.github/workflows/test-e2e-samples.yml' + pull_request: + paths: + - 'testdata/**' + - '.github/workflows/test-e2e-samples.yml' + +jobs: + e2e-tests-project-v4: + runs-on: ubuntu-latest + strategy: + fail-fast: true + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Install the latest version of kind + run: | + curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-$(go env GOARCH) + chmod +x ./kind + sudo mv ./kind /usr/local/bin/kind + + - name: Verify kind installation + run: kind version + + - name: Create kind cluster + run: kind create cluster + + - name: Prepare project-v4 + run: | + # Enable [METRICS-WITH-CERTS] by uncommenting the lines in kustomization.yaml + KUSTOMIZATION_FILE_PATH="testdata/project-v4/config/default/kustomization.yaml" + sed -i '47,49s/^#//' $KUSTOMIZATION_FILE_PATH + cd testdata/project-v4/ + go mod tidy + + - name: Testing make test-e2e for project-v4 + working-directory: testdata/project-v4/ + run: | + make test-e2e + + e2e-tests-project-v4-with-plugins: + runs-on: ubuntu-latest + strategy: + fail-fast: true + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Install the latest version of kind + run: | + curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-$(go env GOARCH) + chmod +x ./kind + sudo mv ./kind /usr/local/bin/kind + + - name: Verify kind installation + run: kind version + + - name: Create kind cluster + run: kind create cluster + + - name: Prepare project-v4-with-plugins + run: | + cd testdata/project-v4-with-plugins/ + go mod tidy + + - name: Testing make test-e2e for project-v4-with-plugins + working-directory: testdata/project-v4-with-plugins/ + run: | + make test-e2e + + e2e-tests-project-v4-multigroup: + runs-on: ubuntu-latest + strategy: + fail-fast: true + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Install the latest version of kind + run: | + curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-$(go env GOARCH) + chmod +x ./kind + sudo mv ./kind /usr/local/bin/kind + + - name: Verify kind installation + run: kind version + + - name: Create kind cluster + run: kind create cluster + + - name: Prepare project-v4-multigroup + run: | + cd testdata/project-v4-multigroup + go mod tidy + + - name: Testing make test-e2e for project-v4-multigroup + working-directory: testdata/project-v4-multigroup/ + run: | + make test-e2e + + # Test to validate e2e integration when no APIs are scaffolded + e2e-test-basic-project: + runs-on: ubuntu-latest + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Install the latest version of kind + run: | + curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-$(go env GOARCH) + chmod +x ./kind + sudo mv ./kind /usr/local/bin/kind + + - name: Verify kind installation + run: kind version + + - name: Create kind cluster + run: kind create cluster + + - name: Build kubebuilder CLI from this repo + run: make install + + - name: Scaffold empty go/v4 project + run: | + mkdir -p /tmp/basic-project-v4 + cd /tmp/basic-project-v4 + kubebuilder init --plugins go/v4 --domain example.com --repo example.com/empty-operator + go mod tidy + make + + - name: Run make test-e2e on empty project + working-directory: /tmp/basic-project-v4 + run: make test-e2e diff --git a/.github/workflows/test-helm-book.yml b/.github/workflows/test-helm-book.yml new file mode 100644 index 00000000000..b84aa506312 --- /dev/null +++ b/.github/workflows/test-helm-book.yml @@ -0,0 +1,101 @@ +name: Helm Docs Tutorials + +on: + push: + paths: + - "docs/book/src/cronjob-tutorial/testdata/project/**" + - "docs/book/src/getting-started/testdata/project/**" + - "docs/book/src/multiversion-tutorial/testdata/project/**" + - ".github/workflows/test-helm-book.yml" + pull_request: + paths: + - "docs/book/src/cronjob-tutorial/testdata/project/** " + - "docs/book/src/getting-started/testdata/project/**" + - "docs/book/src/multiversion-tutorial/testdata/project/**" + - ".github/workflows/test-helm-book.yml" + +jobs: + helm-test: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + folder: [ + "docs/book/src/getting-started/testdata/project", + "docs/book/src/cronjob-tutorial/testdata/project", + "docs/book/src/multiversion-tutorial/testdata/project" + ] + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Set project name + id: project + run: echo "name=$(basename ${{ matrix.folder }})" >> $GITHUB_OUTPUT + + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Install the latest version of kind + run: | + curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-$(go env GOARCH) + chmod +x ./kind + sudo mv ./kind /usr/local/bin/kind + + - name: Verify kind installation + run: kind version + + - name: Create kind cluster + run: kind create cluster + + - name: Prepare project + run: | + cd ${{ matrix.folder }} + go mod tidy + make docker-build IMG=${{ steps.project.outputs.name}}:v0.1.0 + kind load docker-image ${{ steps.project.outputs.name}}:v0.1.0 + + - name: Install Helm + run: | + curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + + - name: Verify Helm installation + run: helm version + + - name: Lint Helm chart + run: | + helm lint ${{ matrix.folder }}/dist/chart + + - name: Install Prometheus Operator CRDs + run: | + helm repo add prometheus-community https://prometheus-community.github.io/helm-charts + helm repo update + helm install prometheus-crds prometheus-community/prometheus-operator-crds + + - name: Install cert-manager via Helm + run: | + helm repo add jetstack https://charts.jetstack.io + helm repo update + helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true + + - name: Wait for cert-manager to be ready + run: | + kubectl wait --namespace cert-manager --for=condition=available --timeout=300s deployment/cert-manager + kubectl wait --namespace cert-manager --for=condition=available --timeout=300s deployment/cert-manager-cainjector + kubectl wait --namespace cert-manager --for=condition=available --timeout=300s deployment/cert-manager-webhook + + - name: Render Helm chart + run: | + helm template ${{ matrix.folder }}/dist/chart --namespace=${{ steps.project.outputs.name }}-system + + - name: Install Helm chart + run: | + helm install my-release ${{ matrix.folder }}/dist/chart --create-namespace --namespace ${{ steps.project.outputs.name}}-system + + - name: Check Helm release status + run: | + helm status my-release --namespace ${{ steps.project.outputs.name}}-system + diff --git a/.github/workflows/test-helm-samples.yml b/.github/workflows/test-helm-samples.yml new file mode 100644 index 00000000000..b4c32874acd --- /dev/null +++ b/.github/workflows/test-helm-samples.yml @@ -0,0 +1,189 @@ +name: Helm Testdata Sample + +on: + push: + paths: + - "testdata/project-v4-with-plugins/**" + - ".github/workflows/test-helm-samples.yml" + pull_request: + paths: + - "testdata/project-v4-with-plugins/**" + - ".github/workflows/test-helm-samples.yml" + +jobs: + helm-test-project-v4-with-plugins: + runs-on: ubuntu-latest + strategy: + fail-fast: true + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Enable Prometheus in kustomize (testdata sample) + run: | + sed -i 's/^#- \.\.\/prometheus/- ..\/prometheus/' testdata/project-v4-with-plugins/config/default/kustomization.yaml + + - name: Build kubebuilder CLI + run: make build + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Prepare project-v4-with-plugins + run: | + cd testdata/project-v4-with-plugins/ + go mod tidy + make all + + - name: Rebuild installer and regenerate Helm chart (v2-alpha) + working-directory: testdata/project-v4-with-plugins + run: | + make build-installer + ../../bin/kubebuilder edit --plugins=helm/v2-alpha --force + + - name: Install the latest version of kind + run: | + curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-$(go env GOARCH) + chmod +x ./kind + sudo mv ./kind /usr/local/bin/kind + + - name: Verify kind installation + run: kind version + + - name: Create kind cluster + run: kind create cluster + + - name: Install Helm + run: | + curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + + - name: Verify Helm installation + run: helm version + + - name: Lint Helm chart for project-v4-with-plugins + run: | + helm lint testdata/project-v4-with-plugins/dist/chart + + - name: Build project-v4-with-plugins + run: | + cd testdata/project-v4-with-plugins/ + go mod tidy + make docker-build IMG=project-v4-with-plugins:v0.1.0 + kind load docker-image project-v4-with-plugins:v0.1.0 + + - name: Install Prometheus Operator CRDs + run: | + helm repo add prometheus-community https://prometheus-community.github.io/helm-charts + helm repo update + helm install prometheus-crds prometheus-community/prometheus-operator-crds + + - name: Install cert-manager via Helm (wait for readiness) + run: | + helm repo add jetstack https://charts.jetstack.io + helm repo update + helm install cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --create-namespace \ + --set crds.enabled=true \ + --wait \ + --timeout 300s + + - name: Render Helm chart for project-v4-with-plugins + run: | + helm template testdata/project-v4-with-plugins/dist/chart --namespace=project-v4-with-plugins-system + + - name: Install Helm chart for project-v4-with-plugins + run: | + helm install my-release \ + testdata/project-v4-with-plugins/dist/chart \ + --namespace project-v4-with-plugins-system \ + --create-namespace \ + --set prometheus.enable=true + + - name: Check Helm release status + run: | + helm status my-release --namespace project-v4-with-plugins-system + + - name: Delete kind cluster + if: always() + run: | + kind delete cluster || true + + # Test scenario: + # - scaffold project without creating webhooks, + # - deploy helm chart without installing cert manager; + # - check that deployment has been deployed; + # + # Command to use to scaffold project without creating webhooks and so no need to install cert manager: + # - kubebuilder init + # - kubebuilder create api --group example.com --version v1 --kind App --controller=true --resource=true + # - kubebuilder edit --plugins=helm.kubebuilder.io/v2-alpha + test-helm-no-webhooks: + runs-on: ubuntu-latest + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Install the latest version of kind + run: | + curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-$(go env GOARCH) + chmod +x ./kind + sudo mv ./kind /usr/local/bin/kind + + - name: Create kind cluster + run: kind create cluster + + - name: Install Helm + run: | + curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + + - name: Install kubebuilder binary + run: make install + + - name: Create test directory + run: mkdir -p test-helm-no-webhooks + + - name: Scaffold project with kubebuilder commands + working-directory: test-helm-no-webhooks + run: | + go mod init test-helm-no-webhooks + kubebuilder init + kubebuilder create api --group example.com --version v1 --kind App --controller=true --resource=true + kubebuilder edit --plugins=helm.kubebuilder.io/v1-alpha + + - name: Build and load Docker image + working-directory: test-helm-no-webhooks + run: | + make docker-build IMG=test-helm-no-webhooks:v0.1.0 + kind load docker-image test-helm-no-webhooks:v0.1.0 + + - name: Lint Helm chart + working-directory: test-helm-no-webhooks + run: helm lint ./dist/chart + + - name: Deploy Helm chart without cert-manager + working-directory: test-helm-no-webhooks + run: | + helm install my-release \ + ./dist/chart \ + --create-namespace \ + --namespace test-helm-no-webhooks-system + + - name: Verify deployment is working + working-directory: test-helm-no-webhooks + run: | + helm status my-release --namespace test-helm-no-webhooks-system + + - name: Delete kind cluster + if: always() + run: | + kind delete cluster || true diff --git a/.github/workflows/testdata.yml b/.github/workflows/testdata.yml index 827554deeed..08cd12bf8af 100644 --- a/.github/workflows/testdata.yml +++ b/.github/workflows/testdata.yml @@ -1,6 +1,5 @@ name: Testdata verification -# Trigger the workflow on pull requests and direct pushes to any branch on: push: pull_request: @@ -14,23 +13,16 @@ jobs: if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository steps: - name: Clone the code - uses: actions/checkout@v3 + uses: actions/checkout@v5 - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v6 with: - go-version: '1.19' + go-version-file: go.mod - name: Remove pre-installed kustomize # This step is needed as the following one tries to remove # kustomize for each test but has no permission to do so run: sudo rm -f /usr/local/bin/kustomize - name: Verify testdata directory run: make check-testdata - - name: Report failure - uses: nashmaniac/create-issue-action@v1.1 - # Only report failures of pushes (PRs have are visible through the Checks section) to the default branch - if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/master' - with: - title: 🐛 Testadata verification failed for ${{ github.sha }} - token: ${{ secrets.GITHUB_TOKEN }} - labels: kind/bug - body: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + - name: Verify docs update + run: make check-docs diff --git a/.github/workflows/unit-tests-legacy.yml b/.github/workflows/unit-tests-legacy.yml deleted file mode 100644 index 5feb81dc5fb..00000000000 --- a/.github/workflows/unit-tests-legacy.yml +++ /dev/null @@ -1,50 +0,0 @@ -# todo: remove this file when go/v2 be removed -name: Unit tests Legacy (go/v2) - -# Trigger the workflow on pull requests and direct pushes to any branch -on: - push: - pull_request: - -jobs: - test: - name: ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: - - ubuntu-latest - - macos-latest - # Pull requests from the same repository won't trigger this checks as they were already triggered by the push - if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) - steps: - - name: Clone the code - uses: actions/checkout@v3 - - name: Setup Go - uses: actions/setup-go@v3 - with: - # the go/v2 cannot be updated and is scaffold with golang 1.13 - # (version used by its dep version of the controller-runtime) - # however, we are unable to downgrade the version here - # because we will face errors - # So we are keeping the latest version where it works - # and highlighting that must be fixed - # Therefore, we probably will deprecate go/v2 soon since we cannot upgrade it - # to use the versions of controller-runtime > v0.9 - # and controller-tools > v0.6 as k8s > 1.21 then it might not be valid we spend effort on this fix - go-version: "1.19" - # This step is needed as the following one tries to remove - # kustomize for each test but has no permission to do so - - name: Remove pre-installed kustomize - run: sudo rm -f /usr/local/bin/kustomize - - name: Perform the test - run: make test-legacy - - name: Report failure - uses: nashmaniac/create-issue-action@v1.1 - # Only report failures of pushes (PRs have are visible through the Checks section) to the default branch - if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/master' - with: - title: 🐛 Unit tests failed on ${{ matrix.os }} for ${{ github.sha }} - token: ${{ secrets.GITHUB_TOKEN }} - labels: kind/bug - body: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml deleted file mode 100644 index d1f4edc3917..00000000000 --- a/.github/workflows/unit-tests.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: Unit tests - -# Trigger the workflow on pull requests and direct pushes to any branch -on: - push: - pull_request: - -jobs: - check_docs_only: - name: check_docs_only - runs-on: ubuntu-18.04 - outputs: - skip: ${{ steps.check_docs_only.outputs.skip }} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - id: check_docs_only - # Since PR's are squashed prior to merging to the branch checked out (default branch), - # HEAD^ will resolve to the previous point in history. - run: | - REF="HEAD^" - [[ -z "${{ github.base_ref }}" ]] || REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2) - echo "::set-output name=skip::$(test/check-docs-only.sh $REF)" - - test: - name: ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: - - ubuntu-latest - - macos-latest - needs: check_docs_only - # Pull requests from the same repository won't trigger this checks as they were already triggered by the push - if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) && needs.check_docs_only.outputs.skip != 'true' - steps: - - name: Clone the code - uses: actions/checkout@v3 - - name: Setup Go - uses: actions/setup-go@v3 - with: - go-version: "1.19" - # This step is needed as the following one tries to remove - # kustomize for each test but has no permission to do so - - name: Remove pre-installed kustomize - run: sudo rm -f /usr/local/bin/kustomize - - name: Perform the test - run: make test - - name: Report failure - uses: nashmaniac/create-issue-action@v1.1 - # Only report failures of pushes (PRs have are visible through the Checks section) to the default branch - if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/master' - with: - title: 🐛 Unit tests failed on ${{ matrix.os }} for ${{ github.sha }} - token: ${{ secrets.GITHUB_TOKEN }} - labels: kind/bug - body: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - - coverage: - name: Code coverage - needs: - - test - - check_docs_only - runs-on: ubuntu-latest - # Pull requests from the same repository won't trigger this checks as they were already triggered by the push - if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) && needs.check_docs_only.outputs.skip != 'true' - steps: - - name: Clone the code - uses: actions/checkout@v3 - - name: Setup Go - uses: actions/setup-go@v3 - with: - go-version: "1.19" - - name: Generate the coverage output - run: make test-coverage - - name: Send the coverage output - uses: shogo82148/actions-goveralls@v1 - with: - path-to-profile: coverage-all.out - - name: Report failure - uses: nashmaniac/create-issue-action@v1.1 - # Only report failures of pushes (PRs have are visible through the Checks section) to the default branch - if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/master' - with: - title: 🐛 Coverage report failed for ${{ github.sha }} - token: ${{ secrets.GITHUB_TOKEN }} - labels: kind/bug - body: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 0cb5bf54830..359e086e8f8 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -1,18 +1,36 @@ -name: PR Verifier +name: "PR Title Verifier" on: - pull_request_target: - types: [opened, edited, reopened] - + pull_request: + types: [opened, edited, synchronize, reopened] jobs: - verify: - name: Verify PR contents runs-on: ubuntu-latest + steps: - - name: Verifier action - id: verifier - uses: kubernetes-sigs/kubebuilder-release-tools@v0.2.0 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} + - name: Checkout code + uses: actions/checkout@v5 + + - name: Validate PR Title Format + env: + TITLE: ${{ github.event.pull_request.title }} + run: | + if [[ -z "$TITLE" ]]; then + echo "Error: PR title cannot be empty." + exit 1 + fi + + if ! [[ "$TITLE" =~ ^($'\u26A0'|$'\u2728'|$'\U0001F41B'|$'\U0001F4D6'|$'\U0001F680'|$'\U0001F331') ]]; then + echo "Error: Invalid PR title format." + echo "Your PR title must start with one of the following indicators:" + echo "- Breaking change: ⚠ (U+26A0)" + echo "- Non-breaking feature: ✨ (U+2728)" + echo "- Patch fix: 🐛 (U+1F41B)" + echo "- Docs: 📖 (U+1F4D6)" + echo "- Release: 🚀 (U+1F680)" + echo "- Infra/Tests/Other: 🌱 (U+1F331)" + exit 1 + fi + + echo "PR title is valid: '$TITLE'" diff --git a/.gitignore b/.gitignore index 6c268d876bb..44d8a0a31ca 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ .idea/ .vscode/ WORKSPACE +.DS_Store # don't check in the build output of the book docs/book/book/ +# ignore auto-generated dir by `mdbook serve` +docs/book/src/docs + # Editor temp files *~ \#*# @@ -22,4 +26,8 @@ docs/book/book/ # skip testdata go.sum, since it may have # different result depending on go version /testdata/**/go.sum -/docs/book/src/simple-external-plugin-tutorial/testdata/sampleexternalplugin/v1/bin \ No newline at end of file +/docs/book/src/simple-external-plugin-tutorial/testdata/sampleexternalplugin/v1/bin +/testdata/**legacy** + +## Skip testdata files that generate by tests using TestContext +**/e2e-*/** diff --git a/.golangci.yml b/.golangci.yml index 88e1f7b5285..b42f5b24b45 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,45 +1,137 @@ -issues: - # don't skip warning about doc comments - # don't exclude the default set of lint - exclude-use-default: false - # restore some of the defaults - # (fill in the rest as needed) - exclude-rules: - - linters: [gosec] - path: "test/e2e/*" - -linters-settings: - govet: - enable=fieldalignment: true - revive: - rules: - - name: if-return - disabled: true - +version: "2" +run: + allow-parallel-runners: true linters: - disable-all: true + default: none enable: + - asciicheck + - bidichk + - copyloopvar - dupl - errcheck - - exportloopref + - ginkgolinter - goconst - gocyclo - - gofmt - - goimports - - gosec - - gosimple - govet + - importas - ineffassign - lll - misspell - nakedret + - nolintlint - prealloc - revive - staticcheck - - typecheck - unconvert - unparam - unused - -run: - deadline: 5m + - wrapcheck + - whitespace + settings: + ginkgolinter: + forbid-focus-container: true + forbid-spec-pollution: true + govet: + disable: + - fieldalignment + enable-all: true + importas: + no-unaliased: true + alias: + - pkg: sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha + alias: helmv1alpha + - pkg: sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v2alpha + alias: helmv2alpha + - pkg: sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha + alias: grafanav1alpha + - pkg: "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/autoupdate/v1alpha" + alias: autoupdatev1alpha + - pkg: sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/deploy-image/v1alpha1 + alias: deployimagev1alpha1 + - pkg: sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/v4 + alias: golangv4 + - pkg: sigs.k8s.io/kubebuilder/v4/pkg/plugins/common/kustomize/v2 + alias: kustomizecommonv2 + nolintlint: + allow-unused: false + revive: + rules: + - name: blank-imports + - name: context-as-argument + - name: context-keys-type + - name: dot-imports + arguments: + - allowedPackages: + - github.com/onsi/ginkgo/v2 + - github.com/onsi/gomega + - name: error-return + - name: error-strings + - name: error-naming + - name: exported + disabled: true + - name: if-return + - name: import-shadowing + - name: increment-decrement + - name: var-naming + severity: warning + arguments: + - ["ID"] # allowed initialisms + - ["VM"] # disallowed initialisms + - [ + # <-- this is a list containing one map + { + skip-initialism-name-checks: true, + upper-case-const: true, + skip-package-name-checks: true, + extra-bad-package-names: ["helpers", "models"], + }, + ] + - name: var-declaration + - name: package-comments + disabled: true + - name: range + - name: receiver-naming + - name: time-naming + - name: unexported-return + - name: indent-error-flow + - name: errorf + - name: empty-block + - name: superfluous-else + - name: unused-parameter + - name: unreachable-code + - name: redefines-builtin-id + - name: bool-literal-in-expr + - name: constant-logical-expr + - name: comment-spacings + exclusions: + generated: lax + rules: + - linters: + - gosec + path: test/e2e/* + - linters: + - gosec + - lll + path: hack/docs/* + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gci + - gofmt + - gofumpt + - goimports + settings: + gci: + sections: + - standard + - default + - prefix(sigs.k8s.io/kubebuilder) + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..7ebd2ce878e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,224 @@ +# Kubebuilder AI Agent Guide + +**Kubebuilder** is a **framework** and **command-line interface (CLI)** for building **Kubernetes APIs** using **Custom Resource Definitions (CRDs)**. +It provides scaffolding and abstractions that accelerate the development of **controllers**, **webhooks**, and **APIs** written in **Go**. + +## Quick Reference + +| Item | Value | +|------|-------| +| Language | Go >= 1.25 | +| Module | `sigs.k8s.io/kubebuilder/v4` | +| Binary | `./bin/kubebuilder` | +| Core deps | `controller-runtime`, `controller-tools`, Helm, Kustomize | +| Docs | https://book.kubebuilder.io | + +## Directory Map + +``` +pkg/ + cli/ CLI commands (init, create api, create webhook, edit, alpha) + machinery/ Scaffolding engine (templates, markers, injectors, filesystem) + model/ Resource and stage models + plugin/ Plugin interfaces and utilities + plugins/ Plugin implementations + golang/v4/ Main Go operator scaffolding (used by default combined with kustomize/v2; see PluginBundle in cli/init.go) + golang/deployimage/ Implements create api interface to generate code to deploy and manage container images with controller + common/kustomize/v2/ Kustomize manifests (used by default combined with go/v4; see PluginBundle in cli/init.go) + optional/helm/ Helm chart generation to distribute the projects (v1alpha; deprecated, v2alpha) + optional/grafana/ Grafana dashboards + optional/autoupdate/ Auto-update workflow + external/ External plugin support +docs/book/ mdBook sources + tutorial samples +test/ + e2e/ End-to-end tests (v4, helm, grafana, deployimage, alpha*) + testdata/ Testdata generation scripts +testdata/ Generated sample projects (DO NOT EDIT) +hack/docs/ Documentation generation scripts +``` + +## Critical Rules + +### NEVER Manually Edit +- `testdata/` - regenerated via `make generate-testdata` +- `docs/book/**/testdata/` - regenerated via `make generate-docs` +- `*/dist/chart/` - regenerated via `make generate-charts` + +### Always Run Before PR +```bash +make generate # Regenerate all (testdata + docs + k8s version + tidy) +make lint-fix # Auto-fix Go code style +make test-unit # Verify unit tests pass +``` + +### File-Specific Requirements +- After editing `*.go` → `make lint-fix` +- After editing `*.md` → `make remove-spaces` +- After modifying scaffolding/templates → `make generate` + +## Development Workflow + +### Build & Install +```bash +make build # Build to ./bin/kubebuilder +make install # Copy to $(go env GOBIN) +``` + +### Generate Everything +```bash +make generate # Master command (runs all below + tidy + remove-spaces) +make generate-testdata # Recreate testdata/project-* +make generate-docs # Regenerate docs samples & marker docs +make generate-charts # Rebuild Helm charts +``` + +### Lint & Format +```bash +make lint # Check only (golangci-lint + yamllint) +make lint-fix # Auto-fix Go code +``` + +### Testing +```bash +make test-unit # Fast unit tests (./pkg/..., ./test/e2e/utils/...) +make test-integration # Integration tests +make test-features # Feature tests +make test-testdata # Test all testdata projects +make test-e2e-local # Full e2e (creates kind cluster) +make test # CI aggregate (all of above + license) +``` + +## PR Submission + +### Title Format (MANDATORY) +``` +:emoji: (optional/scope): User-facing description +``` + +**Emojis:** +- ⚠️ - Breaking change +- ✨ - New feature +- 🐛 - Bug fix +- 📖 - Documentation +- 🌱 - Infrastructure/tests/non-user-facing/refactor + +**Examples:** +``` +✨ (helm/v2-alpha): Add chart generation for cluster-scoped resources +🐛: Fix project creation failure when GOBIN is unset +📖: Update migration guide for Go 1.25 compatibility +``` + +### Pre-PR Checklist +- [ ] One commit per PR (squash all) +- [ ] Add/update tests for new behavior +- [ ] Add/update docs for new behavior +- [ ] Run `make generate` +- [ ] Run `make lint-fix` +- [ ] Run `make test-unit` +- [ ] Update docs if adding features: + - `docs/book/src/reference/reference.md` for features + - `docs/book/src/plugins/plugins.md` for plugins + - `docs/book/src/reference/cli.md` for CLI changes + +## Core Concepts + +### Plugin Architecture +Plugins implement interfaces from `pkg/plugin/`: +- `Plugin` - base interface (Name, Version, SupportedProjectVersions) +- `Init` - provides `init` subcommand +- `CreateAPI` - provides `create api` subcommand +- `CreateWebhook` - provides `create webhook` subcommand +- `Edit` - provides `edit` subcommand +- `Bundle` - groups multiple plugins + +### Scaffolding Machinery +From `pkg/machinery/`: +- `Template` - file generation via Go templates +- `Inserter` - code injection at markers +- `Marker` - special comments (e.g., `// +kubebuilder:scaffold:imports`) +- `Filesystem` - abstraction over afero for testability + +### Scaffolded Project Structure +`kubebuilder init` creates: +- `cmd/main.go` - Entry point (manager setup) +- `api/v1/*_types.go` - API definitions with `+kubebuilder` markers +- `internal/controller/*_controller.go` - Reconcile logic +- `config/` - Kustomize manifests (CRDs, RBAC, manager, webhooks) +- `Dockerfile`, `Makefile` - Build and deployment automation + +### Reconciliation Pattern +Controllers implement `Reconcile(ctx, req) (ctrl.Result, error)`: +- **Idempotent** - Safe to run multiple times +- **Level-triggered** - React to current state, not events +- **Requeue on pending work** - Return `ctrl.Result{Requeue: true}` + +### Testing Pattern +E2E tests use `test/e2e/utils/test_context.go`: +```go +ctx := utils.NewTestContext("kubebuilder", "GO111MODULE=on") +ctx.Init() // Run kubebuilder init +ctx.CreateAPI(...) // Run create api +ctx.Make("build") // Run make targets +ctx.LoadImageToKindCluster() // Load image to kind +``` + +## Tool Commands + +### CLI Commands +```bash +kubebuilder init --domain example.com --repo github.com/example/myproject +kubebuilder create api --group batch --version v1 --kind CronJob +kubebuilder create webhook --group batch --version v1 --kind CronJob +kubebuilder edit --plugins=helm/v2-alpha +``` + +### Alpha Commands (Experimental) +```bash +kubebuilder alpha generate # Generate from existing PROJECT file +kubebuilder alpha update # Update to latest plugin versions +``` + +## Common Patterns + +### Code Style +- Avoid abbreviations: `context` not `ctx` (except receivers) +- Descriptive names: `projectConfig` not `pc` +- Single/double-letter receivers OK: `(c CLI)` or `(p Plugin)` + +### Testing Philosophy +- Test behaviors, not implementations +- Use real components over mocks +- Test cases as specifications (Ginkgo: `Describe`, `It`, `Context`, `By`) +- Use **Ginkgo v2** + **Gomega** for BDD-style tests. +- Tests depending on the Kubebuilder binary should use: `utils.NewTestContext(util.KubebuilderBinName, "GO111MODULE=on")` + +### Scaffolding +- Use library helpers from `pkg/plugin/util/` +- Use markers for extensibility +- Follow existing template patterns in `pkg/machinery` + +## Search Tips + +```bash +# Use rg (ripgrep) for searching +rg "pattern" --type go +rg "\\+kubebuilder:scaffold" --type go # Find markers to inject code via Machinery +rg "\\+kubebuilder" --type go # Find all markers +rg "type.*Plugin struct" pkg/plugins/ # Find plugins +``` + +## Design Philosophy + +- **Libraries over code generation** - Use libraries when possible; generated code is hard to maintain +- **Common cases easy, uncommon cases possible** - 80-90% use cases should be simple +- **Batteries included** - Projects should be deployable/testable out-of-box +- **No copy-paste** - Refactor into libraries or remote Kustomize bases + +## References + +- `Makefile` - All automation targets (source of truth for commands) +- `CONTRIBUTING.md` - CLA, pre-submit checklist, PR emoji policy +- `VERSIONING.md` - Release workflow and PR tagging +- `docs/book/` - User documentation (https://book.kubebuilder.io) +- `test/e2e/utils/test_context.go` - E2E test helpers diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 981541cb9c8..88c1114c0f2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ Please see https://git.k8s.io/community/CLA.md for more info. ## Prerequisites -- [go](https://golang.org/dl/) version v1.16+. +- [go](https://golang.org/dl/) version v1.23+. - [docker](https://docs.docker.com/install/) version 17.03+. - [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) version v1.11.3+. - [kustomize](https://github.com/kubernetes-sigs/kustomize/blob/master/site/content/en/docs/Getting%20started/installation.md) v3.1.0+ @@ -24,6 +24,13 @@ Please see https://git.k8s.io/community/CLA.md for more info. 1. Fork the desired repo, develop and test your code changes. 1. Submit a pull request. +In addition to the above steps, we adhere to the following best practices to maintain consistency and efficiency in our project: + +- **Single Commit per PR:** Each Pull Request (PR) should contain only one commit. This approach simplifies tracking changes and makes the history more readable. +- **One Issue per PR:** Each PR should address a single specific issue or need. This helps in streamlining our workflow and makes it easier to identify and resolve problems such as revert the changes if required. + +For more detailed guidelines, refer to the [Kubernetes Contributor Guide][k8s-contrubutiong-guide]. + ## How to build kubebuilder locally Note that, by building the kubebuilder from the source code we are allowed to test the changes made locally. @@ -46,7 +53,7 @@ $ git clone git@github.com:/kubebuilder.git $GOPATH/src/sigs.k8s.io/kubebu - e2e tests use [`kind`][kind] and [`setup-envtest`][setup-envtest]. If you want to bring your own binaries, place them in `$(go env GOPATH)/bin`. -**IMPORTANT:** The `make generate` is very helpful. By using it, you can check if good part of the commands still working successfully after the changes. Also, note that its usage is a pre-requirement to submit a PR. +**IMPORTANT:** The `make generate` is very helpful. By using it, you can check if good part of the commands still working successfully after the changes. Also, note that its usage is a prerequisite to submit a PR. Following the targets that can be used to test your changes locally. @@ -60,7 +67,26 @@ Following the targets that can be used to test your changes locally. | make check-testdata | Checks if the testdata dir is updated with the latest changes | yes | | make test-e2e-local | Runs the CI e2e tests locally | no | -**NOTE** To use the `make lint` is required to install `golangci-lint` locally. More info: https://github.com/golangci/golangci-lint#install +**NOTE** `make lint` requires a local installation of `golangci-lint`. More info: https://github.com/golangci/golangci-lint#install + +### Running e2e tests locally + +See that you can run `test-e2e-local` to setup Kind and run e2e tests locally. +Another option is by manually starting up Kind and configuring it and then, +you can for example via your IDEA debug the e2e tests. + +To manually setup run: + +```shell +# To generate an Kubebuilder local binary with your changes +make install +# To create the cluster +kind create cluster --config ./test/e2e/kind-config.yaml +``` + +Now, you can for example, run in debug mode the `test/e2e/v4/e2e_suite_test.go`: + +![example](https://github.com/kubernetes-sigs/kubebuilder/assets/7708031/277d26d5-c94d-41f0-8f02-1381458ef750) ### Test Plugin @@ -82,7 +108,7 @@ To fully test the proposed plugin: 3. Create `generate_test.go` ([ref](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/v4/generate_test.go)). That should: - Introduce/Receive a `TextContext` instance - Trigger the plugin's bound subcommands. See [Init](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L213), [CreateAPI](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.6.0/test/e2e/utils/test_context.go#L222) - - Use [PluginUtil](https://pkg.go.dev/sigs.k8s.io/kubebuilder/v3/pkg/plugin/util) to verify the scaffolded outputs. See [InsertCode](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/pkg/plugin/util/util.go#L67), [ReplaceInFile](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.6.0/pkg/plugin/util/util.go#L196), [UncommendCode](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.6.0/pkg/plugin/util/util.go#L86) + - Use [PluginUtil](https://pkg.go.dev/sigs.k8s.io/kubebuilder/v4/pkg/plugin/util) to verify the scaffolded outputs. See [InsertCode](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/pkg/plugin/util/util.go#L67), [ReplaceInFile](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.6.0/pkg/plugin/util/util.go#L196), [UncommendCode](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.6.0/pkg/plugin/util/util.go#L86) 4. Create `plugin_cluster_test.go` ([ref](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/v4/plugin_cluster_test.go)). That should: - 4.1. Setup testing environment, e.g: @@ -96,7 +122,7 @@ To fully test the proposed plugin: - Execute commands in your `Makefile`. See [Make](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L240) - Temporary load image of the testing controller. See [LoadImageToKindCluster](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L283) - - Call Kubectl to validate running resources. See [utils.Kubectl](https://pkg.go.dev/sigs.k8s.io/kubebuilder/v3/test/e2e/utils#Kubectl) + - Call Kubectl to validate running resources. See [utils.Kubectl](https://pkg.go.dev/sigs.k8s.io/kubebuilder/v4/test/e2e/utils#Kubectl) - 4.4. Delete temporary resources after testing exited, e.g: - Uninstall prerequisites CRDs: See [UninstallPrometheusOperManager](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L183) @@ -131,7 +157,6 @@ a: - Patch fix: :bug: (`:bug:`) - Docs: :book: (`:book:`) - Infra/Tests/Other: :seedling: (`:seedling:`) -- No release note: :ghost: (`:ghost:`) Use :ghost: (no release note) only for the PRs that change or revert unreleased changes, which don't deserve a release note. Please don't abuse it. @@ -139,6 +164,13 @@ changes, which don't deserve a release note. Please don't abuse it. You can also use the equivalent emoji directly, since GitHub doesn't render the `:xyz:` aliases in PR titles. +If the PR is "plugin" scoped, you may also append the responding plugin names in the prefix. +[For instance](https://github.com/kubernetes-sigs/kubebuilder/commit/0b36d0c4021bbf52f29d5a990157466761ec180c): + +``` +🐛 (kustomize/v2-alpha): Fix typo issue in the labels added to the manifests +``` + Individual commits should not be tagged separately, but will generally be assumed to match the PR. For instance, if you have a bugfix in with a breaking change, it's generally encouraged to submit the bugfix @@ -156,7 +188,8 @@ separately. The docs are published off of three branches: -- `book-v3`: [book.kubebuilder.io](https://book.kubebuilder.io) -- current docs +- `book-v4`: [book.kubebuilder.io](https://book.kubebuilder.io) -- current docs +- `book-v3`: [book-v3.book.kubebuilder.io](https://book-v3.book.kubebuilder.io) -- legacy docs - `book-v2`: [book-v2.book.kubebuilder.io](https://book-v2.book.kubebuilder.io) -- legacy docs - `book-v1`: [book-v1.book.kubebuilder.io](https://book-v1.book.kubebuilder.io) -- legacy docs - `master`: [master.book.kubebuilder.io](https://master.book.kubebuilder.io) -- "nightly" docs @@ -191,3 +224,4 @@ Participation in the Kubernetes community is governed by the [Kubernetes Code of [golangci]: https://github.com/golangci/golangci-lint [kind]: https://kind.sigs.k8s.io/#installation-and-usage [setup-envtest]: https://book.kubebuilder.io/reference/envtest +[k8s-contrubutiong-guide]: https://www.kubernetes.dev/docs/guide/contributing/ diff --git a/Makefile b/Makefile index 5e1e9c8c13c..cb1ce743de2 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Copyright 2019 The Kubernetes Authors. +# Copyright 2023 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -26,11 +26,16 @@ else GOBIN=$(shell go env GOBIN) endif +## Location to install dependencies to +LOCALBIN ?= $(shell pwd)/bin +$(LOCALBIN): + mkdir -p $(LOCALBIN) + ##@ General # The help target prints out all targets with their descriptions organized # beneath their categories. The categories are represented by '##@' and the -# target descriptions by '##'. The awk commands is responsible for reading the +# target descriptions by '##'. The awk command is responsible for reading the # entire set of makefiles included in this invocation, looking for lines of the # file as xyz: ## something, and then pretty-format the target and help. Then, # if there's a line with ##@ something, that gets pretty-printed as a category. @@ -45,59 +50,102 @@ help: ## Display this help ##@ Build +K8S_VERSION ?= $(shell go list -m -modfile=./testdata/project-v4/go.mod -f "{{ .Version }}" k8s.io/api | awk -F'[v.]' '{printf "1.%d.%d", $$3, $$4}') + LD_FLAGS=-ldflags " \ - -X main.kubeBuilderVersion=$(shell git describe --tags --dirty --broken) \ - -X main.goos=$(shell go env GOOS) \ - -X main.goarch=$(shell go env GOARCH) \ - -X main.gitCommit=$(shell git rev-parse HEAD) \ - -X main.buildDate=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') \ + -X sigs.k8s.io/kubebuilder/v4/cmd.kubeBuilderVersion=$(shell git describe --tags --dirty --broken) \ + -X sigs.k8s.io/kubebuilder/v4/cmd.kubernetesVendorVersion=$(K8S_VERSION) \ + -X sigs.k8s.io/kubebuilder/v4/cmd.goos=$(shell go env GOOS) \ + -X sigs.k8s.io/kubebuilder/v4/cmd.goarch=$(shell go env GOARCH) \ + -X sigs.k8s.io/kubebuilder/v4/cmd.gitCommit=$(shell git rev-parse HEAD) \ + -X sigs.k8s.io/kubebuilder/v4/cmd.buildDate=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') \ " .PHONY: build build: ## Build the project locally - go build $(LD_FLAGS) -o bin/kubebuilder ./cmd + go build $(LD_FLAGS) -o bin/kubebuilder .PHONY: install install: build ## Build and install the binary with the current source code. Use it to test your changes locally. + rm -f $(GOBIN)/kubebuilder cp ./bin/kubebuilder $(GOBIN)/kubebuilder ##@ Development .PHONY: generate -generate: generate-testdata ## Update/generate all mock data. You should run this commands to update the mock data after your changes. +generate: generate-testdata generate-docs update-k8s-version ## Update/generate all mock data. You should run this commands to update the mock data after your changes. go mod tidy + make remove-spaces + +.PHONY: remove-spaces +remove-spaces: + @echo "Removing trailing spaces" + @bash -c ' \ + if sed --version 2>&1 | grep -q "GNU"; then \ + find . -type f -name "*.md" -exec sed -i "s/[[:space:]]*$$//" {} + || true; \ + else \ + find . -type f -name "*.md" -exec sed -i "" "s/[[:space:]]*$$//" {} + || true; \ + fi' .PHONY: generate-testdata generate-testdata: ## Update/generate the testdata in $GOPATH/src/sigs.k8s.io/kubebuilder + chmod -R +w testdata/ rm -rf testdata/ ./test/testdata/generate.sh +.PHONY: generate-docs +generate-docs: ## Update/generate the docs + ./hack/docs/generate.sh + +.PHONY: generate-charts +generate-charts: build ## Re-generate the helm chart testdata and docs samples + rm -rf testdata/project-v4-with-plugins/dist/chart + rm -rf docs/book/src/getting-started/testdata/project/dist/chart + rm -rf docs/book/src/cronjob-tutorial/testdata/project/dist/chart + rm -rf docs/book/src/multiversion-tutorial/testdata/project/dist/chart + + # Generate helm charts from kustomize manifests using v2-alpha plugin + (cd testdata/project-v4-with-plugins && make build-installer && ../../bin/kubebuilder edit --plugins=helm/v2-alpha) + (cd docs/book/src/getting-started/testdata/project && make build-installer && ../../../../../../bin/kubebuilder edit --plugins=helm/v2-alpha) + (cd docs/book/src/cronjob-tutorial/testdata/project && make build-installer && ../../../../../../bin/kubebuilder edit --plugins=helm/v2-alpha) + (cd docs/book/src/multiversion-tutorial/testdata/project && make build-installer && ../../../../../../bin/kubebuilder edit --plugins=helm/v2-alpha) + +.PHONY: check-docs +check-docs: ## Run the script to ensure that the docs are updated + ./hack/docs/check.sh + .PHONY: lint -lint: golangci-lint ## Run golangci-lint linter +lint: golangci-lint yamllint ## Run golangci-lint linter & yamllint $(GOLANGCI_LINT) run .PHONY: lint-fix lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes $(GOLANGCI_LINT) run --fix -GOLANGCI_LINT = $(shell pwd)/bin/golangci-lint +.PHONY: lint-config +lint-config: golangci-lint ## Verify golangci-lint linter configuration + $(GOLANGCI_LINT) config verify + +.PHONY: yamllint +yamllint: + @files=$$(find testdata -name '*.yaml' ! -path 'testdata/*/dist/*'); \ + docker run --rm $$(tty -s && echo "-it" || echo) -v $(PWD):/data cytopia/yamllint:latest $$files -d "{extends: relaxed, rules: {line-length: {max: 120}}}" --no-warnings + +.PHONY: golangci-lint golangci-lint: - @[ -f $(GOLANGCI_LINT) ] || { \ - set -e ;\ - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell dirname $(GOLANGCI_LINT)) v1.49.0 ;\ - } + $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,${GOLANGCI_LINT_VERSION}) .PHONY: apidiff apidiff: go-apidiff ## Run the go-apidiff to verify any API differences compared with origin/master - $(GOBIN)/go-apidiff master --compare-imports --print-compatible --repo-path=. + $(GO_APIDIFF) master --compare-imports --print-compatible --repo-path=. .PHONY: go-apidiff go-apidiff: - go install github.com/joelanford/go-apidiff@v0.4.0 + $(call go-install-tool,$(GO_APIDIFF),github.com/joelanford/go-apidiff,$(GO_APIDIFF_VERSION)) ##@ Tests .PHONY: test -test: test-unit test-integration test-testdata test-book test-license ## Run the unit and integration tests (used in the CI) +test: test-unit test-integration test-features test-testdata test-book test-license ## Run the unit and integration tests (used in the CI) .PHONY: test-unit TEST_PKGS := ./pkg/... ./test/e2e/utils/... @@ -109,6 +157,10 @@ test-coverage: ## Run unit tests creating the output to report coverage - rm -rf *.out # Remove all coverage files if exists go test -race -failfast -tags=integration -coverprofile=coverage-all.out -coverpkg="./pkg/cli/...,./pkg/config/...,./pkg/internal/...,./pkg/machinery/...,./pkg/model/...,./pkg/plugin/...,./pkg/plugins/golang" $(TEST_PKGS) +.PHONY: test-features +test-features: ## Run the integration tests + ./test/features.sh + .PHONY: test-integration test-integration: ## Run the integration tests ./test/integration.sh @@ -121,12 +173,6 @@ check-testdata: ## Run the script to ensure that the testdata is updated test-testdata: ## Run the tests of the testdata directory ./test/testdata/test.sh -#todo(remove the test-legacy whne the go/v2 be removed from kubebuilder) - -.PHONY: test-legacy -test-legacy: ## Run the legacy tests (go/v2) of the testdata directory - ./test/testdata/test_legacy.sh - .PHONY: test-e2e-local test-e2e-local: ## Run the end-to-end tests locally ## To keep the same kind cluster between test runs, use `SKIP_KIND_CLEANUP=1 make test-e2e-local` @@ -139,9 +185,68 @@ test-e2e-ci: ## Run the end-to-end tests (used in the CI)` .PHONY: test-book test-book: ## Run the cronjob tutorial's unit tests to make sure we don't break it cd ./docs/book/src/cronjob-tutorial/testdata/project && make test - cd ./docs/book/src/component-config-tutorial/testdata/project && make test cd ./docs/book/src/multiversion-tutorial/testdata/project && make test + cd ./docs/book/src/getting-started/testdata/project && make test .PHONY: test-license test-license: ## Run the license check ./test/check-license.sh + +.PHONY: test-external-plugin +test-external-plugin: install ## Run tests for external plugin + make -C docs/book/src/simple-external-plugin-tutorial/testdata/sampleexternalplugin/v1 install + make -C docs/book/src/simple-external-plugin-tutorial/testdata/sampleexternalplugin/v1 test-plugin + +.PHONY: test-spaces +test-spaces: ## Run the trailing spaces check + ./test/check_spaces.sh + +## TODO: Remove me when go/v4 plugin be removed +## Deprecated +.PHONY: test-legacy +test-legacy: ## Run the tests to validate legacy path for webhooks + rm -rf ./testdata/**legacy**/ + ./test/testdata/legacy-webhook-path.sh + +.PHONY: install-helm +install-helm: ## Install the latest version of Helm locally + @curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + +.PHONY: helm-lint +helm-lint: install-helm ## Lint the Helm chart in testdata + helm lint testdata/project-v4-with-plugins/dist/chart + +.PHONY: update-k8s-version +update-k8s-version: ## Update Kubernetes API version in version.go and .goreleaser.yml + @if [ -z "$(K8S_VERSION)" ]; then echo "Error: K8S_VERSION is empty"; exit 1; fi + @echo "Updating Kubernetes version to $(K8S_VERSION)" + @# Update version.go + @sed -i.bak 's/kubernetesVendorVersion = .*/kubernetesVendorVersion = "$(K8S_VERSION)"/' cmd/version.go + @# Update .goreleaser.yml + @sed -i.bak 's/KUBERNETES_VERSION=.*/KUBERNETES_VERSION=$(K8S_VERSION)/' build/.goreleaser.yml + @# Clean up backup files + @find . -name "*.bak" -type f -delete + +## Tool Binaries +GO_APIDIFF ?= $(LOCALBIN)/go-apidiff +GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint + +## Tool Versions +GO_APIDIFF_VERSION ?= v0.6.1 +GOLANGCI_LINT_VERSION ?= v2.5.0 + +# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist +# $1 - target path with name of binary +# $2 - package url which can be installed +# $3 - specific version of package +define go-install-tool +@[ -f "$(1)-$(3)" ] && [ "$$(readlink -- "$(1)" 2>/dev/null)" = "$(1)-$(3)" ] || { \ +set -e; \ +package=$(2)@$(3) ;\ +echo "Downloading $${package}" ;\ +rm -f $(1) ;\ +GOBIN=$(LOCALBIN) go install $${package} ;\ +mv $(1) $(1)-$(3) ;\ +} ;\ +ln -sf $$(realpath $(1)-$(3)) $(1) +endef diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index 9ae98625774..2bcbb49ffb3 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -4,26 +4,29 @@ aliases: # active folks who can be contacted to perform admin-related # tasks on the repo, or otherwise approve any PRs. kubebuilder-admins: - - pwittrock - camilamacedo86 - - jmrodri - varshaprasad96 # non-admin folks who can approve any PRs in the repo kubebuilder-approvers: + - Kavinjsir # folks who can review and LGTM any PRs in the repo (doesn't include # approvers & admins -- those count too via the OWNERS file) kubebuilder-reviewers: - - joelanford - rashmigottipati - - everettraven # folks who may have context on ancient history, # but are no longer directly involved kubebuilder-emeritus-approvers: + - adirio - directxman12 - droot - - mengqiy - estroz - - adirio + - jmrodri + - joelanford + - mengqiy + - pwittrock + + kubebuilder-emeritus-reviewers: + - everettraven diff --git a/README.md b/README.md index aad4f893766..bdbdd62d71d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Lint](https://github.com/kubernetes-sigs/kubebuilder/actions/workflows/lint.yml/badge.svg)](https://github.com/kubernetes-sigs/kubebuilder/actions/workflows/lint.yml) -[![Unit tests](https://github.com/kubernetes-sigs/kubebuilder/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/kubernetes-sigs/kubebuilder/actions/workflows/unit-tests.yml) [![Go Report Card](https://goreportcard.com/badge/sigs.k8s.io/kubebuilder)](https://goreportcard.com/report/sigs.k8s.io/kubebuilder) [![Coverage Status](https://coveralls.io/repos/github/kubernetes-sigs/kubebuilder/badge.svg?branch=master)](https://coveralls.io/github/kubernetes-sigs/kubebuilder?branch=master) +[![Latest release](https://badgen.net/github/release/kubernetes-sigs/kubebuilder)](https://github.com/kubernetes-sigs/kubebuilder/releases) ## Kubebuilder @@ -19,13 +19,13 @@ and features. To learn more about this see the [Plugin section][plugin-section]. Kubebuilder is developed on top of the [controller-runtime][controller-runtime] and [controller-tools][controller-tools] libraries. -### Kubebuilder is also a framework +### Kubebuilder is also a library Kubebuilder is extensible and can be used as a library in other projects. -[Operator-SDK][operator-sdk] is a good example of a project that uses Kubebuilder as a library. +[Operator-SDK][operator-sdk] is a good example of a project that uses Kubebuilder as a library. [Operator-SDK][operator-sdk] uses the plugin feature to include non-Go operators _e.g. operator-sdk's Ansible and Helm-based language Operators_. -To learn more see [how to create your own plugins][your-own-plugins]. +To learn more see [how to create your own plugins][your-own-plugins]. ### Installation @@ -36,11 +36,11 @@ Follow the [instructions](https://book.kubebuilder.io/quick-start.html#installat See the [Getting Started](https://book.kubebuilder.io/quick-start.html) documentation. -![Quick Start](docs/gif/kb-demo.v2.0.1.svg) +![Quick Start](docs/gif/kb-demo.v3.11.1.svg) -Also, ensure that you check out the [Deploy Image](https://book.kubebuilder.io/plugins/deploy-image-plugin-v1-alpha.html) -Plugin. This plugin allows users to scaffold API/Controllers to deploy and manage an -Operand (image) on the cluster following the guidelines and best practices. It abstracts the +Also, ensure that you check out the [Deploy Image](./docs/book/src/plugins/available/deploy-image-plugin-v1-alpha.md) +Plugin. This plugin allows users to scaffold API/Controllers to deploy and manage an +Operand (image) on the cluster following the guidelines and best practices. It abstracts the complexities of achieving this goal while allowing users to customize the generated code. ## Documentation @@ -51,16 +51,16 @@ Check out the Kubebuilder [book](https://book.kubebuilder.io). - Kubebuilder Book: [book.kubebuilder.io](https://book.kubebuilder.io) - GitHub Repo: [kubernetes-sigs/kubebuilder](https://github.com/kubernetes-sigs/kubebuilder) -- Slack channel: [#kubebuilder](https://slack.k8s.io/#kubebuilder) +- Slack channel: [#kubebuilder](https://kubernetes.slack.com/messages/#kubebuilder) - Google Group: [kubebuilder@googlegroups.com](https://groups.google.com/forum/#!forum/kubebuilder) -- Design Documents: [designs](designs/). +- Design Documents: [designs](designs/) - Plugin: [plugins][plugin-section] ## Motivation Building Kubernetes tools and APIs involves making a lot of decisions and writing a lot of boilerplate. -In order to facilitate easily building Kubernetes APIs and tools using the canonical approach, this framework +To facilitate easily building Kubernetes APIs and tools using the canonical approach, this framework provides a collection of Kubernetes development tools to minimize toil. Kubebuilder attempts to facilitate the following developer workflow for building APIs @@ -74,7 +74,7 @@ Kubebuilder attempts to facilitate the following developer workflow for building ## Scope -Building APIs using CRDs, Controllers and Admission Webhooks. +Building APIs using CRDs, Controllers, and Admission Webhooks. ## Philosophy @@ -82,21 +82,21 @@ See [DESIGN.md](DESIGN.md) for the guiding principles of the various Kubebuilder TL;DR: -Provide clean library abstractions with clear and well exampled godocs. +Provide clean library abstractions with clear and well-exampled go docs. -- Prefer using go *interfaces* and *libraries* over relying on *code generation* +- Prefer using go *interfaces* and *libraries* over-relying on *code generation* - Prefer using *code generation* over *1 time init* of stubs - Prefer *1 time init* of stubs over forked and modified boilerplate - Never fork and modify boilerplate ## Techniques -- Provide higher level libraries on top of low level client libraries - - Protect developers from breaking changes in low level libraries +- Provide higher-level libraries on top of low-level client libraries + - Protect developers from breaking changes in low-level libraries - Start minimal and provide progressive discovery of functionality - Provide sane defaults and allow users to override when they exist - Provide code generators to maintain common boilerplate that can't be addressed by interfaces - - Driven off of `//+` comments + - Driven off of `// +` comments - Provide bootstrapping commands to initialize new packages ## Versioning and Releasing @@ -110,44 +110,61 @@ See [VERSIONING.md](VERSIONING.md). Before you file an issue, please search existing issues to see if your issue is already covered. - ### Slack - For realtime discussion, you can join the [#kubebuilder](https://slack.k8s.io/#kubebuilder) slack channel. Slack requires registration, but the Kubernetes team is open invitation to anyone to register here. Feel free to come and ask any questions. + For real-time discussion, you can join the [#kubebuilder](https://slack.k8s.io/#kubebuilder) slack channel. Slack requires registration, but the Kubernetes team is an open invitation to anyone to register here. Feel free to come and ask any questions. ## Contributing -Contributions are greatly appreciated. The maintainers actively manage the issues list, and try to highlight issues suitable for newcomers. +Contributions are greatly appreciated. The maintainers actively manage the issues list and try to highlight issues suitable for newcomers. The project follows the typical GitHub pull request model. See [CONTRIBUTING.md](CONTRIBUTING.md) for more details. -Before starting any work, please either comment on an existing issue, or file a new one. +Before starting any work, please either comment on an existing issue or file a new one. -## Supportability +## Operating Systems Supported -Currently, Kubebuilder officially supports OSX and Linux platforms. -So, if you are using a Windows OS you may find issues. Contributions towards -supporting Windows are welcome. +Currently, Kubebuilder officially supports macOS and Linux platforms. If you are using a Windows OS, we recommend you read the instructions in [here](docs/windows.md). -### Apple Silicon +Contributions towards supporting Windows are not planned. -Apple Silicon (`darwin/arm64`) is supported using the `go/v4-alpha` plugin which provides support for this platform. +## Versions Compatibility and Supportability -```bash -kubebuilder init --domain my.domain --repo my.domain/guestbook --plugins=go/v4-alpha -``` +Projects created by Kubebuilder contain a `Makefile` that installs tools at versions defined during project creation. The main tools included are: -**Note**: The `go/v4-alpha` plugin is an unstable version and can have breaking changes in future releases. The previous kustomize -version (`v3.Y.Z`) used in the `go/v3` has no available binaries for this -platform [kubernetes-sigs/kustomize/issues/4612](https://github.com/kubernetes-sigs/kustomize/issues/4612) -Because of this, we cannot support this `darwin/arm64` on the stable scaffold done by default with the Kubebuilder with the `go/v3` plugin. +- [kustomize](https://github.com/kubernetes-sigs/kustomize) +- [controller-gen](https://github.com/kubernetes-sigs/controller-tools) +- [setup-envtest](https://github.com/kubernetes-sigs/controller-runtime/tree/main/tools/setup-envtest) + +Additionally, these projects include a `go.mod` file specifying dependency versions. +Kubebuilder relies on [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) and its Go and Kubernetes dependencies. +Therefore, the versions defined in the `Makefile` and `go.mod` files are the ones that have been tested, supported, and recommended. + +Each minor version of Kubebuilder is tested with a specific minor version of the client-go. +While a Kubebuilder minor version *may* be compatible with other client-go minor versions, +or other tools this compatibility is not guaranteed, supported, or tested. + +The minimum Go version required by Kubebuilder is determined by the highest minimum +Go version required by its dependencies. This is usually aligned with the minimum +Go version required by the corresponding `k8s.io/*` dependencies. + +Compatible `k8s.io/*` versions, client-go versions, and minimum Go versions can be found in the `go.mod` +file scaffolded for each project for each [tag release](https://github.com/kubernetes-sigs/kubebuilder/tags). + +**Example:** For the `4.1.1` release, the minimum Go version compatibility is `1.22`. +You can refer to the samples in the testdata directory of the tag released [v4.1.1](https://github.com/kubernetes-sigs/kubebuilder/tree/v4.1.1/testdata), +such as the [go.mod](https://github.com/kubernetes-sigs/kubebuilder/blob/v4.1.1/testdata/project-v4/go.mod#L3) file for `project-v4`. You can also check the versions of the tools supported and +tested for this release by examining the [Makefile](https://github.com/kubernetes-sigs/kubebuilder/blob/v4.1.1/testdata/project-v4/Makefile#L160-L165). ## Community Meetings - + The following meetings happen biweekly: - -- Kubebuilder, Controller Runtime, and Controller Tools -- Kubebuilder Triage + +- Kubebuilder Meeting You are more than welcome to attend. For further info join to [kubebuilder@googlegroups.com](https://groups.google.com/g/kubebuilder). +Every month, our team meets on the first Thursday at 11:00 PT (Pacific Time) to discuss our progress and plan for the upcoming weeks. +Please note that we have been syncing more frequently offline via Slack lately. However, if you add a topic to the agenda, we will hold the meeting as scheduled. +Additionally, we can use this channel to demonstrate new features. [operator-sdk]: https://github.com/operator-framework/operator-sdk [plugin-section]: https://book.kubebuilder.io/plugins/plugins.html [controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime -[your-own-plugins]: https://book.kubebuilder.io/plugins/creating-plugins.html -[controller-tools]: https://github.com/kubernetes-sigs/controller-tools \ No newline at end of file +[your-own-plugins]: https://book.kubebuilder.io/plugins/extending +[controller-tools]: https://github.com/kubernetes-sigs/controller-tools diff --git a/RELEASE.md b/RELEASE.md index 4f00aad65b7..0d6b0b95f91 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -25,11 +25,14 @@ process was done to ensure that we have an aligned process under the org (simila > **Note** > - You will need to have checkout locally from the remote repository the previous branch > - Also, ensure that you fetch all tags from the remote `git fetch --all --tags` +> - Also, if you face issues to generate the release notes you might want to able to sort it out by running i.e.: +> `go run sigs.k8s.io/kubebuilder-release-tools/notes --use-upstream=false --from=v3.11.0 --branch=release-X` + ### Draft a new release from GitHub 1. Create a new tag with the correct version from the new `release-` branch -2. Verify the Release Github Action. It should build the assets and publish in the draft release +2. Verify the Release Github Action. It should build the assets and publish in the draft release 3. You also need to manually add the changelog generated above on the release page and publish it. Now, the code source is released ! ### Update the website docs (https://book.kubebuilder.io/quick-start.html) @@ -50,28 +53,6 @@ For more info, see the release page: https://github.com/kubernetes-sigs/kubebuil 2. Announce the new release via email is sent to `kubebuilder@googlegroups.com` with the subject `[ANNOUNCE] Kubebuilder $VERSION is released` -## What to do if things goes wrong? How to release from my local env as a workaround? - -As a workaround we can release from locally by: - -PS.: _This workaround uses the google cloud. Note that we move the binary CLI release from google cloud to use Github Actions instead_ - -1. Download google container builder: https://github.com/GoogleCloudPlatform/cloud-build-local -2. Verify that you can use the cloud-build-local CLI tool -3. Ensure that you are locally in the branch created for the release (`release-`) -4. Ensure that it has no changes in the code source ( `git status`) -5. Create the directory `cloudbuild` (`mkdir cloudbuild`) -6. Then, update the file `build/cloudbuild_local.yaml` with: - -The following change is required for Goreleaser be able to add the binaries in the release page. - -```sh -env: ["SNAPSHOT=1","GITHUB_TOKEN=your github token with access in the repo"] -``` -**NOTE** You can create a token [here](https://github.com/settings/tokens/new). - -7. Then, update the file `build/build_kubebuilder.sh` to remove the flag `--snapshot` (Otherwise, the binaries will be built with snapshot git commit hash instead of the tag version) -8. Run the command to trigger the release `$ cloud-build-local --config=build/cloudbuild_local.yaml --dryrun=false --write-workspace=./cloudbuild .` ## HEAD releases @@ -86,36 +67,37 @@ The releases occur in an account in the Google Cloud (See [here](https://console ### To build the Kubebuilder CLI binaries: -A trigger `build-kb-release` is configured to call [build/cloudbuild.yaml](build/cloudbuild.yaml). -This trigger will be executed when any new tag be published. -The tags must be built from the release branch (Currently, `release-3`). +A trigger GitHub action [release](.github/workflows/release.yml) is trigged when a new tag is pushed. +This action will call the job [./build/.goreleaser.yml](./build/.goreleaser.yml). -Also, we have a trigger to generate snapshots builds from the master branch. -This trigger will call [build/cloudbuild_snapshot.yaml](build/cloudbuild_snapshot.yaml) -when any change needs to be performed on master. +### (Deprecated) - To build the Kubebuilder-tools: (Artifacts required to use ENV TEST) -### To build the Kubebuilder-tools: (Artifacts required to use ENV TEST) +> We no longer build the artifacts and the promotion of those is deprecated. For more info +see: https://github.com/kubernetes-sigs/kubebuilder/discussions/4082 Kubebuilder projects requires artifacts which are used to do test with ENV TEST (when we call `make test` target) These artifacts can be checked in the service page: https://storage.googleapis.com/kubebuilder-tools -The build is made from the branch [tools-releases](https://github.com/kubernetes-sigs/kubebuilder/tree/tools-releases) and the trigger will call the `build/cloudbuild_tools.yaml` passing +The build is made from the branch [tools-releases](https://github.com/kubernetes-sigs/kubebuilder/tree/tools-releases) and the trigger will call the `build/cloudbuild_tools.yaml` passing as argument the architecture and the SO that should be used, e.g: Screenshot 2022-04-30 at 10 15 41 For further information see the [README](https://github.com/kubernetes-sigs/kubebuilder/blob/tools-releases/README.md). -### To build the `kube-rbac-proxy` images: +### (Deprecated) - To build the `kube-rbac-proxy` images: + +> We no longer build the images and the promotion of those images is deprecated. For more info +see: https://github.com/kubernetes-sigs/kubebuilder/discussions/3907 These images are built from the project [brancz/kube-rbac-proxy](https://github.com/brancz/kube-rbac-proxy). The projects built with Kubebuilder creates a side container with `kube-rbac-proxy` to protect the Manager. -These images are can be checked in the consolse, see [here](https://console.cloud.google.com/gcr/images/kubebuilder/GLOBAL/kube-rbac-proxy). +These images can be checked in the console, see [here](https://console.cloud.google.com/gcr/images/kubebuilder/GLOBAL/kube-rbac-proxy). The project `kube-rbac-proxy` is in the process to be donated to the k8s org. However, it is going on for a long time and then, we have no ETA for that to occur. When that occurs we can automate this process. But until there we need to generate these images -by bumping the versions/tags released by `kube-rbac-proxy` on the branch +by bumping the versions/tags released by `kube-rbac-proxy` on the branch [kube-rbac-proxy-releases](https://github.com/kubernetes-sigs/kubebuilder/tree/kube-rbac-proxy-releases) then the `build/cloudbuild_kube-rbac-proxy.yaml` will generate the images. @@ -124,7 +106,9 @@ To check an example, see the pull request [#2578](https://github.com/kubernetes- **Note**: we cannot use the images produced by the project `kube-rbac-proxy` because we need to ensure to Kubebuilder users that these images will be available. -### To build the `gcr.io/kubebuilder/pr-verifier` images: +### (Deprecated) - To build the `gcr.io/kubebuilder/pr-verifier` images: + +> We are working on to move all out from GCP Kubebuilder project. For further information see: https://github.com/kubernetes/k8s.io/issues/2647#issuecomment-2111182864 These images are used to verify the PR title and description. They are built from [kubernetes-sigs/kubebuilder-release-tools](https://github.com/kubernetes-sigs/kubebuilder-release-tools/). In Kubebuilder, we have been using this project via the GitHub action [.github/workflows/verify.yml](.github/workflows/verify.yml) @@ -142,8 +126,8 @@ and not the image, see: github_token: ${{ secrets.GITHUB_TOKEN }} ``` -However, the image should still be built and maintained since other projects under the org might be using them. +However, the image should still be built and maintained since other projects under the org might be using them. [kubebuilder-release-tools]: https://github.com/kubernetes-sigs/kubebuilder-release-tools [release-notes-generation]: https://github.com/kubernetes-sigs/kubebuilder-release-tools/blob/master/README.md#release-notes-generation -[release-process]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/VERSIONING.md#releasing \ No newline at end of file +[release-process]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/VERSIONING.md#releasing diff --git a/SECURITY_CONTACTS b/SECURITY_CONTACTS index cc49f4ee79b..1e2a02f2676 100644 --- a/SECURITY_CONTACTS +++ b/SECURITY_CONTACTS @@ -10,5 +10,5 @@ # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE # INSTRUCTIONS AT https://kubernetes.io/security/ -droot -pwittrock +camilamacedo86 +varshaprasad96 diff --git a/VERSIONING.md b/VERSIONING.md index d26a8552434..8d5e7e2a971 100644 --- a/VERSIONING.md +++ b/VERSIONING.md @@ -59,4 +59,4 @@ take care of building and publishing the artifacts. [envtest-ref]: https://book.kubebuilder.io/reference/artifacts.html [tools-branch]: https://github.com/kubernetes-sigs/kubebuilder/tree/tools-releases [kb-releases]:https://github.com/kubernetes-sigs/kubebuilder/releases -[cli-plugins-versioning]:docs/book/src/plugins/extending-cli.md#plugin-versioning +[cli-plugins-versioning]:docs/book/src/plugins/extending#plugin-versioning diff --git a/build/.goreleaser.yml b/build/.goreleaser.yml index 881dab0aa54..d622fa45f28 100644 --- a/build/.goreleaser.yml +++ b/build/.goreleaser.yml @@ -16,6 +16,8 @@ # Make sure to check the documentation at http://goreleaser.com # Global environment variables that are needed for hooks and builds. +version: 2 + env: - GO111MODULE=on @@ -27,29 +29,29 @@ before: # Build a binary for each target in targets. builds: - id: kubebuilder - main: ./cmd binary: kubebuilder mod_timestamp: "{{ .CommitTimestamp }}" ldflags: - - -X main.kubeBuilderVersion={{ .Version }} - - -X main.goos={{ .Os }} - - -X main.goarch={{ .Arch }} - - -X main.gitCommit={{ .Commit }} - - -X main.buildDate={{ .Date }} - - -X main.kubernetesVendorVersion={{ .Env.KUBERNETES_VERSION }} + - -X sigs.k8s.io/kubebuilder/v4/cmd.kubeBuilderVersion={{ .Version }} + - -X sigs.k8s.io/kubebuilder/v4/cmd.goos={{ .Os }} + - -X sigs.k8s.io/kubebuilder/v4/cmd.goarch={{ .Arch }} + - -X sigs.k8s.io/kubebuilder/v4/cmd.gitCommit={{ .Commit }} + - -X sigs.k8s.io/kubebuilder/v4/cmd.buildDate={{ .Date }} + - -X sigs.k8s.io/kubebuilder/v4/cmd.kubernetesVendorVersion={{ .Env.KUBERNETES_VERSION }} targets: - linux_amd64 - linux_arm64 - linux_ppc64le + - linux_s390x - darwin_amd64 - darwin_arm64 env: - - KUBERNETES_VERSION=1.25.0 + - KUBERNETES_VERSION=1.34.1 - CGO_ENABLED=0 # Only binaries of the form "kubebuilder_${goos}_${goarch}" will be released. archives: - - format: binary + - formats: ['binary'] # Setting name_template correctly maps checksums to binary names. name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}" @@ -65,3 +67,12 @@ release: github: owner: kubernetes-sigs name: kubebuilder + +# Add the SBOM configuration at the end to generate SBOM files +sboms: + - id: kubebuilder-sbom + artifacts: binary + cmd: syft + args: ["$artifact", "--output", "cyclonedx-json=$document"] + documents: + - "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.cyclonedx.sbom.json" diff --git a/build/build_kubebuilder.sh b/build/build_kubebuilder.sh deleted file mode 100755 index 6569396b865..00000000000 --- a/build/build_kubebuilder.sh +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2018 The Kubernetes 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 script runs goreleaser using the build/.goreleaser.yml config. -# While it can be run locally, it is intended to be run by cloudbuild -# in the goreleaser/goreleaser image. - -function usage() { - echo " - This script runs goreleaser using the build/.goreleaser.yml config. - While it can be run locally, it is intended to be run by cloudbuild - in the goreleaser/goreleaser image. - - GORELEASER_FLAGS: contains flags to pass to the goreleaser binary (default: only --config is set). - - SNAPSHOT: if set to any value, runs goreleaser in snapshot mode with mock release notes (default: unset). - - NOTES_FLAGS: contains flags to pass to the notes binary (sigs.k8s.io/kubebuilder-release-tools/notes). - Does nothing if SNAPSHOT is set. (default: unset). - - Examples: - - # Run in snapshot mode: fake release notes, nothing is published, binaries build in '$(pwd)/dist' - \$ SNAPSHOT=1 $0 - - # Add a release type to the release notes - \$ NOTES_FLAGS=\"-r beta\" $0 -" -} - -# GORELEASER_FLAGS contains flags for goreleaser such that the binary can be run -# in local/snapshot/prod mode from the same script. -# NOTE: if --snapshot is in GORELEASER_FLAGS, the release is not published to GitHub -# and the build is available under $PWD/dist. -GORELEASER_FLAGS="${GORELEASER_FLAGS:-}" -# NOTES_FLAGS contains flags for the release notes generator (see install_notes for details). -NOTES_FLAGS="${NOTES_FLAGS:-}" -# SNAPSHOT is set by the CLI flag parser if --snapshot is a passed flag. -# If not set, release notes are not generated. -SNAPSHOT="${SNAPSHOT:-}" - -while [ $# -gt 0 ]; do - case $1 in - -h|--help) - usage - exit 0 - ;; - esac -done - - -# install_notes installs kubebuilder's release notes generator globally with name "notes". -function install_notes() { - local tmp=$(mktemp -d) - pushd "$tmp" - go mod init tmp - # Get by commit because v0.1.1 cannot be retrieved via `go get`. - go get sigs.k8s.io/kubebuilder-release-tools/notes@4777888c377a26956f1831d5b9207eea1fa3bf29 - popd - rm -rf "$tmp" -} - -set -o errexit -set -o pipefail - -# Generate real release notes. -if [ -z "$SNAPSHOT" ]; then - tmp_notes="$(mktemp)" - trap "rm -f ${tmp_notes}" EXIT - install_notes - if [[ -n "${CLOUD_BUILD}" ]]; then - # we refresh just before this, no point (plus, we fiddle with the current branch a bit) - NOTES_FLAGS+=" --use-upstream=false" - # we can look for tag alpha/beta here too - # (TODO(directxman12): this should be in the tool) - [[ "${TAG_NAME}" == "v"*"-alpha."* ]] && NOTES_FLAGS+=" -r alpha" - [[ "${TAG_NAME}" == "v"*"-beta."* ]] && NOTES_FLAGS+=" -r beta" - [[ "${TAG_NAME}" == "v"*"-rc."* ]] && NOTES_FLAGS+=" -r rc" - fi - # TODO(cmacedo): figure out how to download the release notes and let it available in the cloud build - # Currently it does not work: https://github.com/kubernetes-sigs/kubebuilder/issues/2667 - # notes $NOTES_FLAGS | tee "$tmp_notes" - notes="Mock Release Notes for $(git describe --tags --always --broken)" - # we need to delete the tag for the release notes script, so restore it when done so that - # go releaser can find the right tag - if [[ -n "${TAG_NAME}" ]]; then - git tag ${TAG_NAME} - fi - GORELEASER_FLAGS="${GORELEASER_FLAGS} --release-notes=${tmp_notes}" -else - # TODO(estroz): figure out how to generate snapshot release notes with the kubebuilder generator. - echo "Running in snapshot mode. Release notes will not be generated from commits." - notes="Mock Release Notes for $(git describe --tags --always --broken)" - GORELEASER_FLAGS="${GORELEASER_FLAGS} --snapshot --rm-dist --skip-validate --release-notes <(echo \"${notes}\")" -fi - -# eval to run process substitution. -eval goreleaser release --config=build/.goreleaser.yml $GORELEASER_FLAGS diff --git a/build/cloudbuild.yaml b/build/cloudbuild.yaml deleted file mode 100644 index 70c62748c40..00000000000 --- a/build/cloudbuild.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2018 The Kubernetes 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. - -# Instructions to run locally: -# Download google container builder: https://github.com/GoogleCloudPlatform/cloud-build-local -# $ mkdir cloudbuild -# $ cloud-build-local --config=build/cloudbuild_local.yaml --dryrun=false --write-workspace=./cloudbuild . -# Release tar will be in ./cloudbuild - -steps: -- name: "gcr.io/cloud-builders/git" - entrypoint: 'bash' - args: - - '-c' - - | - git fetch --tags --unshallow - git for-each-ref --contains HEAD - # TAG_NAME is defined by GCB, so uses 1 dollar sign, BRANCH_NAME is bash, so we need to escape it - # with two dollar signs - export BRANCH_NAME=$(git for-each-ref --format="%(refname:strip=-1)" --contains HEAD 'refs/remotes/origin/release-*') - export ALL_BRANCHES=$(git for-each-ref --format="%(refname:strip=-1)" 'refs/remotes/origin/release-*') - echo "branch: $${BRANCH_NAME}, tag: ${TAG_NAME}, all release branches: $${ALL_BRANCHES}" - for branch in $${ALL_BRANCHES}; do - git branch $${branch} origin/$${branch} - done - git branch -f $${BRANCH_NAME} HEAD - git checkout $${BRANCH_NAME} - git branch --set-upstream-to=origin/$${BRANCH_NAME} - git tag -d ${TAG_NAME} -- name: "goreleaser/goreleaser:v1.11.2" - entrypoint: "bash" - args: ["build/build_kubebuilder.sh"] - env: - - 'TAG_NAME=$TAG_NAME' - - 'CLOUD_BUILD=true' - - 'GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}' \ No newline at end of file diff --git a/build/cloudbuild_local.yaml b/build/cloudbuild_local.yaml deleted file mode 100644 index ed97f90aa34..00000000000 --- a/build/cloudbuild_local.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2018 The Kubernetes 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. - -# Instructions to run locally: -# Download google container builder: https://github.com/GoogleCloudPlatform/cloud-build-local -# $ mkdir cloudbuild -# $ cloud-build-local --config=build/cloudbuild_local.yaml --dryrun=false --write-workspace=./cloudbuild . -# Release tar will be in ./cloudbuild - -steps: -- name: "goreleaser/goreleaser:v1.11.2" - entrypoint: "bash" - env: ["SNAPSHOT=1"] - args: ["build/build_kubebuilder.sh"] diff --git a/build/cloudbuild_snapshot.yaml b/build/cloudbuild_snapshot.yaml deleted file mode 100644 index 9eaf2d4ffc4..00000000000 --- a/build/cloudbuild_snapshot.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2018 The Kubernetes 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. - -# Instructions to run locally: -# Download google container builder: https://github.com/GoogleCloudPlatform/cloud-build-local -# $ mkdir cloudbuild -# $ cloud-build-local --config=build/cloudbuild_snapshot.yaml --dryrun=false --write-workspace=./cloudbuild . -# Release tar will be in ./cloudbuild - -steps: -- name: "goreleaser/goreleaser:v1.11.2" - entrypoint: "bash" - env: ["SNAPSHOT=1"] - args: ["build/build_kubebuilder.sh"] - timeout: 30m -- name: "ubuntu" - args: ["tar", "-zcvf", "kubebuilder_linux_amd64.tar.gz", "-C", "dist/kubebuilder_linux_amd64_v1", "kubebuilder"] -- name: "gcr.io/cloud-builders/gsutil" - args: ["-h", "Content-Type:application/gzip", "cp", "kubebuilder_linux_amd64.tar.gz", "gs://kubebuilder-release/kubebuilder_master_linux_amd64.tar.gz"] -- name: "ubuntu" - args: ["tar", "-zcvf", "kubebuilder_linux_arm64.tar.gz", "-C", "dist/kubebuilder_linux_arm64", "kubebuilder"] -- name: "gcr.io/cloud-builders/gsutil" - args: ["-h", "Content-Type:application/gzip", "cp", "kubebuilder_linux_arm64.tar.gz", "gs://kubebuilder-release/kubebuilder_master_linux_arm64.tar.gz"] -- name: "ubuntu" - args: ["tar", "-zcvf", "kubebuilder_linux_ppc64le.tar.gz", "-C", "dist/kubebuilder_linux_ppc64le", "kubebuilder"] -- name: "gcr.io/cloud-builders/gsutil" - args: ["-h", "Content-Type:application/gzip", "cp", "kubebuilder_linux_ppc64le.tar.gz", "gs://kubebuilder-release/kubebuilder_master_linux_ppc64le.tar.gz"] -- name: "ubuntu" - args: ["tar", "-zcvf", "kubebuilder_darwin_amd64.tar.gz", "-C", "dist/kubebuilder_darwin_amd64_v1", "kubebuilder"] -- name: "gcr.io/cloud-builders/gsutil" - args: ["-h", "Content-Type:application/gzip", "cp", "kubebuilder_darwin_amd64.tar.gz", "gs://kubebuilder-release/kubebuilder_master_darwin_amd64.tar.gz"] -- name: "ubuntu" - args: ["tar", "-zcvf", "kubebuilder_darwin_arm64.tar.gz", "-C", "dist/kubebuilder_darwin_arm64", "kubebuilder"] -- name: "gcr.io/cloud-builders/gsutil" - args: ["-h", "Content-Type:application/gzip", "cp", "kubebuilder_darwin_arm64.tar.gz", "gs://kubebuilder-release/kubebuilder_master_darwin_arm64.tar.gz"] - - diff --git a/cmd/cmd.go b/cmd/cmd.go new file mode 100644 index 00000000000..c4a26fefa16 --- /dev/null +++ b/cmd/cmd.go @@ -0,0 +1,92 @@ +/* +Copyright 2017 The Kubernetes 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 ( + "log/slog" + "os" + + "github.com/spf13/afero" + + "sigs.k8s.io/kubebuilder/v4/pkg/cli" + cfgv3 "sigs.k8s.io/kubebuilder/v4/pkg/config/v3" + "sigs.k8s.io/kubebuilder/v4/pkg/logging" + "sigs.k8s.io/kubebuilder/v4/pkg/machinery" + "sigs.k8s.io/kubebuilder/v4/pkg/plugin" + kustomizecommonv2 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/common/kustomize/v2" + "sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang" + deployimagev1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/deploy-image/v1alpha1" + golangv4 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/v4" + autoupdatev1alpha "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/autoupdate/v1alpha" + grafanav1alpha "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha" + helmv1alpha "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha" + helmv2alpha "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v2alpha" +) + +// Run bootstraps & runs the CLI +func Run() { + // Initialize custom logging handler FIRST - applies to ALL CLI operations + opts := logging.HandlerOptions{ + SlogOpts: slog.HandlerOptions{ + Level: slog.LevelInfo, + }, + } + handler := logging.NewHandler(os.Stdout, opts) + logger := slog.New(handler) + slog.SetDefault(logger) + // Bundle plugin which built the golang projects scaffold with base.go/v4 and kustomize/v2 plugins + gov4Bundle, _ := plugin.NewBundleWithOptions(plugin.WithName(golang.DefaultNameQualifier), + plugin.WithVersion(plugin.Version{Number: 4}), + plugin.WithPlugins(kustomizecommonv2.Plugin{}, golangv4.Plugin{}), + ) + + fs := machinery.Filesystem{ + FS: afero.NewOsFs(), + } + externalPlugins, err := cli.DiscoverExternalPlugins(fs.FS) + if err != nil { + slog.Error("error discovering external plugins", "error", err) + } + + c, err := cli.New( + cli.WithCommandName("kubebuilder"), + cli.WithVersion(versionString()), + cli.WithCliVersion(getKubebuilderVersion()), + cli.WithPlugins( + golangv4.Plugin{}, + gov4Bundle, + &kustomizecommonv2.Plugin{}, + &deployimagev1alpha1.Plugin{}, + &grafanav1alpha.Plugin{}, + &helmv1alpha.Plugin{}, + &helmv2alpha.Plugin{}, + &autoupdatev1alpha.Plugin{}, + ), + cli.WithPlugins(externalPlugins...), + cli.WithDefaultPlugins(cfgv3.Version, gov4Bundle), + cli.WithDefaultProjectVersion(cfgv3.Version), + cli.WithCompletion(), + ) + if err != nil { + slog.Error("failed to create CLI", "error", err) + os.Exit(1) + } + if err := c.Run(); err != nil { + slog.Error("CLI run failed", "error", err) + os.Exit(1) + } +} diff --git a/cmd/main.go b/cmd/main.go deleted file mode 100644 index 7dc5d59d92e..00000000000 --- a/cmd/main.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 ( - "log" - - "github.com/sirupsen/logrus" - "github.com/spf13/afero" - "sigs.k8s.io/kubebuilder/v3/pkg/cli" - cfgv2 "sigs.k8s.io/kubebuilder/v3/pkg/config/v2" - cfgv3 "sigs.k8s.io/kubebuilder/v3/pkg/config/v3" - "sigs.k8s.io/kubebuilder/v3/pkg/machinery" - "sigs.k8s.io/kubebuilder/v3/pkg/model/stage" - "sigs.k8s.io/kubebuilder/v3/pkg/plugin" - kustomizecommonv1 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/common/kustomize/v1" - kustomizecommonv2alpha "sigs.k8s.io/kubebuilder/v3/pkg/plugins/common/kustomize/v2-alpha" - "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang" - declarativev1 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/declarative/v1" - deployimagev1alpha1 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/deploy-image/v1alpha1" - golangv2 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/v2" - golangv3 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/v3" - grafanav1alpha1 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/optional/grafana/v1alpha" -) - -func main() { - - // Bundle plugin which built the golang projects scaffold by Kubebuilder go/v3 - gov3Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 3}, - kustomizecommonv1.Plugin{}, - golangv3.Plugin{}, - ) - // Bundle plugin which built the golang projects scaffold by Kubebuilder go/v3 with kustomize alpha-v2 - gov4Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 4, Stage: stage.Alpha}, - kustomizecommonv2alpha.Plugin{}, - golangv3.Plugin{}, - ) - - fs := machinery.Filesystem{ - FS: afero.NewOsFs(), - } - externalPlugins, err := cli.DiscoverExternalPlugins(fs.FS) - if err != nil { - logrus.Error(err) - } - - c, err := cli.New( - cli.WithCommandName("kubebuilder"), - cli.WithVersion(versionString()), - cli.WithPlugins( - golangv2.Plugin{}, - golangv3.Plugin{}, - gov3Bundle, - gov4Bundle, - &kustomizecommonv1.Plugin{}, - &kustomizecommonv2alpha.Plugin{}, - &declarativev1.Plugin{}, - &deployimagev1alpha1.Plugin{}, - &grafanav1alpha1.Plugin{}, - ), - cli.WithPlugins(externalPlugins...), - cli.WithDefaultPlugins(cfgv2.Version, golangv2.Plugin{}), - cli.WithDefaultPlugins(cfgv3.Version, gov3Bundle), - cli.WithDefaultProjectVersion(cfgv3.Version), - cli.WithCompletion(), - ) - if err != nil { - log.Fatal(err) - } - if err := c.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/cmd/version.go b/cmd/version.go index 7c37c5f2bcd..0f26a98c3b5 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -14,19 +14,35 @@ See the License for the specific language governing permissions and limitations under the License. */ -package main +package cmd import ( "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" + "runtime/debug" + "strconv" + "strings" + "time" + + "golang.org/x/mod/semver" +) + +const ( + unknown = "unknown" + develVersion = "(devel)" + pseudoVersionTimestampLayout = "20060102150405" ) // var needs to be used instead of const as ldflags is used to fill this // information in the release process var ( - kubeBuilderVersion = "unknown" - kubernetesVendorVersion = "unknown" - goos = "unknown" - goarch = "unknown" + kubeBuilderVersion = unknown + kubernetesVendorVersion = "1.34.1" + goos = unknown + goarch = unknown gitCommit = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD) buildDate = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') @@ -42,8 +58,10 @@ type version struct { GoArch string `json:"goArch"` } -// versionString returns the CLI version +// versionString returns the Full CLI version func versionString() string { + kubeBuilderVersion = getKubebuilderVersion() + return fmt.Sprintf("Version: %#v", version{ kubeBuilderVersion, kubernetesVendorVersion, @@ -53,3 +71,190 @@ func versionString() string { goarch, }) } + +// getKubebuilderVersion returns only the CLI version string +func getKubebuilderVersion() string { + if strings.Contains(kubeBuilderVersion, "dirty") { + return develVersion + } + if shouldResolveVersion(kubeBuilderVersion) { + kubeBuilderVersion = resolveKubebuilderVersion() + } + return kubeBuilderVersion +} + +func shouldResolveVersion(v string) bool { + return v == "" || v == unknown || v == develVersion +} + +func resolveKubebuilderVersion() string { + if info, ok := debug.ReadBuildInfo(); ok { + if info.Main.Sum == "" { + return develVersion + } + mainVersion := strings.TrimSpace(info.Main.Version) + if mainVersion != "" && mainVersion != develVersion { + return mainVersion + } + + if v := pseudoVersionFromGit(info.Main.Path); v != "" { + return v + } + } + + if v := pseudoVersionFromGit(""); v != "" { + return v + } + + return unknown +} + +func pseudoVersionFromGit(modulePath string) string { + repoRoot, err := findRepoRoot() + if err != nil { + return "" + } + return pseudoVersionFromGitDir(modulePath, repoRoot) +} + +func pseudoVersionFromGitDir(modulePath, repoRoot string) string { + dirty, err := repoDirty(repoRoot) + if err != nil { + return "" + } + if dirty { + return develVersion + } + + commitHash, err := runGitCommand(repoRoot, "rev-parse", "--short=12", "HEAD") + if err != nil || commitHash == "" { + return "" + } + + commitTimestamp, err := runGitCommand(repoRoot, "show", "-s", "--format=%ct", "HEAD") + if err != nil || commitTimestamp == "" { + return "" + } + seconds, err := strconv.ParseInt(commitTimestamp, 10, 64) + if err != nil { + return "" + } + timestamp := time.Unix(seconds, 0).UTC().Format(pseudoVersionTimestampLayout) + + if tag, err := runGitCommand(repoRoot, "describe", "--tags", "--exact-match"); err == nil { + tag = strings.TrimSpace(tag) + if tag != "" { + return tag + } + } + + if baseTag, err := runGitCommand(repoRoot, "describe", "--tags", "--abbrev=0"); err == nil { + baseTag = strings.TrimSpace(baseTag) + if semver.IsValid(baseTag) { + if next := incrementPatch(baseTag); next != "" { + return fmt.Sprintf("%s-0.%s-%s", next, timestamp, commitHash) + } + } + if baseTag != "" { + return baseTag + } + } + + major := moduleMajorVersion(modulePath) + return buildDefaultPseudoVersion(major, timestamp, commitHash) +} + +func repoDirty(repoRoot string) (bool, error) { + status, err := runGitCommand(repoRoot, "status", "--porcelain", "--untracked-files=no") + if err != nil { + return false, err + } + return status != "", nil +} + +func incrementPatch(tag string) string { + trimmed := strings.TrimPrefix(tag, "v") + trimmed = strings.SplitN(trimmed, "-", 2)[0] + parts := strings.Split(trimmed, ".") + if len(parts) < 3 { + return "" + } + major, err := strconv.Atoi(parts[0]) + if err != nil { + return "" + } + minor, err := strconv.Atoi(parts[1]) + if err != nil { + return "" + } + patch, err := strconv.Atoi(parts[2]) + if err != nil { + return "" + } + patch++ + return fmt.Sprintf("v%d.%d.%d", major, minor, patch) +} + +func buildDefaultPseudoVersion(major int, timestamp, commitHash string) string { + if major < 0 { + major = 0 + } + return fmt.Sprintf("v%d.0.0-%s-%s", major, timestamp, commitHash) +} + +func moduleMajorVersion(modulePath string) int { + if modulePath == "" { + return 0 + } + lastSlash := strings.LastIndex(modulePath, "/v") + if lastSlash == -1 || lastSlash == len(modulePath)-2 { + return 0 + } + majorStr := modulePath[lastSlash+2:] + if strings.Contains(majorStr, "/") { + majorStr = majorStr[:strings.Index(majorStr, "/")] + } + major, err := strconv.Atoi(majorStr) + if err != nil { + return 0 + } + return major +} + +func findRepoRoot() (string, error) { + _, currentFile, _, ok := runtime.Caller(0) + if !ok { + return "", fmt.Errorf("failed to determine caller") + } + + if !filepath.IsAbs(currentFile) { + abs, err := filepath.Abs(currentFile) + if err != nil { + return "", fmt.Errorf("getting absolute path: %w", err) + } + currentFile = abs + } + + dir := filepath.Dir(currentFile) + for { + if dir == "" || dir == filepath.Dir(dir) { + return "", fmt.Errorf("git repository root not found from %s", currentFile) + } + + if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil { + return dir, nil + } + dir = filepath.Dir(dir) + } +} + +func runGitCommand(dir string, args ...string) (string, error) { + cmd := exec.Command("git", args...) + cmd.Dir = dir + cmd.Env = append(os.Environ(), "LC_ALL=C", "LANG=C") + output, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("running git %v: %w", args, err) + } + return strings.TrimSpace(string(output)), nil +} diff --git a/cmd/version_test.go b/cmd/version_test.go new file mode 100644 index 00000000000..dc86477729e --- /dev/null +++ b/cmd/version_test.go @@ -0,0 +1,148 @@ +/* +Copyright 2025 The Kubernetes 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 ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "testing" + "time" +) + +func TestPseudoVersionFromGitDirExactTag(t *testing.T) { + repo := initGitRepo(t) + + if _, err := runGitCommand(repo, "tag", "v1.2.3"); err != nil { + t.Fatalf("tagging repo: %v", err) + } + + version := pseudoVersionFromGitDir("example.com/module/v1", repo) + if version != "v1.2.3" { + t.Fatalf("expected tag version, got %q", version) + } +} + +func TestPseudoVersionFromGitDirAfterTag(t *testing.T) { + repo := initGitRepo(t) + + if _, err := runGitCommand(repo, "tag", "v1.2.3"); err != nil { + t.Fatalf("tagging repo: %v", err) + } + createCommit(t, repo, "second file", "second change") + + version := pseudoVersionFromGitDir("example.com/module/v1", repo) + if version == "" { + t.Fatalf("expected pseudo version, got empty string") + } + + hash, err := runGitCommand(repo, "rev-parse", "--short=12", "HEAD") + if err != nil { + t.Fatalf("retrieving hash: %v", err) + } + timestampStr, err := runGitCommand(repo, "show", "-s", "--format=%ct", "HEAD") + if err != nil { + t.Fatalf("retrieving timestamp: %v", err) + } + seconds, err := strconv.ParseInt(timestampStr, 10, 64) + if err != nil { + t.Fatalf("parsing timestamp: %v", err) + } + expected := fmt.Sprintf("v1.2.4-0.%s-%s", time.Unix(seconds, 0).UTC().Format(pseudoVersionTimestampLayout), hash) + if version != expected { + t.Fatalf("expected %q, got %q", expected, version) + } +} + +func TestPseudoVersionFromGitDirDirty(t *testing.T) { + repo := initGitRepo(t) + + if _, err := runGitCommand(repo, "tag", "v1.2.3"); err != nil { + t.Fatalf("tagging repo: %v", err) + } + createCommit(t, repo, "second file", "second change") + + targetFile := filepath.Join(repo, "tracked.txt") + if err := os.WriteFile(targetFile, []byte("dirty change\n"), 0o644); err != nil { + t.Fatalf("creating dirty file: %v", err) + } + + version := pseudoVersionFromGitDir("example.com/module/v1", repo) + if version != develVersion { + t.Fatalf("expected %q for dirty repo, got %q", develVersion, version) + } +} + +func TestPseudoVersionFromGitDirWithoutTag(t *testing.T) { + repo := initGitRepo(t) + version := pseudoVersionFromGitDir("example.com/module/v4", repo) + if !strings.HasPrefix(version, "v4.0.0-") { + t.Fatalf("expected prefix v4.0.0-, got %q", version) + } +} + +func TestGetKubebuilderVersionDirtyString(t *testing.T) { + t.Cleanup(func() { kubeBuilderVersion = unknown }) + kubeBuilderVersion = "v1.2.3+dirty" + if got := getKubebuilderVersion(); got != develVersion { + t.Fatalf("expected %q, got %q", develVersion, got) + } +} + +func initGitRepo(t *testing.T) string { + t.Helper() + + dir := t.TempDir() + + commands := [][]string{ + {"init"}, + {"config", "user.email", "dev@kubebuilder.test"}, + {"config", "user.name", "Kubebuilder Dev"}, + } + for _, args := range commands { + if _, err := runGitCommand(dir, args...); err != nil { + t.Fatalf("initializing repo (%v): %v", args, err) + } + } + + createCommit(t, dir, "tracked.txt", "initial") + return dir +} + +func createCommit(t *testing.T, repo, file, content string) { + t.Helper() + + if err := os.WriteFile(filepath.Join(repo, file), []byte(content+"\n"), 0o644); err != nil { + t.Fatalf("writing file: %v", err) + } + if _, err := runGitCommand(repo, "add", file); err != nil { + t.Fatalf("git add: %v", err) + } + commitEnv := append(os.Environ(), + "GIT_COMMITTER_DATE=2006-01-02T15:04:05Z", + "GIT_AUTHOR_DATE=2006-01-02T15:04:05Z", + ) + cmd := exec.Command("git", "commit", "-m", fmt.Sprintf("commit %s", file)) + cmd.Dir = repo + cmd.Env = append(commitEnv, "LC_ALL=C", "LANG=C") + if output, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("git commit: %v: %s", err, output) + } +} diff --git a/designs/README.md b/designs/README.md index 13750b3ca9d..fbeac49abe5 100644 --- a/designs/README.md +++ b/designs/README.md @@ -30,7 +30,7 @@ why things changed. For example: # Out of Date -This change is out of date. It turns out curly braces a frustrating to +This change is out of date. It turns out curly braces are frustrating to type, so we had to abandon functions entirely, and have users specify custom functionality using strings of Common LISP instead. See #000 for more information. diff --git a/designs/code-generate-image-plugin.md b/designs/code-generate-image-plugin.md index a2cafabc65c..9c512e9d050 100644 --- a/designs/code-generate-image-plugin.md +++ b/designs/code-generate-image-plugin.md @@ -1,64 +1,55 @@ ---- -title: Neat-Enhancement-Idea -authors: - - "@camilamacedo86" -reviewers: - - TBD -approvers: - - TBD -creation-date: 2020-11-09 -last-updated: 2021-02-14 -status: implementable ---- +| Authors | Creation Date | Status | Extra | +|---------------|---------------|-------------|---| +| @camilamacedo86 | 2021-02-14 | Implemented | [deploy-image-plugin-v1-alpha](../docs/book/src/plugins/available/deploy-image-plugin-v1-alpha.md) | # New Plugin (`deploy-image.go.kubebuilder.io/v1beta1`) to generate code ## Summary -This proposal defines a new plugin which allow users get the scaffold with the +This proposal defines a new plugin that allows users to get the scaffold with the required code to have a project that will deploy and manage an image on the cluster following the guidelines and what have been considered as good practices. - + ## Motivation -The biggest part of the Kubebuilder users looking for to create a project that will at the end only deploy an image. In this way, one of the mainly motivations of this proposal is to abstract the complexities to achieve this goal and still giving the possibility of users improve and customize their projects according to their requirements. +The biggest part of the Kubebuilder users looking for to create a project that will at the end only deploy an image. In this way, one of the mainly motivations of this proposal is to abstract the complexities to achieve this goal and still giving the possibility of users improve and customize their projects according to their requirements. **Note:** This plugin will address requests that has been raised for a while and for many users in the community. Check [here](https://github.com/operator-framework/operator-sdk/pull/2158), for example, a request done in the past for the SDK project which is integrated with Kubebuidler to address the same need. ### Goals - Add a new plugin to generate the code required to deploy and manage an image on the cluster -- Promote the best practices as give example of common implementations -- Make the process to develop operators projects easier and more agil. +- Promote the best practices by giving examples of common implementations +- Make the process of developing operator's projects easier and more agile. - Give flexibility to the users and allow them to change the code according to their needs -- Provide examples of code implementations and of the most common features usage and reduce the learning curve - +- Provide examples of code implementations and of the usage of the most common features and reduce the learning curve + ### Non-Goals -The idea of this proposal is provide a facility for the users. This plugin can be improved +The idea of this proposal is to provide a facility for the users. This plugin can be improved in the future, however, this proposal just covers the basic requirements. In this way, is a non-goal -allow extra configurations such as; scaffold the project using webhooks and the controller covered by tests. +allow extra configurations such as; scaffolding the project using webhooks and the controller covered by tests. ## Proposal -Add the new plugin code generate which will scaffold code implementation to deploy the image informed which would like such as; `kubebuilder create api --group=crew --version=v1 --image=myexample:0.0.1 --kind=App --plugins=deploy-image.go.kubebuilder.io/v1beta1` which will: +Add the new plugin code generated which will scaffold code implementation to deploy the image informed which would like such as; `kubebuilder create api --group=crew --version=v1 --image=myexample:0.0.1 --kind=App --plugins=deploy-image.go.kubebuilder.io/v1beta1` which will: -- Add a code implementation which will do the Custom Resource reconciliation and create a Deployment resource for the `--image`; +- Add a code implementation that will do the Custom Resource reconciliation and create a Deployment resource for the `--image`; -- Add an EnvVar on the manager manifest (`config/manager/manager.yaml`) which will store the image informed and shows its possibility to users: +- Add an EnvVar on the manager manifest (`config/manager/manager.yaml`) which will store the image informed and show its possibility to users: ```yaml - .. + .. spec: containers: - name: manager env: - - name: {{ resource}}-IMAGE + - name: {{ resource}}-IMAGE value: {{image:tag}} image: controller:latest ... ``` -- Add a check into reconcile to ensure that the replicas of the deployment on cluster are equals the size defined in the CR: +- Add a check into reconcile to ensure that the replicas of the deployment on the cluster are equal the size defined in the CR: ```go // Ensure the deployment size is the same as the spec @@ -75,9 +66,9 @@ Add the new plugin code generate which will scaffold code implementation to depl } ``` -- Add the watch feature for the Deployment managed by the controller: +- Add the watch feature for the Deployment managed by the controller: -```go +```go func (r *{{ resource }}Reconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&cachev1alpha1.{{ resource }}{}). @@ -92,23 +83,23 @@ func (r *{{ resource }}Reconciler) SetupWithManager(mgr ctrl.Manager) error { // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete ``` -- A status [conditions][conditions] to allow users check that if the deployment occurred successfully or its errors +- A status [conditions][conditions] to allow users to check if the deployment occurred successfully or if its errors - Add a [marker][markers] in the spec definition to demonstrate how to use OpenAPI schemas validation such as `+kubebuilder:validation:Minimum=1` -- Add the specs on the `_types.go` to generate the CRD/CR sample with default values for `ImagePullPolicy` (`Always`), `ContainerPort` (`80`) and the `Replicas Size` (`3`) +- Add the specs on the `_types.go` to generate the CRD/CR sample with default values for `ImagePullPolicy` (`Always`), `ContainerPort` (`80`) and the `Replicas Size` (`3`) + +- Add a finalizer implementation with TODO for the CR managed by the controller such as described in the SDK doc [Handle Cleanup on Deletion](https://sdk.operatorframework.io/docs/building-operators/golang/advanced-topics/#handle-cleanup-on-deletion) -- Add a finalizer implementation with TODO for the CR managed by the controller such as described in the SDK doc [Handle Cleanup on Deletion](https://sdk.operatorframework.io/docs/building-operators/golang/advanced-topics/#handle-cleanup-on-deletion) - ### User Stories -- I am as user, would like to use a command to scaffold my common need which is deploy an image of my application, so that I do not need to know exactly how to implement it +- I am a user, who would like to use a command to scaffold my common need which is to deploy an image of my application, so that I do not need to know exactly how to implement it -- I am as user, would like to have a good example code base which uses the common features, so that I can easily learn its concepts and have a good start point to address my needs. +- I am a user, would like to have a good example code base that uses the common features so that I can easily learn its concepts and have a good starting point to address my needs. - I am as maintainer, would like to have a good example to address the common questions, so that I can easily describe how to implement the projects and/or use the common features. - -### Implementation Details/Notes/Constraints + +### Implementation Details/Notes/Constraints **Example of the controller template** @@ -169,9 +160,9 @@ func (r *{{ resource }}.Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, er // Spec updated - return and requeue return ctrl.Result{Requeue: true}, nil } - + // TODO: add here code implementation to update/manage the status - + return ctrl.Result{}, nil } @@ -223,7 +214,7 @@ func labelsFor{{ resource }}(name string) map[string]string { // imageFor{{ resource }} returns the image for the resources // belonging to the given {{ resource }} CR name. func imageFor{{ resource }}(name string) string { - // TODO: this method will return the value of the envvar create to store the image:tag informed + // TODO: this method will return the value of the envvar create to store the image:tag informed } func (r *{{ resource }}Reconciler) SetupWithManager(mgr ctrl.Manager) error { @@ -233,7 +224,7 @@ func (r *{{ resource }}Reconciler) SetupWithManager(mgr ctrl.Manager) error { Complete(r) } -``` +``` **Example of the spec for the _types.go template** @@ -250,7 +241,7 @@ type {{ resource }}Spec struct { // ImagePullPolicy defines the policy to pull the container images ImagePullPolicy string `json:"image-pull-policy,omitempty"` - // ContainerPort specifies the port which will be used by the image container + // ContainerPort specifies the port which will be used by the image container ContainerPort int `json:"container-port,omitempty"` } @@ -260,12 +251,12 @@ type {{ resource }}Spec struct { ### Test Plan -To ensure this implementation a new project example should be generated in the [testdata](../testdata/) directory of the project. See the [test/testadata/generate.sh](../test/testadata/generate.sh). Also, we should use this scaffold in the [integration tests](../test/e2e/) to ensure that the data scaffolded with works on the cluster as expected. +To ensure this implementation a new project example should be generated in the [testdata](../testdata/) directory of the project. See the [test/testdata/generate.sh](../test/testadata/generate.sh). Also, we should use this scaffold in the [integration tests](../test/e2e/) to ensure that the data scaffold works on the cluster as expected. ### Graduation Criteria -- The new plugin will only be support `project-version=3` -- The attribute image with the value informed should be added to the resources model in the PROJECT file to let the tool know that the Resource get done with the common basic code implementation: +- The new plugin will only support `project-version=3` +- The attribute image with the value informed should be added to the resources model in the PROJECT file to let the tool know that the Resource gets done with the common basic code implementation: ```yaml plugins: @@ -276,34 +267,34 @@ plugins: kind: Captain version: v1 image: "/: -``` +``` -For further information check the definition agreement register in the comment https://github.com/kubernetes-sigs/kubebuilder/issues/1941#issuecomment-778649947. +For further information check the definition agreement register in the comment https://github.com/kubernetes-sigs/kubebuilder/issues/1941#issuecomment-778649947. -## Open Questions +## Open Questions -1. Should we allow to scaffold the code for an API that is already created for the project? -No, at least in the first moment to keep the simplicity. +1. Should we allow to scaffold the code for an API that is already created for the project? +No, at least in the first moment to keep the simplicity. 2. Should we support StatefulSet and Deployments? The idea is we start it by using a Deployment. However, we can improve the feature in follow-ups to support more default types of scaffolds which could be like `kubebuilder create api --group=crew --version=v1 --image=myexample:0.0.1 --kind=App --plugins=deploy-image.go.kubebuilder.io/v1beta1 --type=[deployment|statefulset|webhook]` -3. Could this feature be useful to other languages or is it just valid to Go based operators? +3. Could this feature be useful to other languages or is it just valid to Go-based operators? -This plugin would is reponsable to scaffold content and files for Go-based operators. In a future, if other language-based operators starts to be supported (either officially or by the community) this plugin could be used as reference to create an equivalent one for their languages. Therefore, it should probably not to be a `subdomain` of `go.kubebuilder.io.` +This plugin would is reponsable to scaffold content and files for Go-based operators. In a future, if other language-based operators starts to be supported (either officially or by the community) this plugin could be used as reference to create an equivalent one for their languages. Therefore, it should probably not to be a `subdomain` of `go.kubebuilder.io.` -For its integration with SDK, it might be valid for the Ansible-based operators where a new `playbook/role` could be generated as well. However, for example, for the Helm plugin it might to be useless. E.g `deploy-image.ansible.sdk.operatorframework.io/v1beta1` +For its integration with SDK, it might be valid for the Ansible-based operators where a new `playbook/role` could be generated as well. However, for example,for the Helm plugin, it might be useless. E.g `deploy-image.ansible.sdk.operatorframework.io/v1beta1` -4. Should we consider create a separate repo for plugins? +4. Should we consider creating a separate repo for plugins? -In the long term yes. However, see that currently, Kubebuilder has not too many plugins yet. And then, and the preliminary support for plugins did not indeed release. For more info see the [Extensible CLI and Scaffolding Plugins][plugins-phase1-design-doc]. +In the long term yes. However, see that currently, Kubebuilder does not have too many plugins yet. And then, the preliminary support for plugins was not indeed released. For more info see the [Extensible CLI and Scaffolding Plugins][plugins-phase1-design-doc]. -In this way, at this moment, it shows to be a little Premature Optimization. Note that the issue [#2016](https://github.com/kubernetes-sigs/kubebuilder/issues/1378) will check the possibility of the plugins be as separate binaries that can be discovered by the Kubebuilder CLI binary via user-specified plugin file paths. Then, the discussion over the best approach to dealing with many plugins and if they should or not leave in the Kubebuilder repository would be better addressed after that. +In this way, at this moment, it shows to be a little Premature Optimization. Note that the issue [#2016](https://github.com/kubernetes-sigs/kubebuilder/issues/1378) will check the possibility of the plugins be as separate binaries that can be discovered by the Kubebuilder CLI binary via user-specified plugin file paths. Then, the discussion over the best approach to dealing with many plugins and if they should or not leave in the Kubebuilder repository would be better addressed after that. -5. Is Kubebuilder prepared to receive this implementation already? +5. Is Kubebuilder prepared to receive this implementation already? -The [Extensible CLI and Scaffolding Plugins - Phase 1.5](extensible-cli-and-scaffolding-plugins-phase-1-5.md) and the issue #1941 requires to be implemented before this proposal. Also, to have a better idea over the proposed solutions made so for the Plugin Ecosystem see the meta issue [#2016](https://github.com/kubernetes-sigs/kubebuilder/issues/2016) +The [Extensible CLI and Scaffolding Plugins - Phase 1.5](extensible-cli-and-scaffolding-plugins-phase-1-5.md) and issue #1941 are required to be implemented before this proposal. Also, to have a better idea of the proposed solutions made so for the Plugin Ecosystem see the meta issue [#2016](https://github.com/kubernetes-sigs/kubebuilder/issues/2016) -[markers]: ../docs/book/src/reference/markers.md +[markers]: ../docs/book/src/reference/markers.md [conditions]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties -[plugins-phase1-design-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/extensible-cli-and-scaffolding-plugins-phase-1.md \ No newline at end of file +[plugins-phase1-design-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/extensible-cli-and-scaffolding-plugins-phase-1.md diff --git a/designs/crd_version_conversion.md b/designs/crd_version_conversion.md index 3bb0d748550..8176e024cde 100644 --- a/designs/crd_version_conversion.md +++ b/designs/crd_version_conversion.md @@ -1,7 +1,8 @@ -# API Versioning in Kubebuilder +| Authors | Creation Date | Status | Extra | +|---------------|---------------|-------------|-------| +| @droot | 01/30/2019| implementable | - | -Authors: @droot -Last Updated on: 01/30/2019 +# API Versioning in Kubebuilder This document describes high level design and workflow for supporting multiple versions in an API built using Kubebuilder. Multi-version support was added as an alpha feature in kubernetes project in 1.13 release. Here are links to some recommended reading material. @@ -19,7 +20,7 @@ This document describes high level design and workflow for supporting multiple v ## Hub and Spoke -The basic concept is that all versions of an object share the storage. So say if you have versions v1, v2 and v3 of a Kind Toy, kubernetes will use one of the versions to persist the object in stable storage i.e. Etcd. User can specify the version to be used for storage in the Custom Resource definition for that API. +The basic concept is that all versions of an object share the storage. So say if you have versions v1, v2 and v3 of a Kind Toy, kubernetes will use one of the versions to persist the object in stable storage i.e. Etcd. User can specify the version to be used for storage in the Custom Resource definition for that API. One can think storage version as the hub and other versions as spoke to visualize the relationship between storage and other versions (as shown below in the diagram). The key thing to note is that conversion between storage and other version should be lossless (round trippable). As shown in the diagram below, v3 is the storage/hub version and v1, v2 and v4 are spoke version. The document uses storage version and hub interchangeably. @@ -57,7 +58,7 @@ func (ej *ExternalJob) ConvertTo(dst conversion.Hub) error { jobv3 := dst.(*v3.ExternalJob) jobv3.ObjectMeta = ej.ObjectMeta // conversion implementation - // + // return nil default: return fmt.Errorf("unsupported type %v", t) @@ -157,12 +158,12 @@ func (ch *conversionHandler) convertObject(src, dst runtime.Object) error { err = src.(conversion.Convertible).ConvertTo(hub) if err != nil { - return fmt.Errorf("%T failed to convert to hub version %T : %v", src, hub, err) + return fmt.Errorf("%T failed to convert to hub version %T : %w", src, hub, err) } err = dst.(conversion.Convertible).ConvertFrom(hub) if err != nil { - return fmt.Errorf("%T failed to convert from hub version %T : %v", dst, hub, err) + return fmt.Errorf("%T failed to convert from hub version %T : %w", dst, hub, err) } return nil } @@ -180,7 +181,7 @@ The tool that generates the CRD manifests lives under controller-tools repo. Cur ## Storage/Serve annotations: -The resource annotation will be extended to indicate storage/serve attributes as shown below. +The resource annotation will be extended to indicate storage/serve attributes as shown below. ```Go // ... diff --git a/designs/discontinue_usage_of_kube_rbac_proxy.md b/designs/discontinue_usage_of_kube_rbac_proxy.md new file mode 100644 index 00000000000..b4efa6b41d3 --- /dev/null +++ b/designs/discontinue_usage_of_kube_rbac_proxy.md @@ -0,0 +1,354 @@ +| Authors | Creation Date | Status | Extra | +|-----------------|---------------|---------------|-------| +| @camilamacedo86 | 07/04/2024 | Implementable | - | + +# Discontinue Kube RBAC Proxy in Default Kubebuilder Scaffolding + +This proposal highlights the need to reassess the usage of [kube-rbac-proxy](https://github.com/brancz/kube-rbac-proxy) +in the default scaffold due to the evolving k8s infra and community feedback. Key considerations include the transition to a shared infrastructure requiring +all images to be published on [registry.k8s.io][registry.k8s.io], the deprecation +of Google Cloud Platform's [Container Registry](https://cloud.google.com/artifact-registry/docs/transition/prepare-gcr-shutdown), and the fact +that [kube-rbac-proxy][kube-rbac-proxy] is yet to be part of the Kubernetes ecosystem umbrella. + +The dependency on a potentially discontinuable Google infrastructure, +**which is out of our control**, paired with the challenges of maintaining, +building, or promoting [kube-rbac-proxy][kube-rbac-proxy] images, +calls for a change. + +In this document is proposed to replace the [kube-rbac-proxy][kube-rbac-proxy] within +[Network Policies][k8s-doc-networkpolicies] follow-up for potentially enhancements +to protect the metrics endpoint combined with [cert-manager][cert-manager] and a new +a feature introduced in controller-runtime, see [here][cr-pr]. + +**For the future (when kube-rbac-proxy be part of the k8s umbrella)**, it is proposed the usage of the +[Plugins API provided by Kubebuilder](./../docs/book/src/plugins/plugins.md), +to create an [external plugin](./../docs/book/src/plugins/creating-plugins.md) +to properly integrate the solution with Kubebuilder and provide a helper to allow users to opt-in as they please them. + +## Open Questions + +- 1) [Network Policies][k8s-doc-networkpolicies] is implemented by the cluster’s CNI. Are we confident that all the major CNIs in use support the proposed policy? + +> Besides [Network Policies][k8s-doc-networkpolicies] being part of the core Kubernetes API, their enforcement relies on the CNI plugin installed in +the Kubernetes cluster. While support and implementation details vary among CNIs, the most commonly used ones, +such as Calico, Cilium, WeaveNet, and Canal, offer support for NetworkPolicies. +> +>Also, there was concern in the past because AWS did not support it. However, this changed, +>as detailed in their announcement: [Amazon VPC CNI now supports Kubernetes Network Policies](https://aws.amazon.com/blogs/containers/amazon-vpc-cni-now-supports-kubernetes-network-policies/). +> +>Moreover, under this proposal, users can still disable/enable this option as they please them. + +- 2) NetworkPolicy is a simple firewall and does not provide `authn/authz` and encryption. + +> Yes, that's correct. NetworkPolicy acts as a basic firewall for pods within a Kubernetes cluster, controlling traffic +> flow at the IP address or port level. However, it doesn't handle authentication (authn), authorization (authz), +> or encryption directly like kube-rbac-proxy solution. +> +> However, if we can combine the cert-manager and the new feature provided +> by controller-runtime, we can achieve the same or a superior level of protection +> without relying on any extra third-party dependency. + +- 3) Could not Kubebuilder maintainers use the shared infrastructure to continue building and promoting those images under the new `registry.k8s.io`? + +> We tried to do that, see [here](https://github.com/kubernetes/test-infra/blob/master/config/jobs/image-pushing/k8s-staging-kubebuilder.yaml) the recipe implemented. +> However, it does not work because kube-rbac-proxy is not under the +> kubernetes umbrella. Moreover, we experimented with the GitHub Repository as an alternative approach, see the [PR](https://github.com/kubernetes-sigs/kubebuilder/pull/3854) but seems +> that we are not allowed to use it. Nevertheless, neither approach sorts out all motivations and requirements +> Ideally, Kubebuilder should not be responsible for maintaining and promoting third-party artefacts. + +- 4) However, is not Kubebuilder also building and promoting the binaries required to be used within [EnvTest](./../docs/book/src/reference/envtest.md) +feature implemented in controller-runtime? + +> Yes, but it also will need to change. Controller-runtime maintainers are looking for solutions to +> build those binaries inside its project since it seems part of its domain. This change is likely +> to be transparent to the community users. + +- 5) Could we not use the Controller-Runtime feature [controller-runtime][cr-pr] which enable secure metrics serving over HTTPS? + +Yes, after some changes are addressed. After we ask for a hand for reviews from skilled auth maintainers and receive feedback, it appears that this configuration needs to +align with best practices. See the [issue](https://github.com/kubernetes-sigs/controller-runtime/issues/2781) +raised to track this need. + +- 6) Could we not make [cert-manager][cert-manager] mandatory? + +> No, we can not. One of the goals of Kubebuilder is to make it easier for new +users. So, we cannot make mandatory the usage of a third party as cert-manager +for users by default and to only quick-start. +> +> However, we can make mandatory the usage of +[cert-manager][cert-manager] for some specific features like use kube-rbac-proxy +or, as it is today, using webhooks, a more advanced and optional option. + +## Summary + +Starting with release `3.15.0`, Kubebuilder will no longer scaffold +new projects with [kube-rbac-proxy][kube-rbac-proxy]. +Existing users are encouraged to switch to images hosted by the project +on [quay.io](https://quay.io/repository/brancz/kube-rbac-proxy?tab=tags&tag=latest) **OR** +to adapt their projects to utilize [Network Policies][k8s-doc-networkpolicies], following the updated scaffold guidelines. + +For project updates, users can manually review scaffold changes or utilize the +provided [upgrade assistance helper](https://book.kubebuilder.io/reference/rescaffold). + +Communications and guidelines would be provided along with the release. + +## Motivation + +- **Infrastructure Reliability Concerns**: Kubebuilder’s reliance on Google's infrastructure, which may be discontinued +at their discretion, poses a risk to image availability and project reliability. [Discussion thread](https://kubernetes.slack.com/archives/CCK68P2Q2/p1711914533693319?thread_ts=1711913605.487359&cid=CCK68P2Q2) and issues: https://github.com/kubernetes/k8s.io/issues/2647 and https://github.com/kubernetes-sigs/kubebuilder/issues/3230 +- **Registry Changes and Image Availability**: The transition from `gcr.io` to [registry.k8s.io][registry.k8s.io] and +the [Container Registry][container-registry-dep] deprecation implies that **all** images provided so far by Kubebuilder +[here][kb-images-repo] will unassailable by **April 22, 2025**. [More info][container-registry-dep] and [slack ETA thread][slack-eta-thread] +- **Security and Endorsement Concerns**: [kube-rbac-proxy][kube-rbac-proxy] is a process to be part of +auth-sig for an extended period, however, it is not there yet. The Kubernetes Auth SIG’s review reveals that kube-rbac-proxy +must undergo significant updates to secure an official endorsement and to be supported, highlighting pressing concerns. +You can check the ongoing process and changes required by looking at the [project issue](https://github.com/brancz/kube-rbac-proxy/issues/238) +- **Evolving User Requirements and Deprecations**: The anticipated requirement for certificate management, potentially +necessitating cert-manager, underlines Kubebuilder's aim to simplify setup and reduce third-party dependencies. [More info, see issue #3524](https://github.com/kubernetes-sigs/kubebuilder/issues/3524) +- **Aim for a Transparent and Collaborative Infrastructure**: As an open-source project, Kubebuilder strives for +a community-transparent infrastructure that allows broader contributions. This goal aligns with our initiative +to migrate Kubebuilder CLI release builds from GCP to GitHub Actions and using Go-Releaser see [here](./../build/.goreleaser.yml), +or promoting infrastructure managed under the k8s-infra umbrella. +- **Community Feedback**: Some community members preferred its removal from the default scaffolding. [Issue 3482](https://github.com/kubernetes-sigs/kubebuilder/issues/3482) +- **Enhancing Service Monitor with Proper TLS/Certificate Usage Requested by Community:** [Issue #3657](https://github.com/kubernetes-sigs/kubebuilder/issues/3657). It is achievable with [kube-rbac-proxy][kube-rbac-proxy] OR [Network Policies][k8s-doc-networkpolicies] usage within [cert-manager][cert-manager]. + +### Goals + +- **Maximize Protection for the Metrics Endpoint without relay in third-part(s)**: Aim to provide the highest level of +protection achievable for the metrics endpoint without relying on new third-party dependencies or the need to build +and promote images from other projects. +- **Avoid Breaking Changes**: Ensure that users who generated projects with previous versions can still use the +new version with scaffold changes and adapt their project at their convenience. +- **Sustainable Project Maintenance**: Ensure all projects scaffolded by Kubebuilder can be +maintained and supported by its maintainers. +- **Independence from Google Cloud Platform**: Move away from reliance on Google Cloud Platform, +considering the potential for unilateral shutdowns. +- **Kubernetes Umbrella Compliance**: Cease the promotion or endorsement of solutions +not yet endorsed by the Kubernetes umbrella organization, mainly when used and shipped with the workload. +- **Promote Use of External Plugins**: Adhere to Kubebuilder's directive to avoid direct third-party +integrations, favouring the support of projects through the Kubebuilder API and [external plugins][external-plugins]. +This approach empowers users to add or integrate solutions with the Kubebuilder scaffold on their own, ensuring that +third-party project maintainers—who are more familiar with their solutions—can maintain and update +their integrations, as implementing it following the best practices to use their project, enhancing the user experience. +External plugins should reside within third-party repository solutions and remain up-to-date as part of those changes, +aligning with their domain of responsibility. +- **Flexible Network Policy Usage**: Allow users to opt-out of the default-enabled usage of [Network Policies][k8s-doc-networkpolicies] +if they prefer another solution, plan to deploy their solution with a vendor or use a CNI that does not support NetworkPolicies. + +### Non-Goals + +- **Replicate kube-rbac-proxy Features or Protection Level**: It is not a goal to provide the same features +or layer of protection as [kube-rbac-proxy][kube-rbac-proxy]. Since [Network Policies][k8s-doc-networkpolicies]operate differently +and do not offer the same kind of functionality as [kube-rbac-proxy][kube-rbac-proxy], achieving identical protection levels through +[Network Policies][k8s-doc-networkpolicies]alone is not feasible. + +However, incorporating NetworkPolicies, cert-manager, and/or the features introduced +in the [controller-runtime pull request #2407][cr-pr] we are mainly addressing the security concerns that +kube-rbac-proxy handles. + +## Proposal + +### Phase 1: Transition to network policies + +The immediate action outlined in this proposal is the replacement of [kube-rbac-proxy][kube-rbac-proxy] +with Kubernetes API NetworkPolicies. + +### Phase 2: Add Cert-Manager as an Optional option to be used with metrics + +Looking beyond the initial phase, this proposal envisions integrating cert-manager for TLS certificate management +and exploring synergies with new features in Controller Runtime, as demonstrated in [PR #2407](https://github.com/kubernetes-sigs/controller-runtime/pull/2407). + +These enhancements would introduce encrypted communication for metrics endpoints and potentially incorporate authentication mechanisms, +significantly elevating the security model employed by projects scaffolded by Kubebuilder. + +- **cert-manager**: Automates the management and issuance of TLS certificates, facilitating encrypted communication and, when configured with mTLS, adding a layer of authentication. + Currently, we leverage cert-manager when webhooks are scaffolded. So, the proposal idea would be to allow users to enable the cert-manager for the metrics such as those provided + and required for the webhook feature. However, it MUST be optional. One of the goals of Kubebuilder is to make it easier for new users. Therefore, new users should + not need to deal with cert-manager by default or have the need to install it to just a quick start. + +That would mean, in a follow-up to the [current open PR](https://github.com/kubernetes-sigs/kubebuilder/pull/3853) to address the above `phase 1 - Transition to NetworkPolices`, +we aim to introduce a configurable Kustomize patch that will enable patching the ServiceMonitor in `config/prometheus/monitor.yaml` and certificates similar to our +existing setup for webhooks. This enhancement will ensure more flexible deployment configurations and enhance the security +features of the service monitoring components. + +Currently, in the `config/default/`, we have implemented patches for cert-manager along with webhooks, as seen in +`config/default/kustomization.yaml` ([example](https://github.com/kubernetes-sigs/kubebuilder/blob/bd0876b8132ff66da12d8d8a0fdc701fde00f54b/docs/book/src/component-config-tutorial/testdata/project/config/default/kustomization.yaml#L51-L149)). +These patches handle annotations for the cert-manager CA injection across various configurations, like +ValidatingWebhookConfiguration, MutatingWebhookConfiguration, and CRDs. + +For the proposed enhancements, we need to integrate similar configurations for the ServiceMonitor. +This involves the creation of a patch file named `metrics_https_patch.yaml`, which will include +configurations necessary for enabling HTTPS for the ServiceMonitor. + +Here's an example of how this configuration might look: + +```sh +# [METRICS WITH HTTPS] To enable the ServiceMonitor using HTTPS, uncomment the following line +# Note that for this to work, you also need to ensure that cert-manager is enabled in your project +- path: metrics_https_patch.yaml +``` + +This patch should apply similar changes as the current webhook patches, +targeting necessary updates in the manifest to support HTTPS communication secured by +cert-manager certificates. + +Here is an example of how the `ServiceMonitor` configured to work with cert-manager might look: + +```yaml +# Prometheus Monitor Service (Metrics) with cert-manager +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: project-v4 + app.kubernetes.io/managed-by: kustomize + name: controller-manager-metrics-monitor + namespace: system + annotations: + cert-manager.io/inject-ca-from: $(NAMESPACE)/controller-manager-certificate +spec: + endpoints: + - path: /metrics + port: https + scheme: https + bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + tlsConfig: + # We should recommend ensure that TLS verification is not skipped in production + insecureSkipVerify: false + caFile: /etc/prometheus/secrets/ca.crt # CA certificate injected by cert-manager + certFile: /etc/prometheus/secrets/tls.crt # TLS certificate injected by cert-manager + keyFile: /etc/prometheus/secrets/tls.key # TLS private key injected by cert-manager + selector: + matchLabels: + control-plane: controller-manager +``` + +### Phase 3: When Controller-Runtime feature is enhanced + +After we have the [issue](https://github.com/kubernetes-sigs/controller-runtime/issues/2781) +addressed, and we plan to use it to protect the endpoint. See, that would mean ensuring +that we are either `handle authentication (authn), authorization (authz)`. +Examples of its implementation can be found [here](https://github.com/kubernetes-sigs/cluster-api/blob/v1.6.3/util/flags/diagnostics.go#L79-L82). + +### Phase 4: When kube-rbac-proxy be accepted under the umbrella + +Once kube-rbac-proxy is included in the Kubernetes umbrella, +Kubebuilder maintainers can support its integration through a [plugin](https://kubebuilder.io/plugins/plugins). +We can following up the ongoing process and changes required for the project be accepted +by looking at the [project issue](https://github.com/brancz/kube-rbac-proxy/issues/238). + +This enables a seamless way to incorporate kube-rbac-proxy into Kubebuilder scaffolds, +allowing users to run: + +```sh +kubebuilder init|edit --plugins="kube-rbac-proxy/v1" +``` + +So that the plugin could use the [plugin/util](../pkg/plugin/util) lib provide +to comment (We can add a method like the [UncommentCode](https://github.com/kubernetes-sigs/kubebuilder/blob/72586d386cfbcaecea6321a703d1d7560c521885/pkg/plugin/util/util.go#L102)) +the patches in the `config/default/kustomization` and disable the default network policy used within +and [replace the code](https://github.com/kubernetes-sigs/kubebuilder/blob/72586d386cfbcaecea6321a703d1d7560c521885/pkg/plugin/util/util.go#L231) +in the `main.go` bellow with to not use the controller-runtime +feature instead. + +```go +ctrlOptions := ctrl.Options{ + MetricsFilterProvider: filters.WithAuthenticationAndAuthorization, + MetricsSecureServing: true, +} +``` + +### Documentation Updates + +Each phase of implementation associated with this proposal must include corresponding +updates to the documentation. This is essential to ensure end users understand +how to enable, configure, and utilize the options effectively. Documentation updates should be +completed as part of the pull request to introduce code changes. + +### Proof of Concept + +- **(Phase 1)NetworkPolicies:** https://github.com/kubernetes-sigs/kubebuilder/pull/3853 +- Example of Controller-Runtime new feature to protect Metrics Endpoint: https://github.com/sbueringer/controller-runtime-tests/tree/master/metrics-auth + +### Risks and Mitigations + +#### Loss of Previously Promoted Images + +The transition to the new shared infrastructure for Kubernetes SIG projects has rendered us unable to automatically build and promote images as before. +The process only works for projects under the umbrella. +However, the k8s-infra maintainers could manually transfer these images +to the new [registry.k8s.io][registry.k8s.io] as a "contingent approach". +See: [https://explore.ggcr.dev/?repo=gcr.io%2Fk8s-staging-kubebuilder%2Fkube-rbac-proxy](https://explore.ggcr.dev/?repo=registry.k8s.io%2Fkubebuilder%2Fkube-rbac-proxy) + +To continue using kube-rbac-proxy, users must update their projects to reference images +from the new registry. This requires a project update and a new release, +ensuring the image references in the `config/default/manager_auth_proxy_patch.yaml` point +to a new place. + +Therefore, the best approach here for those still interested in using +kube-rbac-proxy seems to direct them to the images hosted +at [quay.io](https://quay.io/repository/brancz/kube-rbac-proxy?tab=tags&tag=latest), +which are maintained by the project itself and then, +we keep those images in the registry.k8s.io as a "contingent approach". + +Ensuring that these images will continue to be promoted under any infrastructure available to +Kubebuilder is not reliable or achievable for Kubebuilder maintainers. It is definitely out of our control. + +#### Impact of Google Cloud Platform Kubebuilder project + +Kubebuilder hasn't received any official notice regarding a shutdown of its project there so far, but there's a proactive move to transition away +from Google Cloud Platform services due to factors beyond our control. Open communication with our community is key as +we explore alternatives. It's important to note the [Container Registry Deprecation][container-registry-dep] results +in users no longer able to consume those images from the current location from **early 2025**, +emphasizing the need to shift away from dependent images as soon as possible and communicate it extensively +through mailing lists and other channels to ensure community awareness and readiness. + +## Alternatives + +### Replace the current images `gcr.io/kubebuilder/kube-rbac-proxy` with `registry.k8s.io/kubebuilder/kube-rbac-proxy` + +The k8s-infra maintainers assist in ensuring these images will not be lost by: +- Manually adding them to [gcr.io/k8s-staging-kubebuilder/kube-rbac-proxy](https://explore.ggcr.dev/?repo=gcr.io%2Fk8s-staging-kubebuilder%2Fkube-rbac-proxy) and promoting them via [registry.k8s.io/kubebuilder/kube-rbac-proxy](https://explore.ggcr.dev/?image=registry.k8s.io%2Fkubebuilder%2Fkube-rbac-proxy:v0.16.0). + +An available option would be to communicate to users to: +- a) Replace their registry from `gcr.io/k8s-staging-kubebuilder/kube-rbac-proxy` to `registry.k8s.io/kubebuilder/kube-rbac-proxy` +- b) Clearly state in the docs, Kubebuilder scaffolds, and all channels, including email communications, that kube-rbac-proxy is in the process of becoming part of Kubernetes/auth-sig but is not yet there and hence is a "not supported/secure" solution + +**Cons:** +- Kubebuilder would still not be fully compliant with its goals since it would be scaffolding a third-party integration instead of properly endorsing and promoting the usage of external-plugin APIs. +- Kubebuilder would still be promoting a solution not deemed secure/safe according to the review by auth-sig maintainers. +- We would still need to manually request k8s-infra maintainers to build and promote these images in the new registry manually. +- Changes in the manager/project solution delivered in the scaffold have a critical impact. For example, in this case, users +will need to change **ALL** projects they support and ensure that their users no longer use their previously released versions. +Following this path, when kube-rbac-proxy is accepted under the Kubernetes/auth-sig, they will start to maintain and manage +their own images, which means this path will change again, and Kubebuilder maintainers have no control over ensuring that +these images will still be available and promoted for a long period. + +### Retain kube-rbac-proxy as an Opt-in Feature and move it to an alpha plugin (Unsupported Feature) AND/OR use the project registry + +This alternative keeps kube-rbac-proxy out of the default scaffolds, offering it as an optional plugin for users who choose +to integrate it. Clear communication will be crucial to inform users about the implications of using kube-rbac-proxy. + +**Cons:** + +Mainly, all cons added for the above alternative option `Replace the current images gcr.io/kubebuilder/kube-rbac-proxy` +with `registry.k8s.io/kubebuilder/kube-rbac-proxy` within the exception that we would make clear that we kubebuilder +is unable to manage those images and move the current implementation for the alpha plugin +it would maybe make the process to move it from the Kubebuilder repository to `kube-rbac-proxy` an +easier process to allow them to work with the external plugin. + +However, that is a double effort for users and Kubebuilder maintainers to deal with breaking changes +resulting from achieving the ultimate go. Therefore, it would make more sense +to encourage using external-plugins API and add this option in their +repo once, then create these intermediate steps. + +[kube-rbac-proxy]: https://github.com/brancz/kube-rbac-proxy +[external-plugins]: https://kubebuilder.io/plugins/external-plugins +[registry.k8s.io]: https://github.com/kubernetes/registry.k8s.io +[container-registry-dep]: https://cloud.google.com/artifact-registry/docs/transition/prepare-gcr-shutdown +[kb-images-repo]: https://console.cloud.google.com/gcr/images/kubebuilder/GLOBAL/kube-rbac-proxy +[slack-eta-thread]: https://kubernetes.slack.com/archives/CCK68P2Q2/p1712622102206909 +[cr-pr]: https://github.com/kubernetes-sigs/controller-runtime/pull/2407 +[k8s-doc-networkpolicies]: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +[cert-manager]:https://cert-manager.io/ diff --git a/designs/extensible-cli-and-scaffolding-plugins-phase-1-5.md b/designs/extensible-cli-and-scaffolding-plugins-phase-1-5.md index e96e9a0f649..e71dfb6ced7 100644 --- a/designs/extensible-cli-and-scaffolding-plugins-phase-1-5.md +++ b/designs/extensible-cli-and-scaffolding-plugins-phase-1-5.md @@ -1,3 +1,7 @@ +| Authors | Creation Date | Status | Extra | +|---------------|---------------|-------------|-----------------------------------------------------------------| +| @adirio | Mar 9, 2021 | Implemented | [Plugins doc](https://book.kubebuilder.io/plugins/plugins.html) | + # Extensible CLI and Scaffolding Plugins - Phase 1.5 Continuation of [Extensible CLI and Scaffolding Plugins](./extensible-cli-and-scaffolding-plugins-phase-1.md). @@ -84,7 +88,7 @@ therefore, use this error to tell the CLI that no further execution step should ### Initialization hooks #### Update metadata -This hook will be used for two purposes. It provides CLI-related metadata to the Subcommand (e.g., +This hook will be used for two purposes. It provides CLI-related metadata to the Subcommand (e.g., command name) and update the subcommands metadata such as the description or examples. - Required/optional @@ -180,7 +184,7 @@ configuration at this hook will not be persisted. - [x] Edit - [x] Create API - [x] Create webhook - + ### Override plugins for single subcommand calls Defining plugins at initialization and using them for every command call will solve most of the cases. diff --git a/designs/extensible-cli-and-scaffolding-plugins-phase-1.md b/designs/extensible-cli-and-scaffolding-plugins-phase-1.md index 0e9d75c6c9d..0b1f679a3cf 100644 --- a/designs/extensible-cli-and-scaffolding-plugins-phase-1.md +++ b/designs/extensible-cli-and-scaffolding-plugins-phase-1.md @@ -1,3 +1,8 @@ + +| Authors | Creation Date | Status | Extra | +|---------------|---------------|-------------|-----------------------------------------------------------------| +| @estroz,@joelanford | Dec 10, 2019 | Implemented | [Plugins doc](https://book.kubebuilder.io/plugins/plugins.html) | + # Extensible CLI and Scaffolding Plugins ## Overview diff --git a/designs/extensible-cli-and-scaffolding-plugins-phase-2.md b/designs/extensible-cli-and-scaffolding-plugins-phase-2.md index 249d30d6171..02046857e9c 100644 --- a/designs/extensible-cli-and-scaffolding-plugins-phase-2.md +++ b/designs/extensible-cli-and-scaffolding-plugins-phase-2.md @@ -1,3 +1,7 @@ +| Authors | Creation Date | Status | Extra | +|---------------|---------------|-------------|-----------------------------------------------------------------| +| @rashmigottipati | Mar 9, 2021 | partial implemented | [Plugins doc](https://book.kubebuilder.io/plugins/plugins.html) | + # Extensible CLI and Scaffolding Plugins - Phase 2 ## Overview @@ -99,14 +103,14 @@ Note: If the name is ambiguous, then the qualified name `myexternalplugin.my.dom ### What Plugin system should we use -I propose we use our own plugin system that passes JSON blobs back and forth across `stdin/stdout/stderr` and make this the only option for now as it’s a language-agnostic medium and it is easy to work with in most languages. +I propose we use our own plugin system that passes JSON blobs back and forth across `stdin/stdout/stderr` and make this the only option for now as it's a language-agnostic medium and it is easy to work with in most languages. -We came to the conclusion that a kubebuilder-specific plugin library should be written after evaluating plugin libraries such as the [built-in go-plugin library](https://golang.org/pkg/plugin/) and [Hashicorp’s plugin library](https://github.com/hashicorp/go-plugin): +We came to the conclusion that a kubebuilder-specific plugin library should be written after evaluating plugin libraries such as the [built-in go-plugin library](https://golang.org/pkg/plugin/) and [Hashicorp's plugin library](https://github.com/hashicorp/go-plugin): -* The built-in plugin library seems to be more suitable for in-tree plugins rather than out-of-tree plugins and it doesn’t offer cross-language support, thereby making it a non-starter. -* Hashicorp’s go plugin system is more suitable than the built-in go-plugin library as it enables cross language/platform support. However, it is more suited for long running plugins as opposed to short lived plugins and the usage of protobuf could be overkill as we will not be handling 10s of 1000s of deserializations. +* The built-in plugin library seems to be more suitable for in-tree plugins rather than out-of-tree plugins and it doesn't offer cross-language support, thereby making it a non-starter. +* Hashicorp's go plugin system is more suitable than the built-in go-plugin library as it enables cross-language/platform support. However, it is more suited for long-running plugins as opposed to short-lived plugins and the usage of protobuf could be overkill as we will not be handling 10s of 1000s of deserializations. -In the future, if a need arises (for example, users are hitting performance issues), we can then explore the possibility of using the Hashicorp’s go plugin library. From a design standpoint, to leave it architecturally open, I propose using a `type` field in the PROJECT file to potentially allow other plugin libraries in the future and make this a seperate field in the PROJECT file per plugin; and this field determines how the `universe` will be passed for a given plugin. However, for the sake of simplicity in initial design and not to introduce any breaking changes as Project version 3 would suffice for our needs, this option is out of scope in this proposal. +In the future, if a need arises (for example, users are hitting performance issues), we can then explore the possibility of using the Hashicorp's go plugin library. From a design standpoint, to leave it architecturally open, I propose using a `type` field in the PROJECT file to potentially allow other plugin libraries in the future and make this a separate field in the PROJECT file per plugin; and this field determines how the `universe` will be passed for a given plugin. However, for the sake of simplicity in initial design and not to introduce any breaking changes as Project version 3 would suffice for our needs, this option is out of scope in this proposal. ### Project configuration @@ -125,7 +129,7 @@ Example `PROJECT` file: ```yaml version: "3" domain: testproject.org -layout: +layout: - go.kubebuilder.io/v3 - myexternalplugin/v2 plugins: @@ -134,7 +138,7 @@ plugins: - domain: testproject.org group: crew kind: Captain - version: v2-alpha + version: v2 declarative.go.kubebuilder.io/v1: resources: - domain: testproject.org @@ -161,19 +165,19 @@ resources: ![Kubebuilder to external plugins sequence diagram](https://github.com/rashmigottipati/POC-Phase2-Plugins/blob/main/docs/externalplugins-sequence-diagram.png) -* What to pass between `kubebuilder` and an external plugin? +* What should be passed between `kubebuilder` and an external plugin? Message passing between `kubebuilder` and the external plugin will occur through a request / response mechanism. The `PluginRequest` will contain information that `kubebuilder` sends *to* the external plugin. The `PluginResponse` will contain information that `kubebuilder` receives *from* the external plugin. -The following scenarios shows what `kubebuilder` will send/receive to the external plugin: +The following scenarios show what `kubebuilder` will send/receive to the external plugin: * `kubebuilder` to external plugin: - * `kubebuilder` constructs a `PluginRequest` that contains the `Command` (such as `init`, `create api`, or `create webhook`), `Args` containing all the raw flags from the CLI request and license boilerplate without comment delimiters, and an empty `Universe` that contains the current virtual state of file contents that is not written to the disk yet. `kubebuilder` writes the `PluginRequest` through `stdin`. + * `kubebuilder` constructs a `PluginRequest` that contains the `Command` (such as `init`, `create api`, or `create webhook`), `Args` containing all the raw flags from the CLI request and license boilerplate without comment delimiters, and an empty `Universe` that contains the current virtual state of file contents that are not written to disk yet. `kubebuilder` writes the `PluginRequest` through `stdin`. * External plugin to `kubebuilder`: * The plugin reads the `PluginRequest` through its `stdin` and processes the request based on the `Command` that was sent. If the `Command` doesn't match what the plugin supports, it writes back an error immediately without any further processing. If the `Command` matches what the plugin supports, it constructs a `PluginResponse` containing the `Command` that was executed by the plugin, and modified `Universe` based on the new files that were scaffolded by the external plugin, `Error` and `ErrorMsg` that add any error information, and writes the `PluginResponse` back to `kubebuilder` through `stdout`. -* Note: If `--help` flag is being passed from `kubebuilder` to the external plugin through `PluginRequest`, the plugin attaches its help text information in the `Help` field of the `PluginResponse`. Both `PluginRequest` and `PluginResponse` also contain `APIVersion` field to have compatible versioned schemas. +* Note: If `--help` flag is being passed from `kubebuilder` to the external plugin through `PluginRequest`, the plugin attaches its help text information in the `Metadata` field of the `PluginResponse`. Both `PluginRequest` and `PluginResponse` also contain `APIVersion` field to have compatible versioned schemas. * Handling plugin failures across the chain: @@ -208,9 +212,9 @@ type PluginResponse struct { // Command holds the command that gets executed by the plugin such as init, create api, etc. Command string `json:"command"` - // Help contains the plugin specific help text that the plugin returns to kubebuilder when it receives + // Metadata contains the plugin specific help text that the plugin returns to Kubebuilder when it receives // `--help` flag from Kubebuilder. - Help string `json:"help,omitempty"` + Metadata plugin.SubcommandMetadata `json:"metadata"` // APIVersion defines the versioned schema of the PluginResponse that will be written back to kubebuilder. // Initially, this will be marked as alpha (v1alpha1). @@ -274,7 +278,7 @@ What happens when the above is invoked? `PluginRequest JSON`: ```JSON -{ +{ "command":"init", "args":["--domain","example.com"], "universe":{} @@ -310,7 +314,7 @@ What happens when the above is invoked? #### User specified file paths -A user will provide a list of file paths for `kubebuilder` to discover the plugins in. We will define a variable `KUBEBUILDER_PLUGINS_DIRS` that will take a list of file paths to search for the plugin name. It will also have a default value to search in, in case no file paths are provided. It will search for the plugin name that was provided to the `--plugins` flag in the CLI. `kubebuilder` will recursively search for all file paths until the plugin name is found and returns the successful match, and if it doesn’t exist, it returns an error message that the plugin is not found in the provided file paths. Also use the host system mechanism for PATH separation. +A user will provide a list of file paths for `kubebuilder` to discover the plugins in. We will define a variable `KUBEBUILDER_PLUGINS_DIRS` that will take a list of file paths to search for the plugin name. It will also have a default value to search in, in case no file paths are provided. It will search for the plugin name that was provided to the `--plugins` flag in the CLI. `kubebuilder` will recursively search for all file paths until the plugin name is found and returns the successful match, and if it doesn't exist, it returns an error message that the plugin is not found in the provided file paths. Also use the host system mechanism for PATH separation. * Alternatively, this could be handled in a way that [helm kustomize plugin](https://helm.sh/docs/topics/advanced/#post-rendering) discovers the plugin based on the non-existence of a separator in the path provided, in which case `kubebuilder` will search in `$PATH`, otherwise resolve any relative paths to a fully qualified path. @@ -326,9 +330,9 @@ A user will provide a list of file paths for `kubebuilder` to discover the plugi Another approach is adding plugin executables with a prefix `kubebuilder-` followed by the plugin name to the PATH variable. This will enable `kubebuilder` to traverse through the PATH looking for the plugin executables starting with the prefix `kubebuilder-` and matching by the plugin name that was provided in the CLI. Furthermore, a check should be added to verify that the match is an executable or not and return an error if it's not an executable. This approach provides a lot of flexibility in terms of plugin discovery as all the user needs to do is to add the plugin executable to the PATH and `kubebuilder` will discover it. * Pros - * `kubectl` and `git` follow the same approach for discovering plugins, so there’s prior art. + * `kubectl` and `git` follow the same approach for discovering plugins, so there's prior art. - * There’s a lot of flexibility in just dropping plugin binaries to PATH variable and enabling the discovery without having to enforce any other constraints on the placements of the plugins. + * There's a lot of flexibility in just dropping plugin binaries to PATH variable and enabling the discovery without having to enforce any other constraints on the placements of the plugins. * Cons * Enumerating the list of all available plugins might be a bit tough compared to having a single folder with the list of available plugins and having to enumerate those. diff --git a/designs/helm-chart-autogenerate-plugin.md b/designs/helm-chart-autogenerate-plugin.md new file mode 100644 index 00000000000..329daa55486 --- /dev/null +++ b/designs/helm-chart-autogenerate-plugin.md @@ -0,0 +1,567 @@ +| Authors | Creation Date | Status | Extra | +|----------------------------------------|---------------|--------------|-------| +| @dashanji,@camilamacedo86,@LCaparelli | Sep, 2023 | Implemented | - | + +# New Plugin to allow project distribution via helm charts + +This proposal aims to introduce an optional mechanism that allows users +to generate a Helm Chart from their Kubebuilder-scaffolded project. This will +enable them to effectively package and distribute their solutions. + +To achieve this goal, we are proposing a new native Kubebuilder +[plugin](https://book.kubebuilder.io/plugins/plugins) (i.e., `helm-chart/v1-alpha`) +which will provide the necessary scaffolds. The plugin will function similarly +to the existing [Grafana Plugin](https://book.kubebuilder.io/plugins/grafana-v1-alpha), generating or regenerating HelmChart files using the init and edit +sub-commands (i.e., `kubebuilder init|edit --plugins helm-chart/v1-alpha`). + +An alternative solution could be to implement an alpha command, +similar to the [helper provided to upgrade projects](https://book.kubebuilder.io/reference/rescaffold) that would +provide the HelmChart under the `dist`directory, similar to what +is done by [helmify](https://github.com/arttor/helmify). + +## Example of Usage + +**To enable the helm-chart generation when a project is initialized** + +> kubebuilder init --plugins=`go/v4,helm/v1-alpha` + +**To enable the helm-chart generation after the project be scaffolded** + +> kubebuilder edit --plugins=`helm/v1-alpha` + +> Note that the HelmChart should be scaffold under the `dist/` directory in both scenarios: +> ```shell +> example-project/ +> dist/ +> chart/ +> ``` + + +**To sync the HelmChart with the latest changes and add the manifests generated** + +> kubebuilder edit --plugins=`helm/v1-alpha` + +The above command will be responsible for ensuring that the Helm Chart is properly updated +with the latest changes in the project, including the files generated by +controller-gen when users run make manifests. + +## Open Questions + +### 1) How to manage and scaffold the CRDs for the HelmChart? + +According to [Helm Best Practices for Custom Resource Definitions](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/#method-1-let-helm-do-it-for-you), +there are two main methods for handling CRDs: + +- **Method 1:Let Helm Do It For You:** Place CRDs in the `crds/` directory. Helm installs these CRDs during the initial + install but does not manage upgrades or deletions. +- **Method 2:Separate Charts:** Place the CRD definition in one chart + and the resources using the CRD in another chart. + This method requires separate installations for each chart. + +**Raised Considerations and Concerns** +- **Use Helm crd directory** The upgraded chart versions will silently ignore CRDs even if they differ from the installed versions. This could lead to surprising and unexpected behavior. Therefore, Kubebuilder should not encourage or promote this approach. +- **Templates Folder**: Moving CRDs to the `templates` folder facilitates upgrades but uninstalls CRDs when the operator is uninstalled. However, it allows users easier manage the CRDs and install them on upgrades. It is a common approach adopted by maintainers but is not considered a good practice by Helm itself. +- **Separate Helm Chart for CRDs:** This approach allows control over both CRD and operator versions without deleting CRDs when the operator chart is deleted. Also, follows the HelmChart best practices. Another problem with this approach is to ensure that the CRDs will be applied before the CRs since both will be under the template directory. +- **When Webhooks are used:** If a CRD specifies, for example, a conversion webhook, the "API chart" needs to contain the CRDs and the webhook `service/workload`. + It would also make sense to include `validating/mutating` webhooks, requiring the scaffolding of separate main modules and image builds for + webhooks and controllers which does not shows to be compatible with Kubebuilder Golang scaffold. + +**Proposed Solution** + +Follow the same approach adopted by [Cert-Manager](https://cert-manager.io/docs/installation/helm/). +Add the CRDs under the `template` directory and have a spec in the `values.yaml` +which will define if the CRDs should or not be applied + +```shell +helm install|upgrade \ + myrelease \ + --namespace my-namespace \ + --set `crds.enabled=true` +``` + +Also, add another spec to the `values.yaml` to not allow the CRDs +be deleted when the helm is uninstalled: + +```yaml + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} +``` + +Additionally, we might want to +scaffold separate charts for the APIs and support both. +An example of this approach provided as feedback +was [karpenter-provider-aws](https://github.com/aws/karpenter-provider-aws/tree/main/charts). + +We should either make clear the usage of both supported +ways and clarify their limitations. However, the proposed +solution would result in the following layout: + +``` +example-project/ + dist/ + chart/ + example-project-crd/ + ├── Chart.yaml + ├── templates/ + │ ├── _helpers.tpl + │ ├── crds/ + │ │ └── + └── values.yaml + example-project/ + ├── Chart.yaml + ├── templates/ + │ ├── _helpers.tpl + │ ├── crds/ + │ └── + │ ├── ... +``` + +### 2) How to manage dependencies such as Cert-Manager and Prometheus? + +Helm charts allow maintainers to define dependencies via the `Chart.yaml` file. +However, in the initial version of this plugin at least, we do not need to consider management of dependencies. + +Adding dependencies such as **Cert-Manager** and **Prometheus** directly in the `Chart.yaml` +could introduce issues since these components are intended to be installed only once per cluster. +Attempting to manage multiple installations could lead to conflicts and cause unintended behaviors, +especially in shared cluster environments. + +To avoid these issues, the plugin for now will not scaffold this file and will not try to +manage it. Instead, users will be responsible for managing these dependencies outside of +the generated Helm chart, ensuring they are correctly installed and only installed once in the cluster. + +## Motivation + +Currently, projects scaffolded with Kubebuilder can be distributed via YAML. Users can run +`make build-installer IMG=/:tag`, which will generate `dist/install.yaml`. +Therefore, its consumers can install the solution by applying this YAML file, such as: +`kubectl apply -f https://raw.githubusercontent.com////dist/install.yaml`. + +However, many adopt solutions require the Helm Chart format, such as FluxCD. Therefore, +maintainers are looking to also provide their solutions via Helm Chart. Users currently face the challenges of lacking +an officially supported distribution mechanism for Helm Charts. They seek to: + +- Harness the power of Helm Chart as a package manager for the project, enabling seamless adaptation to diverse deployment environments. +- Take advantage of Helm's dependency management capabilities to simplify the installation process of project dependencies, such as cert-manager. +- Seamlessly integrate with Helm's ecosystem, including FluxCD, to efficiently manage the project. + +Consequently, this proposal aims to introduce a method that allows Kubebuilder users to easily distribute their projects through Helm Charts, a strategy that many well-known projects have adopted: + +- [mongodb](https://artifacthub.io/packages/helm/mongodb-helm-charts/community-operator) +- [cert-manager](https://cert-manager.io/v1.6-docs/installation/helm/#1-add-the-jetstack-helm-repository) +- [prometheus](https://bitnami.com/stack/prometheus-operator/helm) +- [aws-load-balancer-controller](https://github.com/kubernetes-sigs/aws-load-balancer-controller/tree/main/helm/aws-load-balancer-controller) + +**NOTE:** For further context see the [discussion topic](https://github.com/kubernetes-sigs/kubebuilder/discussions/3074) + +## Goals + +- Allow Kubebuilder users distribute their projects using Helm easily. +- Make the best effort to preserve any customizations made to the Helm Charts by the users, which means we will skip syncs in the `values.ymal`. +- Stick with Helm layout definitions and externalize into the relevant values-only options to distribute the default scaffold done by Kubebuilder. We should follow https://helm.sh/docs/chart_best_practices. + +## Non-Goals + +- Converting any Kustomize configuration to Helm Charts like [helmify](https://github.com/arttor/helmify) does. +- Support the deprecated plugins. This option should be supported from `go/v4` and `kustomize/v2` +- Introduce support for Helm in addition to Kustomize, or replace Kustomize with Helm entirely, similar to the approach +taken by Operator-SDK, thereby allowing users to utilize Helm Charts to build their Project. +- Attend standard practices that deviate from Helm Chart layout, definition, or conventions to workaround its limitations. + +## User Stories + +- As a developer, I want to be able to generate a helm chart from a kustomize directory so that I can distribute the helm chart to my users. Also, I want the + generation to be as simple as possible without the need to write any additional duplicate files. +- As a user, I want the helm chart can cover all potential configurations when I deploy it on the Kubernetes cluster. +- As a platform engineer, I want to be able to manage different versions and configurations of a project across multiple clusters and environments based on the same distribution artifact (Helm Chart), with versioning and dependency locking for supply chain security. + +## Implementation Details/Notes/Constraints + +### Plugin Layout + +- **Location and Versioning**: The new plugin should follow Kubebuilder standards and +be implemented under `pkg/plugins/optional`. It should be introduced as an alpha version +(`v1alpha`), similar to the [Grafana plugin](https://github.com/kubernetes-sigs/kubebuilder/tree/master/pkg/plugins/optional/grafana/v1alpha). + +- **The data should be tracked in PROJECT File**: Usage of the plugin should be tracked in the `PROJECT` +file with the input via flags and options if required. Example entry in the `PROJECT` file: + +```yaml +... +plugins: + helm.go.kubebuilder.io/v1-alpha: + options: ## (If ANY) + : +``` + +Ensure that user-provided input is properly tracked, similar to how it's done in +other plugins [(see the code in the plugin.go)](https://github.com/kubernetes-sigs/kubebuilder/blob/c058fb95fe0ccd8d2a3147990251ca501df5eb26/pkg/plugins/golang/deploy-image/v1alpha1/plugin.go#L58-L75) +and the [(code source to track the data)](https://github.com/kubernetes-sigs/kubebuilder/blob/c058fb95fe0ccd8d2a3147990251ca501df5eb26/pkg/plugins/golang/deploy-image/v1alpha1/api.go#L191-L217) +of the deploy-image plugin for reference. + +**NOTE** We might not need options/flags in the first implementation. However, we should still track the plugin as +we do for the Grafana plugin. + +### Plugin Implementation Structure + +Following the structure implementation for the source code of this plugin: + +```shell +. +├── helm-chart +│ └── v1alpha1 +│ ├── init.go +│ ├── edit.go +│ ├── plugin.go +│ └── scaffolds +│ ├── init.go +│ ├── edit.go +│ └── internal +│ └── templates +``` + +### SubCommand implementation + +For each subCommand we will need to check the resources which +are scaffold for each subCommand via the [kustomize](https://kubebuilder.io/plugins/kustomize-v2) plugin +and ensure that we will implement the subCommand of the HelmChart plugin +to the respective scaffolds as well. + +#### To Sync the Manifests Created with `controller-gen` + +Users will need to call the subcommand `edit` passing the plugin to +ensure that the Helm chart is properly synced. + +Therefore, the `PostScaffold` of this command could perform steps such as: + +- **Run `make manifests`**: Generate the latest CRDs and other manifests. +- **Copy the files to Helm chart templates**: + - Copy CRDs: `cp config/crd/bases/*.yaml chart/example-project-crd/templates/crds/` + - Copy RBAC manifests: `cp config/rbac/*.yaml chart/example-project/templates/rbac/` + - Copy webhook configurations: `cp config/webhook/*.yaml chart/example-project/templates/webhook/` + - Copy the manager manifest: `cp config/default/manager.yaml chart/example-project/templates/manager/manager.ymal0` +- **Replace placeholders with Helm values**: Ensure that customized fields, such as the namespace, are properly replaced accordingly. + Example: Replace `name: system` with `{{ .Values.Release.name }}`. + +This ensures the Helm chart is always up-to-date with the latest +manifests generated by Kubebuilder, maintaining consistency with the +configured namespace and other customizable fields. + +We will need to use the utils helpers such as [ReplaceInFile](https://github.com/kubernetes-sigs/kubebuilder/blob/c058fb95fe0ccd8d2a3147990251ca501df5eb26/pkg/plugin/util/util.go#L303-L323) +or [EnsureExistAndReplace](https://github.com/kubernetes-sigs/kubebuilder/blob/c058fb95fe0ccd8d2a3147990251ca501df5eb26/pkg/plugin/util/util.go#L276) +to achieve this goal. + +### HelmChart Values Scaffolded by the Plugin + +- **Allow values.yaml to be fully re-generated with the flag --force**: + +By default, the `values.yaml` file should not +be overwritten. However, users should have the option to overwrite it using +a flag (`--force=true`). + +This can be implemented in the specific template as done for other plugins: + +```go +if f.Force { + f.IfExistsAction = machinery.OverwriteFile +} else { + f.IfExistsAction = machinery.Error +} +``` + +**NOTE:** We will evaluate the cases when we implement `webhook.go` and `api.go` +for the HelmChart plugin. However, we might use the force flag to replicate +the same behavior implemented in the subCommands of the kustomize plugin. +For instance, if the flag is used when creating an API, it forces +the overwriten of the generated samples. Similarly, if the api subCommand +of the HelmChart plugin is called with `--force`, we should replace +all samples with the latest versions instead of only adding the new one. + +- **Helm Chart Templates should have conditions**: + +Ensure templates install resources based on +conditions defined in the `values.yaml`. Example for CRDs: + +``` +# To install CRDs +{{- if .Values.crd.enable }} +... +{{- end }} +``` + +- **Customizable Values**: Set customizable values in the `values.yaml`, + such as defining ServiceAccount names, and whether they should be created or not. + Furthermore, we should include comments to help end-users understand the source + of configurations. Example: + +```yaml +{{- if .Values.rbac.enable }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/name: project-v4 + app.kubernetes.io/managed-by: kustomize + name: {{ .Values.rbac.serviceAccountName }} + namespace: {{ .Release.Namespace }} +{{- end }} +``` + +- **Example of values.yaml**: + +Following an example to illustrate the expected result of this plugin: + +```yaml +# Install CRDs under the template +crd: + enable: false + keep: true + +# Webhook configuration sourced from the `config/webhook` +webhook: + enabled: true + conversion: + enabled: true + +## RBAC configuration under the `config/rbac` directory +rbac: + create: true + serviceAccountName: "controller-manager" + +# Cert-manager configuration +certmanager: + enabled: false + issuerName: "letsencrypt-prod" + commonName: "example.com" + dnsName: "example.com" + +# Network policy configuration sourced from the `config/network_policy` +networkPolicy: + enabled: false + +# Prometheus configuration +prometheus: + enabled: false + +# Manager configuration sourced from the `config/manager` +manager: + replicas: 1 + image: + repository: "controller" + tag: "latest" + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 64Mi + +# Metrics configuration sourced from the `config/metrics` +metrics: + enabled: true + +# Leader election configuration sourced from the `config/leader_election` +leaderElection: + enabled: true + role: "leader-election-role" + rolebinding: "leader-election-rolebinding" + + +# Controller Manager configuration sourced from the `config/manager` +controllerManager: + manager: + args: + - --metrics-bind-address=:8443 + - --leader-elect + - --health-probe-bind-address=:8081 + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + image: + repository: controller + tag: latest + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + replicas: 1 + serviceAccount: + annotations: {} + +# Kubernetes cluster domain configuration +kubernetesClusterDomain: cluster.local + +# Metrics service configuration sourced from the `config/metrics` +metricsService: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: 8443 + type: ClusterIP + +# Webhook service configuration sourced from the `config/webhook` +webhookService: + ports: + - port: 443 + protocol: TCP + targetPort: 9443 + type: ClusterIP +``` + +### Optional configurations should be disabled by default + +The HelmChart plugin should not scaffold optional options enabled +when those are scaffolded as disabled by the default implementation +of `kustomize/v2` and consequently the `go/v4` plugin used by default. Example: + +The dependency on Cert-Manager is disabled by default. + +```yaml +From config/default/kusyomization.yaml +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. +#- ../certmanager +``` + +Therefore, by default the `values.yaml` should be scaffolded with: + +``` +# Cert-manager configuration +certmanager: + enabled: false +``` + +### Layout of the Helm-Chart + +Following an example of the expected result of this plugin: + +```shell +example-project/ + dist/ + chart/ + example-project-crd/ + ├── Chart.yaml + ├── templates/ + │ ├── _helpers.tpl + │ ├── crds/ + │ │ └── + └── values.yaml + example-project/ + ├── Chart.yaml + ├── templates/ + │ ├── _helpers.tpl + │ ├── crds/ + │ └── + │ ├── certmanager/ + │ │ └── certificate.yaml + │ ├── manager/ + │ │ └── manager.yaml + │ ├── network-policy/ + │ │ ├── allow-metrics-traffic.yaml + │ │ └── allow-webhook-traffic.yaml // Should be added by the plugin subCommand webhook.go + │ ├── prometheus/ + │ │ └── monitor.yaml + │ ├── rbac/ + │ │ ├── kind_editor_role.yaml + │ │ ├── kind_viewer_role.yaml + │ │ ├── leader_election_role.yaml + │ │ ├── leader_election_role_binding.yaml + │ │ ├── metrics_auth_role.yaml + │ │ ├── metrics_auth_role_binding.yaml + │ │ ├── metrics_reader_role.yaml + │ │ ├── role.yaml + │ │ ├── role_binding.yaml + │ │ └── service_account.yaml + │ ├── samples/ + │ │ └── kind_version_admiral.yaml + │ ├── webhook/ + │ │ ├── manifests.yaml + │ │ └── service.yaml + └── values.yaml +``` + +### Update the README + +A README.md is scaffold for the projects. (see its implementation [here](https://github.com/kubernetes-sigs/kubebuilder/blob/master/pkg/plugins/golang/v4/scaffolds/internal/templates/readme.go)). +Therefore, if the project is scaffold with the HelmChart plugin then, +we should update the [Distribution](https://github.com/kubernetes-sigs/kubebuilder/blob/master/testdata/project-v4/README.md#project-distribution) +section to add the info and steps over how to keep the HelmChart synced. + +### Tests and samples + +To ensure that the new plugin will work well we will need to: +- Implement e2e tests for the plugin. (for reference see the e2e tests for the [DeployImage](https://github.com/kubernetes-sigs/kubebuilder/tree/master/test/e2e/deployimage)) +- Ensure that the plugin is scaffold with all samples under the [testdata](https://github.com/kubernetes-sigs/kubebuilder/tree/master/testdata) directory (we will need call the plugin in [test/testdata/generate.sh](https://github.com/kubernetes-sigs/kubebuilder/blob/master/test/testdata/generate.sh#L115-L119)) + +### Documentation + +The new plugin should either be properly documented such as the others. +For reference see: +- [Available Plugins](https://book.kubebuilder.io/plugins/available-plugins) +- [DeployImage Plugin](https://book.kubebuilder.io/plugins/deploy-image-plugin-v1-alpha) + +## Risks and Mitigations + +**Difficulty in Maintaining the Solution** + +Maintaining the solution may prove challenging in the long term, +particularly if it does not gain community adoption and, consequently, collaboration. +To mitigate this risk, the proposal aims to introduce an optional alpha plugin or to +implement it through an alpha command. This approach provides us with greater flexibility +to make adjustments or, if necessary, to deprecate the feature without definitively +compromising support. + +## Proof of Concept + +In order to prove that would be possible we could +refer to the open source tool +[helmify](https://github.com/arttor/helmify). + +## Drawbacks + +**Inability to Handle Complex Kubebuilder Scenarios** + +The proposed plugin may struggle to appropriately handle complex scenarios commonly encountered +in Kubebuilder projects, such as intricate webhook configurations. Kubebuilder’s scaffolded +projects can have sophisticated webhook setups, and translating these accurately into Helm +Charts may prove challenging. This could result in Helm Charts that are not fully reflective +of the original project’s functionality or configurations. + +**Incomplete Generation of Valid and Deployable Helm Charts** + +The proposed solution may not be capable of generating a fully valid and deployable Helm Chart +for all use cases supported by Kubebuilder. Given the diversity and complexity of potential +configurations within Kubebuilder projects, there is a risk that the generated Helm Charts +may require significant manual intervention to be functional. This drawback undermines the +goal of simplifying distribution via Helm Charts and could lead to frustration for users who +expect a seamless and automated process. + +## Alternatives + +**Via a new command (Alternative Option)** + +By running the following command, the plugin will generate a helm chart from the specific kustomize directory and output it to the directory specified by the `--output` flag. + +```shell +kubebuilder alpha generate-helm-chart --from= --output= +``` + +The main drawback of this option is that it does not adhere to the Kubebuilder ecosystem. +Additionally, we would not take advantage of Kubebuilder library features, such as avoiding +overwriting the `values.yaml`. It might also be harder to support and maintain since we would +not have the templates as we usually do. + +Lastly, another con is that it would not allow us to scaffold projects with the plugin +enabled and in the future provide further configurations and customizations for this plugin. +These configurations would be tracked in the `PROJECT` file, allowing integration with other +projects, extensions, and the re-scaffolding of the HelmChart while preserving the inputs +provided by the user via plugins flags as it is done for example for +the [Deploy Image](https://book.kubebuilder.io/plugins/deploy-image-plugin-v1-alpha) plugin. diff --git a/designs/helper_to_upgrade_projects_by_rescaffolding.md b/designs/helper_to_upgrade_projects_by_rescaffolding.md new file mode 100644 index 00000000000..344524ff5b1 --- /dev/null +++ b/designs/helper_to_upgrade_projects_by_rescaffolding.md @@ -0,0 +1,210 @@ +| Authors | Creation Date | Status | Extra | +|------------------------------------|---------------|-------------|---| +| @camilamacedo86,@Kavinjsir,@varshaprasad96 | Feb, 2023 | Implementable | - | + +Experimental Helper to upgrade projects by re-scaffolding +=================== + +This proposal aims to provide a new alpha command with a helper which +would be able to re-scaffold the project from the scratch based on +the [PROJECT config][project-config]. + +## Example + +By running a command like following, users would be able to re-scaffold the whole project from the scratch using the +current version of KubeBuilder binary available. + +```shell +kubebuilder alpha generate [OPTIONS] +``` + +### Workflows + +Following some examples of the workflows + +**To update the project with minor changes provided** + +See that for each KubeBuilder release the plugins versions used to scaffold +the projects might have bug fixes and new incremental features added to the +templates which will result in changes to the files that are generated by +the tool for new projects. + +In this case, you previously used the tool to generate the project +and now would like to update your project with the latest changes +provided for the same plugin version. Therefore, you will need to: + +- Download and install KubeBuilder binary ( latest / upper release ) +- You will run the command in the root directory of your project: `kubebuilder alpha generate` +- Then, the command will remove the content of your local directory and re-scaffold the project from the scratch +- It will allow you to compare your local branch with the remote branch of your project to re-add the code on top OR + if you do not use the flag `--no-backup`, then you can compare the local directory with the copy of your project + copied to the path `.backup/project-name/` before the re-scaffold is done. +- Therefore, you can run make all and test the final result. You will have after all your project updated. + +**To update the project with major changes provided** + +In this case, you are looking for to migrate the project from, for example, +`go/v3` to `go/v4`. The steps are very similar to the above ones. However, +in this case you need to inform the plugin that you want to use to do the scaffold +from scratch `kubebuilder alpha generate --plugins=go/v4`. + +## Open Questions + +N/A + +## Summary + +Therefore, a new command can be designed to load user configs from the [PROJECT config][project-config] file, and run the corresponding kubebuilder subcommands to generate the project based on the new kubebuilder version. Thus, it makes it easier for the users to migrate their operator projects to the new scaffolding. + +## Motivation + +A common scenario is to upgrade the project based on the newer Kubebuilder. The recommended (straightforward) steps are: + +- a) re-scaffold all files from scratch using the upper version/plugins +- b) copy user-defined source code to the new layout + +The proposed command will automate the process at maximum, therefore helping operator authors with minimizing the manual effort. + +The main motivation of this proposal is to provide a helper for upgrades and +make this process less painful. Examples: + +- See the discussion [How to regenerate scaffolding?](https://github.com/kubernetes-sigs/kubebuilder/discussions/2864) +- From [slack channel By Paul Laffitte](https://kubernetes.slack.com/archives/CAR30FCJZ/p1675166014762669) + +### Goals + +- Help users upgrade their project with the latest changes +- Help users re-scaffold projects from scratch based on what was done previously with the tool +- Make the upgrade process less painful + +### Non-Goals + +- Change the default layout or how the KubeBuilder CLI works +- Deal with customizations or deviations from the proposed layout +- Be able to perform the project upgrade to the latest changes without human interactions +- Deal and support external plugins +- Provide support to older version before having the Project config (Kubebuilder < 3x) and the go/v2 layout which exists to ensure a backwards compatibility with legacy layout provided by Kubebuilder 2x + +## Proposal + +The proposed solution to achieve this goal is to create an alpha command as described +in the example section above, see: + +```shell +kubebuilder alpha generate \ + --input-dir= + --output-dir= + --no-backup + --backup-path= + --plugins= +``` + +**Where**: + +- input-dir: [Optional] If not informed, then, by default, it is the current directory (project directory). If the `PROJECT` file does not exist, it will fail. +- output-dir: [Optional] If not informed then, it should be the current repository. +- no-backup: [Optional] If not informed then, the current directory should be copied to the path `.backup/project-name` +- backup: [Optional] If not informed then, the backup will be copied to the path `.backup/project-name` +- plugins: [Optional] If not informed then, it is the same plugin chain available in the layout field +- binary: [Optional] If not informed then, the command will use KubeBuilder binary installed globally. + +> Note that the backup created in the current directory must be prefixed with `.`. Otherwise the tool +will not able to perform the scaffold to create a new project from the scratch. + +This command would mainly perform the following operations: + +- 1. Check the flags +- 2. If the backup flag be used, then check if is a valid path and make a backup of the current project +- 3. Copy the whole current directory to `.backup/project-name` +- 4. Ensure that the output path is clean. By default it is the current directory project where the project was scaffolded previously and it should be cleaned up before doing the re-scaffold. +Only the content under `.backup/project-name` should be kept. +- 5. Read the [PROJECT config][project-config] +- 6. Re-run all commands using the KubeBuilder binary to recreate the project in the output directory + +The command should also provide comprehensive help with examples of the proposed workflows. So that, users +are able to understand how to use it when run `--help`. + +### User Stories + +**As an Operator author:** + +- I can re-generate my project from scratch based on the proposed helper, which executes all the +commands according to my previous input to the project. That way, I can easily migrate my project to the new layout +using the newer CLI/plugin versions, which support the latest changes, bug fixes, and features. +- I can regenerate my project from the scratch based on all commands that I used the tool to build +my project previously but informing a new init plugin chain, so that I could upgrade my current project to new +layout versions and experiment alpha ones. +- I would like to re-generate the project from the scratch using the same config provide in the PROJECT file and inform +a path to do a backup of my current directory so that I can also use the backup to compare with the new scaffold and add my custom code +on top again without the need to compare my local directory and new scaffold with any outside source. + +**As a Kubebuiler maintainer:** + +- I can leverage this helper to easily migrate tutorial projects of the Kubebuilder book. +- I can leverage on this helper to encourage its users to migrate to upper versions more often, making it easier to maintain the project. + +### Implementation Details/Notes/Constraints + +Note that in the [e2e tests](https://github.com/kubernetes-sigs/kubebuilder/tree/master/test/e2e) the binary is used to do the scaffolds. +Also, very similar to the implementation that exist in the integration test KubeBuilder has +a code implementation to re-generate the samples used in the docs and add customizations on top, +for further information check the [hack/docs](https://github.com/kubernetes-sigs/kubebuilder/tree/master/hack/docs). + +This subcommand could have a similar implementation that could be used by the tests and this plugin. +Note that to run the commands using the binaries we are mainly using the following golang implementation: + +```go +cmd := exec.Command(t.BinaryName, Options) +_, err := t.Run(cmd) +``` + +### Risks and Mitigations + +**Hard to keep the command maintained** + +A risk to consider is that it would be hard to keep this command maintained +because we need to develop specific code operations for each plugin. The mitigation for +this problem could be developing a design more generic that could work with all plugins. + +However, initially a more generic design implementation does not appear to be achievable and +would be considered out of the scope of this proposal (no goal). It should to be considered +as a second phase of this implementation. + +Therefore, the current achievable mitigation in place is that KubeBuilder's policy of not providing official +support of maintaining and distributing many plugins. + +### Proof of Concept + +All input data is tracked. Also, as described above we have examples of code implementation +that uses the binary to scaffold the projects. Therefore, the goal of this project seems +very reasonable and achievable. An initial work to try to address this requirement can +be checked in this [pull request](https://github.com/kubernetes-sigs/kubebuilder/pull/3022) + +## Drawbacks + +- If the value that feature provides does not pay off the effort to keep it + maintained, then we would need to deprecate and remove the feature in the long term. + +## Alternatives + +N/A + +## Implementation History + +The idea of automate the re-scaffold of the project is what motivates +us track all input data in to the [project config][project-config] +in the past. We also tracked the [issue](https://github.com/kubernetes-sigs/kubebuilder/issues/2068) +based on discussion that we have to indeed try to add further +specific implementations to do operations per major bumps. For example: + +To upgrade from go/v3 to go/v4 we know exactly what are the changes in the layout +then, we could automate these specific operations as well. However, this first idea is harder yet +to be addressed and maintained. + +## Future Vision + +We could use it to do cool future features such as creating a GitHub action which would push-pull requests against the project repositories to help users be updated with, for example, minor changes. By using this command, we might able to git clone the project and to do a new scaffold and then use some [git strategy merge](https://www.geeksforgeeks.org/merge-strategies-in-git/) to result in a PR to purpose the required changes. + +We probably need to store the CLI tool tag release used to do the scaffold to persuade this idea. So that we can know if the project requires updates or not. + +[project-config]: https://book.kubebuilder.io/reference/project-config.html diff --git a/designs/integrating-kubebuilder-and-osdk.md b/designs/integrating-kubebuilder-and-osdk.md index 24de989be0d..730e948cd66 100644 --- a/designs/integrating-kubebuilder-and-osdk.md +++ b/designs/integrating-kubebuilder-and-osdk.md @@ -1,9 +1,12 @@ -Integrating Kubebuilder and Operator SDK -======================================== +| Authors | Creation Date | Status | Extra | +|---------------|---------------|-------------|-------| +| @joelanford | Sep 6, 2019 | implemented | - | + +# Integrating Kubebuilder and Operator SDK ## Goal -To unite Kubebuilder and Operator SDK around Kubebuilder’s project scaffolding, to move Operator SDK’s Go operator features upstream, where appropriate, and to join forces on maintaining Kubebuilder so that both Kubebuilder and Operator SDK support the same project structure and command line interface for Go-based operators. +To unite Kubebuilder and Operator SDK around Kubebuilder's project scaffolding, to move Operator SDK's Go operator features upstream, where appropriate, and to join forces on maintaining Kubebuilder so that both Kubebuilder and Operator SDK support the same project structure and command line interface for Go-based operators. ## Background @@ -22,9 +25,9 @@ The Kubebuilder and Operator SDK contributors created a [GitHub project][kb-osdk ### Upstream code from Operator SDK The Operator SDK project contains various features that can be used by Go operator developers regardless of whether the project is based on Kubebuilder or Operator SDK. These features will be upstreamed into `kubebuilder`, `controller-runtime`, and `controller-tools`, where appropriate. These include: -* a `DynamicRESTMapper` that enables an operator to dynamically and automatically discover new CRDs added to the cluster after the operator has started -* a `GenerationChangedPredicate` that can trigger reconciliation events when a resource's `metadata.generation` field has changed. -* flags and helpers that can be used to provide more fine-grained configuration when constructing the default `zap`-based logger. +* A `DynamicRESTMapper` that enables an operator to dynamically and automatically discover new CRDs added to the cluster after the operator has started +* A `GenerationChangedPredicate` that can trigger reconciliation events when a resource's `metadata.generation` field has changed +* Flags and helpers that can be used to provide more fine-grained configuration when constructing the default `zap`-based logger The Operator SDK contributors plan to begin conducting all development of Go operator related code in upstream Kubebuilder (and related projects) and to spend more time helping the Kubebuilder contributors maintain these projects. @@ -32,7 +35,7 @@ The Operator SDK contributors plan to begin conducting all development of Go ope To make Kubebuilder more extensible, the community has been discussing a proposal to add extension points to Kubebuilder to support different operator patterns. One example of an operator pattern is the [addon pattern][addon-pattern-pr] that uses an existing library to instantiate an opinionated API and controller. -More broadly, the idea is to add support for executable plugin-based extensions that can modify Kubebuilder’s base scaffolding before files are written to disk so that the project (e.g. Go code, kustomize templates, the project Makefile and Dockerfile) can have customized content provided by an extension. +More broadly, the idea is to add support for executable plugin-based extensions that can modify Kubebuilder's base scaffolding before files are written to disk so that the project (e.g. Go code, kustomize templates, the project Makefile and Dockerfile) can have customized content provided by an extension. ### Documentation diff --git a/designs/simplified-scaffolding.md b/designs/simplified-scaffolding.md index 01eae04d417..1d3bd07e53a 100644 --- a/designs/simplified-scaffolding.md +++ b/designs/simplified-scaffolding.md @@ -1,3 +1,7 @@ +| Authors | Creation Date | Status | Extra | +|---------------|---------------|-------------|---| +| @DirectXMan12 | Mar 6, 2019 | Implemented | - | + Simplified Builder-Based Scaffolding ==================================== @@ -133,8 +137,8 @@ they think it is, we're probably better served coming up with a standard "can I create this example YAML file". Furthermore, since the structure is quite convoluted, it makes it more -difficult to write examples, since the actual code we care about ends up -scattered deep in a folder structure. +difficult to write examples, as the actual code we care about ends up +scattered deep in the folder structure. ### Lack of Builder diff --git a/designs/template.md b/designs/template.md index 0dea375b4a6..ffb9858efc8 100644 --- a/designs/template.md +++ b/designs/template.md @@ -1,5 +1,8 @@ -Title of the Design -=================== +| Authors | Creation Date | Status | Extra | +|---------------|---------------|-------------|---| +| @name | date | Implementable | - | + +# Title of the Design/Proposal + +## Open Questions [optional] + + + +## Summary + + + +## Motivation + + + +### Goals + + + +### Non-Goals + + + +## Proposal + + + +### User Stories + + + +### Implementation Details/Notes/Constraints [optional] + + + +### Risks and Mitigations + + + +### Proof of Concept [optional] + + + +## Drawbacks + + + +## Alternatives + + diff --git a/designs/update_action.md b/designs/update_action.md new file mode 100644 index 00000000000..40f5c9572c9 --- /dev/null +++ b/designs/update_action.md @@ -0,0 +1,547 @@ +| Authors | Creation Date | Status | Extra | +|-----------------|---------------|-------------|-------| +| @camilamacedo86 | 2024-11-07 | Implementable | - | +| @vitorfloriano | | Implementable | - | + +# Proposal: Automating Operator Maintenance: Driving Better Results with Less Overhead + +## Introduction + +Code-generation tools like **Kubebuilder** and **Operator-SDK** have revolutionized cloud-native application development by providing scalable, community-driven frameworks. These tools simplify complexity, accelerate development, and enable developers to create tailored solutions while avoiding common pitfalls, establishing a strong foundation for innovation. + +However, as these tools evolve to keep up with ecosystem changes and new features, projects risk becoming outdated. Manual updates are time-consuming, error-prone, and create challenges in maintaining security, adopting advancements, and staying aligned with modern standards. + +This project proposes an **automated solution for Kubebuilder**, with potential applications for similar tools or those built on its foundation. By streamlining maintenance, projects remain modern, secure, and adaptable, fostering growth and innovation across the ecosystem. The automation lets developers focus on what matters most: **building great solutions**. + + +## Problem Statement + +Kubebuilder is widely used for developing Kubernetes operators, providing a standardized scaffold. However, as the ecosystem evolves, keeping projects up-to-date presents challenges due to: + +- **Manual re-scaffolding processes**: These are time-intensive and error-prone. +- **Increased risk of outdated configurations**: Leads to security vulnerabilities and incompatibility with modern practices. + +## Proposed Solution + +This proposal introduces a **workflow-based tool** (such as a GitHub Action) that automates updates for Kubebuilder projects. Whenever a new version of Kubebuilder is released, the tool initiates a workflow that: + +1. **Detects the new release**. +2. **Generates an updated scaffold**. +3. **Performs a three-way merge to retain customizations**. +4. **Creates a pull request (PR) summarizing the updates** for review and merging. + +## Example Usage + +### GitHub Actions Workflow: + +1. A user creates a project with Kubebuilder `v4.4.3`. +2. When Kubebuilder `v4.5.0` is released, a **pull request** is automatically created. +3. The PR includes scaffold updates while preserving the user’s customizations, allowing easy review and merging. + +### Local Tool Usage: + +1. A user creates a project with Kubebuilder `v4.4.3` +2. When Kubebuilder `v4.5.0` is released, they run `kubebuilder alpha update` which calls `kubebuilder alpha generate` behind the scenes +3. The tool updates the scaffold and preserves customizations for review and application. +4. In case of conflicts, the tool allows users to resolve them before push a pull request with the changes. + +### Handling Merge Conflicts + +**Local Tool Usage**: + +If conflicts cannot be resolved automatically, developers can manually address +them before completing the update. + +**GitHub Actions Workflow**: + +If conflicts arise during the merge, the action will create a pull request and +the conflicst will be highlighted in the PR. Developers can then review and resolve +them. The PR will contains the default markers: + +**Example** + +```go +<<<<<<< HEAD + _ = logf.FromContext(ctx) +======= +log := log.FromContext(ctx) +>>>>>>> original +``` + +## Open Questions + +### 1. Do we need to create branches to perform the three-way merge,or can we use local temporary directories? + +> While temporary directories are sufficient for simple three-way merges, branches are better suited for complex scenarios. +> They provide history tracking, support collaboration, integrate with CI/CD workflows, and offer more advanced +> conflict resolution through Git’s merge command. For these reasons, it seems more appropriate to use branches to ensure +> flexibility and maintainability in the merging process. + +> Furthermore, branches allows a better resolution strategy, +> since allows us to use `kubebuilder alpha generate` command to-rescaffold the projects +> using the same name directory and provide a better history for the PRs +> allowing users to see the changes and have better insights for conflicts +> resolution. + +### 2. What Git configuration options can facilitate the three-way merge? + +Several Git configuration options can improve the three-way merge process: + +```bash +# Show all three versions (base, current, and updated) during conflicts +git config --global merge.conflictStyle diff3 + +# Enable "reuse recorded resolution" to remember and reuse previous conflict resolutions +git config --global rerere.enabled true + +# Increase the rename detection limit to better handle renamed or moved files +git config --global merge.renameLimit 999999 +``` + +These configurations enhance the merging process by improving conflict visibility, +reusing resolutions, and providing better file handling, making three-way +merges more efficient and developer-friendly. + +### 3. If we change Git configurations, can we isolate these changes to avoid affecting the local developer environment when the tool runs locally? + +It seems that changes can be made using the `-c` flag, which applies the +configuration only for the duration of a specific Git command. This ensures +that the local developer environment remains unaffected. + +For example: + +``` +git -c merge.conflictStyle=diff3 -c rerere.enabled=true merge +``` + +### 4. How can we minimize and resolve conflicts effectively during merges? + +- **Enable Git Features:** + - Use `git config --global rerere.enabled true` to reuse previous conflict resolutions. + - Configure custom merge drivers for specific file types (e.g., `git config --global merge.<driver>.name "Custom Merge Driver"`). + +- **Encourage Standardization:** + - Adopt a standardized scaffold layout to minimize divergence and reduce conflicts. + +- **Apply Frequent Updates:** + - Regularly update projects to avoid significant drift between the scaffold and customizations. + +These strategies help minimize conflicts and simplify their resolution during merges. + +### 5. How to create the PR with the changes for projects that are monorepos? +That means the result of Kubebuilder is not defined in the root dir and might be in other paths. + +We can define an `--output` directory and a configuration for the GitHub Action where +users will define where in their repo the path for the Kubebuilder project is. +However, this might be out of scope for the initial version. + +### 6. How could AI help us solve conflicts? Are there any available solutions? + +While AI tools like GitHub Copilot can assist in code generation and provide suggestions, +however, it might be risky be 100% dependent on AI for conflict resolution, especially in complex scenarios. +Therefore, we might want to use AI as a complementary tool rather than a primary solution. + +AI can help by: +- Providing suggestions for resolving conflicts based on context. +- Analyzing code patterns to suggest potential resolutions. +- Offering explanations for conflicts and suggesting best practices. +- Assisting in summarizing changes. + +## Summary + +### Workflow Example: + +1. A developer creates a project with Kubebuilder `v4.4`. +2. The tooling uses the release of Kubebuilder `v4.5`. +3. The tool: + - Regenerates the original base source code for `v4.4` using the `clientVersion` in the `PROJECT` file. + - Generates the base source code for `v4.5` +4. A three-way merge integrates the changes into the developer’s project while retaining custom code. +5. The changes now can be packaged into a pull request, summarizing updates and conflicts for the developer’s review. + +### Steps: + +The proposed implementation involves the following steps: + +1. **Version Tracking**: + - Record the `clientVersion` (initial Kubebuilder version) in the `PROJECT` file. + - Use this version as a baseline for updates. + - Available in the `PROJECT` file, from [v4.6.0](https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v4.6.0) release onwards. + +2. **Scaffold Generation**: + - Generate the **original scaffold** using the recorded version. + - Generate the **updated scaffold** using the latest Kubebuilder release. + +3. **Three-Way Merge**: + - Ensure git is configured to handle three-way merges. + - Merge the original scaffold, updated scaffold, and the user’s customized project. + - Preserve custom code during the merge. + +4. **(For Actions) - Pull Request Creation**: + - Open a pull request summarizing changes, including details on conflict resolution. + - Schedule updates weekly or provide an on-demand option. + +#### Example Workflow + +The following example code illustrates the proposed idea but has not been evaluated. +This is an early, incomplete draft intended to demonstrate the approach and basic concept. + +We may want to develop a dedicated command-line tool, such as `kubebuilder alpha update`, +to handle tasks like downloading binaries, merging, and updating the scaffold. In this approach, +the GitHub Action would simply invoke this tool to manage the update process and open the +Pull Request, rather than performing each step directly within the Action itself. + +```yaml +name: Workflow Auto-Update + +permissions: + contents: write + pull-requests: write + +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * 1" # Every Monday 00:00 UTC + +jobs: + alpha-update: + runs-on: ubuntu-latest + + steps: + # 1) Checkout the repository with full history + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + # 2) Install the latest stable Go toolchain + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 'stable' + + # 3) Install Kubebuilder CLI + - name: Install Kubebuilder + run: | + curl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)" + chmod +x kubebuilder + sudo mv kubebuilder /usr/local/bin/ + + # 4) Extract Kubebuilder version (e.g., v4.6.0) for branch/title/body + - name: Get Kubebuilder version + id: kb + shell: bash + run: | + RAW="$(kubebuilder version 2>/dev/null || true)" + VERSION="$(printf "%s" "$RAW" | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' | head -1)" + echo "version=${VERSION:-vunknown}" >> "$GITHUB_OUTPUT" + + # 5) Run kubebuilder alpha update + - name: Run kubebuilder alpha update + run: | + kubebuilder alpha update --force + + # 6) Restore workflow files so the update doesn't overwrite CI config + - name: Restore workflows directory + run: | + git restore --source=main --staged --worktree .github/workflows + git add .github/workflows + git commit --amend --no-edit || true + + # 7) Push to a versioned branch; create PR if missing, otherwise it just updates + - name: Push branch and create/update PR + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + set -euo pipefail + VERSION="${{ steps.kb.outputs.version }}" + PR_BRANCH="kubebuilder-update-to-${VERSION}" + + # Create or update the branch and push + git checkout -B "$PR_BRANCH" + git push -u origin "$PR_BRANCH" --force + + PR_TITLE="chore: update scaffolding to Kubebuilder ${VERSION}" + PR_BODY=$'Automated update of Kubebuilder project scaffolding to '"${VERSION}"$'.\n\nMore info: https://github.com/kubernetes-sigs/kubebuilder/releases\n\n :warning: If conflicts arise, resolve them and run:\n```bash\nmake manifests generate fmt vet lint-fix\n```' + + # Try to create the PR; ignore error only if it already exists + if ! gh pr create \ + --title "${PR_TITLE}" \ + --body "${PR_BODY}" \ + --base main \ + --head "$PR_BRANCH" + then + EXISTING="$(gh pr list --state open --head "$PR_BRANCH" --json number --jq '.[0].number' || true)" + if [ -n "${EXISTING}" ]; then + echo "PR #${EXISTING} already exists for ${PR_BRANCH}, branch updated." + else + echo "Failed to create PR for ${PR_BRANCH} and no open PR found." + exit 1 + fi + fi +``` + +## Motivation + +A significant challenge faced by Kubebuilder users is keeping their projects up-to-date with the latest +scaffolds while preserving customizations. The manual processes required for updates are time-consuming, +error-prone, and often discourage users from adopting new versions, leading to outdated and insecure projects. + +The primary motivation for this proposal is to simplify and automate the process of maintaining Kubebuilder +projects. By providing a streamlined workflow for updates, this solution ensures that users can keep +their projects aligned with modern standards while retaining their customizations. + +### Goals + +- **Automate Updates**: Detect and apply scaffold updates while preserving customizations. +- **Simplify Updates**: Generate pull requests for easy review and merging. +- **Provide Local Tooling**: Allow developers to run updates locally with preserved customizations. +- **Keep Projects Current**: Ensure alignment with the latest scaffold improvements. +- **Minimize Disruptions**: Enable scheduled or on-demand updates. + +### Non-Goals + +- **Automating conflict resolution for heavily customized projects**. +- **Automatically merging updates without developer review**. +- **Supporting monorepo project layouts or handling repositories that contain more than just the Kubebuilder-generated code**. + +## Proposal + +### User Stories + +- **As a Kubebuilder maintainer**, I want to help users keep their projects updated with minimal effort, ensuring they adhere to best practices and maintain alignment with project standards. +- **As a user of Kubebuilder**, I want my project to stay up-to-date with the latest scaffold best practices while preserving customizations. +- **As a user of Kubebuilder**, I want an easy way to apply updates across multiple repositories, saving time on manual updates. +- **As a user of Kubebuilder**, I want to ensure my codebases remain secure and maintainable without excessive manual effort. + +### Implementation Details/Notes/Constraints + +- Introduce a new [Kubebuilder Plugin](https://book.kubebuilder.io/plugins/plugins) that scaffolds the + **GitHub Action** based on the POC. This plugin will be released as an **alpha feature**, + allowing users to opt-in for automated updates. + +- The plugin should be added by default in the Golang projects build with Kubebuilder, so new + projects can benefit from the automated updates without additional configuration. While it will not be escaffolded + by default in tools which extend Kubebuilder such as the Operator-SDK, where the alpha generate and update + features cannot be ported or extended. + +- Documentation should be provided to guide users on how to enable and use the new plugin as the new alpha command + +- The alpha command update should + - provide help and examples of usage + - allow users to specify the version of Kubebuilder they want to update to or from to + - allow users to specify the path of the project they want to update + - allow users to specify the output directory where the updated scaffold should be generated + - re-use the existing `kubebuilder alpha generate` command to generate the updated scaffold + +- The `kubebuilder alpha update` command should be covered with e2e tests to ensure it works as expected + and that the generated scaffold is valid and can be built. + +## Risks and Mitigations +- **Risk**: Frequent conflicts may make the process cumbersome. + - *Mitigation*: Provide clear conflict summaries and leverage GitHub preview tools. +- **Risk**: High maintenance overhead. + - *Mitigation*: Build a dedicated command-line tool (`kubebuilder alpha update`) to streamline updates and minimize complexity. + +## Proof of Concept + +The feasibility of re-scaffolding projects has been demonstrated by the +`kubebuilder alpha generate` command. + +**Command Example:** + +```bash +kubebuilder alpha generate +``` + +For more details, refer to the [Alpha Generate Documentation](https://kubebuilder.io/reference/rescaffold). + +This command allows users to manually re-scaffold a project, to allow users add their code on top. +It confirms the technical capability of regenerating and updating scaffolds effectively. + +This proposal builds upon this foundation by automating the process. The proposed tool would extend this functionality +to automatically update projects with new scaffold versions, preserving customizations. + +The three-way merge approach is a common strategy for integrating changes from multiple sources. +It is widely used in version control systems to combine changes from a common ancestor with two sets of modifications. +In the context of this proposal, the three-way merge would combine the original scaffold, the updated scaffold, and the user’s custom code +seems to be very promising. + +### POC Implementation using 3-way merge: + +Following some POCs done to demonstrate the three-way merge approach +where a project was escaffolded with Kubebuilder `v4.5.0` or `v4.5.2` +and then updated to `v4.6.0` + +```shell +## The following options were passed when merging UPGRADE: + +git config --global merge.yaml.name "Custom YAML merge" +git config --global merge.yaml.driver "yaml-merge %O %A %B" +git config merge.conflictStyle diff3 +git config rerere.enabled true +git config merge.renameLimit 999999 +Here are the steps taken: + +## On main: + +git checkout -b ancestor +Clean up the ancestor and commit + +rm -fr * +git add . +git commit -m "clean up ancestor" + +## Bring back the PROJECT file, re-scaffold with v4.5.0, and commit + +git checkout main -- PROJECT +kubebuilder alpha generate +git add . +git commit -m "alpha generate on ancestor with 4.5.0" +## Then proceed to create the original (ours) branch, bring back the code on main, add and commit: + +git checkout -b original +git checkout main -- . +git add . +git commit -m "add code back in original" + +## Then create the upgrade branch (theirs), run kubebuilder alpha generate with v4.6.0 add and commit: + +git checkout ancestor +git checkout -b upgrade +kubebuilder alpha generate +git add . +git commit -m "alpha generate on upgrade with 4.6.0" + +## So now we have the ancestor, the original, and the upgrade branches all set, we can create a branch to commit the merge with the conflict markers: + +git checkout original +git checkout -b merge +git merge upgrade +git add . +git commit -m "Merge with upgrade with conflict markers" +## Now that we have performed the three way merge and commited the conflict markers, we can open a PR against main. +``` + +As the script: + +```bash +#!/bin/bash + +set -euo pipefail + +# CONFIG — change as needed +REPO_PATH="$HOME/go/src/github/camilamacedo86/wordpress-operator" +KUBEBUILDER_SRC="$HOME/go/src/sigs.k8s.io/kubebuilder" +PROJECT_FILE="PROJECT" + +echo "📦 Kubebuilder 3-way merge upgrade (v4.5.0 → v4.6.0)" +echo "📂 Working in: $REPO_PATH" +echo "🧪 Kubebuilder source: $KUBEBUILDER_SRC" + +cd "$REPO_PATH" + +# Step 1: Create ancestor branch and clean it up +echo "🌱 Creating 'ancestor' branch" +git checkout -b ancestor main + +echo "🧼 Cleaning all files and folders (including dotfiles), except .git and PROJECT" +find . -mindepth 1 -maxdepth 1 ! -name '.git' ! -name 'PROJECT' -exec rm -rf {} + + +git add -A +git commit -m "Clean ancestor branch" + +# Step 2: Install Kubebuilder v4.5.0 and regenerate scaffold +echo "⬇️ Installing Kubebuilder v4.5.0" +cd "$KUBEBUILDER_SRC" +git checkout upstream/release-4.5 +make install +kubebuilder version + +cd "$REPO_PATH" +echo "📂 Restoring PROJECT file" +git checkout main -- "$PROJECT_FILE" +kubebuilder alpha generate +make manifests generate fmt vet lint-fix +git add -A +git commit -m "alpha generate on ancestor with v4.5.0" + +# Step 3: Create original branch with user's code +echo "📦 Creating 'original' branch with user code" +git checkout -b original +git checkout main -- . +git add -A +git commit -m "Add project code into original" + +# Step 4: Install Kubebuilder v4.6.0 and scaffold upgrade +echo "⬆️ Installing Kubebuilder v4.6.0" +cd "$KUBEBUILDER_SRC" +git checkout upstream/release-4.6 +make install +kubebuilder version + +cd "$REPO_PATH" +echo "🌿 Creating 'upgrade' branch from ancestor" +git checkout ancestor +git checkout -b upgrade +echo "🧼 Cleaning all files and folders (including dotfiles), except .git and PROJECT" +find . -mindepth 1 -maxdepth 1 ! -name '.git' ! -name 'PROJECT' -exec rm -rf {} + + +kubebuilder alpha generate +make manifests generate fmt vet lint-fix +git add -A +git commit -m "alpha generate on upgrade with v4.6.0" + +# Step 5: Merge original into upgrade and preserve conflicts +echo "🔀 Creating 'merge' branch from upgrade and merging original" +git checkout upgrade +git checkout -b merge + +# Do a non-interactive merge and commit manually +echo "🤖 Running non-interactive merge..." +set +e +git merge --no-edit --no-commit original +MERGE_EXIT_CODE=$? +set -e + +# Stage everything and commit with an appropriate message +if [ $MERGE_EXIT_CODE -ne 0 ]; then + # Manually the alpha generate should out put the info so the person can fix it + echo "⚠️ Conflicts occurred." + echo "You will need to fix the conflicts manually and run the following commands:" + echo "make manifests generate fmt vet lint-fix" + echo "⚠️ Conflicts occurred. Keeping conflict markers and committing them." + git add -A + git commit -m "upgrade has conflicts to be solved" +else + echo "Merge successful with no conflicts. Running commands" + make manifests generate fmt vet lint-fix + + echo "✅ Merge successful with no conflicts." + git add -A + git commit -m "upgrade worked without conflicts" +fi + +echo "" +echo "📍 You are now on the 'merge' branch." +echo "📤 Push with: git push -u origin merge" +echo "🔁 Then open a PR to 'main' on GitHub." +echo "" +``` + +## Drawbacks + +- **Frequent Conflicts:** Automated updates may often result in conflicts, making the process cumbersome for users. +- **Complex Resolutions:** If conflicts are hard to review and resolve, users may find the solution impractical. +- **Maintenance Overhead:** The implementation could become too complex for maintainers to develop and support effectively. + +## Alternatives + +- **Manual Update Workflow**: Continue with manual updates where users regenerate +and merge changes independently, though this is time-consuming and error-prone. +- **Use alpha generate command**: Continue with partially automated updates provided +by the alpha generate command. +- **Dependabot Integration**: Leverage Dependabot for dependency updates, though this +doesn’t fully support scaffold updates and could lead to incomplete upgrades. diff --git a/doc.go b/doc.go deleted file mode 100644 index f9a0cc4d13f..00000000000 --- a/doc.go +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -//go:generate go run github.com/markbates/pkger/cmd/pkger - -// Package kubebuilder contains pkged files compiled into the -// go binaries. -package kubebuilder diff --git a/docs/CONTRIBUTING-ROLES.md b/docs/CONTRIBUTING-ROLES.md index d7536b03924..76d48acdf75 100644 --- a/docs/CONTRIBUTING-ROLES.md +++ b/docs/CONTRIBUTING-ROLES.md @@ -14,7 +14,7 @@ project, or the project as a whole. We follow a similar set of definitions to the [main Kubernetes project itself][kube-ladder], with slightly looser requirements. -As much as possible, we want people to help take on responsibility in the +As much as possible, we want people to help take on responsibility for the project -- these guidelines are attempts to make it *easier* for this to happen, *not harder*. If you've got any questions, just reach out on Slack to one of the [subproject leads][kb-leads] (called @@ -24,7 +24,7 @@ kubebuilder-admins in the `OWNERS_ALIASES` file). Anyone who wants to become a reviewer or approver must first be a [member of the Kubernetes project][kube-member]. The aforementioned doc has more -details, but the gist is that you must have made a couple contributions to +details, but the gist is that you must have made a couple of contributions to some part of the Kubernetes project -- *this includes Kubebuilder and related repos*. Then, you need two existing members to sponsor you. @@ -33,23 +33,23 @@ sponsor you, just ping us on Slack :-)** ## Reviewers -Reviewers are recongized as able to provide code reviews for parts of the -codebase, and are entered into the `reviewers` section of one or more +Reviewers are recognized as able to provide code reviews for parts of the +codebase and are entered into the `reviewers` section of one or more `OWNERS` files. You'll get auto-assigned reviews for your area of the -codebase, and are generally expected to review for both correctness, +codebase and are generally expected to review for correctness, testing, general code organization, etc. Reviewers may review for design as well, but approvers have the final say on that. Things to look for: -- does this code work, and is it written performantly and idomatically? +- does this code work, and is it written performantly and idiomatically? - is it tested? - is it organized nicely? Is it maintainable? - is it documented? - does it need to be threadsafe? Is it? - Take a glance at the stuff for approvers, if you can. -Reviewers' `/lgtm` marks are generally trusted by approvers to mean that +Reviewers' `/lgtm` marks are generally trusted by approvers to means that the code is ready for one last look-over before merging. ### Becoming a Reviewer @@ -65,7 +65,7 @@ worked on a cross-cutting feature, it's ok to count PRs across repositories. Once you meet those criteria, submit yourself as a reviewer in the -`OWNERS` file or files that you feel represent your areas of knowlege via +`OWNERS` file or files that you feel represent your areas of knowledge via a PR to the relevant repository. ## Approvers @@ -75,34 +75,34 @@ Once approvals (`/approve`) are given for each piece of the affected code (and a reviewer or approver has added `/lgtm`), the code will merge. Approvers are responsible for giving the code a final once-over before -merge, and doing an overall design/API review. +merge, and do an overall design/API review. Things to look for: - Does the API exposed to the user make sense, and is it easy to use? -- Is it backwards compatible? +- Is it backward compatible? - Will it accommodate new changes in the future? -- Is it extesnible/layerable (see [DESIGN.md](../DESIGN.md))? +- Is it extensible/layer-able (see [DESIGN.md](../DESIGN.md))? - Does it expose a new type from `k8s.io/XYZ`, and, if so, is it worth it? Is that piece well-designed? -**For large changes, approvers are responsible for getting reasonble +**For large changes, approvers are responsible for getting reasonable consensus**. With the power to approve such changes comes the responsibility of ensuring that the project as a whole has time to discuss them. ### Becoming an Approver -All approvers need to start out as reviewers. The criteria for becoming -an approver are: +All approvers need to start as reviewers. The criteria for becoming +an approver is: -- Be a reviewer in the area for a couple months +- Be a reviewer in the area for a couple of months - Be the "main" reviewer or contributor for 5-10 substantial (bugfixes, features, etc) PRs where approvers did not need to leave substantial additional comments (i.e. where you were acting as a defacto approver). Once you've met those criteria, you can submit yourself as an approver -using a PR that edits the revelant `OWNERS` files appropriately. The +using a PR that edits the relevant `OWNERS` files appropriately. The existing approvers will then approve the change with lazy consensus. If you feel more comfortable asking before submitting the PR, feel free to ping one of the [subproject leads][kb-leads] (called kubebuilder-admins in @@ -110,7 +110,7 @@ the `OWNERS_ALIASES` file) on Slack. ## Indirectly Code-Related/Non-Code Roles -We're always looking help with other areas of the project as well, such +We're always looking for help with other areas of the project as well, such as: ### Docs @@ -120,15 +120,15 @@ reviewers/approvers for the book by following the same process above. ### Triage -Help triaging our issues is also welcome. Folks doing triage are +Help to triage our issues is also welcome. Folks doing triage are responsible for using the following commands to mark PRs and issues with one or more labels, and should also feel free to help answer questions: - `/kind {bug|feature|documentation}`: things that are broken/new - things/things with lots of words, repsectively + things/things with lots of words, respectively - `/triage support`: questions, and things that might be bugs but might - just be confusion of how to use something + just be confused about how to use something - `/priority {backlog|important-longterm|important-soon|critical-urgent}`: how soon we need to deal with the thing (if someone wants diff --git a/docs/README.md b/docs/README.md index 63c3996b1a5..9e90ab3c7ef 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,9 +2,9 @@ The kubebuilder book is served using [mdBook](https://github.com/rust-lang-nursery/mdBook). If you want to test changes to the book locally, follow these directions: -1. Follow the instructions at [https://github.com/rust-lang-nursery/mdBook#installation](https://github.com/rust-lang-nursery/mdBook#installation) to +1. Follow the instructions at [https://rust-lang.github.io/mdBook/guide/installation.html](https://rust-lang.github.io/mdBook/guide/installation.html) to install mdBook. -2. Make sure [controller-gen](https://pkg.go.dev/sigs.k8s.io/controller-tools/cmd/controller-gen) is install in `$GOPATH`. +2. Make sure [controller-gen](https://pkg.go.dev/sigs.k8s.io/controller-tools/cmd/controller-gen) is installed in `$GOPATH`. 3. cd into the `docs/book` directory 4. Run `mdbook serve` 5. Visit [http://localhost:3000](http://localhost:3000) diff --git a/docs/book/book.toml b/docs/book/book.toml index 7aadb547fc5..494f7e82917 100644 --- a/docs/book/book.toml +++ b/docs/book/book.toml @@ -5,12 +5,20 @@ src = "src" title = "The Kubebuilder Book" [output.html] -google-analytics = "UA-119864590-1" -curly-quotes = true -additional-css = ["theme/css/markers.css", "theme/css/custom.css"] +smart-punctuation = true +additional-css = ["theme/css/markers.css", "theme/css/custom.css", "theme/css/version-dropdown.css"] +git-repository-url = "https://github.com/kubernetes-sigs/kubebuilder" +edit-url-template = "https://github.com/kubernetes-sigs/kubebuilder/edit/master/docs/book/{path}" [preprocessor.literatego] command = "./litgo.sh" [preprocessor.markerdocs] command = "./markerdocs.sh" + +[context.environment] + environment = { GO_VERSION = "1.23" } + +[context.deploy-preview.environment] + environment = { GO_VERSION = "1.23" } + diff --git a/docs/book/install-and-build.sh b/docs/book/install-and-build.sh index cb973a4cdfb..59c6d8976f2 100755 --- a/docs/book/install-and-build.sh +++ b/docs/book/install-and-build.sh @@ -23,7 +23,10 @@ THIS_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) cd "$THIS_DIR" -[[ -n "$(command -v gimme)" ]] && eval "$(gimme stable)" +if [[ -n "$(command -v gimme)" ]]; then + GO_VERSION=${GO_VERSION:-stable} # Use the provided GO_VERSION or default to 'stable' + eval "$(gimme $GO_VERSION)" +fi echo go version GOBIN=$THIS_DIR/functions go install ./... @@ -35,6 +38,10 @@ if [[ ${arch} == "amd64" ]]; then arch="x86_64" elif [[ ${arch} == "x86" ]]; then arch="i686" +elif [[ ${arch} == "arm64" ]]; then + # arm64 is not supported for v0.4.40 mdbook, so using x86_64 type. + # Once the mdbook is upgraded to latest, use 'aarch64' + arch="x86_64" fi # translate os to rust's conventions (if we can) @@ -60,14 +67,21 @@ esac # grab mdbook # we hardcode linux/amd64 since rust uses a different naming scheme and it's a pain to tran -echo "downloading mdBook-v0.4.21-${arch}-${target}.${ext}" +MDBOOK_VERSION="v0.4.40" +MDBOOK_BASENAME="mdBook-${MDBOOK_VERSION}-${arch}-${target}" +MDBOOK_URL="https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/${MDBOOK_BASENAME}.${ext}" + +echo "downloading ${MDBOOK_BASENAME}.${ext} from ${MDBOOK_URL}" set -x -curl -sL -o /tmp/mdbook.${ext} https://github.com/rust-lang-nursery/mdBook/releases/download/v0.4.2/mdBook-v0.4.2-${arch}-${target}.${ext} +curl -fL -o /tmp/mdbook.${ext} "${MDBOOK_URL}" ${cmd} /tmp/mdbook.${ext} chmod +x /tmp/mdbook -echo "grabbing the latest released controller-gen" -go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.10.0 +CONTROLLER_GEN_VERSION="v0.19.0" + +echo "grabbing the controller-gen version: ${CONTROLLER_GEN_VERSION}" +go version +go install sigs.k8s.io/controller-tools/cmd/controller-gen@${CONTROLLER_GEN_VERSION} # make sure we add the go bin directory to our path gobin=$(go env GOBIN) diff --git a/docs/book/src/404.md b/docs/book/src/404.md deleted file mode 120000 index cde952be386..00000000000 --- a/docs/book/src/404.md +++ /dev/null @@ -1 +0,0 @@ -TODO.md \ No newline at end of file diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md index 277cb55d186..1645dbb07dd 100644 --- a/docs/book/src/SUMMARY.md +++ b/docs/book/src/SUMMARY.md @@ -2,10 +2,13 @@ [Introduction](./introduction.md) +[Architecture](./architecture.md) + [Quick Start](./quick-start.md) -[Architecture](./architecture.md) +[Getting Started](./getting-started.md) +[Versions Compatibility and Supportability](./versions_compatibility_supportability.md) --- - [Tutorial: Building CronJob](cronjob-tutorial/cronjob-tutorial.md) @@ -26,7 +29,7 @@ - [Implementing defaulting/validating webhooks](./cronjob-tutorial/webhook-implementation.md) - [Running and deploying the controller](./cronjob-tutorial/running.md) - - [Deploying the cert manager](./cronjob-tutorial/cert-manager.md) + - [Deploying cert-manager](./cronjob-tutorial/cert-manager.md) - [Deploying webhooks](./cronjob-tutorial/running-webhook.md) - [Writing tests](./cronjob-tutorial/writing-tests.md) @@ -43,45 +46,46 @@ - [Deployment and Testing](./multiversion-tutorial/deployment.md) -- [Tutorial: Component Config](./component-config-tutorial/tutorial.md) - - - [Changing things up](./component-config-tutorial/api-changes.md) - - [Defining your Config](./component-config-tutorial/define-config.md) - - - [Using a custom type](./component-config-tutorial/custom-type.md) - - - [Adding a new Config Type](./component-config-tutorial/config-type.md) - - [Updating main](./component-config-tutorial/updating-main.md) - - [Defining your Custom Config](./component-config-tutorial/define-custom-config.md) - --- - [Migrations](./migrations.md) - - [Kubebuilder v1 vs v2](./migration/v1vsv2.md) + - [Legacy (before <= v3.0.0)](./migration/legacy.md) + - [Kubebuilder v1 vs v2](migration/legacy/v1vsv2.md) - - [Migration Guide](./migration/legacy/migration_guide_v1tov2.md) + - [Migration Guide](./migration/legacy/migration_guide_v1tov2.md) - - [Kubebuilder v2 vs v3](./migration/v2vsv3.md) + - [Kubebuilder v2 vs v3](migration/legacy/v2vsv3.md) - - [Migration Guide](./migration/migration_guide_v2tov3.md) - - [Migration by updating the files](./migration/manually_migration_guide_v2_v3.md) + - [Migration Guide](migration/legacy/migration_guide_v2tov3.md) + - [Migration by updating the files](migration/legacy/manually_migration_guide_v2_v3.md) + - [From v3.0.0 with plugins](./migration/v3-plugins.md) + - [go/v3 vs go/v4](migration/v3vsv4.md) + - [Migration Guide](migration/migration_guide_gov3_to_gov4.md) + - [Migration by updating the files](migration/manually_migration_guide_gov3_to_gov4.md) - [Single Group to Multi-Group](./migration/multi-group.md) +- [Alpha Commands](./reference/alpha_commands.md) + + - [alpha generate](./reference/commands/alpha_generate.md) + - [alpha update](./reference/commands/alpha_update.md) + --- - [Reference](./reference/reference.md) - [Generating CRDs](./reference/generating-crd.md) - [Using Finalizers](./reference/using-finalizers.md) + - [Good Practices](./reference/good-practices.md) + - [Raising Events](./reference/raising-events.md) - [Watching Resources](./reference/watching-resources.md) - - [Resources Managed by the Operator](./reference/watching-resources/operator-managed.md) - - [Externally Managed Resources](./reference/watching-resources/externally-managed.md) - - [Kind cluster](reference/kind.md) + - [Owned Resources](./reference/watching-resources/secondary-owned-resources.md) + - [Not Owned Resources](./reference/watching-resources/secondary-resources-not-owned.md) + - [Using Predicates](./reference/watching-resources/predicates-with-watch.md) + - [Kind for Dev & CI](reference/kind.md) - [What's a webhook?](reference/webhook-overview.md) - [Admission webhook](reference/admission-webhook.md) - - [Webhooks for Core Types](reference/webhook-for-core-types.md) - [Markers for Config/Code Generation](./reference/markers.md) - [CRD Generation](./reference/markers/crd.md) @@ -90,18 +94,25 @@ - [Webhook](./reference/markers/webhook.md) - [Object/DeepCopy](./reference/markers/object.md) - [RBAC](./reference/markers/rbac.md) + - [Scaffold](./reference/markers/scaffold.md) - [controller-gen CLI](./reference/controller-gen.md) - [completion](./reference/completion.md) - [Artifacts](./reference/artifacts.md) - [Platform Support](./reference/platform.md) + - [Monitoring with Pprof](./reference/pprof-tutorial.md) + + - [Manager and CRDs Scope](./reference/scopes.md) + + - [Sub-Module Layouts](./reference/submodule-layouts.md) + - [Using an external Resource / API](./reference/using_an_external_resource.md) + - [Configuring EnvTest](./reference/envtest.md) - [Metrics](./reference/metrics.md) - [Reference](./reference/metrics-reference.md) - - [Makefile Helpers](./reference/makefile-helpers.md) - [Project config](./reference/project-config.md) --- @@ -109,24 +120,22 @@ - [Plugins][plugins] - [Available Plugins](./plugins/available-plugins.md) - - [To create a project](./docs/invalid) - - [go/v2 (Deprecated)](./plugins/go-v2-plugin.md) - - [go/v3 (Default init scaffold)](./plugins/go-v3-plugin.md) - - [go/v4-alpha](./plugins/go-v4-plugin.md) - - [To add optional features](./docs/invalid) - - [declarative/v1](./plugins/declarative-v1.md) - - [grafana/v1-alpha](./plugins/grafana-v1-alpha.md) - - [deploy-image/v1-alpha](./plugins/deploy-image-plugin-v1-alpha.md) - - [To be extended for others tools](./docs/invalid) - - [kustomize/v1](./plugins/kustomize-v1.md) - - [kustomize/v2-alpha](./plugins/kustomize-v2-alpha.md) - - [Extending the CLI](./plugins/extending-cli.md) - - [Creating your own plugins](./plugins/creating-plugins.md) - - [Testing your own plugins](./plugins/testing-plugins.md) + - [autoupdate/v1-alpha](./plugins/available/autoupdate-v1-alpha.md) + - [deploy-image/v1-alpha](./plugins/available/deploy-image-plugin-v1-alpha.md) + - [go/v4](./plugins/available/go-v4-plugin.md) + - [grafana/v1-alpha](./plugins/available/grafana-v1-alpha.md) + - [helm/v1-alpha](./plugins/available/helm-v1-alpha.md) + - [helm/v2-alpha](./plugins/available/helm-v2-alpha.md) + - [kustomize/v2](./plugins/available/kustomize-v2.md) + - [Extending](./plugins/extending.md) + - [CLI and Plugins](./plugins/extending/extending_cli_features_and_plugins.md) + - [External Plugins](./plugins/extending/external-plugins.md) + - [E2E Tests](./plugins/extending/testing-plugins.md) - [Plugins Versioning](./plugins/plugins-versioning.md) + --- -[Appendix: The TODO Landing Page](./TODO.md) +[FAQ](./faq.md) [plugins]: ./plugins/plugins.md diff --git a/docs/book/src/TODO.md b/docs/book/src/TODO.md index 37a00404fe5..f69f6cae0e9 100644 --- a/docs/book/src/TODO.md +++ b/docs/book/src/TODO.md @@ -1,8 +1,17 @@ -# TODO - -If you're seeing this page, it's probably because something's not done in -the book yet, or you stumbled upon an old link. Go [see if anyone else -has found -this](https://github.com/kubernetes-sigs/kubebuilder/issues?q=is%3Aopen+is%3Aissue+label%3Akind%2Fdocumentation) -or [bug the -maintainers](https://github.com/kubernetes-sigs/kubebuilder/issues/new?assignees=&labels=kind%2Fdocumentation). +# Page Not Found + +The page you are looking for could not be found. This might be because: + +1. The page has been moved or renamed +2. The page is no longer available +3. The URL was entered incorrectly + +Please try: + +- Going back to the [home page](https://book.kubebuilder.io/) +- Using the search function +- Suggest an edit [documentation index](https://github.com/kubernetes-sigs/kubebuilder/tree/master/docs/book/src) + +Check out if someone is working on your issue [report an issue](https://github.com/kubernetes-sigs/kubebuilder/issues) +If you believe this is an error, please [report an issue](https://github.com/kubernetes-sigs/kubebuilder/issues/new?template=BLANK_ISSUE) +Reach out to us on [Slack](https://kubernetes.slack.com/messages/kubebuilder) \ No newline at end of file diff --git a/docs/book/src/architecture.md b/docs/book/src/architecture.md index ef12bd22fa2..bccb71898c1 100644 --- a/docs/book/src/architecture.md +++ b/docs/book/src/architecture.md @@ -1,6 +1,6 @@ # Architecture Concept Diagram -The following diagram will help you get a better idea over the Kubebuilder concepts and architecture. +The following diagram will help you get a better idea over the Kubebuilder concepts and architecture. {{#include ./kb_concept_diagram.svg}} diff --git a/docs/book/src/component-config-tutorial/api-changes.md b/docs/book/src/component-config-tutorial/api-changes.md deleted file mode 100644 index 850fb1411cb..00000000000 --- a/docs/book/src/component-config-tutorial/api-changes.md +++ /dev/null @@ -1,134 +0,0 @@ -# Changing things up - -This tutorial will show you how to create a custom configuration file for your -project by modifying a project generated with the `--component-config` flag -passed to the `init` command. The full tutorial's source can be found -[here][tutorial-source]. Make sure you've gone through the [installation -steps](/quick-start.md#installation) before continuing. - -## New project: - -```bash -# we'll use a domain of tutorial.kubebuilder.io, -# so all API groups will be .tutorial.kubebuilder.io. -kubebuilder init --domain tutorial.kubebuilder.io --component-config -``` - -## Setting up an exising project - -If you've previously generated a project we can add support for parsing the -config file by making the following changes to `main.go`. - -First, add a new `flag` to specify the path that the component config file -should be loaded from. - -```go -var configFile string -flag.StringVar(&configFile, "config", "", - "The controller will load its initial configuration from this file. "+ - "Omit this flag to use the default configuration values. "+ - "Command-line flags override configuration from this file.") -``` - -Now, we can setup the `Options` struct and check if the `configFile` is set, -this allows backwards compatibility, if it's set we'll then use the `AndFrom` -function on `Options` to parse and populate the `Options` from the config. - - -```go -var err error -options := ctrl.Options{Scheme: scheme} -if configFile != "" { - options, err = options.AndFrom(ctrl.ConfigFile().AtPath(configFile)) - if err != nil { - setupLog.Error(err, "unable to load the config file") - os.Exit(1) - } -} -``` - - - -Lastly, we'll change the `NewManager` call to use the `options` varible we -defined above. - -```go -mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) -``` - -With that out of the way, we can get on to defining our new config! - -[tutorial-source]: https://github.com/kubernetes-sigs/kubebuilder/tree/master/docs/book/src/component-config-tutorial/testdata/project - -Create the file `/config/manager/controller_manager_config.yaml` with the following content: - -```yaml -apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 -kind: ControllerManagerConfig -health: - healthProbeBindAddress: :8081 -metrics: - bindAddress: 127.0.0.1:8080 -webhook: - port: 9443 -leaderElection: - leaderElect: true - resourceName: ecaf1259.tutorial.kubebuilder.io -# leaderElectionReleaseOnCancel defines if the leader should step down volume -# when the Manager ends. This requires the binary to immediately end when the -# Manager is stopped, otherwise, this setting is unsafe. Setting this significantly -# speeds up voluntary leader transitions as the new leader don't have to wait -# LeaseDuration time first. -# In the default scaffold provided, the program ends immediately after -# the manager stops, so would be fine to enable this option. However, -# if you are doing or is intended to do any operation such as perform cleanups -# after the manager stops then its usage might be unsafe. -# leaderElectionReleaseOnCancel: true -``` - -Update the file `/config/manager/kustomization.yaml` by adding at the bottom the following content: - -```yaml -generatorOptions: - disableNameSuffixHash: true - -configMapGenerator: -- name: manager-config - files: - - controller_manager_config.yaml -``` - -Update the file `default/kustomization.yaml` by adding under the patchesStrategicMerge: the following patch: - -# Mount the controller config file for loading manager configurations -# through a ComponentConfig type -- manager_config_patch.yaml - -Update the file `default/manager_config_patch.yaml` by adding under the spec: the following patch: - -```yaml -spec: - template: - spec: - containers: - - name: manager - args: - - "--config=controller_manager_config.yaml" - volumeMounts: - - name: manager-config - mountPath: /controller_manager_config.yaml - subPath: controller_manager_config.yaml - volumes: - - name: manager-config - configMap: - name: manager-config -``` - diff --git a/docs/book/src/component-config-tutorial/config-type.md b/docs/book/src/component-config-tutorial/config-type.md deleted file mode 100644 index 5a9660b001e..00000000000 --- a/docs/book/src/component-config-tutorial/config-type.md +++ /dev/null @@ -1,26 +0,0 @@ -# Adding a new Config Type - -To scaffold out a new config Kind, we can use `kubebuilder create api`. - -```bash -kubebuilder create api --group config --version v2 --kind ProjectConfig --resource --controller=false --make=false -``` - - - - -This will create a new type file in `api/config/v2/` for the `ProjectConfig` -kind. We'll need to change this file to embed the -[v1alpha1.ControllerManagerConfigurationSpec](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1/#ControllerManagerConfigurationSpec) - -{{#literatego ./testdata/projectconfig_types.go}} - -Lastly, we'll change the `main.go` to reference this type for parsing the file. \ No newline at end of file diff --git a/docs/book/src/component-config-tutorial/custom-type.md b/docs/book/src/component-config-tutorial/custom-type.md deleted file mode 100644 index 76dfeda43d2..00000000000 --- a/docs/book/src/component-config-tutorial/custom-type.md +++ /dev/null @@ -1,19 +0,0 @@ -# Using a Custom Type - - - -If your project needs to accept additional non-controller runtime specific -configurations, e.g. `ClusterName`, `Region` or anything serializable into -`yaml` you can do this by using `kubebuilder` to create a new type and then -updating your `main.go` to setup the new type for parsing. - -The rest of this tutorial will walk through implementing a custom component -config type. \ No newline at end of file diff --git a/docs/book/src/component-config-tutorial/define-config.md b/docs/book/src/component-config-tutorial/define-config.md deleted file mode 100644 index d745f43fceb..00000000000 --- a/docs/book/src/component-config-tutorial/define-config.md +++ /dev/null @@ -1,12 +0,0 @@ -# Defining your Config - -Now that you have a component config base project we need to customize the -values that are passed into the controller, to do this we can take a look at -`config/manager/controller_manager_config.yaml`. - -{{#literatego ./testdata/controller_manager_config.yaml}} - -To see all the available fields you can look at the `v1alpha` Controller -Runtime config [ControllerManagerConfiguration][configtype] - -[configtype]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1#ControllerManagerConfigurationSpec \ No newline at end of file diff --git a/docs/book/src/component-config-tutorial/define-custom-config.md b/docs/book/src/component-config-tutorial/define-custom-config.md deleted file mode 100644 index fcd3e3f0490..00000000000 --- a/docs/book/src/component-config-tutorial/define-custom-config.md +++ /dev/null @@ -1,11 +0,0 @@ -# Defining your Custom Config - -Now that you have a custom component config we change the -`config/manager/controller_manager_config.yaml` to use the new GVK you defined. - -{{#literatego ./testdata/project/config/manager/controller_manager_config.yaml}} - -This type uses the new `ProjectConfig` kind under the GVK -`config.tutorial.kubebuilder.io/v2`, with these custom configs we can add any -`yaml` serializable fields that your controller needs and begin to reduce the -reliance on `flags` to configure your project. \ No newline at end of file diff --git a/docs/book/src/component-config-tutorial/testdata/controller_manager_config.yaml b/docs/book/src/component-config-tutorial/testdata/controller_manager_config.yaml deleted file mode 100644 index cb5e0786bd3..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/controller_manager_config.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 -kind: ControllerManagerConfig -metrics: - bindAddress: 127.0.0.1:8080 -webhook: - port: 9443 -leaderElection: - leaderElect: true - resourceName: 80807133.tutorial.kubebuilder.io diff --git a/docs/book/src/component-config-tutorial/testdata/generate_componentconfig.sh b/docs/book/src/component-config-tutorial/testdata/generate_componentconfig.sh deleted file mode 100755 index 48848190407..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/generate_componentconfig.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2020 The Kubernetes 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 script is a helper which has just the commands -# to generate the conjob tutorial to let us know update manually the testdata dir -# It allows us run ./generate_cronjob.sh and git diff with to check what requires updates -# NOTE: run make install from the project root before execute it. -# - -set -o errexit -set -o pipefail - -# Turn colors in this script off by setting the NO_COLOR variable in your -# environment to any value: -# -# $ NO_COLOR=1 test.sh -NO_COLOR=${NO_COLOR:-""} -if [ -z "$NO_COLOR" ]; then - header=$'\e[1;33m' - reset=$'\e[0m' -else - header='' - reset='' -fi - -build_kb() { - go build -o ./bin/kubebuilder sigs.k8s.io/kubebuilder/cmd -} - -function header_text { - echo "$header$*$reset" -} - -function gen_component_config_tutorial { - header_text "removing project ..." - rm -rf project - header_text "starting to generate the component config ..." - mkdir project - cd project - header_text "creating tutorial.kubebuilder.io base ..." - kubebuilder init --domain tutorial.kubebuilder.io --repo tutorial.kubebuilder.io/project --component-config --license apache2 --owner "The Kubernetes authors" - kubebuilder create api --group config --version v2 --kind ProjectConfig --resource --controller=false --make=false - go mod tidy - make -} - -gen_component_config_tutorial diff --git a/docs/book/src/component-config-tutorial/testdata/project/.dockerignore b/docs/book/src/component-config-tutorial/testdata/project/.dockerignore deleted file mode 100644 index 0f046820f18..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/.dockerignore +++ /dev/null @@ -1,4 +0,0 @@ -# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file -# Ignore build and test binaries. -bin/ -testbin/ diff --git a/docs/book/src/component-config-tutorial/testdata/project/.gitignore b/docs/book/src/component-config-tutorial/testdata/project/.gitignore deleted file mode 100644 index e917e5cefe5..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ - -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib -bin -testbin/* -Dockerfile.cross - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Kubernetes Generated files - skip generated files, except for vendored files - -!vendor/**/zz_generated.* - -# editor and IDE paraphernalia -.idea -*.swp -*.swo -*~ diff --git a/docs/book/src/component-config-tutorial/testdata/project/Dockerfile b/docs/book/src/component-config-tutorial/testdata/project/Dockerfile deleted file mode 100644 index 8f9cca18eb6..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -# Build the manager binary -FROM golang:1.19 as builder -ARG TARGETOS -ARG TARGETARCH - -WORKDIR /workspace -# Copy the Go Modules manifests -COPY go.mod go.mod -COPY go.sum go.sum -# cache deps before building and copying source so that we don't need to re-download as much -# and so that source changes don't invalidate our downloaded layer -RUN go mod download - -# Copy the go source -COPY main.go main.go -COPY api/ api/ -COPY controllers/ controllers/ - -# Build -# the GOARCH has not a default value to allow the binary be built according to the host where the command -# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO -# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, -# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. -RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager main.go - -# Use distroless as minimal base image to package the manager binary -# Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot -WORKDIR / -COPY --from=builder /workspace/manager . -USER 65532:65532 - -ENTRYPOINT ["/manager"] diff --git a/docs/book/src/component-config-tutorial/testdata/project/Makefile b/docs/book/src/component-config-tutorial/testdata/project/Makefile deleted file mode 100644 index 8f0d39872c2..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/Makefile +++ /dev/null @@ -1,152 +0,0 @@ - -# Image URL to use all building/pushing image targets -IMG ?= controller:latest -# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.25.0 - -# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) -ifeq (,$(shell go env GOBIN)) -GOBIN=$(shell go env GOPATH)/bin -else -GOBIN=$(shell go env GOBIN) -endif - -# Setting SHELL to bash allows bash commands to be executed by recipes. -# Options are set to exit when a recipe line exits non-zero or a piped command fails. -SHELL = /usr/bin/env bash -o pipefail -.SHELLFLAGS = -ec - -.PHONY: all -all: build - -##@ General - -# The help target prints out all targets with their descriptions organized -# beneath their categories. The categories are represented by '##@' and the -# target descriptions by '##'. The awk commands is responsible for reading the -# entire set of makefiles included in this invocation, looking for lines of the -# file as xyz: ## something, and then pretty-format the target and help. Then, -# if there's a line with ##@ something, that gets pretty-printed as a category. -# More info on the usage of ANSI control characters for terminal formatting: -# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters -# More info on the awk command: -# http://linuxcommand.org/lc3_adv_awk.php - -.PHONY: help -help: ## Display this help. - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) - -##@ Development - -.PHONY: manifests -manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases - -.PHONY: generate -generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. - $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." - -.PHONY: fmt -fmt: ## Run go fmt against code. - go fmt ./... - -.PHONY: vet -vet: ## Run go vet against code. - go vet ./... - -.PHONY: test -test: manifests generate fmt vet envtest ## Run tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out - -##@ Build - -.PHONY: build -build: generate fmt vet ## Build manager binary. - go build -o bin/manager main.go - -.PHONY: run -run: manifests generate fmt vet ## Run a controller from your host. - go run ./main.go - -# If you wish built the manager image targeting other platforms you can use the --platform flag. -# (i.e. docker build --platform linux/arm64 ). However, you must enable docker buildKit for it. -# More info: https://docs.docker.com/develop/develop-images/build_enhancements/ -.PHONY: docker-build -docker-build: test ## Build docker image with the manager. - docker build -t ${IMG} . - -.PHONY: docker-push -docker-push: ## Push docker image with the manager. - docker push ${IMG} - -# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple -# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: -# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/ -# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/ -# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=> than the export will fail) -# To properly provided solutions that supports more than one platform you should use this option. -PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le -.PHONY: docker-buildx -docker-buildx: test ## Build and push docker image for the manager for cross-platform support - # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile - sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross - - docker buildx create --name project-v3-builder - docker buildx use project-v3-builder - - docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross - - docker buildx rm project-v3-builder - rm Dockerfile.cross - -##@ Deployment - -ifndef ignore-not-found - ignore-not-found = false -endif - -.PHONY: install -install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. - $(KUSTOMIZE) build config/crd | kubectl apply -f - - -.PHONY: uninstall -uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. - $(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f - - -.PHONY: deploy -deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. - cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} - $(KUSTOMIZE) build config/default | kubectl apply -f - - -.PHONY: undeploy -undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. - $(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f - - -##@ Build Dependencies - -## Location to install dependencies to -LOCALBIN ?= $(shell pwd)/bin -$(LOCALBIN): - mkdir -p $(LOCALBIN) - -## Tool Binaries -KUSTOMIZE ?= $(LOCALBIN)/kustomize -CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen -ENVTEST ?= $(LOCALBIN)/setup-envtest - -## Tool Versions -KUSTOMIZE_VERSION ?= v4.5.7 -CONTROLLER_TOOLS_VERSION ?= v0.10.0 - -KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -.PHONY: kustomize -kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. -$(KUSTOMIZE): $(LOCALBIN) - test -s $(LOCALBIN)/kustomize || { curl -Ss $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); } - -.PHONY: controller-gen -controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. -$(CONTROLLER_GEN): $(LOCALBIN) - test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) - -.PHONY: envtest -envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. -$(ENVTEST): $(LOCALBIN) - test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest diff --git a/docs/book/src/component-config-tutorial/testdata/project/PROJECT b/docs/book/src/component-config-tutorial/testdata/project/PROJECT deleted file mode 100644 index 7b606a9374c..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/PROJECT +++ /dev/null @@ -1,16 +0,0 @@ -componentConfig: true -domain: tutorial.kubebuilder.io -layout: -- go.kubebuilder.io/v3 -projectName: project -repo: tutorial.kubebuilder.io/project -resources: -- api: - crdVersion: v1 - namespaced: true - domain: tutorial.kubebuilder.io - group: config - kind: ProjectConfig - path: tutorial.kubebuilder.io/project/api/v2 - version: v2 -version: "3" diff --git a/docs/book/src/component-config-tutorial/testdata/project/README.md b/docs/book/src/component-config-tutorial/testdata/project/README.md deleted file mode 100644 index 58195d83507..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/README.md +++ /dev/null @@ -1,94 +0,0 @@ -# project -// TODO(user): Add simple overview of use/purpose - -## Description -// TODO(user): An in-depth paragraph about your project and overview of use - -## Getting Started -You’ll need a Kubernetes cluster to run against. You can use [KIND](https://sigs.k8s.io/kind) to get a local cluster for testing, or run against a remote cluster. -**Note:** Your controller will automatically use the current context in your kubeconfig file (i.e. whatever cluster `kubectl cluster-info` shows). - -### Running on the cluster -1. Install Instances of Custom Resources: - -```sh -kubectl apply -f config/samples/ -``` - -2. Build and push your image to the location specified by `IMG`: - -```sh -make docker-build docker-push IMG=/project:tag -``` - -3. Deploy the controller to the cluster with the image specified by `IMG`: - -```sh -make deploy IMG=/project:tag -``` - -### Uninstall CRDs -To delete the CRDs from the cluster: - -```sh -make uninstall -``` - -### Undeploy controller -UnDeploy the controller to the cluster: - -```sh -make undeploy -``` - -## Contributing -// TODO(user): Add detailed information on how you would like others to contribute to this project - -### How it works -This project aims to follow the Kubernetes [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) - -It uses [Controllers](https://kubernetes.io/docs/concepts/architecture/controller/) -which provides a reconcile function responsible for synchronizing resources untile the desired state is reached on the cluster - -### Test It Out -1. Install the CRDs into the cluster: - -```sh -make install -``` - -2. Run your controller (this will run in the foreground, so switch to a new terminal if you want to leave it running): - -```sh -make run -``` - -**NOTE:** You can also run this in one step by running: `make install run` - -### Modifying the API definitions -If you are editing the API definitions, generate the manifests such as CRs or CRDs using: - -```sh -make manifests -``` - -**NOTE:** Run `make --help` for more information on all potential `make` targets - -More information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html) - -## License - -Copyright 2022 The Kubernetes 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. - diff --git a/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go b/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go deleted file mode 100644 index 48c9fa19d75..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright 2022 The Kubernetes 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 contains API Schema definitions for the config v2 API group -// +kubebuilder:object:generate=true -// +groupName=config.tutorial.kubebuilder.io -package v2 - -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/scheme" -) - -var ( - // GroupVersion is group version used to register these objects - GroupVersion = schema.GroupVersion{Group: "config.tutorial.kubebuilder.io", Version: "v2"} - - // SchemeBuilder is used to add go types to the GroupVersionKind scheme - SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} - - // AddToScheme adds the types in this group-version to the given scheme. - AddToScheme = SchemeBuilder.AddToScheme -) diff --git a/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go b/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go deleted file mode 100644 index d18031021b0..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright 2022 The Kubernetes 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" - cfg "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1" -) - -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - -// ProjectConfigSpec defines the desired state of ProjectConfig -type ProjectConfigSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file - - // Foo is an example field of ProjectConfig. Edit projectconfig_types.go to remove/update - Foo string `json:"foo,omitempty"` -} - -// ProjectConfigStatus defines the observed state of ProjectConfig -type ProjectConfigStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file -} - -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status - -// ProjectConfig is the Schema for the projectconfigs API -type ProjectConfig struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec ProjectConfigSpec `json:"spec,omitempty"` - Status ProjectConfigStatus `json:"status,omitempty"` - - // ControllerManagerConfigurationSpec returns the contfigurations for controllers - cfg.ControllerManagerConfigurationSpec `json:",inline"` - - ClusterName string `json:"clusterName,omitempty"` -} - -//+kubebuilder:object:root=true - -// ProjectConfigList contains a list of ProjectConfig -type ProjectConfigList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []ProjectConfig `json:"items"` -} - -func init() { - SchemeBuilder.Register(&ProjectConfig{}, &ProjectConfigList{}) -} diff --git a/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go b/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go deleted file mode 100644 index 8cc16418fcb..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go +++ /dev/null @@ -1,116 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright 2022 The Kubernetes 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 ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ProjectConfig) DeepCopyInto(out *ProjectConfig) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec - out.Status = in.Status - in.ControllerManagerConfigurationSpec.DeepCopyInto(&out.ControllerManagerConfigurationSpec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectConfig. -func (in *ProjectConfig) DeepCopy() *ProjectConfig { - if in == nil { - return nil - } - out := new(ProjectConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ProjectConfig) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ProjectConfigList) DeepCopyInto(out *ProjectConfigList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ProjectConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectConfigList. -func (in *ProjectConfigList) DeepCopy() *ProjectConfigList { - if in == nil { - return nil - } - out := new(ProjectConfigList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ProjectConfigList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ProjectConfigSpec) DeepCopyInto(out *ProjectConfigSpec) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectConfigSpec. -func (in *ProjectConfigSpec) DeepCopy() *ProjectConfigSpec { - if in == nil { - return nil - } - out := new(ProjectConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ProjectConfigStatus) DeepCopyInto(out *ProjectConfigStatus) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectConfigStatus. -func (in *ProjectConfigStatus) DeepCopy() *ProjectConfigStatus { - if in == nil { - return nil - } - out := new(ProjectConfigStatus) - in.DeepCopyInto(out) - return out -} diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/crd/bases/config.tutorial.kubebuilder.io_projectconfigs.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/crd/bases/config.tutorial.kubebuilder.io_projectconfigs.yaml deleted file mode 100644 index 40777ad4082..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/crd/bases/config.tutorial.kubebuilder.io_projectconfigs.yaml +++ /dev/null @@ -1,189 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.10.0 - creationTimestamp: null - name: projectconfigs.config.tutorial.kubebuilder.io -spec: - group: config.tutorial.kubebuilder.io - names: - kind: ProjectConfig - listKind: ProjectConfigList - plural: projectconfigs - singular: projectconfig - scope: Namespaced - versions: - - name: v2 - schema: - openAPIV3Schema: - description: ProjectConfig is the Schema for the projectconfigs API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - cacheNamespace: - description: "CacheNamespace if specified restricts the manager's cache - to watch objects in the desired namespace Defaults to all namespaces - \n Note: If a namespace is specified, controllers can still Watch for - a cluster-scoped resource (e.g Node). For namespaced resources the - cache will only hold objects from the desired namespace." - type: string - clusterName: - type: string - controller: - description: Controller contains global configuration options for controllers - registered within this manager. - properties: - cacheSyncTimeout: - description: CacheSyncTimeout refers to the time limit set to wait - for syncing caches. Defaults to 2 minutes if not set. - format: int64 - type: integer - groupKindConcurrency: - additionalProperties: - type: integer - description: "GroupKindConcurrency is a map from a Kind to the number - of concurrent reconciliation allowed for that controller. \n When - a controller is registered within this manager using the builder - utilities, users have to specify the type the controller reconciles - in the For(...) call. If the object's kind passed matches one of - the keys in this map, the concurrency for that controller is set - to the number specified. \n The key is expected to be consistent - in form with GroupKind.String(), e.g. ReplicaSet in apps group (regardless - of version) would be `ReplicaSet.apps`." - type: object - type: object - gracefulShutDown: - description: GracefulShutdownTimeout is the duration given to runnable - to stop before the manager actually returns on stop. To disable graceful - shutdown, set to time.Duration(0) To use graceful shutdown without timeout, - set to a negative duration, e.G. time.Duration(-1) The graceful shutdown - is skipped for safety reasons in case the leader election lease is lost. - type: string - health: - description: Health contains the controller health configuration - properties: - healthProbeBindAddress: - description: HealthProbeBindAddress is the TCP address that the controller - should bind to for serving health probes - type: string - livenessEndpointName: - description: LivenessEndpointName, defaults to "healthz" - type: string - readinessEndpointName: - description: ReadinessEndpointName, defaults to "readyz" - type: string - type: object - 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 - leaderElection: - description: LeaderElection is the LeaderElection config to be used when - configuring the manager.Manager leader election - properties: - leaderElect: - description: leaderElect enables a leader election client to gain - leadership before executing the main loop. Enable this when running - replicated components for high availability. - type: boolean - leaseDuration: - description: leaseDuration is the duration that non-leader candidates - will wait after observing a leadership renewal until attempting - to acquire leadership of a led but unrenewed leader slot. This is - effectively the maximum duration that a leader can be stopped before - it is replaced by another candidate. This is only applicable if - leader election is enabled. - type: string - renewDeadline: - description: renewDeadline is the interval between attempts by the - acting master to renew a leadership slot before it stops leading. - This must be less than or equal to the lease duration. This is only - applicable if leader election is enabled. - type: string - resourceLock: - description: resourceLock indicates the resource object type that - will be used to lock during leader election cycles. - type: string - resourceName: - description: resourceName indicates the name of resource object that - will be used to lock during leader election cycles. - type: string - resourceNamespace: - description: resourceName indicates the namespace of resource object - that will be used to lock during leader election cycles. - type: string - retryPeriod: - description: retryPeriod is the duration the clients should wait between - attempting acquisition and renewal of a leadership. This is only - applicable if leader election is enabled. - type: string - required: - - leaderElect - - leaseDuration - - renewDeadline - - resourceLock - - resourceName - - resourceNamespace - - retryPeriod - type: object - metadata: - type: object - metrics: - description: Metrics contains thw controller metrics configuration - properties: - bindAddress: - description: BindAddress is the TCP address that the controller should - bind to for serving prometheus metrics. It can be set to "0" to - disable the metrics serving. - type: string - type: object - spec: - description: ProjectConfigSpec defines the desired state of ProjectConfig - properties: - foo: - description: Foo is an example field of ProjectConfig. Edit projectconfig_types.go - to remove/update - type: string - type: object - status: - description: ProjectConfigStatus defines the observed state of ProjectConfig - type: object - syncPeriod: - description: SyncPeriod determines the minimum frequency at which watched - resources are reconciled. A lower period will correct entropy more quickly, - but reduce responsiveness to change if there are many watched resources. - Change this value only if you know what you are doing. Defaults to 10 - hours if unset. there will a 10 percent jitter between the SyncPeriod - of all controllers so that all controllers will not send list requests - simultaneously. - type: string - webhook: - description: Webhook contains the controllers webhook configuration - properties: - certDir: - description: CertDir is the directory that contains the server key - and certificate. if not set, webhook server would look up the server - key and certificate in {TempDir}/k8s-webhook-server/serving-certs. - The server key and certificate must be named tls.key and tls.crt, - respectively. - type: string - host: - description: Host is the hostname that the webhook server binds to. - It is used to set webhook.Server.Host. - type: string - port: - description: Port is the port that the webhook server serves at. It - is used to set webhook.Server.Port. - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/crd/kustomization.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/crd/kustomization.yaml deleted file mode 100644 index 3689b6319c3..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/crd/kustomization.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# This kustomization.yaml is not intended to be run by itself, -# since it depends on service name and namespace that are out of this kustomize package. -# It should be run by config/default -resources: -- bases/config.tutorial.kubebuilder.io_projectconfigs.yaml -#+kubebuilder:scaffold:crdkustomizeresource - -patchesStrategicMerge: -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. -# patches here are for enabling the conversion webhook for each CRD -#- patches/webhook_in_projectconfigs.yaml -#+kubebuilder:scaffold:crdkustomizewebhookpatch - -# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. -# patches here are for enabling the CA injection for each CRD -#- patches/cainjection_in_projectconfigs.yaml -#+kubebuilder:scaffold:crdkustomizecainjectionpatch - -# the following config is for teaching kustomize how to do kustomization for CRDs. -configurations: -- kustomizeconfig.yaml diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/crd/patches/cainjection_in_projectconfigs.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/crd/patches/cainjection_in_projectconfigs.yaml deleted file mode 100644 index d655ae5f8c7..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/crd/patches/cainjection_in_projectconfigs.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: projectconfigs.config.tutorial.kubebuilder.io diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/crd/patches/webhook_in_projectconfigs.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/crd/patches/webhook_in_projectconfigs.yaml deleted file mode 100644 index 4046e3632f9..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/crd/patches/webhook_in_projectconfigs.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: projectconfigs.config.tutorial.kubebuilder.io -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/default/kustomization.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/default/kustomization.yaml deleted file mode 100644 index c5d1f660399..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/default/kustomization.yaml +++ /dev/null @@ -1,75 +0,0 @@ -# Adds namespace to all resources. -namespace: project-system - -# Value of this field is prepended to the -# names of all resources, e.g. a deployment named -# "wordpress" becomes "alices-wordpress". -# Note that it should also match with the prefix (text before '-') of the namespace -# field above. -namePrefix: project- - -# Labels to add to all resources and selectors. -#commonLabels: -# someName: someValue - -bases: -- ../crd -- ../rbac -- ../manager -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -#- ../webhook -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. -#- ../certmanager -# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. -#- ../prometheus - -patchesStrategicMerge: -# Protect the /metrics endpoint by putting it behind auth. -# If you want your controller-manager to expose the /metrics -# endpoint w/o any authn/z, please comment the following line. -- manager_auth_proxy_patch.yaml - - -# Mount the controller config file for loading manager configurations -# through a ComponentConfig type -- manager_config_patch.yaml - -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -#- manager_webhook_patch.yaml - -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -#- webhookcainjection_patch.yaml - -# the following config is for teaching kustomize how to do var substitution -vars: -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -#- name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -#- name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -#- name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_auth_proxy_patch.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_auth_proxy_patch.yaml deleted file mode 100644 index caf52d82500..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_auth_proxy_patch.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# This patch inject a sidecar container which is a HTTP proxy for the -# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: kubernetes.io/arch - operator: In - values: - - amd64 - - arm64 - - ppc64le - - s390x - - key: kubernetes.io/os - operator: In - values: - - linux - containers: - - name: kube-rbac-proxy - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - "ALL" - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 - args: - - "--secure-listen-address=0.0.0.0:8443" - - "--upstream=http://127.0.0.1:8080/" - - "--logtostderr=true" - - "--v=0" - ports: - - containerPort: 8443 - protocol: TCP - name: https - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 5m - memory: 64Mi diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_config_patch.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_config_patch.yaml deleted file mode 100644 index 6c400155cfb..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/default/manager_config_patch.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - args: - - "--config=controller_manager_config.yaml" - volumeMounts: - - name: manager-config - mountPath: /controller_manager_config.yaml - subPath: controller_manager_config.yaml - volumes: - - name: manager-config - configMap: - name: manager-config diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/manager/controller_manager_config.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/manager/controller_manager_config.yaml deleted file mode 100644 index 1391a7ad490..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/manager/controller_manager_config.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 -kind: ControllerManagerConfig -metadata: - labels: - app.kubernetes.io/name: controllermanagerconfig - app.kubernetes.io/instance: controller-manager-configuration - app.kubernetes.io/component: manager - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize -health: - healthProbeBindAddress: :8081 -metrics: - bindAddress: 127.0.0.1:8080 -webhook: - port: 9443 -leaderElection: - leaderElect: true - resourceName: 80807133.tutorial.kubebuilder.io -clusterName: example-test diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/manager/kustomization.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/manager/kustomization.yaml deleted file mode 100644 index 2bcd3eeaa94..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/manager/kustomization.yaml +++ /dev/null @@ -1,10 +0,0 @@ -resources: -- manager.yaml - -generatorOptions: - disableNameSuffixHash: true - -configMapGenerator: -- name: manager-config - files: - - controller_manager_config.yaml diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/manager/manager.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/manager/manager.yaml deleted file mode 100644 index 6f8a6a56c37..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/manager/manager.yaml +++ /dev/null @@ -1,100 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - control-plane: controller-manager - app.kubernetes.io/name: namespace - app.kubernetes.io/instance: system - app.kubernetes.io/component: manager - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: system ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system - labels: - control-plane: controller-manager - app.kubernetes.io/name: deployment - app.kubernetes.io/instance: controller-manager - app.kubernetes.io/component: manager - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize -spec: - selector: - matchLabels: - control-plane: controller-manager - replicas: 1 - template: - metadata: - annotations: - kubectl.kubernetes.io/default-container: manager - labels: - control-plane: controller-manager - spec: - # TODO(user): Uncomment the following code to configure the nodeAffinity expression - # according to the platforms which are supported by your solution. - # It is considered best practice to support multiple architectures. You can - # build your manager image using the makefile target docker-buildx. - # affinity: - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: kubernetes.io/arch - # operator: In - # values: - # - amd64 - # - arm64 - # - ppc64le - # - s390x - # - key: kubernetes.io/os - # operator: In - # values: - # - linux - securityContext: - runAsNonRoot: true - # TODO(user): For common cases that do not require escalating privileges - # it is recommended to ensure that all your Pods/Containers are restrictive. - # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted - # Please uncomment the following code if your project does NOT have to work on old Kubernetes - # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). - # seccompProfile: - # type: RuntimeDefault - containers: - - command: - - /manager - image: controller:latest - name: manager - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - "ALL" - livenessProbe: - httpGet: - path: /healthz - port: 8081 - initialDelaySeconds: 15 - periodSeconds: 20 - readinessProbe: - httpGet: - path: /readyz - port: 8081 - initialDelaySeconds: 5 - periodSeconds: 10 - # TODO(user): Configure the resources accordingly based on the project requirements. - # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 10m - memory: 64Mi - serviceAccountName: controller-manager - terminationGracePeriodSeconds: 10 diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/prometheus/kustomization.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/prometheus/kustomization.yaml deleted file mode 100644 index ed137168a1d..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/prometheus/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: -- monitor.yaml diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/prometheus/monitor.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/prometheus/monitor.yaml deleted file mode 100644 index b694c241666..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/prometheus/monitor.yaml +++ /dev/null @@ -1,26 +0,0 @@ - -# Prometheus Monitor Service (Metrics) -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - labels: - control-plane: controller-manager - app.kubernetes.io/name: servicemonitor - app.kubernetes.io/instance: controller-manager-metrics-monitor - app.kubernetes.io/component: metrics - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: controller-manager-metrics-monitor - namespace: system -spec: - endpoints: - - path: /metrics - port: https - scheme: https - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token - tlsConfig: - insecureSkipVerify: true - selector: - matchLabels: - control-plane: controller-manager diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_client_clusterrole.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_client_clusterrole.yaml deleted file mode 100644 index 500386b28f0..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_client_clusterrole.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: metrics-reader - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: metrics-reader -rules: -- nonResourceURLs: - - "/metrics" - verbs: - - get diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_role.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_role.yaml deleted file mode 100644 index 85e39513cc1..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_role.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: proxy-role - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: proxy-role -rules: -- apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create -- apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_role_binding.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_role_binding.yaml deleted file mode 100644 index 8b5ff114fa1..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_role_binding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: clusterrolebinding - app.kubernetes.io/instance: proxy-rolebinding - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: proxy-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: proxy-role -subjects: -- kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_service.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_service.yaml deleted file mode 100644 index f40b3d2c0bd..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/auth_proxy_service.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - control-plane: controller-manager - app.kubernetes.io/name: service - app.kubernetes.io/instance: controller-manager-metrics-service - app.kubernetes.io/component: kube-rbac-proxy - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: controller-manager-metrics-service - namespace: system -spec: - ports: - - name: https - port: 8443 - protocol: TCP - targetPort: https - selector: - control-plane: controller-manager diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/kustomization.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/kustomization.yaml deleted file mode 100644 index 731832a6ac3..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/kustomization.yaml +++ /dev/null @@ -1,18 +0,0 @@ -resources: -# All RBAC will be applied under this service account in -# the deployment namespace. You may comment out this resource -# if your manager will use a service account that exists at -# runtime. Be sure to update RoleBinding and ClusterRoleBinding -# subjects if changing service account names. -- service_account.yaml -- role.yaml -- role_binding.yaml -- leader_election_role.yaml -- leader_election_role_binding.yaml -# Comment the following 4 lines if you want to disable -# the auth proxy (https://github.com/brancz/kube-rbac-proxy) -# which protects your /metrics endpoint. -- auth_proxy_service.yaml -- auth_proxy_role.yaml -- auth_proxy_role_binding.yaml -- auth_proxy_client_clusterrole.yaml diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/leader_election_role.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/leader_election_role.yaml deleted file mode 100644 index 1488e1ce2fc..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/leader_election_role.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# permissions to do leader election. -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - labels: - app.kubernetes.io/name: role - app.kubernetes.io/instance: leader-election-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: leader-election-role -rules: -- apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - events - verbs: - - create - - patch diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/leader_election_role_binding.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/leader_election_role_binding.yaml deleted file mode 100644 index e54e64cda0b..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/leader_election_role_binding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - labels: - app.kubernetes.io/name: rolebinding - app.kubernetes.io/instance: leader-election-rolebinding - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: leader-election-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: leader-election-role -subjects: -- kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/projectconfig_editor_role.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/projectconfig_editor_role.yaml deleted file mode 100644 index 55f1a364ea8..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/projectconfig_editor_role.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# permissions for end users to edit projectconfigs. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: projectconfig-editor-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: projectconfig-editor-role -rules: -- apiGroups: - - config.tutorial.kubebuilder.io - resources: - - projectconfigs - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - config.tutorial.kubebuilder.io - resources: - - projectconfigs/status - verbs: - - get diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/projectconfig_viewer_role.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/projectconfig_viewer_role.yaml deleted file mode 100644 index 2c010b4fb24..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/projectconfig_viewer_role.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# permissions for end users to view projectconfigs. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: projectconfig-viewer-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: projectconfig-viewer-role -rules: -- apiGroups: - - config.tutorial.kubebuilder.io - resources: - - projectconfigs - verbs: - - get - - list - - watch -- apiGroups: - - config.tutorial.kubebuilder.io - resources: - - projectconfigs/status - verbs: - - get diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/role_binding.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/role_binding.yaml deleted file mode 100644 index b8189618ab9..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/role_binding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: clusterrolebinding - app.kubernetes.io/instance: manager-rolebinding - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: manager-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: manager-role -subjects: -- kind: ServiceAccount - name: controller-manager - namespace: system diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/service_account.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/rbac/service_account.yaml deleted file mode 100644 index 018f2dd1b59..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/rbac/service_account.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/name: serviceaccount - app.kubernetes.io/instance: controller-manager - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: project - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - name: controller-manager - namespace: system diff --git a/docs/book/src/component-config-tutorial/testdata/project/config/samples/config_v2_projectconfig.yaml b/docs/book/src/component-config-tutorial/testdata/project/config/samples/config_v2_projectconfig.yaml deleted file mode 100644 index 145f0f503c7..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/config/samples/config_v2_projectconfig.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: config.tutorial.kubebuilder.io/v2 -kind: ProjectConfig -metadata: - labels: - app.kubernetes.io/name: projectconfig - app.kubernetes.io/instance: projectconfig-sample - app.kubernetes.io/part-of: project - app.kubernetes.io/managed-by: kustomize - app.kubernetes.io/created-by: project - name: projectconfig-sample -spec: - # TODO(user): Add fields here diff --git a/docs/book/src/component-config-tutorial/testdata/project/go.mod b/docs/book/src/component-config-tutorial/testdata/project/go.mod deleted file mode 100644 index 3e750b59f08..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/go.mod +++ /dev/null @@ -1,79 +0,0 @@ -module tutorial.kubebuilder.io/project - -go 1.19 - -require ( - k8s.io/apimachinery v0.25.0 - k8s.io/client-go v0.25.0 - sigs.k8s.io/controller-runtime v0.13.0 -) - -require ( - cloud.google.com/go v0.97.0 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.27 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect - github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/go-logr/logr v1.2.3 // indirect - github.com/go-logr/zapr v1.2.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect - github.com/go-openapi/swag v0.19.14 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.2.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.8 // indirect - github.com/google/gofuzz v1.1.0 // indirect - github.com/google/uuid v1.1.2 // indirect - github.com/imdario/mergo v0.3.12 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.6 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/spf13/pflag v1.0.5 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect - golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect - gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.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/api v0.25.0 // indirect - k8s.io/apiextensions-apiserver v0.25.0 // indirect - k8s.io/component-base v0.25.0 // indirect - k8s.io/klog/v2 v2.70.1 // indirect - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect - k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect -) diff --git a/docs/book/src/component-config-tutorial/testdata/project/go.sum b/docs/book/src/component-config-tutorial/testdata/project/go.sum deleted file mode 100644 index 7441f108840..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/go.sum +++ /dev/null @@ -1,794 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= -github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= -github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -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/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= -github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -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-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -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.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -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/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -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.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -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.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= -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.4.1/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.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -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/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/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.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -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/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -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/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/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -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.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -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.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -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.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -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.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -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/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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -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.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -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.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -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-20190108225652-1e06a53dbb7e/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-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -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-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/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-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -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-20190227155943-e225da77a7e6/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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -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.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -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/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -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.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.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -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-20180628173108-788fd7840127/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-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/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.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0= -k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk= -k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY= -k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E= -k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU= -k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0= -k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E= -k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8= -k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y= -k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= -k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= -sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt b/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt deleted file mode 100644 index b54e305f300..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt +++ /dev/null @@ -1,15 +0,0 @@ -/* -Copyright 2022 The Kubernetes 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. -*/ \ No newline at end of file diff --git a/docs/book/src/component-config-tutorial/testdata/project/main.go b/docs/book/src/component-config-tutorial/testdata/project/main.go deleted file mode 100644 index 1aa06d1a2c4..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/project/main.go +++ /dev/null @@ -1,97 +0,0 @@ -/* -Copyright 2022 The Kubernetes 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 ( - "flag" - "os" - - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) - // to ensure that exec-entrypoint and run can make use of them. - _ "k8s.io/client-go/plugin/pkg/client/auth" - - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - clientgoscheme "k8s.io/client-go/kubernetes/scheme" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/healthz" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - - configv2 "tutorial.kubebuilder.io/project/api/v2" - //+kubebuilder:scaffold:imports -) - -var ( - scheme = runtime.NewScheme() - setupLog = ctrl.Log.WithName("setup") -) - -func init() { - utilruntime.Must(clientgoscheme.AddToScheme(scheme)) - - utilruntime.Must(configv2.AddToScheme(scheme)) - //+kubebuilder:scaffold:scheme -} - -func main() { - var configFile string - flag.StringVar(&configFile, "config", "", - "The controller will load its initial configuration from this file. "+ - "Omit this flag to use the default configuration values. "+ - "Command-line flags override configuration from this file.") - opts := zap.Options{ - Development: true, - } - opts.BindFlags(flag.CommandLine) - flag.Parse() - - ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) - - var err error - ctrlConfig := configv2.ProjectConfig{} - options := ctrl.Options{Scheme: scheme} - if configFile != "" { - options, err = options.AndFrom(ctrl.ConfigFile().AtPath(configFile).OfKind(&ctrlConfig)) - if err != nil { - setupLog.Error(err, "unable to load the config file") - os.Exit(1) - } - } - - mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) - if err != nil { - setupLog.Error(err, "unable to start manager") - os.Exit(1) - } - - //+kubebuilder:scaffold:builder - - if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { - setupLog.Error(err, "unable to set up health check") - os.Exit(1) - } - if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { - setupLog.Error(err, "unable to set up ready check") - os.Exit(1) - } - - setupLog.Info("starting manager") - if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { - setupLog.Error(err, "problem running manager") - os.Exit(1) - } -} diff --git a/docs/book/src/component-config-tutorial/testdata/projectconfig_types.go b/docs/book/src/component-config-tutorial/testdata/projectconfig_types.go deleted file mode 100644 index 137015030ce..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/projectconfig_types.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2020 The Kubernetes 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. -*/ - -// +kubebuilder:docs-gen:collapse=Apache License - -/* -We start out simply enough: we import the `config/v1alpha1` API group, which is -exposed through ControllerRuntime. -*/ -package v2 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - cfg "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1" -) - -// +kubebuilder:object:root=true - -/* -Next, we'll remove the default `ProjectConfigSpec` and `ProjectConfigList` then -we'll embed `cfg.ControllerManagerConfigurationSpec` in `ProjectConfig`. -*/ - -// ProjectConfig is the Schema for the projectconfigs API -type ProjectConfig struct { - metav1.TypeMeta `json:",inline"` - - // ControllerManagerConfigurationSpec returns the contfigurations for controllers - cfg.ControllerManagerConfigurationSpec `json:",inline"` - - ClusterName string `json:"clusterName,omitempty"` -} - -/* -If you haven't, you'll also need to remove the `ProjectConfigList` from the -`SchemeBuilder.Register`. -*/ -func init() { - SchemeBuilder.Register(&ProjectConfig{}) -} diff --git a/docs/book/src/component-config-tutorial/tutorial.md b/docs/book/src/component-config-tutorial/tutorial.md deleted file mode 100644 index 4b5b1785c75..00000000000 --- a/docs/book/src/component-config-tutorial/tutorial.md +++ /dev/null @@ -1,33 +0,0 @@ -# Tutorial: ComponentConfig - -Nearly every project that is built for Kubernetes will eventually need to -support passing in additional configurations into the controller. These could -be to enable better logging, turn on/off specific feature gates, set the sync -period, or a myriad of other controls. Previously this was commonly done using -cli `flags` that your `main.go` would parse to make them accessible within your -program. While this _works_ it's not a future forward design and the Kubernetes -community has been migrating the core components away from this and toward -using versioned config files, referred to as "component configs". - -The rest of this tutorial will show you how to configure your kubebuilder -project with the a component config type then moves on to implementing a custom -type so that you can extend this capability. - - - - -## Resources - -* [Versioned Component Configuration File Design](https://docs.google.com/document/d/1FdaEJUEh091qf5B98HM6_8MS764iXrxxigNIdwHYW9c/) - -* [Config v1alpha1 Go Docs](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1/) diff --git a/docs/book/src/component-config-tutorial/updating-main.md b/docs/book/src/component-config-tutorial/updating-main.md deleted file mode 100644 index 56a6772e8fd..00000000000 --- a/docs/book/src/component-config-tutorial/updating-main.md +++ /dev/null @@ -1,44 +0,0 @@ -# Updating main - -Once you have defined your new custom component config type we need to make -sure our new config type has been imported and the types are registered with -the scheme. _If you used `kubebuilder create api` this should have been -automated._ - -```go -import ( - // ... other imports - configv2 "tutorial.kubebuilder.io/project/apis/config/v2" - // +kubebuilder:scaffold:imports -) -``` -With the package imported we can confirm the types have been added. - -```go -func init() { - // ... other scheme registrations - utilruntime.Must(configv2.AddToScheme(scheme)) - // +kubebuilder:scaffold:scheme -} -``` - -Lastly, we need to change the options parsing in -`main.go` to use this new type. To do this we'll chain `OfKind` onto -`ctrl.ConfigFile()` and pass in a pointer to the config kind. - -```go -var err error -ctrlConfig := configv2.ProjectConfig{} -options := ctrl.Options{Scheme: scheme} -if configFile != "" { - options, err = options.AndFrom(ctrl.ConfigFile().AtPath(configFile).OfKind(&ctrlConfig)) - if err != nil { - setupLog.Error(err, "unable to load the config file") - os.Exit(1) - } -} -``` - -Now if you need to use the `.clusterName` field we defined in our custom kind -you can call `ctrlConfig.ClusterName` which will be populated from the config -file supplied. \ No newline at end of file diff --git a/docs/book/src/cronjob-tutorial/basic-project.md b/docs/book/src/cronjob-tutorial/basic-project.md index b850834cc3a..d333cecc3fd 100644 --- a/docs/book/src/cronjob-tutorial/basic-project.md +++ b/docs/book/src/cronjob-tutorial/basic-project.md @@ -7,7 +7,7 @@ basic pieces of boilerplate. First up, basic infrastructure for building your project: -
`go.mod`: A new Go module matching our project, with +
go.mod: A new Go module matching our project, with basic dependencies ```go @@ -15,14 +15,14 @@ basic dependencies
```
-
`Makefile`: Make targets for building and deploying your controller +
Makefile: Make targets for building and deploying your controller ```makefile {{#include ./testdata/project/Makefile}} ```
-
`PROJECT`: Kubebuilder metadata for scaffolding new components +
PROJECT: Kubebuilder metadata for scaffolding new components ```yaml {{#include ./testdata/project/PROJECT}} diff --git a/docs/book/src/cronjob-tutorial/cert-manager.md b/docs/book/src/cronjob-tutorial/cert-manager.md index 48d84ef5373..8fd0e4cbe21 100644 --- a/docs/book/src/cronjob-tutorial/cert-manager.md +++ b/docs/book/src/cronjob-tutorial/cert-manager.md @@ -1,24 +1,26 @@ -# Deploying the cert manager +# Deploying cert-manager -We suggest using [cert manager](https://github.com/jetstack/cert-manager) for +We suggest using [cert-manager](https://github.com/cert-manager/cert-manager) for provisioning the certificates for the webhook server. Other solutions should also work as long as they put the certificates in the desired location. You can follow -[the cert manager documentation](https://cert-manager.io/docs/installation/) +[the cert-manager documentation](https://cert-manager.io/docs/installation/) to install it. -Cert manager also has a component called CA injector, which is responsible for -injecting the CA bundle into the Mutating|ValidatingWebhookConfiguration. +cert-manager also has a component called [CA +Injector](https://cert-manager.io/docs/concepts/ca-injector/), which is responsible for +injecting the CA bundle into the [`MutatingWebhookConfiguration`](https://pkg.go.dev/k8s.io/api/admissionregistration/v1#MutatingWebhookConfiguration) +/ [`ValidatingWebhookConfiguration`](https://pkg.go.dev/k8s.io/api/admissionregistration/v1#ValidatingWebhookConfiguration). To accomplish that, you need to use an annotation with key `cert-manager.io/inject-ca-from` -in the Mutating|ValidatingWebhookConfiguration objects. -The value of the annotation should point to an existing certificate CR instance +in the [`MutatingWebhookConfiguration`](https://pkg.go.dev/k8s.io/api/admissionregistration/v1#MutatingWebhookConfiguration) +/ [`ValidatingWebhookConfiguration`](https://pkg.go.dev/k8s.io/api/admissionregistration/v1#ValidatingWebhookConfiguration) objects. +The value of the annotation should point to an existing [certificate request instance](https://cert-manager.io/docs/concepts/certificaterequest/) in the format of `/`. This is the [kustomize](https://github.com/kubernetes-sigs/kustomize) patch we -used for annotating the Mutating|ValidatingWebhookConfiguration objects. -```yaml -{{#include ./testdata/project/config/default/webhookcainjection_patch.yaml}} -``` +used for annotating the [`MutatingWebhookConfiguration`](https://pkg.go.dev/k8s.io/api/admissionregistration/v1#MutatingWebhookConfiguration) +/ [`ValidatingWebhookConfiguration`](https://pkg.go.dev/k8s.io/api/admissionregistration/v1#ValidatingWebhookConfiguration) objects. + diff --git a/docs/book/src/cronjob-tutorial/controller-implementation.md b/docs/book/src/cronjob-tutorial/controller-implementation.md index 95dc605f152..be548e069a1 100644 --- a/docs/book/src/cronjob-tutorial/controller-implementation.md +++ b/docs/book/src/cronjob-tutorial/controller-implementation.md @@ -18,7 +18,7 @@ The basic logic of our CronJob controller is this: 7. Requeue when we either see a running job (done automatically) or it's time for the next scheduled run. -{{#literatego ./testdata/project/controllers/cronjob_controller.go}} +{{#literatego ./testdata/project/internal/controller/cronjob_controller.go}} That was a doozy, but now we've got a working controller. Let's test against the cluster, then, if we don't have any issues, deploy it! diff --git a/docs/book/src/cronjob-tutorial/cronjob-tutorial.md b/docs/book/src/cronjob-tutorial/cronjob-tutorial.md index 803ece89611..f87ae89d94c 100644 --- a/docs/book/src/cronjob-tutorial/cronjob-tutorial.md +++ b/docs/book/src/cronjob-tutorial/cronjob-tutorial.md @@ -53,15 +53,18 @@ kubebuilder init --domain tutorial.kubebuilder.io --repo tutorial.kubebuilder.io ``` Now that we've got a project in place, let's take a look at what Kubebuilder has scaffolded for us so far... -[design-doc]: ./extending-cli.md -[cli-plugins-versioning]:./extending-cli.md#plugin-versioning + [semver]: https://semver.org/ [migrations]: ../migrations.md [kb-releases]:https://github.com/kubernetes-sigs/kubebuilder/releases +[design-doc]: ./extending +[cli-plugins-versioning]:./extending#plugin-versioning \ No newline at end of file diff --git a/docs/book/src/plugins/plugins.md b/docs/book/src/plugins/plugins.md index cc341c340c1..66dae4859b6 100644 --- a/docs/book/src/plugins/plugins.md +++ b/docs/book/src/plugins/plugins.md @@ -1,40 +1,47 @@ # Plugins -Since the `3.0.0` Kubebuilder version, preliminary support for plugins was added. You can [Extend the CLI and Scaffolds][extending-cli] as well. See that when users run the CLI commands to perform the scaffolds, the plugins are used: +Kubebuilder's architecture is fundamentally plugin-based. +This design enables the Kubebuilder CLI to evolve while maintaining +backward compatibility with older versions, allowing users to opt-in or +opt-out of specific features, and enabling seamless integration +with external tools. -- To initialize a project with a chain of global plugins: +By leveraging plugins, projects can extend Kubebuilder and use it as a +library to support new functionalities or implement custom scaffolding +tailored to their users' needs. This flexibility allows maintainers +to build on top of Kubebuilder’s foundation, adapting it to specific +use cases while benefiting from its powerful scaffolding engine. -```sh -kubebuilder init --plugins=pluginA,pluginB -``` +Plugins offer several key advantages: + +- **Backward compatibility**: Ensures older layouts and project structures remain functional with newer versions. +- **Customization**: Allows users to opt-in or opt-out for specific features (i.e. [Grafana][grafana-plugin] and [Deploy Image][deploy-image] plugins) +- **Extensibility**: Facilitates integration with third-party tools and projects that wish to provide their own [External Plugins][external-plugins], which can be used alongside Kubebuilder to modify and enhance project scaffolding or introduce new features. -- To perform an optional scaffold using custom plugins: +**For example, to initialize a project with multiple global plugins:** ```sh -kubebuilder create api --plugins=pluginA,pluginB +kubebuilder init --plugins=pluginA,pluginB,pluginC ``` -This section details how to extend Kubebuilder and create your plugins following the same layout structures. - - - - +This section details the available plugins, how to extend Kubebuilder, +and how to create your own plugins while following the same layout structures. -- [Extending the CLI and Scaffolds](extending-cli.md) -- [Creating your own plugins](creating-plugins.md) -- [Testing your plugins](testing-plugins.md) +- [Available Plugins](./available-plugins.md) +- [Extending](./extending.md) +- [Plugins Versioning](./plugins-versioning.md) -[plugins-phase1-design-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/extensible-cli-and-scaffolding-plugins-phase-1.md -[plugins-phase1-design-doc-1.5]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/extensible-cli-and-scaffolding-plugins-phase-1-5.md -[extending-cli]: extending-cli.md -[section-future-vision-plugins]: https://book.kubebuilder.io/plugins/creating-plugins.html#future-vision-for-kubebuilder-plugins +[extending-cli]: extending.md +[grafana-plugin]: ./available/grafana-v1-alpha.md +[deploy-image]: ./available/deploy-image-plugin-v1-alpha.md +[external-plugins]: ./extending/external-plugins.md \ No newline at end of file diff --git a/docs/book/src/plugins/testing-plugins.md b/docs/book/src/plugins/testing-plugins.md deleted file mode 100644 index 0215ca71294..00000000000 --- a/docs/book/src/plugins/testing-plugins.md +++ /dev/null @@ -1,84 +0,0 @@ -# Test Your Plugins - -You can test your plugin in two dimenstion: - -1. Validate your plugin behavior through E2E tests -2. Generate sample projects based on your plugin that can be placed in `./testdata/` - -## Write E2E Tests - -You can check [Kubebuilder/v3/test/e2e/utils](https://pkg.go.dev/sigs.k8s.io/kubebuilder/v3/test/e2e/utils) package that offers `TestContext` of rich methods: - -- [NewTestContext](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L51) helps define: - - Temporary folder for testing projects - - Temporary controller-manager image - - [Kubectl execution method](https://pkg.go.dev/sigs.k8s.io/kubebuilder/v3/test/e2e/utils#Kubectl) - - The cli executable (`kubebuilder`, `operator-sdk`, OR your extended-cli) - -Once defined, you can use `TestContext` to: - -1. Setup testing environment, e.g: - - Cleanup environment, create temp dir. See [Prepare](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L97) - - Install prerequisites CRDs: See [InstallCertManager](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L138), [InstallPrometheusManager](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.6.0/test/e2e/utils/test_context.go#L171) -2. Validate the plugin behavior, e.g: - - Trigger the plugin's bound subcommands. See [Init](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L213), [CreateAPI](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.6.0/test/e2e/utils/test_context.go#L222) - - Use [PluginUtil](https://pkg.go.dev/sigs.k8s.io/kubebuilder/v3/pkg/plugin/util) to verify the scaffolded outputs. See [InsertCode](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/pkg/plugin/util/util.go#L67), [ReplaceInFile](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.6.0/pkg/plugin/util/util.go#L196), [UncommendCode](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.6.0/pkg/plugin/util/util.go#L86) -3. Further make sure the scaffolded output works, e.g: - - Execute commands in your `Makefile`. See [Make](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L240) - - Temporary load image of the testing controller. See [LoadImageToKindCluster](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L283) - - Call Kubectl to validate running resources. See [utils.Kubectl](https://pkg.go.dev/sigs.k8s.io/kubebuilder/v3/test/e2e/utils#Kubectl) -4. Delete temporary resources after testing exited, e.g: - - Uninstall prerequisites CRDs: See [UninstallPrometheusOperManager](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L183) - - Delete temp dir. See [Destroy](https://github.com/kubernetes-sigs/kubebuilder/blob/v3.7.0/test/e2e/utils/test_context.go#L255) - -**References:** [operator-sdk e2e tests](https://github.com/operator-framework/operator-sdk/tree/master/test/e2e/go), [kubebuiler e2e tests](https://github.com/kubernetes-sigs/kubebuilder/tree/master/test/e2e/v3) - -## Generate Test Samples - -It can be straightforward to view content of sample projects generated by your plugin. - -For example, Kubebuilder generate [sample projects](https://github.com/kubernetes-sigs/kubebuilder/tree/v3.7.0/testdata) based on different plugins to validate the layouts. - -Simiply, you can also use `TextContext` to generate folders of scaffolded projects from your plugin. -The commands are very similar as mentioned in [creating-plugins](creating-plugins.md#write-e2e-tests). - -Following is a general workflow to create a sample by the plugin `go/v3`: (`kbc` is an instance of `TextContext`) - -- To initialized a project: - ```go - By("initializing a project") - err = kbc.Init( - "--plugins", "go/v3", - "--project-version", "3", - "--domain", kbc.Domain, - "--fetch-deps=false", - "--component-config=true", - ) - ExpectWithOffset(1, err).NotTo(HaveOccurred()) - ``` -- To define API: - ```go - By("creating API definition") - err = kbc.CreateAPI( - "--group", kbc.Group, - "--version", kbc.Version, - "--kind", kbc.Kind, - "--namespaced", - "--resource", - "--controller", - "--make=false", - ) - ExpectWithOffset(1, err).NotTo(HaveOccurred()) - ``` -- To scaffold webhook configurations: - ```go - By("scaffolding mutating and validating webhooks") - err = kbc.CreateWebhook( - "--group", kbc.Group, - "--version", kbc.Version, - "--kind", kbc.Kind, - "--defaulting", - "--programmatic-validation", - ) - ExpectWithOffset(1, err).NotTo(HaveOccurred()) - ``` diff --git a/docs/book/src/plugins/to-add-optional-features.md b/docs/book/src/plugins/to-add-optional-features.md new file mode 100644 index 00000000000..d6d53a06ccf --- /dev/null +++ b/docs/book/src/plugins/to-add-optional-features.md @@ -0,0 +1,17 @@ +## To add optional features + +The following plugins are useful to generate code and take advantage of optional features + +| Plugin | Key | Description | +|-----------------------------------------------------|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [autoupdate.kubebuilder.io/v1-alpha][autoupdate] | `autoupdate/v1-alpha` | Optional helper which scaffolds a scheduled worker that helps keep your project updated with changes in the ecosystem, significantly reducing the burden of manual maintenance. | +| [deploy-image.go.kubebuilder.io/v1-alpha][deploy] | `deploy-image/v1-alpha` | Optional helper plugin which can be used to scaffold APIs and controller with code implementation to Deploy and Manage an Operand(image). | +| [grafana.kubebuilder.io/v1-alpha][grafana] | `grafana/v1-alpha` | Optional helper plugin which can be used to scaffold Grafana Manifests Dashboards for the default metrics which are exported by controller-runtime. | +| [helm.kubebuilder.io/v1-alpha][helm-v1alpha] (deprecated) | `helm/v1-alpha` | **Deprecated** - Optional helper plugin which can be used to scaffold a Helm Chart to distribute the project under the `dist` directory. Use v2-alpha instead. | +| [helm.kubebuilder.io/v2-alpha][helm-v2alpha] | `helm/v2-alpha` | Optional helper plugin which dynamically generates Helm charts from kustomize output, preserving all customizations | + +[grafana]: ./available/grafana-v1-alpha.md +[deploy]: ./available/deploy-image-plugin-v1-alpha.md +[helm-v1alpha]: ./available/helm-v1-alpha.md +[helm-v2alpha]: ./available/helm-v2-alpha.md +[autoupdate]: ./available/autoupdate-v1-alpha.md \ No newline at end of file diff --git a/docs/book/src/plugins/to-be-extended.md b/docs/book/src/plugins/to-be-extended.md new file mode 100644 index 00000000000..962eda6f44d --- /dev/null +++ b/docs/book/src/plugins/to-be-extended.md @@ -0,0 +1,24 @@ +## To be extended + +The following plugins are useful for other tools and [External Plugins][external-plugins] which are looking to extend the +Kubebuilder functionality. + +You can use the kustomize plugin, which is responsible for scaffolding the +kustomize files under `config/`. The base language plugins are responsible +for scaffolding the necessary Golang files, allowing you to create your +own plugins for other languages (e.g., [Operator-SDK][sdk] enables +users to work with Ansible/Helm) or add additional functionality. + +For example, [Operator-SDK][sdk] has a plugin which integrates the +projects with [OLM][olm] by adding its own features on top. + +| Plugin | Key | Description | +|--------------------------------------------------------|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| [kustomize.common.kubebuilder.io/v2][kustomize-plugin] | `kustomize/v2` | Responsible for scaffolding all [kustomize][kustomize] files under the `config/` directory | +| `base.go.kubebuilder.io/v4` | `base/v4` | Responsible for scaffolding all files which specifically requires Golang. This plugin is used in the composition to create the plugin (`go/v4`) | + +[kustomize]: https://kustomize.io/ +[sdk]: https://github.com/operator-framework/operator-sdk +[olm]: https://olm.operatorframework.io/ +[kustomize-plugin]: ./available/kustomize-v2.md +[external-plugins]: ./extending/external-plugins.md diff --git a/docs/book/src/plugins/to-scaffold-project.md b/docs/book/src/plugins/to-scaffold-project.md new file mode 100644 index 00000000000..7e1744e94fc --- /dev/null +++ b/docs/book/src/plugins/to-scaffold-project.md @@ -0,0 +1,10 @@ +## To scaffold the projects + +The following plugins are useful to scaffold the whole project with the tool. + +| Plugin | Key | Description | +|--------------------------------------------------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [go.kubebuilder.io/v4 - (Default scaffold with Kubebuilder init)][go-v4] | `go/v4` | Scaffold composite by `base.go.kubebuilder.io/v4` and [kustomize.common.kubebuilder.io/v2][kustomize-v2]. Responsible for scaffolding Golang projects and its configurations. | + +[go-v4]: ./available/go-v4-plugin.md +[kustomize-v2]: ./available/kustomize-v2.md \ No newline at end of file diff --git a/docs/book/src/quick-start.md b/docs/book/src/quick-start.md index 7670eaf5839..292647c90ff 100644 --- a/docs/book/src/quick-start.md +++ b/docs/book/src/quick-start.md @@ -9,19 +9,15 @@ This Quick Start guide will cover: ## Prerequisites -- [go](https://golang.org/dl/) version v1.19.0+ +- [go](https://go.dev/dl/) version v1.24.5+ - [docker](https://docs.docker.com/install/) version 17.03+. - [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) version v1.11.3+. - Access to a Kubernetes v1.11.3+ cluster. @@ -31,21 +27,22 @@ Install [kubebuilder](https://sigs.k8s.io/kubebuilder): ```bash # download kubebuilder and install locally. -curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/$\(go env GOOS\)/$\(go env GOARCH\) -chmod +x kubebuilder && mv kubebuilder /usr/local/bin/ +curl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)" +chmod +x kubebuilder && sudo mv kubebuilder /usr/local/bin/ ``` @@ -53,20 +50,6 @@ Kubebuilder provides autocompletion support for Bash and Zsh via the command `ku Create a directory, and then run the init command inside of it to initialize a new project. Follows an example. - - ```bash mkdir -p ~/projects/guestbook cd ~/projects/guestbook @@ -83,7 +66,6 @@ Read the [Go modules blogpost][go-modules-blogpost] if unfamiliar with the modul - ## Create an API Run the following command to create a new API (group/version) as `webapp/v1` and the new Kind(CRD) `Guestbook` on it: @@ -96,21 +78,21 @@ kubebuilder create api --group webapp --version v1 --kind Guestbook

Press Options

If you press `y` for Create Resource [y/n] and for Create Controller [y/n] then this will create the files `api/v1/guestbook_types.go` where the API is defined -and the `controllers/guestbook_controller.go` where the reconciliation business logic is implemented for this Kind(CRD). +and the `internal/controllers/guestbook_controller.go` where the reconciliation business logic is implemented for this Kind(CRD). - **OPTIONAL:** Edit the API definition and the reconciliation business logic. For more info see [Designing an API](/cronjob-tutorial/api-design.md) and [What's in a Controller](cronjob-tutorial/controller-overview.md). -If you are editing the API definitions, generate the manifests such as Custom Resources (CRs) or Custom Resource Defintions (CRDs) using +If you are editing the API definitions, generate the manifests such as Custom Resources (CRs) or Custom Resource Definitions (CRDs) using + ```bash make manifests ``` -
Click here to see an example. `(api/v1/guestbook_types.go)` +
Click here to see an example. (api/v1/guestbook_types.go)

```go @@ -130,7 +112,7 @@ type GuestbookSpec struct { ConfigMapName string `json:"configMapName"` // +kubebuilder:validation:Enum=Phone;Address;Name - Type string `json:"alias,omitempty"` + Type string `json:"type,omitempty"` } // GuestbookStatus defines the observed state of Guestbook @@ -163,10 +145,19 @@ type Guestbook struct {

+ + ## Test It Out -You'll need a Kubernetes cluster to run against. You can use -[KIND](https://sigs.k8s.io/kind) to get a local cluster for testing, or +You'll need a Kubernetes cluster to run against. You can use +[KinD][kind] to get a local cluster for testing, or run against a remote cluster. Install the CRDs into the cluster: + ```bash make install ``` -Run your controller (this will run in the foreground, so switch to a new +For quick feedback and code-level debugging, run your controller (this will run in the foreground, so switch to a new terminal if you want to leave it running): + ```bash make run ``` ## Install Instances of Custom Resources -If you pressed `y` for Create Resource [y/n] then you created a CR for your CRD in your samples (make sure to edit them first if you've changed the -API definition): +If you pressed `y` for Create Resource [y/n] then you created a CR for your CRD in your +`config/samples/` directory. + +Edit `config/samples/webapp_v1_guestbook.yaml` to contain a valid `spec`. For example: + +```yaml +# ... +spec: + foo: bar +``` + +Hint: "foo" is a string field defined in `api/v1/guestbook_types.go`: + +```go +// foo is an example field of Guestbook. Edit guestbook_types.go to remove/update +// +optional +Foo *string `json:"foo,omitempty"` +``` ```bash -kubectl apply -f config/samples/ +kubectl apply -k config/samples/ +``` + +You can have a look at your applied resource now: + +```bash +kubectl get guestbooks.webapp.my.domain guestbook-sample -o yaml ``` ## Run It On the Cluster +When your controller is ready to be packaged and tested in other clusters. + Build and push your image to the location specified by `IMG`: ```bash @@ -212,11 +229,22 @@ make deploy IMG=/:tag ```