├── .github ├── PULL_REQUEST_TEMPLATE │ ├── breaking_change.md │ ├── bug_fix.md │ ├── compat_feature.md │ ├── docs.md │ └── other.md ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── golangci-lint.yml │ ├── ossf-scorecard.yaml │ ├── pr-dependabot.yaml │ ├── pr-gh-workflow-approve.yaml │ ├── release.yaml │ └── verify.yml ├── .gitignore ├── .golangci.yml ├── .gomodcheck.yaml ├── CONTRIBUTING.md ├── FAQ.md ├── LICENSE ├── Makefile ├── OWNERS ├── OWNERS_ALIASES ├── README.md ├── RELEASE.md ├── SECURITY_CONTACTS ├── TMP-LOGGING.md ├── VERSIONING.md ├── alias.go ├── code-of-conduct.md ├── designs ├── README.md ├── cache_options.md ├── component-config.md ├── images │ └── component-config-load.png ├── move-cluster-specific-code-out-of-manager.md ├── priorityqueue.md ├── template.md └── use-selectors-at-cache.md ├── doc.go ├── example_test.go ├── examples ├── README.md ├── builtins │ ├── controller.go │ ├── main.go │ ├── mutatingwebhook.go │ └── validatingwebhook.go ├── crd │ ├── main.go │ └── pkg │ │ ├── groupversion_info.go │ │ ├── resource.go │ │ └── zz_generated.deepcopy.go ├── multiclustersync │ └── main.go ├── priorityqueue │ └── main.go ├── scratch-env │ ├── go.mod │ ├── go.sum │ └── main.go ├── tokenreview │ ├── main.go │ └── tokenreview.go └── typed │ └── main.go ├── go.mod ├── go.sum ├── hack ├── apidiff.sh ├── check-everything.sh ├── ci-check-everything.sh ├── common.sh ├── go-install.sh ├── test-all.sh ├── tools │ └── cmd │ │ └── gomodcheck │ │ └── main.go ├── verify-pr-title.sh └── verify.sh ├── pkg ├── builder │ ├── builder_suite_test.go │ ├── controller.go │ ├── controller_test.go │ ├── doc.go │ ├── example_test.go │ ├── example_webhook_test.go │ ├── options.go │ ├── webhook.go │ └── webhook_test.go ├── cache │ ├── cache.go │ ├── cache_suite_test.go │ ├── cache_test.go │ ├── defaulting_test.go │ ├── delegating_by_gvk_cache.go │ ├── doc.go │ ├── informer_cache.go │ ├── informer_cache_test.go │ ├── informer_cache_unit_test.go │ ├── informertest │ │ └── fake_cache.go │ ├── internal │ │ ├── cache_reader.go │ │ ├── informers.go │ │ ├── informers_test.go │ │ ├── internal_suite_test.go │ │ └── selector.go │ └── multi_namespace_cache.go ├── certwatcher │ ├── certwatcher.go │ ├── certwatcher_suite_test.go │ ├── certwatcher_test.go │ ├── doc.go │ ├── example_test.go │ ├── metrics │ │ └── metrics.go │ └── testdata │ │ └── .gitkeep ├── client │ ├── apiutil │ │ ├── apimachinery.go │ │ ├── apimachinery_test.go │ │ ├── apiutil_suite_test.go │ │ ├── errors.go │ │ ├── restmapper.go │ │ ├── restmapper_test.go │ │ ├── restmapper_wb_test.go │ │ └── testdata │ │ │ └── crd.yaml │ ├── client.go │ ├── client_rest_resources.go │ ├── client_suite_test.go │ ├── client_test.go │ ├── codec.go │ ├── config │ │ ├── config.go │ │ ├── config_suite_test.go │ │ ├── config_test.go │ │ └── doc.go │ ├── doc.go │ ├── dryrun.go │ ├── dryrun_test.go │ ├── example_test.go │ ├── fake │ │ ├── client.go │ │ ├── client_suite_test.go │ │ ├── client_test.go │ │ └── doc.go │ ├── fieldowner.go │ ├── fieldowner_test.go │ ├── fieldvalidation.go │ ├── fieldvalidation_test.go │ ├── interceptor │ │ ├── intercept.go │ │ ├── intercept_test.go │ │ └── interceptor_suite_test.go │ ├── interfaces.go │ ├── metadata_client.go │ ├── namespaced_client.go │ ├── namespaced_client_test.go │ ├── object.go │ ├── options.go │ ├── options_test.go │ ├── patch.go │ ├── patch_test.go │ ├── testdata │ │ └── examplecrd.yaml │ ├── typed_client.go │ ├── unstructured_client.go │ ├── watch.go │ └── watch_test.go ├── cluster │ ├── cluster.go │ ├── cluster_suite_test.go │ ├── cluster_test.go │ └── internal.go ├── config │ └── controller.go ├── controller │ ├── controller.go │ ├── controller_integration_test.go │ ├── controller_suite_test.go │ ├── controller_test.go │ ├── controllertest │ │ ├── doc.go │ │ ├── testing.go │ │ ├── unconventionallisttypecrd.go │ │ └── util.go │ ├── controllerutil │ │ ├── controllerutil.go │ │ ├── controllerutil_suite_test.go │ │ ├── controllerutil_test.go │ │ ├── doc.go │ │ └── example_test.go │ ├── doc.go │ ├── example_test.go │ ├── name.go │ ├── priorityqueue │ │ ├── metrics.go │ │ ├── metrics_test.go │ │ ├── priorityqueue.go │ │ ├── priorityqueue_suite_test.go │ │ └── priorityqueue_test.go │ └── testdata │ │ └── crds │ │ └── unconventionallisttype.yaml ├── conversion │ └── conversion.go ├── doc.go ├── envtest │ ├── binaries.go │ ├── binaries_test.go │ ├── crd.go │ ├── crd_test.go │ ├── doc.go │ ├── envtest_suite_test.go │ ├── envtest_test.go │ ├── helper.go │ ├── komega │ │ ├── OWNERS │ │ ├── default.go │ │ ├── default_test.go │ │ ├── equalobject.go │ │ ├── equalobject_test.go │ │ ├── interfaces.go │ │ ├── komega.go │ │ └── komega_test.go │ ├── server.go │ ├── testdata │ │ ├── crds │ │ │ ├── examplecrd3.yaml │ │ │ └── examplecrd_unserved.yaml │ │ ├── crdv1_original │ │ │ └── example_multiversion_crd1.yaml │ │ ├── crdv1_updated │ │ │ └── example_multiversion_crd1_one_more_version.yaml │ │ ├── example_multiversion_crd1.yaml │ │ ├── examplecrd.yaml │ │ ├── examplecrd_v1.yaml │ │ ├── multiplecrds.yaml │ │ ├── notcrd.yaml │ │ └── webhooks │ │ │ └── manifests.yaml │ ├── webhook.go │ └── webhook_test.go ├── event │ ├── doc.go │ └── event.go ├── finalizer │ ├── finalizer.go │ ├── finalizer_test.go │ └── types.go ├── handler │ ├── doc.go │ ├── enqueue.go │ ├── enqueue_mapped.go │ ├── enqueue_owner.go │ ├── eventhandler.go │ ├── eventhandler_suite_test.go │ ├── eventhandler_test.go │ └── example_test.go ├── healthz │ ├── doc.go │ ├── healthz.go │ ├── healthz_suite_test.go │ └── healthz_test.go ├── internal │ ├── controller │ │ ├── controller.go │ │ ├── controller_suite_test.go │ │ ├── controller_test.go │ │ └── metrics │ │ │ └── metrics.go │ ├── field │ │ └── selector │ │ │ ├── utils.go │ │ │ ├── utils_suite_test.go │ │ │ └── utils_test.go │ ├── flock │ │ ├── doc.go │ │ ├── errors.go │ │ ├── flock_other.go │ │ └── flock_unix.go │ ├── httpserver │ │ └── server.go │ ├── log │ │ └── log.go │ ├── metrics │ │ └── workqueue.go │ ├── objectutil │ │ └── objectutil.go │ ├── recorder │ │ ├── recorder.go │ │ ├── recorder_integration_test.go │ │ ├── recorder_suite_test.go │ │ └── recorder_test.go │ ├── source │ │ ├── event_handler.go │ │ ├── internal_suite_test.go │ │ ├── internal_test.go │ │ └── kind.go │ ├── syncs │ │ ├── syncs.go │ │ └── syncs_test.go │ └── testing │ │ ├── addr │ │ ├── addr_suite_test.go │ │ ├── manager.go │ │ └── manager_test.go │ │ ├── certs │ │ ├── certs_suite_test.go │ │ ├── tinyca.go │ │ └── tinyca_test.go │ │ ├── controlplane │ │ ├── apiserver.go │ │ ├── apiserver_test.go │ │ ├── auth.go │ │ ├── auth_test.go │ │ ├── controlplane_suite_test.go │ │ ├── etcd.go │ │ ├── etcd_test.go │ │ ├── kubectl.go │ │ ├── kubectl_test.go │ │ ├── plane.go │ │ ├── plane_test.go │ │ └── testdata │ │ │ ├── fake-1.19-apiserver.sh │ │ │ └── fake-1.20-apiserver.sh │ │ └── process │ │ ├── arguments.go │ │ ├── arguments_test.go │ │ ├── bin_path_finder.go │ │ ├── bin_path_finder_test.go │ │ ├── procattr_other.go │ │ ├── procattr_unix.go │ │ ├── process.go │ │ ├── process_suite_test.go │ │ └── process_test.go ├── leaderelection │ ├── doc.go │ ├── fake │ │ ├── doc.go │ │ └── leader_election.go │ └── leader_election.go ├── log │ ├── deleg.go │ ├── log.go │ ├── log_suite_test.go │ ├── log_test.go │ ├── null.go │ ├── warning_handler.go │ └── zap │ │ ├── flags.go │ │ ├── kube_helpers.go │ │ ├── zap.go │ │ ├── zap_suite_test.go │ │ └── zap_test.go ├── manager │ ├── doc.go │ ├── example_test.go │ ├── internal.go │ ├── internal │ │ └── integration │ │ │ ├── api │ │ │ ├── v1 │ │ │ │ ├── driver_types.go │ │ │ │ └── groupversion_info.go │ │ │ └── v2 │ │ │ │ ├── driver_types.go │ │ │ │ └── groupversion_info.go │ │ │ ├── manager_suite_test.go │ │ │ └── manager_test.go │ ├── manager.go │ ├── manager_suite_test.go │ ├── manager_test.go │ ├── runnable_group.go │ ├── runnable_group_test.go │ ├── server.go │ ├── signals │ │ ├── doc.go │ │ ├── signal.go │ │ ├── signal_posix.go │ │ ├── signal_test.go │ │ ├── signal_windows.go │ │ └── signals_suite_test.go │ └── testdata │ │ └── custom-config.yaml ├── metrics │ ├── client_go_adapter.go │ ├── doc.go │ ├── filters │ │ ├── filter_suite_test.go │ │ ├── filters.go │ │ └── filters_test.go │ ├── leaderelection.go │ ├── registry.go │ ├── server │ │ ├── doc.go │ │ └── server.go │ └── workqueue.go ├── predicate │ ├── doc.go │ ├── example_test.go │ ├── predicate.go │ ├── predicate_suite_test.go │ └── predicate_test.go ├── reconcile │ ├── doc.go │ ├── example_test.go │ ├── reconcile.go │ ├── reconcile_suite_test.go │ └── reconcile_test.go ├── recorder │ ├── example_test.go │ └── recorder.go ├── scheme │ ├── scheme.go │ ├── scheme_suite_test.go │ └── scheme_test.go ├── source │ ├── doc.go │ ├── example_test.go │ ├── source.go │ ├── source_integration_test.go │ ├── source_suite_test.go │ └── source_test.go └── webhook │ ├── admission │ ├── admission_suite_test.go │ ├── decode.go │ ├── decode_test.go │ ├── defaulter_custom.go │ ├── defaulter_custom_test.go │ ├── doc.go │ ├── http.go │ ├── http_test.go │ ├── metrics │ │ └── metrics.go │ ├── multi.go │ ├── multi_test.go │ ├── response.go │ ├── response_test.go │ ├── validator_custom.go │ ├── validator_custom_test.go │ ├── webhook.go │ └── webhook_test.go │ ├── alias.go │ ├── authentication │ ├── authentication_suite_test.go │ ├── doc.go │ ├── http.go │ ├── http_test.go │ ├── response.go │ ├── response_test.go │ ├── webhook.go │ └── webhook_test.go │ ├── conversion │ ├── conversion.go │ ├── conversion_suite_test.go │ ├── conversion_test.go │ ├── decoder.go │ └── testdata │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── PROJECT │ │ ├── api │ │ ├── v1 │ │ │ ├── externaljob_types.go │ │ │ ├── groupversion_info.go │ │ │ └── zz_generated.deepcopy.go │ │ ├── v2 │ │ │ ├── externaljob_types.go │ │ │ ├── groupversion_info.go │ │ │ └── zz_generated.deepcopy.go │ │ └── v3 │ │ │ ├── externaljob_types.go │ │ │ ├── groupversion_info.go │ │ │ └── zz_generated.deepcopy.go │ │ ├── hack │ │ └── boilerplate.go.txt │ │ └── main.go │ ├── doc.go │ ├── example_test.go │ ├── internal │ └── metrics │ │ └── metrics.go │ ├── server.go │ ├── server_test.go │ ├── webhook_integration_test.go │ └── webhook_suite_test.go └── tools └── setup-envtest ├── README.md ├── env ├── env.go ├── env_suite_test.go ├── env_test.go ├── exit.go └── helpers.go ├── go.mod ├── go.sum ├── main.go ├── remote ├── client.go ├── http_client.go └── read_body.go ├── store ├── helpers.go ├── store.go ├── store_suite_test.go └── store_test.go ├── version ├── version.go ├── version_suite_test.go └── version_test.go ├── versions ├── misc_test.go ├── parse.go ├── parse_test.go ├── platform.go ├── selectors_test.go ├── version.go └── versions_suite_test.go └── workflows ├── workflows.go ├── workflows_suite_test.go ├── workflows_test.go └── workflows_testutils_test.go /.github/PULL_REQUEST_TEMPLATE/breaking_change.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/bug_fix.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/compat_feature.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/docs.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/other.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Please see the documentation for all configuration options: 2 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 3 | version: 2 4 | updates: 5 | # GitHub Actions 6 | - package-ecosystem: "github-actions" 7 | # Workflow files stored in the 8 | # default location of `.github/workflows` 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | groups: 13 | all-github-actions: 14 | patterns: [ "*" ] 15 | commit-message: 16 | prefix: ":seedling:" 17 | labels: 18 | - "ok-to-test" 19 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/golangci-lint.yml: -------------------------------------------------------------------------------- 1 | name: golangci-lint 2 | on: 3 | pull_request: 4 | types: [opened, edited, synchronize, reopened] 5 | branches: 6 | - main 7 | 8 | permissions: 9 | # Required: allow read access to the content for analysis. 10 | contents: read 11 | # Optional: allow read access to pull request. Use with `only-new-issues` option. 12 | pull-requests: read 13 | # Optional: Allow write access to checks to allow the action to annotate code in the PR. 14 | checks: write 15 | 16 | jobs: 17 | golangci: 18 | name: lint 19 | runs-on: ubuntu-latest 20 | strategy: 21 | matrix: 22 | working-directory: 23 | - "" 24 | - tools/setup-envtest 25 | steps: 26 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 27 | - name: Calculate go version 28 | id: vars 29 | run: echo "go_version=$(make go-version)" >> $GITHUB_OUTPUT 30 | - name: Set up Go 31 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # tag=v5.5.0 32 | with: 33 | go-version: ${{ steps.vars.outputs.go_version }} 34 | - name: golangci-lint 35 | uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # tag=v8.0.0 36 | with: 37 | version: v2.1.6 38 | args: --output.text.print-linter-name=true --output.text.colors=true --timeout 10m 39 | working-directory: ${{matrix.working-directory}} 40 | -------------------------------------------------------------------------------- /.github/workflows/ossf-scorecard.yaml: -------------------------------------------------------------------------------- 1 | name: Scorecard supply-chain security 2 | on: 3 | # For Branch-Protection check. Only the default branch is supported. See 4 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection 5 | branch_protection_rule: 6 | # To guarantee Maintained check is occasionally updated. See 7 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained 8 | schedule: 9 | # Weekly on Saturdays. 10 | - cron: '30 1 * * 6' 11 | push: 12 | branches: [ "main" ] 13 | 14 | # Declare default permissions as read only. 15 | permissions: read-all 16 | 17 | jobs: 18 | analysis: 19 | name: Scorecard analysis 20 | runs-on: ubuntu-latest 21 | permissions: 22 | # Needed if using Code scanning alerts 23 | security-events: write 24 | # Needed for GitHub OIDC token if publish_results is true 25 | id-token: write 26 | 27 | steps: 28 | - name: "Checkout code" 29 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 30 | with: 31 | persist-credentials: false 32 | 33 | - name: "Run analysis" 34 | uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # tag=v2.4.1 35 | with: 36 | results_file: results.sarif 37 | results_format: sarif 38 | # Public repositories: 39 | # - Publish results to OpenSSF REST API for easy access by consumers 40 | # - Allows the repository to include the Scorecard badge. 41 | # - See https://github.com/ossf/scorecard-action#publishing-results. 42 | publish_results: true 43 | 44 | # Upload the results as artifacts. 45 | - name: "Upload artifact" 46 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # tag=v4.6.2 47 | with: 48 | name: SARIF file 49 | path: results.sarif 50 | retention-days: 5 51 | 52 | # required for Code scanning alerts 53 | - name: "Upload to code-scanning" 54 | uses: github/codeql-action/upload-sarif@83a02f7883b12e0e4e1a146174f5e2292a01e601 # tag=v2.16.4 55 | with: 56 | sarif_file: results.sarif 57 | -------------------------------------------------------------------------------- /.github/workflows/pr-dependabot.yaml: -------------------------------------------------------------------------------- 1 | name: PR dependabot go modules fix 2 | 3 | # This action runs on PRs opened by dependabot and updates modules. 4 | on: 5 | pull_request: 6 | branches: 7 | - dependabot/** 8 | push: 9 | branches: 10 | - dependabot/** 11 | workflow_dispatch: 12 | 13 | permissions: 14 | contents: write # Allow to update the PR. 15 | 16 | jobs: 17 | build: 18 | name: Build 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Check out code 22 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 23 | - name: Calculate go version 24 | id: vars 25 | run: echo "go_version=$(make go-version)" >> $GITHUB_OUTPUT 26 | - name: Set up Go 27 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # tag=v5.5.0 28 | with: 29 | go-version: ${{ steps.vars.outputs.go_version }} 30 | - name: Update all modules 31 | run: make modules 32 | - uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # tag=v9.1.4 33 | name: Commit changes 34 | with: 35 | author_name: dependabot[bot] 36 | author_email: 49699333+dependabot[bot]@users.noreply.github.com 37 | default_author: github_actor 38 | message: 'Update generated code' 39 | -------------------------------------------------------------------------------- /.github/workflows/pr-gh-workflow-approve.yaml: -------------------------------------------------------------------------------- 1 | name: PR approve GH Workflows 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - edited 7 | - labeled 8 | - reopened 9 | - synchronize 10 | 11 | permissions: {} 12 | 13 | jobs: 14 | approve: 15 | name: Approve ok-to-test 16 | if: contains(github.event.pull_request.labels.*.name, 'ok-to-test') 17 | runs-on: ubuntu-latest 18 | permissions: 19 | actions: write 20 | steps: 21 | - name: Update PR 22 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 23 | continue-on-error: true 24 | with: 25 | github-token: ${{ secrets.GITHUB_TOKEN }} 26 | script: | 27 | const result = await github.rest.actions.listWorkflowRunsForRepo({ 28 | owner: context.repo.owner, 29 | repo: context.repo.repo, 30 | event: "pull_request", 31 | status: "action_required", 32 | head_sha: context.payload.pull_request.head.sha, 33 | per_page: 100 34 | }); 35 | 36 | for (var run of result.data.workflow_runs) { 37 | await github.rest.actions.approveWorkflowRun({ 38 | owner: context.repo.owner, 39 | repo: context.repo.repo, 40 | run_id: run.id 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Upload binaries to release 2 | 3 | on: 4 | push: 5 | # Sequence of patterns matched against refs/tags 6 | tags: 7 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 8 | 9 | permissions: 10 | contents: write 11 | 12 | jobs: 13 | build: 14 | name: Upload binaries to release 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Set env 18 | run: echo "RELEASE_TAG=${GITHUB_REF:10}" >> $GITHUB_ENV 19 | - name: Check out code 20 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 21 | - name: Calculate go version 22 | id: vars 23 | run: echo "go_version=$(make go-version)" >> $GITHUB_OUTPUT 24 | - name: Set up Go 25 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # tag=v5.5.0 26 | with: 27 | go-version: ${{ steps.vars.outputs.go_version }} 28 | - name: Generate release binaries 29 | run: | 30 | make release 31 | - name: Release 32 | uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # tag=v2.2.2 33 | with: 34 | draft: false 35 | files: tools/setup-envtest/out/* 36 | -------------------------------------------------------------------------------- /.github/workflows/verify.yml: -------------------------------------------------------------------------------- 1 | name: PR title verifier 2 | 3 | on: 4 | pull_request_target: 5 | types: [opened, edited, synchronize, reopened] 6 | 7 | jobs: 8 | verify: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 13 | 14 | - name: Check if PR title is valid 15 | env: 16 | PR_TITLE: ${{ github.event.pull_request.title }} 17 | run: | 18 | ./hack/verify-pr-title.sh "${PR_TITLE}" 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # editor and IDE paraphernalia 15 | .idea 16 | *.swp 17 | *.swo 18 | *~ 19 | 20 | # Vscode files 21 | .vscode 22 | 23 | # Tools binaries. 24 | hack/tools/bin 25 | 26 | # Release artifacts 27 | tools/setup-envtest/out 28 | 29 | junit-report.xml 30 | /artifacts 31 | -------------------------------------------------------------------------------- /.gomodcheck.yaml: -------------------------------------------------------------------------------- 1 | upstreamRefs: 2 | - k8s.io/api 3 | - k8s.io/apiextensions-apiserver 4 | - k8s.io/apimachinery 5 | - k8s.io/apiserver 6 | - k8s.io/client-go 7 | - k8s.io/component-base 8 | # k8s.io/klog/v2 -> conflicts with k/k deps 9 | # k8s.io/utils -> conflicts with k/k deps 10 | 11 | excludedModules: 12 | # --- test dependencies: 13 | - github.com/onsi/ginkgo/v2 14 | - github.com/onsi/gomega 15 | 16 | # --- We want a newer version with generics support for this 17 | - github.com/google/btree 18 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guidelines 2 | 3 | ## Sign the CLA 4 | 5 | Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests. 6 | 7 | Please see https://git.k8s.io/community/CLA.md for more info 8 | 9 | ## Contributing steps 10 | 11 | 1. Submit an issue describing your proposed change to the repo in question. 12 | 1. The [repo owners](OWNERS) will respond to your issue promptly. 13 | 1. If your proposed change is accepted, and you haven't already done so, sign a Contributor License Agreement (see details above). 14 | 1. Fork the desired repo, develop and test your code changes. 15 | 1. Submit a pull request. 16 | 17 | ## Test locally 18 | 19 | Run the command `make test` to test the changes locally. 20 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs: https://git.k8s.io/community/contributors/guide/owners.md 2 | 3 | approvers: 4 | - controller-runtime-admins 5 | - controller-runtime-maintainers 6 | - controller-runtime-approvers 7 | reviewers: 8 | - controller-runtime-admins 9 | - controller-runtime-maintainers 10 | - controller-runtime-approvers 11 | - controller-runtime-reviewers 12 | -------------------------------------------------------------------------------- /OWNERS_ALIASES: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs: https://git.k8s.io/community/contributors/guide/owners.md 2 | 3 | aliases: 4 | # active folks who can be contacted to perform admin-related 5 | # tasks on the repo, or otherwise approve any PRS. 6 | controller-runtime-admins: 7 | - vincepri 8 | - joelanford 9 | 10 | # non-admin folks who have write-access and can approve any PRs in the repo 11 | controller-runtime-maintainers: 12 | - alvaroaleman 13 | - joelanford 14 | - sbueringer 15 | - vincepri 16 | 17 | # non-admin folks who can approve any PRs in the repo 18 | controller-runtime-approvers: 19 | - fillzpp 20 | 21 | # folks who can review and LGTM any PRs in the repo (doesn't 22 | # include approvers & admins -- those count too via the OWNERS 23 | # file) 24 | controller-runtime-reviewers: 25 | - varshaprasad96 26 | - inteon 27 | - JoelSpeed 28 | - troy0820 29 | 30 | # folks who may have context on ancient history, 31 | # but are no longer directly involved 32 | controller-runtime-emeritus-maintainers: 33 | - directxman12 34 | controller-runtime-emeritus-admins: 35 | - droot 36 | - mengqiy 37 | - pwittrock 38 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Team to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | alvaroaleman 14 | sbueringer 15 | vincepri 16 | -------------------------------------------------------------------------------- /VERSIONING.md: -------------------------------------------------------------------------------- 1 | # Versioning and Branching in controller-runtime 2 | 3 | We follow the [common KubeBuilder versioning guidelines][guidelines], and 4 | use the corresponding tooling. 5 | 6 | For the purposes of the aforementioned guidelines, controller-runtime 7 | counts as a "library project", but otherwise follows the guidelines 8 | exactly. 9 | 10 | [guidelines]: https://sigs.k8s.io/kubebuilder-release-tools/VERSIONING.md 11 | 12 | ## Compatibility and Release Support 13 | 14 | For release branches, we generally tend to support backporting one (1) 15 | major release (`release-{X-1}` or `release-0.{Y-1}`), but may go back 16 | further if the need arises and is very pressing (e.g. security updates). 17 | 18 | ### Dependency Support 19 | 20 | Note the [guidelines on dependency versions][dep-versions]. Particularly: 21 | 22 | - We **DO** guarantee Kubernetes REST API compatibility -- if a given 23 | version of controller-runtime stops working with what should be 24 | a supported version of Kubernetes, this is almost certainly a bug. 25 | 26 | - We **DO NOT** guarantee any particular compatibility matrix between 27 | kubernetes library dependencies (client-go, apimachinery, etc); Such 28 | compatibility is infeasible due to the way those libraries are versioned. 29 | 30 | [dep-versions]: https://sigs.k8s.io/kubebuilder-release-tools/VERSIONING.md#kubernetes-version-compatibility 31 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /designs/README.md: -------------------------------------------------------------------------------- 1 | Designs 2 | ======= 3 | 4 | These are the design documents for changes to Controller Runtime. They 5 | exist to help document the design processes that go into writing 6 | Controller Runtime, but may not be up-to-date (more below). 7 | 8 | Not all changes to Controller Runtime need a design document -- only major 9 | ones. Use your best judgement. 10 | 11 | When submitting a design document, we encourage having written 12 | a proof-of-concept, and it's perfectly acceptable to submit the 13 | proof-of-concept PR simultaneously with the design document, as the 14 | proof-of-concept process can help iron out wrinkles and can help with the 15 | `Example` section of the template. 16 | 17 | ## Out-of-Date Designs 18 | 19 | **Controller Runtime documentation 20 | [GoDoc](https://pkg.go.dev/sigs.k8s.io/controller-runtime) should be 21 | considered the canonical, update-to-date reference and architectural 22 | documentation** for Controller Runtime. 23 | 24 | However, if you see an out-of-date design document, feel free to submit 25 | a PR marking it as such, and add an addendum linking to issues documenting 26 | why things changed. For example: 27 | 28 | ```markdown 29 | 30 | # Out of Date 31 | 32 | This change is out of date. It turns out curly braces are frustrating to 33 | type, so we had to abandon functions entirely, and have users specify 34 | custom functionality using strings of Common LISP instead. See #000 for 35 | more information. 36 | ``` 37 | -------------------------------------------------------------------------------- /designs/images/component-config-load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/1dce6213f6c078f3170921b3a774304d066d5bd4/designs/images/component-config-load.png -------------------------------------------------------------------------------- /designs/template.md: -------------------------------------------------------------------------------- 1 | Title of the Design 2 | =================== 3 | 4 | 8 | 9 | ## Example 10 | 11 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | These two examples represent the usage of `controller-runtime` libraries for built-in Kubernetes resources as well as custom resources. 4 | 5 | ### builtins/ 6 | 7 | This example implements a custom controller and webhooks for the *existing* ReplicaSet resource. 8 | 9 | * `controller.go`: implements a reconciler for ReplicaSets 10 | * `mutatingwebhook.go`: implements a mutating webhook that adds an annotation to every incoming Pod ("example-mutating-admission-webhook" = "foo") 11 | * `validatingwebhook.go`: implements a validating webhook that checks to see if a Pod has the aforementioned annotation 12 | * `main.go` 13 | 1. Creates a new manager 14 | 2. Creates a new controller that watches both ReplicaSets and Pods and reconciles the objects with the implemented reconciler 15 | 3. Registers the mutating and validating webhooks with the manager 16 | 4. Starts the manager 17 | 18 | ### crd/ 19 | 20 | This example implements a *new* Kubernetes resource, ChaosPod, and creates a custom controller that watches it and webhooks that mutate and validate. 21 | 22 | * `pkg/` 23 | * `resource.go`: defines the schema for the ChaosPod API and implements validate and mutate webhooks 24 | * `groupversion_info.go`: specifies the Group and Version for the ChaosPod API 25 | * `zz_generated.deepcopy.go`: deep copy functions generated by kubebuilder 26 | * `main.go` 27 | 1. Creates a new manager 28 | 2. Adds ChaosPod resource to the manager's schema 29 | 3. Implements a reconciler to execute the desired behavior of the ChaosPod API 30 | 4. Creates a new controller that watches ChaosPods and reconciles the objects with the implemented reconciler 31 | 5. Adds ChaosPod webhooks to manager 32 | 6. Starts the manager 33 | 34 | ## Deploying and Running 35 | 36 | To install and run the provided examples, see the Kubebuilder [Quick Start](https://book.kubebuilder.io/quick-start.html). -------------------------------------------------------------------------------- /examples/builtins/mutatingwebhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | 23 | corev1 "k8s.io/api/core/v1" 24 | "k8s.io/apimachinery/pkg/runtime" 25 | 26 | logf "sigs.k8s.io/controller-runtime/pkg/log" 27 | ) 28 | 29 | // +kubebuilder:webhook:path=/mutate--v1-pod,mutating=true,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io 30 | 31 | // podAnnotator annotates Pods 32 | type podAnnotator struct{} 33 | 34 | func (a *podAnnotator) Default(ctx context.Context, obj runtime.Object) error { 35 | log := logf.FromContext(ctx) 36 | pod, ok := obj.(*corev1.Pod) 37 | if !ok { 38 | return fmt.Errorf("expected a Pod but got a %T", obj) 39 | } 40 | 41 | if pod.Annotations == nil { 42 | pod.Annotations = map[string]string{} 43 | } 44 | pod.Annotations["example-mutating-admission-webhook"] = "foo" 45 | log.Info("Annotated Pod") 46 | 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /examples/builtins/validatingwebhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | 23 | corev1 "k8s.io/api/core/v1" 24 | "k8s.io/apimachinery/pkg/runtime" 25 | 26 | logf "sigs.k8s.io/controller-runtime/pkg/log" 27 | "sigs.k8s.io/controller-runtime/pkg/webhook/admission" 28 | ) 29 | 30 | // +kubebuilder:webhook:path=/validate--v1-pod,mutating=false,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=vpod.kb.io 31 | 32 | // podValidator validates Pods 33 | type podValidator struct{} 34 | 35 | // validate admits a pod if a specific annotation exists. 36 | func (v *podValidator) validate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { 37 | log := logf.FromContext(ctx) 38 | pod, ok := obj.(*corev1.Pod) 39 | if !ok { 40 | return nil, fmt.Errorf("expected a Pod but got a %T", obj) 41 | } 42 | 43 | log.Info("Validating Pod") 44 | key := "example-mutating-admission-webhook" 45 | anno, found := pod.Annotations[key] 46 | if !found { 47 | return nil, fmt.Errorf("missing annotation %s", key) 48 | } 49 | if anno != "foo" { 50 | return nil, fmt.Errorf("annotation %s did not have value %q", key, "foo") 51 | } 52 | 53 | return nil, nil 54 | } 55 | 56 | func (v *podValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { 57 | return v.validate(ctx, obj) 58 | } 59 | 60 | func (v *podValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { 61 | return v.validate(ctx, newObj) 62 | } 63 | 64 | func (v *podValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { 65 | return v.validate(ctx, obj) 66 | } 67 | -------------------------------------------------------------------------------- /examples/crd/pkg/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +kubebuilder:object:generate=true 18 | // +groupName=chaosapps.metamagical.io 19 | package pkg 20 | 21 | import ( 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | "sigs.k8s.io/controller-runtime/pkg/scheme" 24 | ) 25 | 26 | var ( 27 | // SchemeGroupVersion is group version used to register these objects 28 | SchemeGroupVersion = schema.GroupVersion{Group: "chaosapps.metamagical.io", Version: "v1"} 29 | 30 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 31 | SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} 32 | 33 | // AddToScheme is required by pkg/client/... 34 | AddToScheme = SchemeBuilder.AddToScheme 35 | ) 36 | -------------------------------------------------------------------------------- /examples/crd/pkg/resource.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package pkg 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | ) 23 | 24 | // ChaosPodSpec defines the desired state of ChaosPod 25 | type ChaosPodSpec struct { 26 | Template corev1.PodTemplateSpec `json:"template"` 27 | // +optional 28 | NextStop metav1.Time `json:"nextStop,omitempty"` 29 | } 30 | 31 | // ChaosPodStatus defines the observed state of ChaosPod. 32 | // It should always be reconstructable from the state of the cluster and/or outside world. 33 | type ChaosPodStatus struct { 34 | LastRun metav1.Time `json:"lastRun,omitempty"` 35 | } 36 | 37 | // +kubebuilder:object:root=true 38 | 39 | // ChaosPod is the Schema for the randomjobs API 40 | // +kubebuilder:printcolumn:name="next stop",type="string",JSONPath=".spec.nextStop",format="date" 41 | // +kubebuilder:printcolumn:name="last run",type="string",JSONPath=".status.lastRun",format="date" 42 | type ChaosPod struct { 43 | metav1.TypeMeta `json:",inline"` 44 | metav1.ObjectMeta `json:"metadata,omitempty"` 45 | 46 | Spec ChaosPodSpec `json:"spec,omitempty"` 47 | Status ChaosPodStatus `json:"status,omitempty"` 48 | } 49 | 50 | // +kubebuilder:object:root=true 51 | 52 | // ChaosPodList contains a list of ChaosPod 53 | type ChaosPodList struct { 54 | metav1.TypeMeta `json:",inline"` 55 | metav1.ListMeta `json:"metadata,omitempty"` 56 | Items []ChaosPod `json:"items"` 57 | } 58 | 59 | func init() { 60 | SchemeBuilder.Register(&ChaosPod{}, &ChaosPodList{}) 61 | } 62 | -------------------------------------------------------------------------------- /examples/priorityqueue/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "os" 23 | "time" 24 | 25 | "go.uber.org/zap/zapcore" 26 | corev1 "k8s.io/api/core/v1" 27 | "k8s.io/utils/ptr" 28 | "sigs.k8s.io/controller-runtime/pkg/builder" 29 | kubeconfig "sigs.k8s.io/controller-runtime/pkg/client/config" 30 | "sigs.k8s.io/controller-runtime/pkg/config" 31 | "sigs.k8s.io/controller-runtime/pkg/log" 32 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 33 | "sigs.k8s.io/controller-runtime/pkg/manager" 34 | "sigs.k8s.io/controller-runtime/pkg/manager/signals" 35 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 36 | ) 37 | 38 | func init() { 39 | } 40 | 41 | func main() { 42 | if err := run(); err != nil { 43 | fmt.Fprintf(os.Stderr, "%v\n", err) 44 | os.Exit(1) 45 | } 46 | } 47 | 48 | func run() error { 49 | log.SetLogger(zap.New(func(o *zap.Options) { 50 | o.Level = zapcore.Level(-5) 51 | })) 52 | 53 | // Setup a Manager 54 | mgr, err := manager.New(kubeconfig.GetConfigOrDie(), manager.Options{ 55 | Controller: config.Controller{UsePriorityQueue: ptr.To(true)}, 56 | }) 57 | if err != nil { 58 | return fmt.Errorf("failed to set up controller-manager: %w", err) 59 | } 60 | 61 | if err := builder.ControllerManagedBy(mgr). 62 | For(&corev1.ConfigMap{}). 63 | Complete(reconcile.Func(func(ctx context.Context, r reconcile.Request) (reconcile.Result, error) { 64 | log.FromContext(ctx).Info("Reconciling") 65 | time.Sleep(10 * time.Second) 66 | 67 | return reconcile.Result{}, nil 68 | })); err != nil { 69 | return fmt.Errorf("failed to set up controller: %w", err) 70 | } 71 | 72 | if err := mgr.Start(signals.SetupSignalHandler()); err != nil { 73 | return fmt.Errorf("failed to start manager: %w", err) 74 | } 75 | 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /examples/tokenreview/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "os" 21 | 22 | _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" 23 | "sigs.k8s.io/controller-runtime/pkg/client/config" 24 | "sigs.k8s.io/controller-runtime/pkg/log" 25 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 26 | "sigs.k8s.io/controller-runtime/pkg/manager" 27 | "sigs.k8s.io/controller-runtime/pkg/manager/signals" 28 | "sigs.k8s.io/controller-runtime/pkg/webhook/authentication" 29 | ) 30 | 31 | func init() { 32 | log.SetLogger(zap.New()) 33 | } 34 | 35 | func main() { 36 | entryLog := log.Log.WithName("entrypoint") 37 | 38 | // Setup a Manager 39 | entryLog.Info("setting up manager") 40 | mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{}) 41 | if err != nil { 42 | entryLog.Error(err, "unable to set up overall controller manager") 43 | os.Exit(1) 44 | } 45 | 46 | // Setup webhooks 47 | entryLog.Info("setting up webhook server") 48 | hookServer := mgr.GetWebhookServer() 49 | 50 | entryLog.Info("registering webhooks to the webhook server") 51 | hookServer.Register("/validate-v1-tokenreview", &authentication.Webhook{Handler: &authenticator{}}) 52 | 53 | entryLog.Info("starting manager") 54 | if err := mgr.Start(signals.SetupSignalHandler()); err != nil { 55 | entryLog.Error(err, "unable to run manager") 56 | os.Exit(1) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/tokenreview/tokenreview.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | 22 | v1 "k8s.io/api/authentication/v1" 23 | 24 | "sigs.k8s.io/controller-runtime/pkg/webhook/authentication" 25 | ) 26 | 27 | // authenticator validates tokenreviews 28 | type authenticator struct { 29 | } 30 | 31 | // authenticator admits a request by the token. 32 | func (a *authenticator) Handle(ctx context.Context, req authentication.Request) authentication.Response { 33 | if req.Spec.Token == "invalid" { 34 | return authentication.Unauthenticated("invalid is an invalid token", v1.UserInfo{}) 35 | } 36 | return authentication.Authenticated("", v1.UserInfo{}) 37 | } 38 | -------------------------------------------------------------------------------- /examples/typed/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | networkingv1 "k8s.io/api/networking/v1" 9 | ctrl "sigs.k8s.io/controller-runtime" 10 | "sigs.k8s.io/controller-runtime/pkg/builder" 11 | "sigs.k8s.io/controller-runtime/pkg/handler" 12 | "sigs.k8s.io/controller-runtime/pkg/manager/signals" 13 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 14 | "sigs.k8s.io/controller-runtime/pkg/source" 15 | ) 16 | 17 | func main() { 18 | if err := run(); err != nil { 19 | fmt.Fprintf(os.Stderr, "%v\n", err) 20 | os.Exit(1) 21 | } 22 | } 23 | 24 | func run() error { 25 | mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{}) 26 | if err != nil { 27 | return fmt.Errorf("failed to construct manager: %w", err) 28 | } 29 | 30 | // Use a request type that is always equal to itself so the workqueue 31 | // de-duplicates all events. 32 | // This can for example be useful for an ingress-controller that 33 | // generates a config from all ingresses, rather than individual ones. 34 | type request struct{} 35 | 36 | r := reconcile.TypedFunc[request](func(ctx context.Context, _ request) (reconcile.Result, error) { 37 | ingressList := &networkingv1.IngressList{} 38 | if err := mgr.GetClient().List(ctx, ingressList); err != nil { 39 | return reconcile.Result{}, fmt.Errorf("failed to list ingresses: %w", err) 40 | } 41 | 42 | buildIngressConfig(ingressList) 43 | return reconcile.Result{}, nil 44 | }) 45 | if err := builder.TypedControllerManagedBy[request](mgr). 46 | WatchesRawSource(source.TypedKind( 47 | mgr.GetCache(), 48 | &networkingv1.Ingress{}, 49 | handler.TypedEnqueueRequestsFromMapFunc(func(context.Context, *networkingv1.Ingress) []request { 50 | return []request{{}} 51 | })), 52 | ). 53 | Named("ingress_controller"). 54 | Complete(r); err != nil { 55 | return fmt.Errorf("failed to construct ingress-controller: %w", err) 56 | } 57 | 58 | ctx := signals.SetupSignalHandler() 59 | if err := mgr.Start(ctx); err != nil { 60 | return fmt.Errorf("failed to start manager: %w", err) 61 | } 62 | 63 | return nil 64 | } 65 | 66 | func buildIngressConfig(*networkingv1.IngressList) {} 67 | -------------------------------------------------------------------------------- /hack/apidiff.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | source $(dirname ${BASH_SOURCE})/common.sh 22 | 23 | REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 24 | cd "${REPO_ROOT}" 25 | 26 | export GOTOOLCHAIN="go$(make --silent go-version)" 27 | 28 | header_text "verifying api diff" 29 | echo "*** Running go-apidiff ***" 30 | APIDIFF_OLD_COMMIT="${PULL_BASE_SHA}" make verify-apidiff 31 | -------------------------------------------------------------------------------- /hack/check-everything.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | hack_dir=$(dirname ${BASH_SOURCE}) 22 | source ${hack_dir}/common.sh 23 | 24 | tmp_root=/tmp 25 | kb_root_dir=$tmp_root/kubebuilder 26 | 27 | export GOTOOLCHAIN="go$(make --silent go-version)" 28 | 29 | # Run verification scripts. 30 | ${hack_dir}/verify.sh 31 | 32 | # Envtest. 33 | ENVTEST_K8S_VERSION=${ENVTEST_K8S_VERSION:-"1.32.0"} 34 | 35 | header_text "installing envtest tools@${ENVTEST_K8S_VERSION} with setup-envtest if necessary" 36 | tmp_bin=/tmp/cr-tests-bin 37 | ( 38 | # don't presume to install for the user 39 | cd ${hack_dir}/../tools/setup-envtest 40 | GOBIN=${tmp_bin} go install . 41 | ) 42 | export KUBEBUILDER_ASSETS="$(${tmp_bin}/setup-envtest use --use-env -p path "${ENVTEST_K8S_VERSION}")" 43 | 44 | # Run tests. 45 | ${hack_dir}/test-all.sh 46 | 47 | header_text "confirming examples compile (via go install)" 48 | go install ${MOD_OPT} ./examples/builtins 49 | go install ${MOD_OPT} ./examples/crd 50 | 51 | echo "passed" 52 | exit 0 53 | -------------------------------------------------------------------------------- /hack/ci-check-everything.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | export TRACE=1 20 | 21 | # Not included or existing by default in Prow 22 | export PATH=$(go env GOPATH)/bin:$PATH 23 | mkdir -p $(go env GOPATH)/bin 24 | 25 | $(dirname ${BASH_SOURCE})/check-everything.sh 26 | -------------------------------------------------------------------------------- /hack/common.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | # Enable tracing in this script off by setting the TRACE variable in your 20 | # environment to any value: 21 | # 22 | # $ TRACE=1 test.sh 23 | TRACE=${TRACE:-""} 24 | if [ -n "$TRACE" ]; then 25 | set -x 26 | fi 27 | 28 | # check if modules are enabled 29 | (go mod edit -json &>/dev/null) 30 | MODULES_ENABLED=$? 31 | 32 | MOD_OPT="" 33 | MODULES_OPT=${MODULES_OPT:-""} 34 | if [[ -n "${MODULES_OPT}" && $MODULES_ENABLED ]]; then 35 | MOD_OPT="-mod=${MODULES_OPT}" 36 | fi 37 | 38 | # Turn colors in this script off by setting the NO_COLOR variable in your 39 | # environment to any value: 40 | # 41 | # $ NO_COLOR=1 test.sh 42 | NO_COLOR=${NO_COLOR:-""} 43 | if [ -z "$NO_COLOR" ]; then 44 | header=$'\e[1;33m' 45 | reset=$'\e[0m' 46 | else 47 | header='' 48 | reset='' 49 | fi 50 | 51 | function header_text { 52 | echo "$header$*$reset" 53 | } 54 | -------------------------------------------------------------------------------- /hack/go-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2021 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -o errexit 17 | set -o nounset 18 | set -o pipefail 19 | 20 | if [ -z "${1}" ]; then 21 | echo "must provide module as first parameter" 22 | exit 1 23 | fi 24 | 25 | if [ -z "${2}" ]; then 26 | echo "must provide binary name as second parameter" 27 | exit 1 28 | fi 29 | 30 | if [ -z "${3}" ]; then 31 | echo "must provide version as third parameter" 32 | exit 1 33 | fi 34 | 35 | if [ -z "${GOBIN}" ]; then 36 | echo "GOBIN is not set. Must set GOBIN to install the bin in a specified directory." 37 | exit 1 38 | fi 39 | 40 | rm -f "${GOBIN}/${2}"* || true 41 | 42 | # install the golang module specified as the first argument 43 | go install "${1}@${3}" 44 | mv "${GOBIN}/${2}" "${GOBIN}/${2}-${3}" 45 | ln -sf "${GOBIN}/${2}-${3}" "${GOBIN}/${2}" 46 | -------------------------------------------------------------------------------- /hack/test-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | source $(dirname ${BASH_SOURCE})/common.sh 20 | 21 | header_text "running go test" 22 | 23 | if [[ -n ${ARTIFACTS:-} ]]; then 24 | GINKGO_ARGS="-ginkgo.junit-report=junit-report.xml" 25 | fi 26 | 27 | result=0 28 | go test -v -race ${P_FLAG} ${MOD_OPT} ./... --ginkgo.fail-fast ${GINKGO_ARGS} || result=$? 29 | 30 | if [[ -n ${ARTIFACTS:-} ]]; then 31 | mkdir -p ${ARTIFACTS} 32 | for file in `find . -name *junit-report.xml`; do 33 | new_file=${file#./} 34 | new_file=${new_file%/junit-report.xml} 35 | new_file=${new_file//"/"/"-"} 36 | mv "$file" "$ARTIFACTS/junit_${new_file}.xml" 37 | done 38 | fi 39 | 40 | exit $result 41 | -------------------------------------------------------------------------------- /hack/verify-pr-title.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2024 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Define regex patterns 18 | WIP_REGEX="^\W?WIP\W" 19 | TAG_REGEX="^\[[[:alnum:]\._-]*\]" 20 | PR_TITLE="$1" 21 | 22 | # Trim WIP and tags from title 23 | trimmed_title=$(echo "$PR_TITLE" | sed -E "s/$WIP_REGEX//" | sed -E "s/$TAG_REGEX//" | xargs) 24 | 25 | # Normalize common emojis in text form to actual emojis 26 | trimmed_title=$(echo "$trimmed_title" | sed -E "s/:warning:/⚠/g") 27 | trimmed_title=$(echo "$trimmed_title" | sed -E "s/:sparkles:/✨/g") 28 | trimmed_title=$(echo "$trimmed_title" | sed -E "s/:bug:/🐛/g") 29 | trimmed_title=$(echo "$trimmed_title" | sed -E "s/:book:/📖/g") 30 | trimmed_title=$(echo "$trimmed_title" | sed -E "s/:rocket:/🚀/g") 31 | trimmed_title=$(echo "$trimmed_title" | sed -E "s/:seedling:/🌱/g") 32 | 33 | # Check PR type prefix 34 | if [[ "$trimmed_title" =~ ^(⚠|✨|🐛|📖|🚀|🌱) ]]; then 35 | echo "PR title is valid: $trimmed_title" 36 | else 37 | echo "Error: No matching PR type indicator found in title." 38 | echo "You need to have one of these as the prefix of your PR title:" 39 | echo "- Breaking change: ⚠ (:warning:)" 40 | echo "- Non-breaking feature: ✨ (:sparkles:)" 41 | echo "- Patch fix: 🐛 (:bug:)" 42 | echo "- Docs: 📖 (:book:)" 43 | echo "- Release: 🚀 (:rocket:)" 44 | echo "- Infra/Tests/Other: 🌱 (:seedling:)" 45 | exit 1 46 | fi 47 | 48 | # Check that PR title does not contain Issue or PR number 49 | if [[ "$trimmed_title" =~ \#[0-9]+ ]]; then 50 | echo "Error: PR title should not contain issue or PR number." 51 | echo "Issue numbers belong in the PR body as either \"Fixes #XYZ\" (if it closes the issue or PR), or something like \"Related to #XYZ\" (if it's just related)." 52 | exit 1 53 | fi 54 | 55 | -------------------------------------------------------------------------------- /hack/verify.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | source $(dirname ${BASH_SOURCE})/common.sh 20 | 21 | REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | cd "${REPO_ROOT}" 23 | 24 | header_text "running modules" 25 | make modules 26 | 27 | # Only run verify-modules in CI, otherwise updating 28 | # go module locally (which is a valid operation) causes `make test` to fail. 29 | if [[ -n ${CI} ]]; then 30 | header_text "verifying modules" 31 | make verify-modules 32 | fi 33 | 34 | header_text "running golangci-lint" 35 | make lint 36 | -------------------------------------------------------------------------------- /pkg/builder/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package builder wraps other controller-runtime libraries and exposes simple 18 | // patterns for building common Controllers. 19 | // 20 | // Projects built with the builder package can trivially be rebased on top of the underlying 21 | // packages if the project requires more customized behavior in the future. 22 | package builder 23 | 24 | import ( 25 | logf "sigs.k8s.io/controller-runtime/pkg/internal/log" 26 | ) 27 | 28 | var log = logf.RuntimeLog.WithName("builder") 29 | -------------------------------------------------------------------------------- /pkg/builder/example_webhook_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package builder_test 18 | 19 | import ( 20 | "os" 21 | 22 | "sigs.k8s.io/controller-runtime/pkg/builder" 23 | "sigs.k8s.io/controller-runtime/pkg/client/config" 24 | logf "sigs.k8s.io/controller-runtime/pkg/log" 25 | "sigs.k8s.io/controller-runtime/pkg/manager" 26 | "sigs.k8s.io/controller-runtime/pkg/manager/signals" 27 | 28 | examplegroup "sigs.k8s.io/controller-runtime/examples/crd/pkg" 29 | ) 30 | 31 | // This example use webhook builder to create a simple webhook that is managed 32 | // by a manager for CRD ChaosPod. And then start the manager. 33 | func ExampleWebhookBuilder() { 34 | var log = logf.Log.WithName("webhookbuilder-example") 35 | 36 | mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{}) 37 | if err != nil { 38 | log.Error(err, "could not create manager") 39 | os.Exit(1) 40 | } 41 | 42 | err = builder. 43 | WebhookManagedBy(mgr). // Create the WebhookManagedBy 44 | For(&examplegroup.ChaosPod{}). // ChaosPod is a CRD. 45 | Complete() 46 | if err != nil { 47 | log.Error(err, "could not create webhook") 48 | os.Exit(1) 49 | } 50 | 51 | if err := mgr.Start(signals.SetupSignalHandler()); err != nil { 52 | log.Error(err, "could not start manager") 53 | os.Exit(1) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /pkg/cache/cache_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cache_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | "k8s.io/client-go/kubernetes" 25 | "k8s.io/client-go/rest" 26 | "sigs.k8s.io/controller-runtime/pkg/envtest" 27 | logf "sigs.k8s.io/controller-runtime/pkg/log" 28 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 29 | ) 30 | 31 | func TestSource(t *testing.T) { 32 | RegisterFailHandler(Fail) 33 | RunSpecs(t, "Cache Suite") 34 | } 35 | 36 | var testenv *envtest.Environment 37 | var cfg *rest.Config 38 | var clientset *kubernetes.Clientset 39 | 40 | var _ = BeforeSuite(func() { 41 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 42 | 43 | testenv = &envtest.Environment{} 44 | 45 | var err error 46 | cfg, err = testenv.Start() 47 | Expect(err).NotTo(HaveOccurred()) 48 | 49 | clientset, err = kubernetes.NewForConfig(cfg) 50 | Expect(err).NotTo(HaveOccurred()) 51 | }) 52 | 53 | var _ = AfterSuite(func() { 54 | Expect(testenv.Stop()).To(Succeed()) 55 | }) 56 | -------------------------------------------------------------------------------- /pkg/cache/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package cache provides object caches that act as caching client.Reader 18 | // instances and help drive Kubernetes-object-based event handlers. 19 | package cache 20 | -------------------------------------------------------------------------------- /pkg/cache/informer_cache_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cache_test 18 | 19 | import ( 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | 23 | "k8s.io/client-go/rest" 24 | 25 | "sigs.k8s.io/controller-runtime/pkg/cache" 26 | "sigs.k8s.io/controller-runtime/pkg/client/apiutil" 27 | "sigs.k8s.io/controller-runtime/pkg/manager" 28 | ) 29 | 30 | var _ = Describe("informerCache", func() { 31 | It("should not require LeaderElection", func() { 32 | cfg := &rest.Config{} 33 | 34 | httpClient, err := rest.HTTPClientFor(cfg) 35 | Expect(err).ToNot(HaveOccurred()) 36 | mapper, err := apiutil.NewDynamicRESTMapper(cfg, httpClient) 37 | Expect(err).ToNot(HaveOccurred()) 38 | 39 | c, err := cache.New(cfg, cache.Options{Mapper: mapper}) 40 | Expect(err).ToNot(HaveOccurred()) 41 | 42 | leaderElectionRunnable, ok := c.(manager.LeaderElectionRunnable) 43 | Expect(ok).To(BeTrue()) 44 | Expect(leaderElectionRunnable.NeedLeaderElection()).To(BeFalse()) 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /pkg/cache/internal/internal_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package internal 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestSource(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Cache Internal Suite") 29 | } 30 | -------------------------------------------------------------------------------- /pkg/cache/internal/selector.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package internal 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | "k8s.io/apimachinery/pkg/fields" 22 | "k8s.io/apimachinery/pkg/labels" 23 | ) 24 | 25 | // Selector specify the label/field selector to fill in ListOptions. 26 | type Selector struct { 27 | Label labels.Selector 28 | Field fields.Selector 29 | } 30 | 31 | // ApplyToList fill in ListOptions LabelSelector and FieldSelector if needed. 32 | func (s Selector) ApplyToList(listOpts *metav1.ListOptions) { 33 | if s.Label != nil { 34 | listOpts.LabelSelector = s.Label.String() 35 | } 36 | if s.Field != nil { 37 | listOpts.FieldSelector = s.Field.String() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /pkg/certwatcher/certwatcher_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package certwatcher_test 18 | 19 | import ( 20 | "os" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo/v2" 24 | . "github.com/onsi/gomega" 25 | 26 | logf "sigs.k8s.io/controller-runtime/pkg/log" 27 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 28 | ) 29 | 30 | var ( 31 | certPath = "testdata/tls.crt" 32 | keyPath = "testdata/tls.key" 33 | ) 34 | 35 | func TestSource(t *testing.T) { 36 | RegisterFailHandler(Fail) 37 | RunSpecs(t, "CertWatcher Suite") 38 | } 39 | 40 | var _ = BeforeSuite(func() { 41 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 42 | }) 43 | 44 | var _ = AfterSuite(func() { 45 | for _, file := range []string{certPath, keyPath, certPath + ".new", keyPath + ".new", certPath + ".old", keyPath + ".old"} { 46 | _ = os.Remove(file) 47 | } 48 | }) 49 | -------------------------------------------------------------------------------- /pkg/certwatcher/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package certwatcher is a helper for reloading Certificates from disk to be used 19 | with tls servers. It provides a helper func `GetCertificate` which can be 20 | called from `tls.Config` and passed into your tls.Listener. For a detailed 21 | example server view pkg/webhook/server.go. 22 | */ 23 | package certwatcher 24 | -------------------------------------------------------------------------------- /pkg/certwatcher/example_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package certwatcher_test 18 | 19 | import ( 20 | "context" 21 | "crypto/tls" 22 | "net/http" 23 | "time" 24 | 25 | ctrl "sigs.k8s.io/controller-runtime" 26 | "sigs.k8s.io/controller-runtime/pkg/certwatcher" 27 | ) 28 | 29 | type sampleServer struct { 30 | } 31 | 32 | func Example() { 33 | // Setup Context 34 | ctx := ctrl.SetupSignalHandler() 35 | 36 | // Initialize a new cert watcher with cert/key pair 37 | watcher, err := certwatcher.New("ssl/tls.crt", "ssl/tls.key") 38 | if err != nil { 39 | panic(err) 40 | } 41 | 42 | // Start goroutine with certwatcher running against supplied cert 43 | go func() { 44 | if err := watcher.Start(ctx); err != nil { 45 | panic(err) 46 | } 47 | }() 48 | 49 | // Setup TLS listener using GetCertficate for fetching the cert when changes 50 | listener, err := tls.Listen("tcp", "localhost:9443", &tls.Config{ 51 | GetCertificate: watcher.GetCertificate, 52 | MinVersion: tls.VersionTLS12, 53 | }) 54 | if err != nil { 55 | panic(err) 56 | } 57 | 58 | // Initialize your tls server 59 | srv := &http.Server{ 60 | Handler: &sampleServer{}, 61 | ReadHeaderTimeout: 5 * time.Second, 62 | } 63 | 64 | // Start goroutine for handling server shutdown. 65 | go func() { 66 | <-ctx.Done() 67 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 68 | defer cancel() 69 | if err := srv.Shutdown(ctx); err != nil { 70 | panic(err) 71 | } 72 | }() 73 | 74 | // Serve t 75 | if err := srv.Serve(listener); err != nil && err != http.ErrServerClosed { 76 | panic(err) 77 | } 78 | } 79 | 80 | func (s *sampleServer) ServeHTTP(http.ResponseWriter, *http.Request) { 81 | } 82 | -------------------------------------------------------------------------------- /pkg/certwatcher/metrics/metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metrics 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | 22 | "sigs.k8s.io/controller-runtime/pkg/metrics" 23 | ) 24 | 25 | var ( 26 | // ReadCertificateTotal is a prometheus counter metrics which holds the total 27 | // number of certificate reads. 28 | ReadCertificateTotal = prometheus.NewCounter(prometheus.CounterOpts{ 29 | Name: "certwatcher_read_certificate_total", 30 | Help: "Total number of certificate reads", 31 | }) 32 | 33 | // ReadCertificateErrors is a prometheus counter metrics which holds the total 34 | // number of errors from certificate read. 35 | ReadCertificateErrors = prometheus.NewCounter(prometheus.CounterOpts{ 36 | Name: "certwatcher_read_certificate_errors_total", 37 | Help: "Total number of certificate read errors", 38 | }) 39 | ) 40 | 41 | func init() { 42 | metrics.Registry.MustRegister( 43 | ReadCertificateTotal, 44 | ReadCertificateErrors, 45 | ) 46 | } 47 | -------------------------------------------------------------------------------- /pkg/certwatcher/testdata/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/1dce6213f6c078f3170921b3a774304d066d5bd4/pkg/certwatcher/testdata/.gitkeep -------------------------------------------------------------------------------- /pkg/client/apiutil/apiutil_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package apiutil 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | "k8s.io/client-go/rest" 25 | 26 | logf "sigs.k8s.io/controller-runtime/pkg/log" 27 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 28 | ) 29 | 30 | func TestSource(t *testing.T) { 31 | RegisterFailHandler(Fail) 32 | RunSpecs(t, "API Utilities Test Suite") 33 | } 34 | 35 | var cfg *rest.Config 36 | 37 | var _ = BeforeSuite(func() { 38 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 39 | 40 | // for things that technically need a rest.Config for defaulting, but don't actually use them 41 | cfg = &rest.Config{} 42 | }) 43 | -------------------------------------------------------------------------------- /pkg/client/apiutil/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package apiutil 18 | 19 | import ( 20 | "fmt" 21 | "sort" 22 | "strings" 23 | 24 | apierrors "k8s.io/apimachinery/pkg/api/errors" 25 | "k8s.io/apimachinery/pkg/api/meta" 26 | 27 | "k8s.io/apimachinery/pkg/runtime/schema" 28 | ) 29 | 30 | // ErrResourceDiscoveryFailed is returned if the RESTMapper cannot discover supported resources for some GroupVersions. 31 | // It wraps the errors encountered, except "NotFound" errors are replaced with meta.NoResourceMatchError, for 32 | // backwards compatibility with code that uses meta.IsNoMatchError() to check for unsupported APIs. 33 | type ErrResourceDiscoveryFailed map[schema.GroupVersion]error 34 | 35 | // Error implements the error interface. 36 | func (e *ErrResourceDiscoveryFailed) Error() string { 37 | subErrors := []string{} 38 | for k, v := range *e { 39 | subErrors = append(subErrors, fmt.Sprintf("%s: %v", k, v)) 40 | } 41 | sort.Strings(subErrors) 42 | return fmt.Sprintf("unable to retrieve the complete list of server APIs: %s", strings.Join(subErrors, ", ")) 43 | } 44 | 45 | func (e *ErrResourceDiscoveryFailed) Unwrap() []error { 46 | subErrors := []error{} 47 | for gv, err := range *e { 48 | if apierrors.IsNotFound(err) { 49 | err = &meta.NoResourceMatchError{PartialResource: gv.WithResource("")} 50 | } 51 | subErrors = append(subErrors, err) 52 | } 53 | return subErrors 54 | } 55 | -------------------------------------------------------------------------------- /pkg/client/client_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package client_test 18 | 19 | import ( 20 | "bytes" 21 | "io" 22 | "testing" 23 | 24 | . "github.com/onsi/ginkgo/v2" 25 | . "github.com/onsi/gomega" 26 | "k8s.io/client-go/kubernetes" 27 | "k8s.io/client-go/kubernetes/scheme" 28 | "k8s.io/client-go/rest" 29 | "k8s.io/klog/v2" 30 | "sigs.k8s.io/controller-runtime/examples/crd/pkg" 31 | "sigs.k8s.io/controller-runtime/pkg/envtest" 32 | 33 | logf "sigs.k8s.io/controller-runtime/pkg/log" 34 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 35 | ) 36 | 37 | func TestClient(t *testing.T) { 38 | RegisterFailHandler(Fail) 39 | RunSpecs(t, "Client Suite") 40 | } 41 | 42 | var ( 43 | testenv *envtest.Environment 44 | cfg *rest.Config 45 | clientset *kubernetes.Clientset 46 | 47 | // Used by tests to inspect controller and client log messages. 48 | log bytes.Buffer 49 | ) 50 | 51 | var _ = BeforeSuite(func() { 52 | // Forwards logs to ginkgo output, and allows tests to inspect logs. 53 | mw := io.MultiWriter(&log, GinkgoWriter) 54 | 55 | // Use prefixes to help us tell the source of the log message. 56 | // controller-runtime uses logf 57 | logf.SetLogger(zap.New(zap.WriteTo(mw), zap.UseDevMode(true)).WithName("logf")) 58 | // client-go logs uses klog 59 | klog.SetLogger(zap.New(zap.WriteTo(mw), zap.UseDevMode(true)).WithName("klog")) 60 | 61 | testenv = &envtest.Environment{CRDDirectoryPaths: []string{"./testdata"}} 62 | 63 | var err error 64 | cfg, err = testenv.Start() 65 | Expect(err).NotTo(HaveOccurred()) 66 | 67 | clientset, err = kubernetes.NewForConfig(cfg) 68 | Expect(err).NotTo(HaveOccurred()) 69 | 70 | Expect(pkg.AddToScheme(scheme.Scheme)).NotTo(HaveOccurred()) 71 | }) 72 | 73 | var _ = AfterSuite(func() { 74 | Expect(testenv.Stop()).To(Succeed()) 75 | }) 76 | -------------------------------------------------------------------------------- /pkg/client/codec.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package client 18 | 19 | import ( 20 | "errors" 21 | "net/url" 22 | 23 | "k8s.io/apimachinery/pkg/conversion/queryparams" 24 | "k8s.io/apimachinery/pkg/runtime" 25 | "k8s.io/apimachinery/pkg/runtime/schema" 26 | ) 27 | 28 | var _ runtime.ParameterCodec = noConversionParamCodec{} 29 | 30 | // noConversionParamCodec is a no-conversion codec for serializing parameters into URL query strings. 31 | // it's useful in scenarios with the unstructured client and arbitrary resources. 32 | type noConversionParamCodec struct{} 33 | 34 | func (noConversionParamCodec) EncodeParameters(obj runtime.Object, to schema.GroupVersion) (url.Values, error) { 35 | return queryparams.Convert(obj) 36 | } 37 | 38 | func (noConversionParamCodec) DecodeParameters(parameters url.Values, from schema.GroupVersion, into runtime.Object) error { 39 | return errors.New("DecodeParameters not implemented on noConversionParamCodec") 40 | } 41 | -------------------------------------------------------------------------------- /pkg/client/config/config_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package config 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | 25 | logf "sigs.k8s.io/controller-runtime/pkg/log" 26 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 27 | ) 28 | 29 | func TestConfig(t *testing.T) { 30 | RegisterFailHandler(Fail) 31 | RunSpecs(t, "Client Config Test Suite") 32 | } 33 | 34 | var _ = BeforeSuite(func() { 35 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 36 | }) 37 | -------------------------------------------------------------------------------- /pkg/client/config/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package config contains libraries for initializing REST configs for talking to the Kubernetes API 18 | package config 19 | -------------------------------------------------------------------------------- /pkg/client/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package client contains functionality for interacting with Kubernetes API 18 | // servers. 19 | // 20 | // # Clients 21 | // 22 | // Clients are split into two interfaces -- Readers and Writers. Readers 23 | // get and list, while writers create, update, and delete. 24 | // 25 | // The New function can be used to create a new client that talks directly 26 | // to the API server. 27 | // 28 | // It is a common pattern in Kubernetes to read from a cache and write to the API 29 | // server. This pattern is covered by the creating the Client with a Cache. 30 | // 31 | // # Options 32 | // 33 | // Many client operations in Kubernetes support options. These options are 34 | // represented as variadic arguments at the end of a given method call. 35 | // For instance, to use a label selector on list, you can call 36 | // 37 | // err := someReader.List(context.Background(), &podList, client.MatchingLabels{"somelabel": "someval"}) 38 | // 39 | // # Indexing 40 | // 41 | // Indexes may be added to caches using a FieldIndexer. This allows you to easily 42 | // and efficiently look up objects with certain properties. You can then make 43 | // use of the index by specifying a field selector on calls to List on the Reader 44 | // corresponding to the given Cache. 45 | // 46 | // For instance, a Secret controller might have an index on the 47 | // `.spec.volumes.secret.secretName` field in Pod objects, so that it could 48 | // easily look up all pods that reference a given secret. 49 | package client 50 | -------------------------------------------------------------------------------- /pkg/client/fake/client_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package fake 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | 25 | logf "sigs.k8s.io/controller-runtime/pkg/log" 26 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 27 | ) 28 | 29 | func TestSource(t *testing.T) { 30 | RegisterFailHandler(Fail) 31 | RunSpecs(t, "Fake client Suite") 32 | } 33 | 34 | var _ = BeforeSuite(func() { 35 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 36 | }) 37 | -------------------------------------------------------------------------------- /pkg/client/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package fake provides a fake client for testing. 19 | 20 | A fake client is backed by its simple object store indexed by GroupVersionResource. 21 | You can create a fake client with optional objects. 22 | 23 | client := NewClientBuilder().WithScheme(scheme).WithObjects(initObjs...).Build() 24 | 25 | You can invoke the methods defined in the Client interface. 26 | 27 | When in doubt, it's almost always better not to use this package and instead use 28 | envtest.Environment with a real client and API server. 29 | 30 | WARNING: ⚠️ Current Limitations / Known Issues with the fake Client ⚠️ 31 | - This client does not have a way to inject specific errors to test handled vs. unhandled errors. 32 | - There is some support for sub resources which can cause issues with tests if you're trying to update 33 | e.g. metadata and status in the same reconcile. 34 | - No OpenAPI validation is performed when creating or updating objects. 35 | - ObjectMeta's `Generation` and `ResourceVersion` don't behave properly, Patch or Update 36 | operations that rely on these fields will fail, or give false positives. 37 | */ 38 | package fake 39 | -------------------------------------------------------------------------------- /pkg/client/interceptor/interceptor_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package interceptor 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | 25 | logf "sigs.k8s.io/controller-runtime/pkg/log" 26 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 27 | ) 28 | 29 | func TestInterceptor(t *testing.T) { 30 | RegisterFailHandler(Fail) 31 | RunSpecs(t, "Fake client Suite") 32 | } 33 | 34 | var _ = BeforeSuite(func() { 35 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 36 | }) 37 | -------------------------------------------------------------------------------- /pkg/client/testdata/examplecrd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: chaospods.chaosapps.metamagical.io 5 | spec: 6 | group: chaosapps.metamagical.io 7 | names: 8 | kind: ChaosPod 9 | plural: chaospods 10 | scope: Namespaced 11 | versions: 12 | - name: "v1" 13 | storage: true 14 | served: true 15 | schema: 16 | openAPIV3Schema: 17 | type: object 18 | -------------------------------------------------------------------------------- /pkg/cluster/cluster_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cluster 18 | 19 | import ( 20 | "net/http" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo/v2" 24 | . "github.com/onsi/gomega" 25 | "k8s.io/client-go/kubernetes" 26 | "k8s.io/client-go/rest" 27 | "sigs.k8s.io/controller-runtime/pkg/envtest" 28 | logf "sigs.k8s.io/controller-runtime/pkg/log" 29 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 30 | ) 31 | 32 | func TestSource(t *testing.T) { 33 | RegisterFailHandler(Fail) 34 | RunSpecs(t, "Cluster Suite") 35 | } 36 | 37 | var testenv *envtest.Environment 38 | var cfg *rest.Config 39 | var clientset *kubernetes.Clientset 40 | 41 | // clientTransport is used to force-close keep-alives in tests that check for leaks. 42 | var clientTransport *http.Transport 43 | 44 | var _ = BeforeSuite(func() { 45 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 46 | 47 | testenv = &envtest.Environment{} 48 | 49 | var err error 50 | cfg, err = testenv.Start() 51 | Expect(err).NotTo(HaveOccurred()) 52 | 53 | cfg.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { 54 | // NB(directxman12): we can't set Transport *and* use TLS options, 55 | // so we grab the transport right after it gets created so that we can 56 | // type-assert on it (hopefully)? 57 | // hopefully this doesn't break 🤞 58 | clientTransport = rt.(*http.Transport) 59 | return rt 60 | } 61 | 62 | clientset, err = kubernetes.NewForConfig(cfg) 63 | Expect(err).NotTo(HaveOccurred()) 64 | }) 65 | 66 | var _ = AfterSuite(func() { 67 | Expect(testenv.Stop()).To(Succeed()) 68 | }) 69 | -------------------------------------------------------------------------------- /pkg/controller/controllertest/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package controllertest contains fake informers for testing controllers 18 | // When in doubt, it's almost always better to test against a real API server 19 | // using envtest.Environment. 20 | package controllertest 21 | -------------------------------------------------------------------------------- /pkg/controller/controllerutil/controllerutil_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllerutil_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | 25 | "k8s.io/client-go/rest" 26 | "sigs.k8s.io/controller-runtime/pkg/client" 27 | "sigs.k8s.io/controller-runtime/pkg/envtest" 28 | ) 29 | 30 | func TestControllerutil(t *testing.T) { 31 | RegisterFailHandler(Fail) 32 | RunSpecs(t, "Controllerutil Suite") 33 | } 34 | 35 | var testenv *envtest.Environment 36 | var cfg *rest.Config 37 | var c client.Client 38 | 39 | var _ = BeforeSuite(func() { 40 | var err error 41 | 42 | testenv = &envtest.Environment{} 43 | 44 | cfg, err = testenv.Start() 45 | Expect(err).NotTo(HaveOccurred()) 46 | 47 | c, err = client.New(cfg, client.Options{}) 48 | Expect(err).NotTo(HaveOccurred()) 49 | }) 50 | 51 | var _ = AfterSuite(func() { 52 | Expect(testenv.Stop()).To(Succeed()) 53 | }) 54 | -------------------------------------------------------------------------------- /pkg/controller/controllerutil/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package controllerutil contains utility functions for working with and implementing Controllers. 19 | */ 20 | package controllerutil 21 | -------------------------------------------------------------------------------- /pkg/controller/controllerutil/example_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllerutil_test 18 | 19 | import ( 20 | "context" 21 | 22 | appsv1 "k8s.io/api/apps/v1" 23 | corev1 "k8s.io/api/core/v1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | 26 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 27 | logf "sigs.k8s.io/controller-runtime/pkg/log" 28 | ) 29 | 30 | var ( 31 | log = logf.Log.WithName("controllerutil-examples") 32 | ) 33 | 34 | // This example creates or updates an existing deployment. 35 | func ExampleCreateOrUpdate() { 36 | // c is client.Client 37 | 38 | // Create or Update the deployment default/foo 39 | deploy := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}} 40 | 41 | op, err := controllerutil.CreateOrUpdate(context.TODO(), c, deploy, func() error { 42 | // Deployment selector is immutable so we set this value only if 43 | // a new object is going to be created 44 | if deploy.ObjectMeta.CreationTimestamp.IsZero() { 45 | deploy.Spec.Selector = &metav1.LabelSelector{ 46 | MatchLabels: map[string]string{"foo": "bar"}, 47 | } 48 | } 49 | 50 | // update the Deployment pod template 51 | deploy.Spec.Template = corev1.PodTemplateSpec{ 52 | ObjectMeta: metav1.ObjectMeta{ 53 | Labels: map[string]string{ 54 | "foo": "bar", 55 | }, 56 | }, 57 | Spec: corev1.PodSpec{ 58 | Containers: []corev1.Container{ 59 | { 60 | Name: "busybox", 61 | Image: "busybox", 62 | }, 63 | }, 64 | }, 65 | } 66 | 67 | return nil 68 | }) 69 | 70 | if err != nil { 71 | log.Error(err, "Deployment reconcile failed") 72 | } else { 73 | log.Info("Deployment successfully reconciled", "operation", op) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /pkg/controller/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package controller provides types and functions for building Controllers. Controllers implement Kubernetes APIs. 19 | 20 | # Creation 21 | 22 | To create a new Controller, first create a manager.Manager and pass it to the controller.New function. 23 | The Controller MUST be started by calling Manager.Start. 24 | */ 25 | package controller 26 | -------------------------------------------------------------------------------- /pkg/controller/name.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "fmt" 21 | "sync" 22 | 23 | "k8s.io/apimachinery/pkg/util/sets" 24 | ) 25 | 26 | var nameLock sync.Mutex 27 | var usedNames sets.Set[string] 28 | 29 | func checkName(name string) error { 30 | nameLock.Lock() 31 | defer nameLock.Unlock() 32 | if usedNames == nil { 33 | usedNames = sets.Set[string]{} 34 | } 35 | 36 | if usedNames.Has(name) { 37 | return fmt.Errorf("controller with name %s already exists. Controller names must be unique to avoid multiple controllers reporting the same metric. This validation can be disabled via the SkipNameValidation option", name) 38 | } 39 | 40 | usedNames.Insert(name) 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /pkg/controller/priorityqueue/priorityqueue_suite_test.go: -------------------------------------------------------------------------------- 1 | package priorityqueue 2 | 3 | import ( 4 | "testing" 5 | 6 | . "github.com/onsi/ginkgo/v2" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | func TestControllerWorkqueue(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "ControllerWorkqueue Suite") 13 | } 14 | -------------------------------------------------------------------------------- /pkg/controller/testdata/crds/unconventionallisttype.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: unconventionallisttypes.chaosapps.metamagical.io 5 | spec: 6 | group: chaosapps.metamagical.io 7 | names: 8 | kind: UnconventionalListType 9 | plural: unconventionallisttypes 10 | scope: Namespaced 11 | versions: 12 | - name: "v1" 13 | storage: true 14 | served: true 15 | schema: 16 | openAPIV3Schema: 17 | type: object 18 | -------------------------------------------------------------------------------- /pkg/conversion/conversion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package conversion provides interface definitions that an API Type needs to 19 | implement for it to be supported by the generic conversion webhook handler 20 | defined under pkg/webhook/conversion. 21 | */ 22 | package conversion 23 | 24 | import "k8s.io/apimachinery/pkg/runtime" 25 | 26 | // Convertible defines capability of a type to convertible i.e. it can be converted to/from a hub type. 27 | type Convertible interface { 28 | runtime.Object 29 | ConvertTo(dst Hub) error 30 | ConvertFrom(src Hub) error 31 | } 32 | 33 | // Hub marks that a given type is the hub type for conversion. This means that 34 | // all conversions will first convert to the hub type, then convert from the hub 35 | // type to the destination type. All types besides the hub type should implement 36 | // Convertible. 37 | type Hub interface { 38 | runtime.Object 39 | Hub() 40 | } 41 | -------------------------------------------------------------------------------- /pkg/envtest/crd_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package envtest 18 | 19 | import ( 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | "k8s.io/apimachinery/pkg/util/sets" 23 | ) 24 | 25 | var _ = Describe("Test", func() { 26 | Describe("readCRDFiles", func() { 27 | It("should not mix up files from different directories", func() { 28 | opt := CRDInstallOptions{ 29 | Paths: []string{ 30 | "testdata/crds", 31 | "testdata/crdv1_original", 32 | }, 33 | } 34 | err := ReadCRDFiles(&opt) 35 | Expect(err).NotTo(HaveOccurred()) 36 | 37 | expectedCRDs := sets.NewString( 38 | "frigates.ship.example.com", 39 | "configs.foo.example.com", 40 | "drivers.crew.example.com", 41 | ) 42 | 43 | foundCRDs := sets.NewString() 44 | for _, crd := range opt.CRDs { 45 | foundCRDs.Insert(crd.Name) 46 | } 47 | 48 | Expect(expectedCRDs).To(Equal(foundCRDs)) 49 | }) 50 | }) 51 | }) 52 | -------------------------------------------------------------------------------- /pkg/envtest/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package envtest provides libraries for integration testing by starting a local control plane 18 | // 19 | // Control plane binaries (etcd and kube-apiserver) are loaded by default from 20 | // /usr/local/kubebuilder/bin. This can be overridden by setting the 21 | // KUBEBUILDER_ASSETS environment variable, or by directly creating a 22 | // ControlPlane for the Environment to use. 23 | // 24 | // Environment can also be configured to work with an existing cluster, and 25 | // simply load CRDs and provide client configuration. 26 | package envtest 27 | -------------------------------------------------------------------------------- /pkg/envtest/helper.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package envtest 18 | 19 | import ( 20 | apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 21 | "k8s.io/client-go/kubernetes/scheme" 22 | ) 23 | 24 | var ( 25 | crdScheme = scheme.Scheme 26 | ) 27 | 28 | // init is required to correctly initialize the crdScheme package variable. 29 | func init() { 30 | _ = apiextensionsv1.AddToScheme(crdScheme) 31 | } 32 | 33 | // mergePaths merges two string slices containing paths. 34 | // This function makes no guarantees about order of the merged slice. 35 | func mergePaths(s1, s2 []string) []string { 36 | m := make(map[string]struct{}) 37 | for _, s := range s1 { 38 | m[s] = struct{}{} 39 | } 40 | for _, s := range s2 { 41 | m[s] = struct{}{} 42 | } 43 | merged := make([]string, len(m)) 44 | i := 0 45 | for key := range m { 46 | merged[i] = key 47 | i++ 48 | } 49 | return merged 50 | } 51 | 52 | // mergeCRDs merges two CRD slices using their names. 53 | // This function makes no guarantees about order of the merged slice. 54 | func mergeCRDs(s1, s2 []*apiextensionsv1.CustomResourceDefinition) []*apiextensionsv1.CustomResourceDefinition { 55 | m := make(map[string]*apiextensionsv1.CustomResourceDefinition) 56 | for _, obj := range s1 { 57 | m[obj.GetName()] = obj 58 | } 59 | for _, obj := range s2 { 60 | m[obj.GetName()] = obj 61 | } 62 | merged := make([]*apiextensionsv1.CustomResourceDefinition, len(m)) 63 | i := 0 64 | for _, obj := range m { 65 | merged[i] = obj.DeepCopy() 66 | i++ 67 | } 68 | return merged 69 | } 70 | -------------------------------------------------------------------------------- /pkg/envtest/komega/OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - controller-runtime-admins 3 | - controller-runtime-maintainers 4 | - controller-runtime-approvers 5 | - schrej 6 | - JoelSpeed 7 | reviewers: 8 | - controller-runtime-admins 9 | - controller-runtime-maintainers 10 | - controller-runtime-approvers 11 | - controller-runtime-reviewers 12 | - schrej 13 | - JoelSpeed 14 | -------------------------------------------------------------------------------- /pkg/envtest/testdata/crds/examplecrd3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: configs.foo.example.com 5 | spec: 6 | group: foo.example.com 7 | names: 8 | kind: Config 9 | plural: configs 10 | scope: Namespaced 11 | versions: 12 | - name: "v1beta1" 13 | storage: true 14 | served: true 15 | schema: 16 | openAPIV3Schema: 17 | type: object 18 | -------------------------------------------------------------------------------- /pkg/envtest/testdata/examplecrd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: bazs.qux.example.com 5 | spec: 6 | group: qux.example.com 7 | names: 8 | kind: Baz 9 | plural: bazs 10 | scope: Namespaced 11 | versions: 12 | - name: "v1beta1" 13 | storage: true 14 | served: true 15 | schema: 16 | openAPIV3Schema: 17 | type: object 18 | -------------------------------------------------------------------------------- /pkg/envtest/testdata/examplecrd_v1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: foos.bar.example.com 5 | spec: 6 | group: bar.example.com 7 | names: 8 | kind: Foo 9 | plural: foos 10 | scope: Namespaced 11 | versions: 12 | - name: "v1" 13 | storage: true 14 | served: true 15 | schema: 16 | openAPIV3Schema: 17 | type: object 18 | -------------------------------------------------------------------------------- /pkg/envtest/testdata/multiplecrds.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: captains.crew.example.com 6 | spec: 7 | group: crew.example.com 8 | names: 9 | kind: Captain 10 | plural: captains 11 | scope: Namespaced 12 | versions: 13 | - name: "v1beta1" 14 | storage: true 15 | served: true 16 | schema: 17 | openAPIV3Schema: 18 | type: object 19 | --- 20 | apiVersion: apiextensions.k8s.io/v1 21 | kind: CustomResourceDefinition 22 | metadata: 23 | name: firstmates.crew.example.com 24 | spec: 25 | group: crew.example.com 26 | names: 27 | kind: FirstMate 28 | plural: firstmates 29 | scope: Namespaced 30 | versions: 31 | - name: "v1beta1" 32 | storage: true 33 | served: true 34 | schema: 35 | openAPIV3Schema: 36 | type: object 37 | --- 38 | -------------------------------------------------------------------------------- /pkg/envtest/testdata/notcrd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment 5 | labels: 6 | app: nginx 7 | spec: 8 | selector: 9 | matchLabels: 10 | app: nginx 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx:1.7.9 19 | -------------------------------------------------------------------------------- /pkg/event/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package event contains the definitions for the Event types produced by source.Sources and transformed into 19 | reconcile.Requests by handler.EventHandler. 20 | 21 | You should rarely need to work with these directly -- instead, use Controller.Watch with 22 | source.Sources and handler.EventHandlers. 23 | 24 | Events generally contain both a full runtime.Object that caused the event, as well 25 | as a direct handle to that object's metadata. This saves a lot of typecasting in 26 | code that works with Events. 27 | */ 28 | package event 29 | -------------------------------------------------------------------------------- /pkg/finalizer/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | package finalizer 15 | 16 | import ( 17 | "context" 18 | 19 | "sigs.k8s.io/controller-runtime/pkg/client" 20 | ) 21 | 22 | // Registerer holds Register that will check if a key is already registered 23 | // and error out and it does; and if not registered, it will add the finalizer 24 | // to the finalizers map as the value for the provided key. 25 | type Registerer interface { 26 | Register(key string, f Finalizer) error 27 | } 28 | 29 | // Finalizer holds Finalize that will add/remove a finalizer based on the 30 | // deletion timestamp being set and return an indication of whether the 31 | // obj needs an update or not. 32 | type Finalizer interface { 33 | Finalize(context.Context, client.Object) (Result, error) 34 | } 35 | 36 | // Finalizers implements Registerer and Finalizer to finalize all registered 37 | // finalizers if the provided object has a deletion timestamp or set all 38 | // registered finalizers if it does not. 39 | type Finalizers interface { 40 | Registerer 41 | Finalizer 42 | } 43 | -------------------------------------------------------------------------------- /pkg/handler/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package handler defines EventHandlers that enqueue reconcile.Requests in response to Create, Update, Deletion Events 19 | observed from Watching Kubernetes APIs. Users should provide a source.Source and handler.EventHandler to 20 | Controller.Watch in order to generate and enqueue reconcile.Request work items. 21 | 22 | Generally, following premade event handlers should be sufficient for most use cases: 23 | 24 | EventHandlers: 25 | 26 | EnqueueRequestForObject - Enqueues a reconcile.Request containing the Name and Namespace of the object in the Event. This will 27 | cause the object that was the source of the Event (e.g. the created / deleted / updated object) to be 28 | reconciled. 29 | 30 | EnqueueRequestForOwner - Enqueues a reconcile.Request containing the Name and Namespace of the Owner of the object in the Event. 31 | This will cause owner of the object that was the source of the Event (e.g. the owner object that created the object) 32 | to be reconciled. 33 | 34 | EnqueueRequestsFromMapFunc - Enqueues reconcile.Requests resulting from a user provided transformation function run against the 35 | object in the Event. This will cause an arbitrary collection of objects (defined from a transformation of the 36 | source object) to be reconciled. 37 | */ 38 | package handler 39 | -------------------------------------------------------------------------------- /pkg/handler/eventhandler_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package handler_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | "k8s.io/client-go/rest" 25 | "sigs.k8s.io/controller-runtime/pkg/envtest" 26 | logf "sigs.k8s.io/controller-runtime/pkg/log" 27 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 28 | ) 29 | 30 | func TestEventhandler(t *testing.T) { 31 | RegisterFailHandler(Fail) 32 | RunSpecs(t, "Eventhandler Suite") 33 | } 34 | 35 | var testenv *envtest.Environment 36 | var cfg *rest.Config 37 | 38 | var _ = BeforeSuite(func() { 39 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 40 | 41 | testenv = &envtest.Environment{} 42 | var err error 43 | cfg, err = testenv.Start() 44 | Expect(err).NotTo(HaveOccurred()) 45 | }) 46 | 47 | var _ = AfterSuite(func() { 48 | Expect(testenv.Stop()).To(Succeed()) 49 | }) 50 | -------------------------------------------------------------------------------- /pkg/healthz/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package healthz contains helpers from supporting liveness and readiness endpoints. 18 | // (often referred to as healthz and readyz, respectively). 19 | // 20 | // This package draws heavily from the apiserver's healthz package 21 | // ( https://github.com/kubernetes/apiserver/tree/master/pkg/server/healthz ) 22 | // but has some changes to bring it in line with controller-runtime's style. 23 | // 24 | // The main entrypoint is the Handler -- this serves both aggregated health status 25 | // and individual health check endpoints. 26 | package healthz 27 | 28 | import ( 29 | logf "sigs.k8s.io/controller-runtime/pkg/internal/log" 30 | ) 31 | 32 | var log = logf.RuntimeLog.WithName("healthz") 33 | -------------------------------------------------------------------------------- /pkg/healthz/healthz_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package healthz_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | logf "sigs.k8s.io/controller-runtime/pkg/log" 25 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 26 | ) 27 | 28 | func TestHealthz(t *testing.T) { 29 | RegisterFailHandler(Fail) 30 | RunSpecs(t, "Healthz Suite") 31 | } 32 | 33 | var _ = BeforeSuite(func() { 34 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 35 | }) 36 | -------------------------------------------------------------------------------- /pkg/internal/controller/controller_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | "k8s.io/client-go/kubernetes" 25 | "k8s.io/client-go/rest" 26 | "sigs.k8s.io/controller-runtime/pkg/envtest" 27 | logf "sigs.k8s.io/controller-runtime/pkg/log" 28 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 29 | ) 30 | 31 | func TestSource(t *testing.T) { 32 | RegisterFailHandler(Fail) 33 | RunSpecs(t, "Controller internal Suite") 34 | } 35 | 36 | var testenv *envtest.Environment 37 | var cfg *rest.Config 38 | var clientset *kubernetes.Clientset 39 | 40 | var _ = BeforeSuite(func() { 41 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 42 | 43 | testenv = &envtest.Environment{} 44 | 45 | var err error 46 | cfg, err = testenv.Start() 47 | Expect(err).NotTo(HaveOccurred()) 48 | 49 | clientset, err = kubernetes.NewForConfig(cfg) 50 | Expect(err).NotTo(HaveOccurred()) 51 | }) 52 | 53 | var _ = AfterSuite(func() { 54 | Expect(testenv.Stop()).To(Succeed()) 55 | }) 56 | -------------------------------------------------------------------------------- /pkg/internal/field/selector/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package selector 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/fields" 21 | "k8s.io/apimachinery/pkg/selection" 22 | ) 23 | 24 | // RequiresExactMatch checks if the given field selector is of the form `k=v` or `k==v`. 25 | func RequiresExactMatch(sel fields.Selector) bool { 26 | reqs := sel.Requirements() 27 | if len(reqs) == 0 { 28 | return false 29 | } 30 | 31 | for _, req := range reqs { 32 | if req.Operator != selection.Equals && req.Operator != selection.DoubleEquals { 33 | return false 34 | } 35 | } 36 | return true 37 | } 38 | -------------------------------------------------------------------------------- /pkg/internal/field/selector/utils_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package selector_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestSource(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Fields Selector Utils Suite") 29 | } 30 | -------------------------------------------------------------------------------- /pkg/internal/field/selector/utils_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package selector_test 18 | 19 | import ( 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | "k8s.io/apimachinery/pkg/fields" 23 | 24 | . "sigs.k8s.io/controller-runtime/pkg/internal/field/selector" 25 | ) 26 | 27 | var _ = Describe("RequiresExactMatch function", func() { 28 | 29 | It("Returns false when the selector matches everything", func() { 30 | requiresExactMatch := RequiresExactMatch(fields.Everything()) 31 | Expect(requiresExactMatch).To(BeFalse()) 32 | }) 33 | 34 | It("Returns false when the selector matches nothing", func() { 35 | requiresExactMatch := RequiresExactMatch(fields.Nothing()) 36 | Expect(requiresExactMatch).To(BeFalse()) 37 | }) 38 | 39 | It("Returns false when the selector has the form key!=val", func() { 40 | requiresExactMatch := RequiresExactMatch(fields.ParseSelectorOrDie("key!=val")) 41 | Expect(requiresExactMatch).To(BeFalse()) 42 | }) 43 | 44 | It("Returns true when the selector has the form key1==val1,key2==val2", func() { 45 | requiresExactMatch := RequiresExactMatch(fields.ParseSelectorOrDie("key1==val1,key2==val2")) 46 | Expect(requiresExactMatch).To(BeTrue()) 47 | }) 48 | 49 | It("Returns true when the selector has the form key==val", func() { 50 | requiresExactMatch := RequiresExactMatch(fields.ParseSelectorOrDie("key==val")) 51 | Expect(requiresExactMatch).To(BeTrue()) 52 | }) 53 | 54 | It("Returns true when the selector has the form key=val", func() { 55 | requiresExactMatch := RequiresExactMatch(fields.ParseSelectorOrDie("key=val")) 56 | Expect(requiresExactMatch).To(BeTrue()) 57 | }) 58 | }) 59 | -------------------------------------------------------------------------------- /pkg/internal/flock/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package flock is copied from k8s.io/kubernetes/pkg/util/flock to avoid 18 | // importing k8s.io/kubernetes as a dependency. 19 | // 20 | // Provides file locking functionalities on unix systems. 21 | package flock 22 | -------------------------------------------------------------------------------- /pkg/internal/flock/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package flock 18 | 19 | import "errors" 20 | 21 | var ( 22 | // ErrAlreadyLocked is returned when the file is already locked. 23 | ErrAlreadyLocked = errors.New("the file is already locked") 24 | ) 25 | -------------------------------------------------------------------------------- /pkg/internal/flock/flock_other.go: -------------------------------------------------------------------------------- 1 | // +build !linux,!darwin,!freebsd,!openbsd,!netbsd,!dragonfly 2 | 3 | /* 4 | Copyright 2016 The Kubernetes Authors. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package flock 20 | 21 | // Acquire is not implemented on non-unix systems. 22 | func Acquire(path string) error { 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /pkg/internal/flock/flock_unix.go: -------------------------------------------------------------------------------- 1 | //go:build linux || darwin || freebsd || openbsd || netbsd || dragonfly 2 | // +build linux darwin freebsd openbsd netbsd dragonfly 3 | 4 | /* 5 | Copyright 2016 The Kubernetes Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package flock 21 | 22 | import ( 23 | "errors" 24 | "fmt" 25 | "os" 26 | 27 | "golang.org/x/sys/unix" 28 | ) 29 | 30 | // Acquire acquires a lock on a file for the duration of the process. This method 31 | // is reentrant. 32 | func Acquire(path string) error { 33 | fd, err := unix.Open(path, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0600) 34 | if err != nil { 35 | if errors.Is(err, os.ErrExist) { 36 | return fmt.Errorf("cannot lock file %q: %w", path, ErrAlreadyLocked) 37 | } 38 | return err 39 | } 40 | 41 | // We don't need to close the fd since we should hold 42 | // it until the process exits. 43 | err = unix.Flock(fd, unix.LOCK_NB|unix.LOCK_EX) 44 | if errors.Is(err, unix.EWOULDBLOCK) { // This condition requires LOCK_NB. 45 | return fmt.Errorf("cannot lock file %q: %w", path, ErrAlreadyLocked) 46 | } 47 | return err 48 | } 49 | -------------------------------------------------------------------------------- /pkg/internal/httpserver/server.go: -------------------------------------------------------------------------------- 1 | package httpserver 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | ) 7 | 8 | // New returns a new server with sane defaults. 9 | func New(handler http.Handler) *http.Server { 10 | return &http.Server{ 11 | Handler: handler, 12 | MaxHeaderBytes: 1 << 20, 13 | IdleTimeout: 90 * time.Second, // matches http.DefaultTransport keep-alive timeout 14 | ReadHeaderTimeout: 32 * time.Second, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pkg/internal/log/log.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package log 18 | 19 | import ( 20 | "github.com/go-logr/logr" 21 | 22 | "sigs.k8s.io/controller-runtime/pkg/log" 23 | ) 24 | 25 | var ( 26 | // RuntimeLog is a base parent logger for use inside controller-runtime. 27 | RuntimeLog logr.Logger 28 | ) 29 | 30 | func init() { 31 | RuntimeLog = log.Log.WithName("controller-runtime") 32 | } 33 | -------------------------------------------------------------------------------- /pkg/internal/objectutil/objectutil.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package objectutil 18 | 19 | import ( 20 | apimeta "k8s.io/apimachinery/pkg/api/meta" 21 | "k8s.io/apimachinery/pkg/labels" 22 | "k8s.io/apimachinery/pkg/runtime" 23 | ) 24 | 25 | // FilterWithLabels returns a copy of the items in objs matching labelSel. 26 | func FilterWithLabels(objs []runtime.Object, labelSel labels.Selector) ([]runtime.Object, error) { 27 | outItems := make([]runtime.Object, 0, len(objs)) 28 | for _, obj := range objs { 29 | meta, err := apimeta.Accessor(obj) 30 | if err != nil { 31 | return nil, err 32 | } 33 | if labelSel != nil { 34 | lbls := labels.Set(meta.GetLabels()) 35 | if !labelSel.Matches(lbls) { 36 | continue 37 | } 38 | } 39 | outItems = append(outItems, obj.DeepCopyObject()) 40 | } 41 | return outItems, nil 42 | } 43 | -------------------------------------------------------------------------------- /pkg/internal/recorder/recorder_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package recorder_test 18 | 19 | import ( 20 | "net/http" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo/v2" 24 | . "github.com/onsi/gomega" 25 | "k8s.io/client-go/kubernetes" 26 | "k8s.io/client-go/rest" 27 | "sigs.k8s.io/controller-runtime/pkg/envtest" 28 | logf "sigs.k8s.io/controller-runtime/pkg/log" 29 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 30 | ) 31 | 32 | func TestRecorder(t *testing.T) { 33 | RegisterFailHandler(Fail) 34 | RunSpecs(t, "Recorder Integration Suite") 35 | } 36 | 37 | var testenv *envtest.Environment 38 | var cfg *rest.Config 39 | var httpClient *http.Client 40 | var clientset *kubernetes.Clientset 41 | 42 | var _ = BeforeSuite(func() { 43 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 44 | 45 | testenv = &envtest.Environment{} 46 | 47 | var err error 48 | cfg, err = testenv.Start() 49 | Expect(err).NotTo(HaveOccurred()) 50 | 51 | httpClient, err = rest.HTTPClientFor(cfg) 52 | Expect(err).ToNot(HaveOccurred()) 53 | 54 | clientset, err = kubernetes.NewForConfig(cfg) 55 | Expect(err).NotTo(HaveOccurred()) 56 | }) 57 | 58 | var _ = AfterSuite(func() { 59 | Expect(testenv.Stop()).To(Succeed()) 60 | }) 61 | -------------------------------------------------------------------------------- /pkg/internal/recorder/recorder_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package recorder_test 18 | 19 | import ( 20 | "github.com/go-logr/logr" 21 | . "github.com/onsi/ginkgo/v2" 22 | . "github.com/onsi/gomega" 23 | "k8s.io/client-go/kubernetes/scheme" 24 | "k8s.io/client-go/tools/record" 25 | "sigs.k8s.io/controller-runtime/pkg/internal/recorder" 26 | ) 27 | 28 | var _ = Describe("recorder.Provider", func() { 29 | makeBroadcaster := func() (record.EventBroadcaster, bool) { return record.NewBroadcaster(), true } 30 | Describe("NewProvider", func() { 31 | It("should return a provider instance and a nil error.", func() { 32 | provider, err := recorder.NewProvider(cfg, httpClient, scheme.Scheme, logr.Discard(), makeBroadcaster) 33 | Expect(provider).NotTo(BeNil()) 34 | Expect(err).NotTo(HaveOccurred()) 35 | }) 36 | 37 | It("should return an error if failed to init client.", func() { 38 | // Invalid the config 39 | cfg1 := *cfg 40 | cfg1.Host = "invalid host" 41 | _, err := recorder.NewProvider(&cfg1, httpClient, scheme.Scheme, logr.Discard(), makeBroadcaster) 42 | Expect(err).To(HaveOccurred()) 43 | Expect(err.Error()).To(ContainSubstring("failed to init client")) 44 | }) 45 | }) 46 | Describe("GetEventRecorder", func() { 47 | It("should return a recorder instance.", func() { 48 | provider, err := recorder.NewProvider(cfg, httpClient, scheme.Scheme, logr.Discard(), makeBroadcaster) 49 | Expect(err).NotTo(HaveOccurred()) 50 | 51 | recorder := provider.GetEventRecorderFor("test") 52 | Expect(recorder).NotTo(BeNil()) 53 | }) 54 | }) 55 | }) 56 | -------------------------------------------------------------------------------- /pkg/internal/source/internal_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package internal_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | logf "sigs.k8s.io/controller-runtime/pkg/log" 25 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 26 | ) 27 | 28 | func TestInternal(t *testing.T) { 29 | RegisterFailHandler(Fail) 30 | RunSpecs(t, "Source Internal Suite") 31 | } 32 | 33 | var _ = BeforeSuite(func() { 34 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 35 | }) 36 | -------------------------------------------------------------------------------- /pkg/internal/syncs/syncs.go: -------------------------------------------------------------------------------- 1 | package syncs 2 | 3 | import ( 4 | "context" 5 | "reflect" 6 | "sync" 7 | ) 8 | 9 | // MergeChans returns a channel that is closed when any of the input channels are signaled. 10 | // The caller must call the returned CancelFunc to ensure no resources are leaked. 11 | func MergeChans[T any](chans ...<-chan T) (<-chan T, context.CancelFunc) { 12 | var once sync.Once 13 | out := make(chan T) 14 | cancel := make(chan T) 15 | cancelFunc := func() { 16 | once.Do(func() { 17 | close(cancel) 18 | }) 19 | <-out 20 | } 21 | cases := make([]reflect.SelectCase, len(chans)+1) 22 | for i := range chans { 23 | cases[i] = reflect.SelectCase{ 24 | Dir: reflect.SelectRecv, 25 | Chan: reflect.ValueOf(chans[i]), 26 | } 27 | } 28 | cases[len(cases)-1] = reflect.SelectCase{ 29 | Dir: reflect.SelectRecv, 30 | Chan: reflect.ValueOf(cancel), 31 | } 32 | go func() { 33 | defer close(out) 34 | _, _, _ = reflect.Select(cases) 35 | }() 36 | 37 | return out, cancelFunc 38 | } 39 | -------------------------------------------------------------------------------- /pkg/internal/syncs/syncs_test.go: -------------------------------------------------------------------------------- 1 | package syncs 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | // This appears to be needed so that the prow test runner won't fail. 8 | _ "github.com/onsi/ginkgo/v2" 9 | _ "github.com/onsi/gomega" 10 | ) 11 | 12 | func TestMergeChans(t *testing.T) { 13 | tests := []struct { 14 | name string 15 | count int 16 | signal int 17 | }{ 18 | { 19 | name: "single channel, close 0", 20 | count: 1, 21 | signal: 0, 22 | }, 23 | { 24 | name: "double channel, close 0", 25 | count: 2, 26 | signal: 0, 27 | }, 28 | { 29 | name: "five channel, close 0", 30 | count: 5, 31 | signal: 0, 32 | }, 33 | { 34 | name: "five channel, close 1", 35 | count: 5, 36 | signal: 1, 37 | }, 38 | { 39 | name: "five channel, close 2", 40 | count: 5, 41 | signal: 2, 42 | }, 43 | { 44 | name: "five channel, close 3", 45 | count: 5, 46 | signal: 3, 47 | }, 48 | { 49 | name: "five channel, close 4", 50 | count: 5, 51 | signal: 4, 52 | }, 53 | { 54 | name: "single channel, cancel", 55 | count: 1, 56 | signal: -1, 57 | }, 58 | { 59 | name: "double channel, cancel", 60 | count: 2, 61 | signal: -1, 62 | }, 63 | { 64 | name: "five channel, cancel", 65 | count: 5, 66 | signal: -1, 67 | }, 68 | } 69 | for _, test := range tests { 70 | t.Run(test.name, func(t *testing.T) { 71 | if callAndClose(test.count, test.signal, 1) { 72 | t.Error("timeout before merged channel closed") 73 | } 74 | }) 75 | } 76 | } 77 | 78 | func callAndClose(numChans, signalChan, timeoutSeconds int) bool { 79 | chans := make([]chan struct{}, numChans) 80 | readOnlyChans := make([]<-chan struct{}, numChans) 81 | for i := range chans { 82 | chans[i] = make(chan struct{}) 83 | readOnlyChans[i] = chans[i] 84 | } 85 | defer func() { 86 | for i := range chans { 87 | close(chans[i]) 88 | } 89 | }() 90 | 91 | merged, cancel := MergeChans(readOnlyChans...) 92 | defer cancel() 93 | 94 | timer := time.NewTimer(time.Duration(timeoutSeconds) * time.Second) 95 | 96 | if signalChan >= 0 { 97 | chans[signalChan] <- struct{}{} 98 | } else { 99 | cancel() 100 | } 101 | select { 102 | case <-merged: 103 | return false 104 | case <-timer.C: 105 | return true 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /pkg/internal/testing/addr/addr_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package addr_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestAddr(t *testing.T) { 27 | t.Parallel() 28 | RegisterFailHandler(Fail) 29 | RunSpecs(t, "Addr Suite") 30 | } 31 | -------------------------------------------------------------------------------- /pkg/internal/testing/certs/certs_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package certs_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestInternal(t *testing.T) { 27 | t.Parallel() 28 | RegisterFailHandler(Fail) 29 | RunSpecs(t, "TinyCA (Internal Certs) Suite") 30 | } 31 | -------------------------------------------------------------------------------- /pkg/internal/testing/controlplane/controlplane_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controlplane_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestIntegration(t *testing.T) { 27 | t.Parallel() 28 | RegisterFailHandler(Fail) 29 | RunSpecs(t, "Control Plane Standup Unit Tests") 30 | } 31 | -------------------------------------------------------------------------------- /pkg/internal/testing/controlplane/etcd_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controlplane_test 18 | 19 | import ( 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | 23 | . "sigs.k8s.io/controller-runtime/pkg/internal/testing/controlplane" 24 | ) 25 | 26 | var _ = Describe("etcd", func() { 27 | // basic coherence test 28 | It("should start and stop successfully", func() { 29 | etcd := &Etcd{} 30 | Expect(etcd.Start()).To(Succeed()) 31 | defer func() { 32 | Expect(etcd.Stop()).To(Succeed()) 33 | }() 34 | Expect(etcd.URL).NotTo(BeNil()) 35 | }) 36 | }) 37 | -------------------------------------------------------------------------------- /pkg/internal/testing/process/procattr_other.go: -------------------------------------------------------------------------------- 1 | //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos 2 | // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos 3 | 4 | /* 5 | Copyright 2016 The Kubernetes Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package process 21 | 22 | import "syscall" 23 | 24 | // GetSysProcAttr returns the SysProcAttr to use for the process, 25 | // for non-unix systems this returns nil. 26 | func GetSysProcAttr() *syscall.SysProcAttr { 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /pkg/internal/testing/process/procattr_unix.go: -------------------------------------------------------------------------------- 1 | //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos 2 | // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos 3 | 4 | /* 5 | Copyright 2023 The Kubernetes Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package process 21 | 22 | import ( 23 | "golang.org/x/sys/unix" 24 | ) 25 | 26 | // GetSysProcAttr returns the SysProcAttr to use for the process, 27 | // for unix systems this returns a SysProcAttr with Setpgid set to true, 28 | // which inherits the parent's process group id. 29 | func GetSysProcAttr() *unix.SysProcAttr { 30 | return &unix.SysProcAttr{ 31 | Setpgid: true, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pkg/internal/testing/process/process_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package process_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestInternal(t *testing.T) { 27 | t.Parallel() 28 | RegisterFailHandler(Fail) 29 | RunSpecs(t, "Envtest Process Launcher Suite") 30 | } 31 | -------------------------------------------------------------------------------- /pkg/leaderelection/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package leaderelection contains a constructor for a leader election resource lock. 19 | This is used to ensure that multiple copies of a controller manager can be run with 20 | only one active set of controllers, for active-passive HA. 21 | 22 | It uses built-in Kubernetes leader election APIs. 23 | */ 24 | package leaderelection 25 | -------------------------------------------------------------------------------- /pkg/leaderelection/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package fake mocks a resource lock for testing purposes. 19 | Always returns leadership. 20 | */ 21 | package fake 22 | -------------------------------------------------------------------------------- /pkg/log/log_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package log 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestSource(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Log Suite") 29 | } 30 | -------------------------------------------------------------------------------- /pkg/log/null.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package log 18 | 19 | import ( 20 | "github.com/go-logr/logr" 21 | ) 22 | 23 | // NB: this is the same as the null logger logr/testing, 24 | // but avoids accidentally adding the testing flags to 25 | // all binaries. 26 | 27 | // NullLogSink is a logr.Logger that does nothing. 28 | type NullLogSink struct{} 29 | 30 | var _ logr.LogSink = NullLogSink{} 31 | 32 | // Init implements logr.LogSink. 33 | func (log NullLogSink) Init(logr.RuntimeInfo) { 34 | } 35 | 36 | // Info implements logr.InfoLogger. 37 | func (NullLogSink) Info(_ int, _ string, _ ...interface{}) { 38 | // Do nothing. 39 | } 40 | 41 | // Enabled implements logr.InfoLogger. 42 | func (NullLogSink) Enabled(level int) bool { 43 | return false 44 | } 45 | 46 | // Error implements logr.Logger. 47 | func (NullLogSink) Error(_ error, _ string, _ ...interface{}) { 48 | // Do nothing. 49 | } 50 | 51 | // WithName implements logr.Logger. 52 | func (log NullLogSink) WithName(_ string) logr.LogSink { 53 | return log 54 | } 55 | 56 | // WithValues implements logr.Logger. 57 | func (log NullLogSink) WithValues(_ ...interface{}) logr.LogSink { 58 | return log 59 | } 60 | -------------------------------------------------------------------------------- /pkg/log/zap/zap_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package zap 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestSource(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Zap Log Suite") 29 | } 30 | -------------------------------------------------------------------------------- /pkg/manager/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package manager is required to create Controllers and provides shared dependencies such as clients, caches, schemes, 19 | etc. Controllers must be started by calling Manager.Start. 20 | */ 21 | package manager 22 | -------------------------------------------------------------------------------- /pkg/manager/internal/integration/api/v1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime/schema" 21 | 22 | "sigs.k8s.io/controller-runtime/pkg/scheme" 23 | ) 24 | 25 | var ( 26 | // GroupVersion is group version used to register these objects. 27 | GroupVersion = schema.GroupVersion{Group: "crew.example.com", Version: "v1"} 28 | 29 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme. 30 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 31 | 32 | // AddToScheme adds the types in this group-version to the given scheme. 33 | AddToScheme = SchemeBuilder.AddToScheme 34 | ) 35 | -------------------------------------------------------------------------------- /pkg/manager/internal/integration/api/v2/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v2 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime/schema" 21 | 22 | "sigs.k8s.io/controller-runtime/pkg/scheme" 23 | ) 24 | 25 | var ( 26 | // GroupVersion is group version used to register these objects. 27 | GroupVersion = schema.GroupVersion{Group: "crew.example.com", Version: "v2"} 28 | 29 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme. 30 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 31 | 32 | // AddToScheme adds the types in this group-version to the given scheme. 33 | AddToScheme = SchemeBuilder.AddToScheme 34 | ) 35 | -------------------------------------------------------------------------------- /pkg/manager/internal/integration/manager_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package integration 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestManager(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Manager Integration Suite") 29 | } 30 | -------------------------------------------------------------------------------- /pkg/manager/signals/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package signals contains libraries for handling signals to gracefully 18 | // shutdown the manager in combination with Kubernetes pod graceful termination 19 | // policy. 20 | package signals 21 | -------------------------------------------------------------------------------- /pkg/manager/signals/signal.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package signals 18 | 19 | import ( 20 | "context" 21 | "os" 22 | "os/signal" 23 | ) 24 | 25 | var onlyOneSignalHandler = make(chan struct{}) 26 | 27 | // SetupSignalHandler registers for SIGTERM and SIGINT. A context is returned 28 | // which is canceled on one of these signals. If a second signal is caught, the program 29 | // is terminated with exit code 1. 30 | func SetupSignalHandler() context.Context { 31 | close(onlyOneSignalHandler) // panics when called twice 32 | 33 | ctx, cancel := context.WithCancel(context.Background()) 34 | 35 | c := make(chan os.Signal, 2) 36 | signal.Notify(c, shutdownSignals...) 37 | go func() { 38 | <-c 39 | cancel() 40 | <-c 41 | os.Exit(1) // second signal. Exit directly. 42 | }() 43 | 44 | return ctx 45 | } 46 | -------------------------------------------------------------------------------- /pkg/manager/signals/signal_posix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | /* 5 | Copyright 2017 The Kubernetes Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package signals 21 | 22 | import ( 23 | "os" 24 | "syscall" 25 | ) 26 | 27 | var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} 28 | -------------------------------------------------------------------------------- /pkg/manager/signals/signal_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package signals 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "os/signal" 23 | "sync" 24 | "time" 25 | 26 | . "github.com/onsi/ginkgo/v2" 27 | . "github.com/onsi/gomega" 28 | ) 29 | 30 | var _ = Describe("runtime signal", func() { 31 | 32 | Context("SignalHandler Test", func() { 33 | 34 | It("test signal handler", func() { 35 | ctx := SetupSignalHandler() 36 | task := &Task{ 37 | ticker: time.NewTicker(time.Second * 2), 38 | } 39 | c := make(chan os.Signal, 1) 40 | signal.Notify(c, os.Interrupt) 41 | task.wg.Add(1) 42 | go func(c chan os.Signal) { 43 | defer task.wg.Done() 44 | task.Run(c) 45 | }(c) 46 | 47 | select { 48 | case sig := <-c: 49 | fmt.Printf("Got %s signal. Aborting...\n", sig) 50 | case _, ok := <-ctx.Done(): 51 | Expect(ok).To(BeFalse()) 52 | } 53 | }) 54 | 55 | }) 56 | 57 | }) 58 | 59 | type Task struct { 60 | wg sync.WaitGroup 61 | ticker *time.Ticker 62 | } 63 | 64 | func (t *Task) Run(c chan os.Signal) { 65 | for { 66 | go sendSignal(c) 67 | handle() 68 | } 69 | } 70 | 71 | func handle() { 72 | for i := 0; i < 5; i++ { 73 | fmt.Print("#") 74 | time.Sleep(time.Millisecond * 100) 75 | } 76 | fmt.Println() 77 | } 78 | 79 | func sendSignal(stopChan chan os.Signal) { 80 | fmt.Printf("...") 81 | time.Sleep(1 * time.Second) 82 | stopChan <- os.Interrupt 83 | } 84 | -------------------------------------------------------------------------------- /pkg/manager/signals/signal_windows.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package signals 18 | 19 | import ( 20 | "os" 21 | ) 22 | 23 | var shutdownSignals = []os.Signal{os.Interrupt} 24 | -------------------------------------------------------------------------------- /pkg/manager/signals/signals_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package signals 18 | 19 | import ( 20 | "os/signal" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo/v2" 24 | . "github.com/onsi/gomega" 25 | ) 26 | 27 | func TestSource(t *testing.T) { 28 | RegisterFailHandler(Fail) 29 | RunSpecs(t, "Runtime Signal Suite") 30 | } 31 | 32 | var _ = BeforeSuite(func() { 33 | signal.Reset() 34 | }) 35 | -------------------------------------------------------------------------------- /pkg/manager/testdata/custom-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: CustomControllerManagerConfiguration 3 | customValue: foo 4 | -------------------------------------------------------------------------------- /pkg/metrics/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package metrics contains controller related metrics utilities 19 | */ 20 | package metrics 21 | -------------------------------------------------------------------------------- /pkg/metrics/leaderelection.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "github.com/prometheus/client_golang/prometheus" 5 | "k8s.io/client-go/tools/leaderelection" 6 | ) 7 | 8 | // This file is copied and adapted from k8s.io/component-base/metrics/prometheus/clientgo/leaderelection 9 | // which registers metrics to the k8s legacy Registry. We require very 10 | // similar functionality, but must register metrics to a different Registry. 11 | 12 | var ( 13 | leaderGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{ 14 | Name: "leader_election_master_status", 15 | Help: "Gauge of if the reporting system is master of the relevant lease, 0 indicates backup, 1 indicates master. 'name' is the string used to identify the lease. Please make sure to group by name.", 16 | }, []string{"name"}) 17 | 18 | leaderSlowpathCounter = prometheus.NewCounterVec(prometheus.CounterOpts{ 19 | Name: "leader_election_slowpath_total", 20 | Help: "Total number of slow path exercised in renewing leader leases. 'name' is the string used to identify the lease. Please make sure to group by name.", 21 | }, []string{"name"}) 22 | ) 23 | 24 | func init() { 25 | Registry.MustRegister(leaderGauge) 26 | leaderelection.SetProvider(leaderelectionMetricsProvider{}) 27 | } 28 | 29 | type leaderelectionMetricsProvider struct{} 30 | 31 | func (leaderelectionMetricsProvider) NewLeaderMetric() leaderelection.LeaderMetric { 32 | return leaderElectionPrometheusAdapter{} 33 | } 34 | 35 | type leaderElectionPrometheusAdapter struct{} 36 | 37 | func (s leaderElectionPrometheusAdapter) On(name string) { 38 | leaderGauge.WithLabelValues(name).Set(1.0) 39 | } 40 | 41 | func (s leaderElectionPrometheusAdapter) Off(name string) { 42 | leaderGauge.WithLabelValues(name).Set(0.0) 43 | } 44 | 45 | func (leaderElectionPrometheusAdapter) SlowpathExercised(name string) { 46 | leaderSlowpathCounter.WithLabelValues(name).Inc() 47 | } 48 | -------------------------------------------------------------------------------- /pkg/metrics/registry.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metrics 18 | 19 | import "github.com/prometheus/client_golang/prometheus" 20 | 21 | // RegistererGatherer combines both parts of the API of a Prometheus 22 | // registry, both the Registerer and the Gatherer interfaces. 23 | type RegistererGatherer interface { 24 | prometheus.Registerer 25 | prometheus.Gatherer 26 | } 27 | 28 | // Registry is a prometheus registry for storing metrics within the 29 | // controller-runtime. 30 | var Registry RegistererGatherer = prometheus.NewRegistry() 31 | -------------------------------------------------------------------------------- /pkg/metrics/server/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package server provides the metrics server implementation. 19 | */ 20 | package server 21 | 22 | import ( 23 | logf "sigs.k8s.io/controller-runtime/pkg/internal/log" 24 | ) 25 | 26 | var log = logf.RuntimeLog.WithName("metrics") 27 | -------------------------------------------------------------------------------- /pkg/metrics/workqueue.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metrics 18 | 19 | // Metrics subsystem and all keys used by the workqueue. 20 | const ( 21 | WorkQueueSubsystem = "workqueue" 22 | DepthKey = "depth" 23 | AddsKey = "adds_total" 24 | QueueLatencyKey = "queue_duration_seconds" 25 | WorkDurationKey = "work_duration_seconds" 26 | UnfinishedWorkKey = "unfinished_work_seconds" 27 | LongestRunningProcessorKey = "longest_running_processor_seconds" 28 | RetriesKey = "retries_total" 29 | ) 30 | -------------------------------------------------------------------------------- /pkg/predicate/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package predicate defines Predicates used by Controllers to filter Events before they are provided to EventHandlers. 19 | */ 20 | package predicate 21 | -------------------------------------------------------------------------------- /pkg/predicate/example_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package predicate_test 18 | 19 | import ( 20 | "sigs.k8s.io/controller-runtime/pkg/event" 21 | "sigs.k8s.io/controller-runtime/pkg/predicate" 22 | ) 23 | 24 | var p predicate.Predicate 25 | 26 | // This example creates a new Predicate to drop Update Events where the Generation has not changed. 27 | func ExampleFuncs() { 28 | p = predicate.Funcs{ 29 | UpdateFunc: func(e event.UpdateEvent) bool { 30 | return e.ObjectOld.GetGeneration() != e.ObjectNew.GetGeneration() 31 | }, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pkg/predicate/predicate_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package predicate_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | logf "sigs.k8s.io/controller-runtime/pkg/log" 25 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 26 | ) 27 | 28 | func TestPredicate(t *testing.T) { 29 | RegisterFailHandler(Fail) 30 | RunSpecs(t, "Predicate Suite") 31 | } 32 | 33 | var _ = BeforeSuite(func() { 34 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 35 | }) 36 | -------------------------------------------------------------------------------- /pkg/reconcile/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package reconcile defines the Reconciler interface to implement Kubernetes APIs. Reconciler is provided 19 | to Controllers at creation time as the API implementation. 20 | */ 21 | package reconcile 22 | -------------------------------------------------------------------------------- /pkg/reconcile/example_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package reconcile_test 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "time" 23 | 24 | "k8s.io/apimachinery/pkg/types" 25 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 26 | ) 27 | 28 | // This example implements a simple no-op reconcile function that prints the object to be Reconciled. 29 | func ExampleFunc() { 30 | r := reconcile.Func(func(_ context.Context, o reconcile.Request) (reconcile.Result, error) { 31 | // Create your business logic to create, update, delete objects here. 32 | fmt.Printf("Name: %s, Namespace: %s", o.Name, o.Namespace) 33 | return reconcile.Result{}, nil 34 | }) 35 | 36 | res, err := r.Reconcile(context.Background(), reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "default", Name: "test"}}) 37 | if err != nil || res.Requeue || res.RequeueAfter != time.Duration(0) { 38 | fmt.Printf("got requeue request: %v, %v\n", err, res) 39 | } 40 | 41 | // Output: Name: test, Namespace: default 42 | } 43 | -------------------------------------------------------------------------------- /pkg/reconcile/reconcile_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package reconcile_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | logf "sigs.k8s.io/controller-runtime/pkg/log" 25 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 26 | ) 27 | 28 | func TestReconcile(t *testing.T) { 29 | RegisterFailHandler(Fail) 30 | RunSpecs(t, "Reconcile Suite") 31 | } 32 | 33 | var _ = BeforeSuite(func() { 34 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 35 | }) 36 | -------------------------------------------------------------------------------- /pkg/recorder/example_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package recorder_test 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | 22 | _ "github.com/onsi/ginkgo/v2" 23 | "sigs.k8s.io/controller-runtime/pkg/recorder" 24 | ) 25 | 26 | var ( 27 | recorderProvider recorder.Provider 28 | somePod *corev1.Pod // the object you're reconciling, for example 29 | ) 30 | 31 | func Example_event() { 32 | // recorderProvider is a recorder.Provider 33 | recorder := recorderProvider.GetEventRecorderFor("my-controller") 34 | 35 | // emit an event with a fixed message 36 | recorder.Event(somePod, corev1.EventTypeWarning, 37 | "WrongTrousers", "It's the wrong trousers, Gromit!") 38 | } 39 | 40 | func Example_eventf() { 41 | // recorderProvider is a recorder.Provider 42 | recorder := recorderProvider.GetEventRecorderFor("my-controller") 43 | 44 | // emit an event with a variable message 45 | mildCheese := "Wensleydale" 46 | recorder.Eventf(somePod, corev1.EventTypeNormal, 47 | "DislikesCheese", "Not even %s?", mildCheese) 48 | } 49 | -------------------------------------------------------------------------------- /pkg/recorder/recorder.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package recorder defines interfaces for working with Kubernetes event recorders. 18 | // 19 | // You can use these to emit Kubernetes events associated with a particular Kubernetes 20 | // object. 21 | package recorder 22 | 23 | import ( 24 | "k8s.io/client-go/tools/record" 25 | ) 26 | 27 | // Provider knows how to generate new event recorders with given name. 28 | type Provider interface { 29 | // NewRecorder returns an EventRecorder with given name. 30 | GetEventRecorderFor(name string) record.EventRecorder 31 | } 32 | -------------------------------------------------------------------------------- /pkg/scheme/scheme_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package scheme_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestScheme(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Scheme Suite") 29 | } 30 | -------------------------------------------------------------------------------- /pkg/source/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package source provides event streams to hook up to Controllers with Controller.Watch. Events are 19 | used with handler.EventHandlers to enqueue reconcile.Requests and trigger Reconciles for Kubernetes 20 | objects. 21 | */ 22 | package source 23 | -------------------------------------------------------------------------------- /pkg/source/example_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package source_test 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | "sigs.k8s.io/controller-runtime/pkg/controller" 22 | "sigs.k8s.io/controller-runtime/pkg/event" 23 | "sigs.k8s.io/controller-runtime/pkg/handler" 24 | "sigs.k8s.io/controller-runtime/pkg/manager" 25 | "sigs.k8s.io/controller-runtime/pkg/source" 26 | ) 27 | 28 | var mgr manager.Manager 29 | var ctrl controller.Controller 30 | 31 | // This example Watches for Pod Events (e.g. Create / Update / Delete) and enqueues a reconcile.Request 32 | // with the Name and Namespace of the Pod. 33 | func ExampleKind() { 34 | err := ctrl.Watch(source.Kind(mgr.GetCache(), &corev1.Pod{}, &handler.TypedEnqueueRequestForObject[*corev1.Pod]{})) 35 | if err != nil { 36 | // handle it 37 | } 38 | } 39 | 40 | // This example reads GenericEvents from a channel and enqueues a reconcile.Request containing the Name and Namespace 41 | // provided by the event. 42 | func ExampleChannel() { 43 | events := make(chan event.GenericEvent) 44 | 45 | err := ctrl.Watch( 46 | source.Channel( 47 | events, 48 | &handler.EnqueueRequestForObject{}, 49 | ), 50 | ) 51 | if err != nil { 52 | // handle it 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /pkg/source/source_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package source_test 18 | 19 | import ( 20 | "context" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo/v2" 24 | . "github.com/onsi/gomega" 25 | "k8s.io/client-go/kubernetes" 26 | "k8s.io/client-go/rest" 27 | "sigs.k8s.io/controller-runtime/pkg/cache" 28 | "sigs.k8s.io/controller-runtime/pkg/envtest" 29 | logf "sigs.k8s.io/controller-runtime/pkg/log" 30 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 31 | ) 32 | 33 | func TestSource(t *testing.T) { 34 | RegisterFailHandler(Fail) 35 | RunSpecs(t, "Source Suite") 36 | } 37 | 38 | var testenv *envtest.Environment 39 | var config *rest.Config 40 | var clientset *kubernetes.Clientset 41 | var icache cache.Cache 42 | var ctx context.Context 43 | var cancel context.CancelFunc 44 | 45 | var _ = BeforeSuite(func() { 46 | ctx, cancel = context.WithCancel(context.Background()) 47 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 48 | 49 | testenv = &envtest.Environment{} 50 | 51 | var err error 52 | config, err = testenv.Start() 53 | Expect(err).NotTo(HaveOccurred()) 54 | 55 | clientset, err = kubernetes.NewForConfig(config) 56 | Expect(err).NotTo(HaveOccurred()) 57 | 58 | icache, err = cache.New(config, cache.Options{}) 59 | Expect(err).NotTo(HaveOccurred()) 60 | 61 | go func() { 62 | defer GinkgoRecover() 63 | Expect(icache.Start(ctx)).NotTo(HaveOccurred()) 64 | }() 65 | }) 66 | 67 | var _ = AfterSuite(func() { 68 | cancel() 69 | Expect(testenv.Stop()).To(Succeed()) 70 | }) 71 | -------------------------------------------------------------------------------- /pkg/webhook/admission/admission_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package admission 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | 25 | logf "sigs.k8s.io/controller-runtime/pkg/log" 26 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 27 | ) 28 | 29 | func TestAdmissionWebhook(t *testing.T) { 30 | RegisterFailHandler(Fail) 31 | RunSpecs(t, "Admission Webhook Suite") 32 | } 33 | 34 | var _ = BeforeSuite(func() { 35 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 36 | }) 37 | -------------------------------------------------------------------------------- /pkg/webhook/admission/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package admission provides implementation for admission webhook and methods to implement admission webhook handlers. 19 | 20 | See examples/mutatingwebhook.go and examples/validatingwebhook.go for examples of admission webhooks. 21 | */ 22 | package admission 23 | -------------------------------------------------------------------------------- /pkg/webhook/admission/metrics/metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metrics 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | "sigs.k8s.io/controller-runtime/pkg/metrics" 22 | ) 23 | 24 | var ( 25 | // WebhookPanics is a prometheus counter metrics which holds the total 26 | // number of panics from webhooks. 27 | WebhookPanics = prometheus.NewCounterVec(prometheus.CounterOpts{ 28 | Name: "controller_runtime_webhook_panics_total", 29 | Help: "Total number of webhook panics", 30 | }, []string{}) 31 | ) 32 | 33 | func init() { 34 | metrics.Registry.MustRegister( 35 | WebhookPanics, 36 | ) 37 | // Init metric. 38 | WebhookPanics.WithLabelValues().Add(0) 39 | } 40 | -------------------------------------------------------------------------------- /pkg/webhook/authentication/authentication_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package authentication 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | 25 | logf "sigs.k8s.io/controller-runtime/pkg/log" 26 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 27 | ) 28 | 29 | func TestAuthenticationWebhook(t *testing.T) { 30 | RegisterFailHandler(Fail) 31 | RunSpecs(t, "Authentication Webhook Suite") 32 | } 33 | 34 | var _ = BeforeSuite(func() { 35 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 36 | }) 37 | -------------------------------------------------------------------------------- /pkg/webhook/authentication/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package authentication provides implementation for authentication webhook and 19 | methods to implement authentication webhook handlers. 20 | 21 | See examples/tokenreview/ for an example of authentication webhooks. 22 | */ 23 | package authentication 24 | -------------------------------------------------------------------------------- /pkg/webhook/authentication/response.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package authentication 18 | 19 | import ( 20 | authenticationv1 "k8s.io/api/authentication/v1" 21 | ) 22 | 23 | // Authenticated constructs a response indicating that the given token 24 | // is valid. 25 | func Authenticated(reason string, user authenticationv1.UserInfo) Response { 26 | return ReviewResponse(true, user, reason) 27 | } 28 | 29 | // Unauthenticated constructs a response indicating that the given token 30 | // is not valid. 31 | func Unauthenticated(reason string, user authenticationv1.UserInfo) Response { 32 | return ReviewResponse(false, authenticationv1.UserInfo{}, reason) 33 | } 34 | 35 | // Errored creates a new Response for error-handling a request. 36 | func Errored(err error) Response { 37 | return Response{ 38 | TokenReview: authenticationv1.TokenReview{ 39 | Spec: authenticationv1.TokenReviewSpec{}, 40 | Status: authenticationv1.TokenReviewStatus{ 41 | Authenticated: false, 42 | Error: err.Error(), 43 | }, 44 | }, 45 | } 46 | } 47 | 48 | // ReviewResponse returns a response for admitting a request. 49 | func ReviewResponse(authenticated bool, user authenticationv1.UserInfo, err string, audiences ...string) Response { 50 | resp := Response{ 51 | TokenReview: authenticationv1.TokenReview{ 52 | Status: authenticationv1.TokenReviewStatus{ 53 | Authenticated: authenticated, 54 | User: user, 55 | Audiences: audiences, 56 | }, 57 | }, 58 | } 59 | if len(err) > 0 { 60 | resp.TokenReview.Status.Error = err 61 | } 62 | return resp 63 | } 64 | -------------------------------------------------------------------------------- /pkg/webhook/conversion/conversion_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package conversion 17 | 18 | import ( 19 | "testing" 20 | 21 | . "github.com/onsi/ginkgo/v2" 22 | . "github.com/onsi/gomega" 23 | 24 | logf "sigs.k8s.io/controller-runtime/pkg/log" 25 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 26 | ) 27 | 28 | func TestConversionWebhook(t *testing.T) { 29 | RegisterFailHandler(Fail) 30 | RunSpecs(t, "CRD conversion Suite") 31 | } 32 | 33 | var _ = BeforeSuite(func() { 34 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 35 | }) 36 | -------------------------------------------------------------------------------- /pkg/webhook/conversion/decoder.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package conversion 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime" 21 | "k8s.io/apimachinery/pkg/runtime/schema" 22 | "k8s.io/apimachinery/pkg/runtime/serializer" 23 | ) 24 | 25 | // Decoder knows how to decode the contents of a CRD version conversion 26 | // request into a concrete object. 27 | // TODO(droot): consider reusing decoder from admission pkg for this. 28 | type Decoder struct { 29 | codecs serializer.CodecFactory 30 | } 31 | 32 | // NewDecoder creates a Decoder given the runtime.Scheme 33 | func NewDecoder(scheme *runtime.Scheme) *Decoder { 34 | if scheme == nil { 35 | panic("scheme should never be nil") 36 | } 37 | return &Decoder{codecs: serializer.NewCodecFactory(scheme)} 38 | } 39 | 40 | // Decode decodes the inlined object. 41 | func (d *Decoder) Decode(content []byte) (runtime.Object, *schema.GroupVersionKind, error) { 42 | deserializer := d.codecs.UniversalDeserializer() 43 | return deserializer.Decode(content, nil, nil) 44 | } 45 | 46 | // DecodeInto decodes the inlined object in the into the passed-in runtime.Object. 47 | func (d *Decoder) DecodeInto(content []byte, into runtime.Object) error { 48 | deserializer := d.codecs.UniversalDeserializer() 49 | return runtime.DecodeInto(deserializer, content, into) 50 | } 51 | -------------------------------------------------------------------------------- /pkg/webhook/conversion/testdata/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Kubernetes Generated files - skip generated files, except for vendored files 17 | 18 | !vendor/**/zz_generated.* 19 | 20 | # editor and IDE paraphernalia 21 | .idea 22 | *.swp 23 | *.swo 24 | *~ 25 | -------------------------------------------------------------------------------- /pkg/webhook/conversion/testdata/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Image URL to use all building/pushing image targets 3 | IMG ?= controller:latest 4 | # Produce CRDs that work back to Kubernetes 1.11 (no version conversion) 5 | CRD_OPTIONS ?= "crd:trivialVersions=true" 6 | 7 | all: manager 8 | 9 | # Run tests 10 | test: generate fmt vet manifests 11 | go test ./api/... ./controllers/... -coverprofile cover.out 12 | 13 | # Build manager binary 14 | manager: generate fmt vet 15 | go build -o bin/manager main.go 16 | 17 | # Run against the configured Kubernetes cluster in ~/.kube/config 18 | run: generate fmt vet 19 | go run ./main.go 20 | 21 | # Install CRDs into a cluster 22 | install: manifests 23 | kubectl apply -f config/crd/bases 24 | 25 | # Deploy controller in the configured Kubernetes cluster in ~/.kube/config 26 | deploy: manifests 27 | kubectl apply -f config/crd/bases 28 | kustomize build config/default | kubectl apply -f - 29 | 30 | # Generate manifests e.g. CRD, RBAC etc. 31 | manifests: controller-gen 32 | $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases 33 | 34 | # Run go fmt against code 35 | fmt: 36 | go fmt ./... 37 | 38 | # Run go vet against code 39 | vet: 40 | go vet ./... 41 | 42 | # Generate code 43 | generate: controller-gen 44 | $(CONTROLLER_GEN) object:headerFile=./hack/boilerplate.go.txt paths=./api/... 45 | 46 | # Build the docker image 47 | docker-build: test 48 | docker build . -t ${IMG} 49 | @echo "updating kustomize image patch file for manager resource" 50 | sed -i'' -e 's@image: .*@image: '"${IMG}"'@' ./config/default/manager_image_patch.yaml 51 | 52 | # Push the docker image 53 | docker-push: 54 | docker push ${IMG} 55 | 56 | # find or download controller-gen 57 | # download controller-gen if necessary 58 | controller-gen: 59 | ifeq (, $(shell which controller-gen)) 60 | go get sigs.k8s.io/controller-tools/cmd/controller-gen@v0.2.0-beta.2 61 | CONTROLLER_GEN=$(shell go env GOPATH)/bin/controller-gen 62 | else 63 | CONTROLLER_GEN=$(shell which controller-gen) 64 | endif 65 | -------------------------------------------------------------------------------- /pkg/webhook/conversion/testdata/PROJECT: -------------------------------------------------------------------------------- 1 | version: "2" 2 | domain: testprojects.kb.io 3 | repo: sigs.k8s.io/controller-runtime/pkg/webhook/conversion/testdata 4 | resources: 5 | - group: jobs 6 | version: v1 7 | kind: ExternalJob 8 | - group: jobs 9 | version: v2 10 | kind: ExternalJob 11 | - group: jobs 12 | version: v3 13 | kind: ExternalJob 14 | -------------------------------------------------------------------------------- /pkg/webhook/conversion/testdata/api/v1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | // Package v1 contains API Schema definitions for the jobs v1 API group 17 | // +kubebuilder:object:generate=true 18 | // +groupName=jobs.testprojects.kb.io 19 | package v1 20 | 21 | import ( 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | "sigs.k8s.io/controller-runtime/pkg/scheme" 24 | ) 25 | 26 | var ( 27 | // GroupVersion is group version used to register these objects 28 | GroupVersion = schema.GroupVersion{Group: "jobs.testprojects.kb.io", Version: "v1"} 29 | 30 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 31 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 32 | 33 | // AddToScheme adds the types in this group-version to the given scheme. 34 | AddToScheme = SchemeBuilder.AddToScheme 35 | ) 36 | -------------------------------------------------------------------------------- /pkg/webhook/conversion/testdata/api/v2/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | // Package v2 contains API Schema definitions for the jobs v2 API group 17 | // +kubebuilder:object:generate=true 18 | // +groupName=jobs.testprojects.kb.io 19 | package v2 20 | 21 | import ( 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | "sigs.k8s.io/controller-runtime/pkg/scheme" 24 | ) 25 | 26 | var ( 27 | // GroupVersion is group version used to register these objects 28 | GroupVersion = schema.GroupVersion{Group: "jobs.testprojects.kb.io", Version: "v2"} 29 | 30 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 31 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 32 | 33 | // AddToScheme adds the types in this group-version to the given scheme. 34 | AddToScheme = SchemeBuilder.AddToScheme 35 | ) 36 | -------------------------------------------------------------------------------- /pkg/webhook/conversion/testdata/api/v3/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | // Package v3 contains API Schema definitions for the jobs v3 API group 17 | // +kubebuilder:object:generate=true 18 | // +groupName=jobs.testprojects.kb.io 19 | package v3 20 | 21 | import ( 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | "sigs.k8s.io/controller-runtime/pkg/scheme" 24 | ) 25 | 26 | var ( 27 | // GroupVersion is group version used to register these objects 28 | GroupVersion = schema.GroupVersion{Group: "jobs.testprojects.kb.io", Version: "v3"} 29 | 30 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 31 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 32 | 33 | // AddToScheme adds the types in this group-version to the given scheme. 34 | AddToScheme = SchemeBuilder.AddToScheme 35 | ) 36 | -------------------------------------------------------------------------------- /pkg/webhook/conversion/testdata/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ -------------------------------------------------------------------------------- /pkg/webhook/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package webhook provides methods to build and bootstrap a webhook server. 19 | 20 | Currently, it only supports admission webhooks. It will support CRD conversion webhooks in the near future. 21 | */ 22 | package webhook 23 | 24 | import ( 25 | logf "sigs.k8s.io/controller-runtime/pkg/internal/log" 26 | ) 27 | 28 | var log = logf.RuntimeLog.WithName("webhook") 29 | -------------------------------------------------------------------------------- /tools/setup-envtest/env/env_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package env_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | 25 | "github.com/go-logr/logr" 26 | "github.com/go-logr/zapr" 27 | "go.uber.org/zap" 28 | "go.uber.org/zap/zapcore" 29 | ) 30 | 31 | var testLog logr.Logger 32 | 33 | func zapLogger() logr.Logger { 34 | testOut := zapcore.AddSync(GinkgoWriter) 35 | enc := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()) 36 | // bleh setting up logging to the ginkgo writer is annoying 37 | zapLog := zap.New(zapcore.NewCore(enc, testOut, zap.DebugLevel), 38 | zap.ErrorOutput(testOut), zap.Development(), zap.AddStacktrace(zap.WarnLevel)) 39 | return zapr.NewLogger(zapLog) 40 | } 41 | 42 | func TestEnv(t *testing.T) { 43 | testLog = zapLogger() 44 | 45 | RegisterFailHandler(Fail) 46 | RunSpecs(t, "Env Suite") 47 | } 48 | -------------------------------------------------------------------------------- /tools/setup-envtest/env/helpers.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2021 The Kubernetes Authors 3 | 4 | package env 5 | 6 | import ( 7 | "fmt" 8 | 9 | "sigs.k8s.io/controller-runtime/tools/setup-envtest/versions" 10 | ) 11 | 12 | // orderPlatforms orders platforms by OS then arch. 13 | func orderPlatforms(first, second versions.Platform) bool { 14 | // sort by OS, then arch 15 | if first.OS != second.OS { 16 | return first.OS < second.OS 17 | } 18 | return first.Arch < second.Arch 19 | } 20 | 21 | // PrintFormat indicates how to print out fetch and switch results. 22 | // It's a valid pflag.Value so it can be used as a flag directly. 23 | type PrintFormat int 24 | 25 | const ( 26 | // PrintOverview prints human-readable data, 27 | // including path, version, arch, and checksum (when available). 28 | PrintOverview PrintFormat = iota 29 | // PrintPath prints *only* the path, with no decoration. 30 | PrintPath 31 | // PrintEnv prints the path with the corresponding env variable, so that 32 | // you can source the output like 33 | // `source $(fetch-envtest switch -p env 1.20.x)`. 34 | PrintEnv 35 | ) 36 | 37 | func (f PrintFormat) String() string { 38 | switch f { 39 | case PrintOverview: 40 | return "overview" 41 | case PrintPath: 42 | return "path" 43 | case PrintEnv: 44 | return "env" 45 | default: 46 | panic(fmt.Sprintf("unexpected print format %d", int(f))) 47 | } 48 | } 49 | 50 | // Set sets the value of this as a flag. 51 | func (f *PrintFormat) Set(val string) error { 52 | switch val { 53 | case "overview": 54 | *f = PrintOverview 55 | case "path": 56 | *f = PrintPath 57 | case "env": 58 | *f = PrintEnv 59 | default: 60 | return fmt.Errorf("unknown print format %q, use one of overview|path|env", val) 61 | } 62 | return nil 63 | } 64 | 65 | // Type is the type of this value as a flag. 66 | func (PrintFormat) Type() string { 67 | return "{overview|path|env}" 68 | } 69 | -------------------------------------------------------------------------------- /tools/setup-envtest/go.mod: -------------------------------------------------------------------------------- 1 | module sigs.k8s.io/controller-runtime/tools/setup-envtest 2 | 3 | go 1.24.0 4 | 5 | require ( 6 | github.com/go-logr/logr v1.4.2 7 | github.com/go-logr/zapr v1.3.0 8 | github.com/onsi/ginkgo/v2 v2.22.2 9 | github.com/onsi/gomega v1.36.2 10 | github.com/spf13/afero v1.12.0 11 | github.com/spf13/pflag v1.0.6 12 | go.uber.org/zap v1.27.0 13 | k8s.io/apimachinery v0.33.0 14 | sigs.k8s.io/yaml v1.4.0 15 | ) 16 | 17 | require ( 18 | github.com/go-task/slim-sprig/v3 v3.0.0 // indirect 19 | github.com/google/go-cmp v0.7.0 // indirect 20 | github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect 21 | go.uber.org/multierr v1.10.0 // indirect 22 | golang.org/x/net v0.38.0 // indirect 23 | golang.org/x/sys v0.31.0 // indirect 24 | golang.org/x/text v0.23.0 // indirect 25 | golang.org/x/tools v0.28.0 // indirect 26 | google.golang.org/protobuf v1.36.5 // indirect 27 | gopkg.in/yaml.v3 v3.0.1 // indirect 28 | ) 29 | -------------------------------------------------------------------------------- /tools/setup-envtest/remote/client.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2024 The Kubernetes Authors 3 | 4 | package remote 5 | 6 | import ( 7 | "context" 8 | "io" 9 | 10 | "sigs.k8s.io/controller-runtime/tools/setup-envtest/versions" 11 | ) 12 | 13 | // Client is an interface to get and list envtest binary archives. 14 | type Client interface { 15 | ListVersions(ctx context.Context) ([]versions.Set, error) 16 | 17 | GetVersion(ctx context.Context, version versions.Concrete, platform versions.PlatformItem, out io.Writer) error 18 | 19 | FetchSum(ctx context.Context, ver versions.Concrete, pl *versions.PlatformItem) error 20 | } 21 | -------------------------------------------------------------------------------- /tools/setup-envtest/remote/read_body.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2024 The Kubernetes Authors 3 | 4 | package remote 5 | 6 | import ( 7 | "crypto/md5" 8 | "crypto/sha512" 9 | "encoding/base64" 10 | "encoding/hex" 11 | "errors" 12 | "fmt" 13 | "hash" 14 | "io" 15 | "net/http" 16 | 17 | "sigs.k8s.io/controller-runtime/tools/setup-envtest/versions" 18 | ) 19 | 20 | func readBody(resp *http.Response, out io.Writer, archiveName string, platform versions.PlatformItem) error { 21 | if platform.Hash != nil { 22 | // stream in chunks to do the checksum, don't load the whole thing into 23 | // memory to avoid causing issues with big files. 24 | buf := make([]byte, 32*1024) // 32KiB, same as io.Copy 25 | var hasher hash.Hash 26 | switch platform.Hash.Type { 27 | case versions.SHA512HashType: 28 | hasher = sha512.New() 29 | case versions.MD5HashType: 30 | hasher = md5.New() 31 | default: 32 | return fmt.Errorf("hash type %s not implemented", platform.Hash.Type) 33 | } 34 | for cont := true; cont; { 35 | amt, err := resp.Body.Read(buf) 36 | if err != nil && !errors.Is(err, io.EOF) { 37 | return fmt.Errorf("unable read next chunk of %s: %w", archiveName, err) 38 | } 39 | if amt > 0 { 40 | // checksum never returns errors according to docs 41 | hasher.Write(buf[:amt]) 42 | if _, err := out.Write(buf[:amt]); err != nil { 43 | return fmt.Errorf("unable write next chunk of %s: %w", archiveName, err) 44 | } 45 | } 46 | cont = amt > 0 && !errors.Is(err, io.EOF) 47 | } 48 | 49 | var sum string 50 | switch platform.Hash.Encoding { 51 | case versions.Base64HashEncoding: 52 | sum = base64.StdEncoding.EncodeToString(hasher.Sum(nil)) 53 | case versions.HexHashEncoding: 54 | sum = hex.EncodeToString(hasher.Sum(nil)) 55 | default: 56 | return fmt.Errorf("hash encoding %s not implemented", platform.Hash.Encoding) 57 | } 58 | if sum != platform.Hash.Value { 59 | return fmt.Errorf("checksum mismatch for %s: %s (computed) != %s (reported)", archiveName, sum, platform.Hash.Value) 60 | } 61 | } else if _, err := io.Copy(out, resp.Body); err != nil { 62 | return fmt.Errorf("unable to download %s: %w", archiveName, err) 63 | } 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /tools/setup-envtest/store/helpers.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2021 The Kubernetes Authors 3 | 4 | package store 5 | 6 | import ( 7 | "errors" 8 | "os" 9 | "path/filepath" 10 | "runtime" 11 | ) 12 | 13 | // DefaultStoreDir returns the default location for the store. 14 | // It's dependent on operating system: 15 | // 16 | // - Windows: %LocalAppData%\kubebuilder-envtest 17 | // - OSX: ~/Library/Application Support/io.kubebuilder.envtest 18 | // - Others: ${XDG_DATA_HOME:-~/.local/share}/kubebuilder-envtest 19 | // 20 | // Otherwise, it errors out. Note that these paths must not be relied upon 21 | // manually. 22 | func DefaultStoreDir() (string, error) { 23 | var baseDir string 24 | 25 | // find the base data directory 26 | switch runtime.GOOS { 27 | case "windows": 28 | baseDir = os.Getenv("LocalAppData") 29 | if baseDir == "" { 30 | return "", errors.New("%LocalAppData% is not defined") 31 | } 32 | case "darwin", "ios": 33 | homeDir := os.Getenv("HOME") 34 | if homeDir == "" { 35 | return "", errors.New("$HOME is not defined") 36 | } 37 | baseDir = filepath.Join(homeDir, "Library/Application Support") 38 | default: 39 | baseDir = os.Getenv("XDG_DATA_HOME") 40 | if baseDir == "" { 41 | homeDir := os.Getenv("HOME") 42 | if homeDir == "" { 43 | return "", errors.New("neither $XDG_DATA_HOME nor $HOME are defined") 44 | } 45 | baseDir = filepath.Join(homeDir, ".local/share") 46 | } 47 | } 48 | 49 | // append our program-specific dir to it (OSX has a slightly different 50 | // convention so try to follow that). 51 | switch runtime.GOOS { 52 | case "darwin", "ios": 53 | return filepath.Join(baseDir, "io.kubebuilder.envtest"), nil 54 | default: 55 | return filepath.Join(baseDir, "kubebuilder-envtest"), nil 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tools/setup-envtest/store/store_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package store_test 18 | 19 | import ( 20 | "context" 21 | "testing" 22 | 23 | "github.com/go-logr/logr" 24 | "github.com/go-logr/zapr" 25 | "go.uber.org/zap" 26 | "go.uber.org/zap/zapcore" 27 | 28 | . "github.com/onsi/ginkgo/v2" 29 | . "github.com/onsi/gomega" 30 | ) 31 | 32 | var testLog logr.Logger 33 | 34 | func zapLogger() logr.Logger { 35 | testOut := zapcore.AddSync(GinkgoWriter) 36 | enc := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()) 37 | // bleh setting up logging to the ginkgo writer is annoying 38 | zapLog := zap.New(zapcore.NewCore(enc, testOut, zap.DebugLevel), 39 | zap.ErrorOutput(testOut), zap.Development(), zap.AddStacktrace(zap.WarnLevel)) 40 | return zapr.NewLogger(zapLog) 41 | } 42 | 43 | func logCtx() context.Context { 44 | return logr.NewContext(context.Background(), testLog) 45 | } 46 | 47 | func TestStore(t *testing.T) { 48 | testLog = zapLogger() 49 | RegisterFailHandler(Fail) 50 | RunSpecs(t, "Store Suite") 51 | } 52 | -------------------------------------------------------------------------------- /tools/setup-envtest/version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import "runtime/debug" 4 | 5 | // Version to be set using ldflags: 6 | // -ldflags "-X sigs.k8s.io/controller-runtime/tools/setup-envtest/version.version=v1.0.0" 7 | // falls back to module information is unse 8 | var version = "" 9 | 10 | // Version returns the version of the main module 11 | func Version() string { 12 | if version != "" { 13 | return version 14 | } 15 | info, ok := debug.ReadBuildInfo() 16 | if !ok || info == nil || info.Main.Version == "" { 17 | // binary has not been built with module support or doesn't contain a version. 18 | return "(unknown)" 19 | } 20 | return info.Main.Version 21 | } 22 | -------------------------------------------------------------------------------- /tools/setup-envtest/version/version_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubernetes Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package version 16 | 17 | import ( 18 | "testing" 19 | 20 | . "github.com/onsi/ginkgo/v2" 21 | . "github.com/onsi/gomega" 22 | ) 23 | 24 | func TestVersioning(t *testing.T) { 25 | RegisterFailHandler(Fail) 26 | RunSpecs(t, "Test Version Suite") 27 | } 28 | -------------------------------------------------------------------------------- /tools/setup-envtest/version/version_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubernetes Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | 12 | See the License for the specific language governing permissions and 13 | 14 | limitations under the License. 15 | */ 16 | 17 | package version 18 | 19 | import ( 20 | "runtime/debug" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | var _ = Describe("TestVersion", func() { 27 | 28 | info, ok := debug.ReadBuildInfo() 29 | Expect(ok).To(BeTrue()) 30 | tests := map[string]struct { 31 | version string 32 | expected string 33 | }{ 34 | "empty returns build info": { 35 | version: "", 36 | expected: info.Main.Version, 37 | }, 38 | "set to a value returns it": { 39 | version: "1.2.3", 40 | expected: "1.2.3", 41 | }, 42 | } 43 | for name, tc := range tests { 44 | It("Version set to "+name, func() { 45 | versionBackup := version 46 | defer func() { 47 | version = versionBackup 48 | }() 49 | version = tc.version 50 | result := Version() 51 | Expect(result).To(Equal(tc.expected)) 52 | }) 53 | } 54 | }) 55 | -------------------------------------------------------------------------------- /tools/setup-envtest/versions/versions_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package versions_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | ) 25 | 26 | func TestVersions(t *testing.T) { 27 | RegisterFailHandler(Fail) 28 | RunSpecs(t, "Versions Suite") 29 | } 30 | -------------------------------------------------------------------------------- /tools/setup-envtest/workflows/workflows_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package workflows_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | 25 | "github.com/go-logr/logr" 26 | "github.com/go-logr/zapr" 27 | "go.uber.org/zap" 28 | "go.uber.org/zap/zapcore" 29 | ) 30 | 31 | var testLog logr.Logger 32 | 33 | func zapLogger() logr.Logger { 34 | testOut := zapcore.AddSync(GinkgoWriter) 35 | enc := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()) 36 | // bleh setting up logging to the ginkgo writer is annoying 37 | zapLog := zap.New(zapcore.NewCore(enc, testOut, zap.DebugLevel), 38 | zap.ErrorOutput(testOut), zap.Development(), zap.AddStacktrace(zap.WarnLevel)) 39 | return zapr.NewLogger(zapLog) 40 | } 41 | 42 | func TestWorkflows(t *testing.T) { 43 | testLog = zapLogger() 44 | RegisterFailHandler(Fail) 45 | RunSpecs(t, "Workflows Suite") 46 | } 47 | --------------------------------------------------------------------------------