From 0e562967e0a192baf562500f49cef0abd8c6f6ec Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Mon, 17 Nov 2025 08:54:53 -0500 Subject: [PATCH] Upgrade to operator-sdk 1.41.1 Rescaffold the watcher-operator to operator-sdk 1.41.1, which includes: - Reorganize project structure (pkg/ -> internal/) - Move webhook implementations to internal/webhook/v1beta1/ - Add new cmd/main.go entrypoint with updated controller initialization - Update RBAC, certmanager, and prometheus configurations - Enhance network policies for metrics and webhook traffic - Set watcher as defaulting resource in PROJECT file - Remove auto-generated test suite scaffolding - Update build workflow and Dockerfile to version 1.41.1 This upgrade modernizes the operator structure and aligns with the latest operator-sdk best practices. Jira: OSPRH-22014 Depends-On: https://github.com/openstack-k8s-operators/openstack-operator/pull/1683 --- .ci-operator.yaml | 2 +- .github/workflows/build-watcher-operator.yaml | 2 +- .github/workflows/force-bump-pr-manual.yaml | 2 +- .../workflows/force-bump-pr-scheduled.yaml | 2 +- .pre-commit-config.yaml | 2 +- .zuul.yaml | 2 + Dockerfile | 2 +- Makefile | 16 +- PROJECT | 2 +- api/v1beta1/common_types.go | 7 +- api/v1beta1/common_webhook.go | 25 -- api/v1beta1/conditions.go | 2 +- api/v1beta1/watcher_types.go | 5 +- api/v1beta1/watcher_webhook.go | 31 +- api/v1beta1/watcherapi_types.go | 4 +- api/v1beta1/watcherapi_webhook.go | 10 - api/v1beta1/watcherapplier_types.go | 6 +- api/v1beta1/watcherapplier_webhook.go | 10 - api/v1beta1/watcherdecisionengine_types.go | 4 +- api/v1beta1/watcherdecisionengine_webhook.go | 10 - cmd/main.go | 307 ++++++++++++++++++ config/certmanager/certificate-metrics.yaml | 20 ++ config/certmanager/certificate-webhook.yaml | 20 ++ config/certmanager/certificate.yaml | 39 --- config/certmanager/issuer.yaml | 13 + config/certmanager/kustomization.yaml | 4 +- config/certmanager/kustomizeconfig.yaml | 10 +- config/crd/kustomization.yaml | 20 +- .../cainjection_in_watcherappliers.yaml | 7 - ...cainjection_in_watcherdecisionengines.yaml | 7 - .../crd/patches/cainjection_in_watchers.yaml | 7 - .../patches/webhook_in_watcherappliers.yaml | 16 - .../webhook_in_watcherdecisionengines.yaml | 16 - config/crd/patches/webhook_in_watchers.yaml | 16 - .../default/cert_metrics_manager_patch.yaml | 30 ++ config/default/kustomization.yaml | 307 ++++++++++++------ config/default/manager_auth_proxy_patch.yaml | 39 --- config/default/manager_config_patch.yaml | 10 - config/default/manager_metrics_patch.yaml | 4 + config/default/manager_webhook_patch.yaml | 54 +-- .../metrics_service.yaml} | 6 +- config/default/webhookcainjection_patch.yaml | 29 -- config/manager/manager.yaml | 26 +- ...atcher-operator.clusterserviceversion.yaml | 1 + .../network-policy/allow-metrics-traffic.yaml | 27 ++ .../network-policy/allow-webhook-traffic.yaml | 27 ++ config/network-policy/kustomization.yaml | 3 + config/prometheus/kustomization.yaml | 9 + config/prometheus/monitor.yaml | 11 +- config/prometheus/monitor_tls_patch.yaml | 19 ++ config/rbac/kustomization.yaml | 30 +- ...proxy_role.yaml => metrics_auth_role.yaml} | 5 +- ...ng.yaml => metrics_auth_role_binding.yaml} | 7 +- ...sterrole.yaml => metrics_reader_role.yaml} | 3 - config/rbac/watcher_admin_role.yaml | 27 ++ config/rbac/watcher_editor_role.yaml | 14 +- config/rbac/watcher_viewer_role.yaml | 14 +- config/rbac/watcherapi_admin_role.yaml | 27 ++ config/rbac/watcherapi_editor_role.yaml | 8 +- config/rbac/watcherapi_viewer_role.yaml | 8 +- config/rbac/watcherapplier_admin_role.yaml | 27 ++ config/rbac/watcherapplier_editor_role.yaml | 14 +- config/rbac/watcherapplier_viewer_role.yaml | 14 +- .../watcherdecisionengine_admin_role.yaml | 27 ++ .../watcherdecisionengine_editor_role.yaml | 14 +- .../watcherdecisionengine_viewer_role.yaml | 14 +- config/scorecard/kustomization.yaml | 8 +- config/scorecard/patches/basic.config.yaml | 2 +- config/scorecard/patches/olm.config.yaml | 10 +- config/webhook/kustomizeconfig.yaml | 5 +- config/webhook/manifests.yaml | 16 +- config/webhook/service.yaml | 10 +- go.mod | 27 ++ go.sum | 62 ++++ hack/stop_integrated_watcher.sh | 8 + .../controller}/watcher_common.go | 4 +- .../controller}/watcher_controller.go | 4 +- .../controller}/watcherapi_controller.go | 6 +- .../controller}/watcherapplier_controller.go | 6 +- .../watcherdecisionengine_controller.go | 6 +- {config/webhook => internal/watcher}/.keep | 0 {pkg => internal}/watcher/constants.go | 0 {pkg => internal}/watcher/dbpurgecronjob.go | 0 {pkg => internal}/watcher/dbsync.go | 0 {pkg => internal}/watcher/volumes.go | 0 {pkg => internal}/watcherapi/statefulset.go | 2 +- .../watcherapplier/statefulset.go | 2 +- .../watcherdecisionengine/statefulset.go | 2 +- internal/webhook/v1beta1/watcher_webhook.go | 133 ++++++++ .../webhook/v1beta1/watcherapi_webhook.go | 120 +++++++ .../webhook/v1beta1/watcherapplier_webhook.go | 120 +++++++ .../v1beta1/watcherdecisionengine_webhook.go | 120 +++++++ main.go | 214 ------------ pkg/watcher/.keep | 0 {tests => test}/functional/base_test.go | 0 {tests => test}/functional/sample_test.go | 0 {tests => test}/functional/suite_test.go | 11 +- .../functional/watcher_controller_test.go | 6 +- .../functional/watcher_test_data.go | 2 +- .../functional/watcher_webhook_test.go | 0 .../functional/watcherapi_controller_test.go | 0 .../watcherapplier_controller_test.go | 0 .../watcherdecisionengine_controller_test.go | 0 .../default/common/cleanup-assert.yaml | 0 .../default/common/cleanup-errors.yaml | 0 .../default/common/cleanup-watcher.yaml | 0 .../default/common/deploy-with-defaults.yaml | 0 .../kuttl/test-suites/default/config.yaml | 4 +- .../kuttl/test-suites/default/deps/infra.yaml | 0 .../test-suites/default/deps/keystone.yaml | 0 .../default/deps/kustomization.yaml | 0 .../test-suites/default/deps/namespace.yaml | 0 .../test-suites/default/deps/telemetry.yaml | 0 .../00-cleanup-watcher.yaml | 0 .../watcher-api-scaling/01-assert.yaml | 0 .../01-deploy-with-defaults.yaml | 0 .../watcher-api-scaling/02-assert.yaml | 0 .../02-scale-up-watcher-api.yaml | 0 .../watcher-api-scaling/03-assert.yaml | 0 .../03-scale-down-watcher-api.yaml | 0 .../watcher-api-scaling/04-assert.yaml | 0 .../watcher-api-scaling/04-errors.yaml | 0 .../04-scale-down-zero-watcher-api.yaml | 0 .../watcher-api-scaling/05-assert.yaml | 0 .../05-cleanup-watcher.yaml | 0 .../watcher-api-scaling/05-errors.yaml | 0 .../watcher-cinder/00-cleanup-watcher.yaml | 0 .../default/watcher-cinder/01-assert.yaml | 0 .../01-deploy-watcher-no-cinder.yaml | 0 .../default/watcher-cinder/02-assert.yaml | 0 .../watcher-cinder/02-deploy-cinder.yaml | 0 .../default/watcher-cinder/03-assert.yaml | 0 .../watcher-cinder/03-remove-cinder.yaml | 0 .../watcher-cinder/04-cleanup-watcher.yaml | 0 .../default/watcher-cinder/04-errors.yaml | 0 .../00-cleanup-watcher.yaml | 0 .../watcher-notification/01-assert.yaml | 0 .../01-deploy-with-notification.yaml | 0 .../02-cleanup-watcher.yaml | 0 .../watcher-notification/02-errors.yaml | 0 .../00-cleanup-watcher.yaml | 0 .../watcher-tls-certs-change/01-assert.yaml | 0 .../01-deploy-with-tlse.yaml | 0 .../watcher-tls-certs-change/02-assert.yaml | 0 .../02-change-public-svc-certificate.yaml | 0 .../watcher-tls-certs-change/03-assert.yaml | 0 .../03-change-internal-svc-certificate.yaml | 0 .../04-cleanup-watcher.yaml | 0 .../watcher-tls-certs-change/04-errors.yaml | 0 .../05-clenaup-certs.yaml | 0 .../watcher-tls-certs-change/05-errors.yaml | 0 .../watcher-tls/00-cleanup-watcher.yaml | 0 .../default/watcher-tls/01-assert.yaml | 0 .../watcher-tls/01-deploy-with-tlse.yaml | 0 .../default/watcher-tls/02-assert-mtls.yaml | 0 .../default/watcher-tls/02-patch-mtls.yaml | 0 .../default/watcher-tls/03-assert.yaml | 0 .../watcher-tls/03-disable-podlevel-tls.yaml | 0 .../default/watcher-tls/04-assert.yaml | 0 .../watcher-tls/04-deploy-without-route.yaml | 0 .../default/watcher-tls/05-assert.yaml | 0 .../default/watcher-tls/05-disable-tls.yaml | 0 .../default/watcher-tls/06-assert.yaml | 0 .../watcher-tls/06-cleanup-watcher.yaml | 0 .../default/watcher-tls/06-errors.yaml | 0 .../default/watcher-tls/07-cleanup-certs.yaml | 0 .../default/watcher-tls/07-errors.yaml | 0 .../watcher-topology/00-cleanup-watcher.yaml | 0 .../default/watcher-topology/01-assert.yaml | 0 .../01-deploy-with-topology.yaml | 0 .../default/watcher-topology/02-assert.yaml | 0 .../watcher-topology/02-cleanup-watcher.yaml | 0 .../default/watcher-topology/02-errors.yaml | 0 .../default/watcher/00-cleanup-watcher.yaml | 0 .../default/watcher/01-assert.yaml | 0 .../watcher/01-deploy-with-defaults.yaml | 0 .../default/watcher/02-cleanup-watcher.yaml | 0 .../watcher/03-precreate-mariadbaccount.yaml | 0 .../default/watcher/04-assert.yaml | 0 .../04-deploy-with-precreated-account.yaml | 0 .../default/watcher/05-assert.yaml | 0 .../default/watcher/05-cleanup-watcher.yaml | 0 .../default/watcher/05-errors.yaml | 0 183 files changed, 1629 insertions(+), 784 deletions(-) delete mode 100644 api/v1beta1/common_webhook.go create mode 100644 cmd/main.go create mode 100644 config/certmanager/certificate-metrics.yaml create mode 100644 config/certmanager/certificate-webhook.yaml delete mode 100644 config/certmanager/certificate.yaml create mode 100644 config/certmanager/issuer.yaml delete mode 100644 config/crd/patches/cainjection_in_watcherappliers.yaml delete mode 100644 config/crd/patches/cainjection_in_watcherdecisionengines.yaml delete mode 100644 config/crd/patches/cainjection_in_watchers.yaml delete mode 100644 config/crd/patches/webhook_in_watcherappliers.yaml delete mode 100644 config/crd/patches/webhook_in_watcherdecisionengines.yaml delete mode 100644 config/crd/patches/webhook_in_watchers.yaml create mode 100644 config/default/cert_metrics_manager_patch.yaml delete mode 100644 config/default/manager_auth_proxy_patch.yaml delete mode 100644 config/default/manager_config_patch.yaml create mode 100644 config/default/manager_metrics_patch.yaml rename config/{rbac/auth_proxy_service.yaml => default/metrics_service.yaml} (64%) delete mode 100644 config/default/webhookcainjection_patch.yaml create mode 100644 config/network-policy/allow-metrics-traffic.yaml create mode 100644 config/network-policy/allow-webhook-traffic.yaml create mode 100644 config/network-policy/kustomization.yaml create mode 100644 config/prometheus/monitor_tls_patch.yaml rename config/rbac/{auth_proxy_role.yaml => metrics_auth_role.yaml} (68%) rename config/rbac/{auth_proxy_role_binding.yaml => metrics_auth_role_binding.yaml} (60%) rename config/rbac/{auth_proxy_client_clusterrole.yaml => metrics_reader_role.yaml} (60%) create mode 100644 config/rbac/watcher_admin_role.yaml create mode 100644 config/rbac/watcherapi_admin_role.yaml create mode 100644 config/rbac/watcherapplier_admin_role.yaml create mode 100644 config/rbac/watcherdecisionengine_admin_role.yaml rename {controllers => internal/controller}/watcher_common.go (99%) rename {controllers => internal/controller}/watcher_controller.go (99%) rename {controllers => internal/controller}/watcherapi_controller.go (99%) rename {controllers => internal/controller}/watcherapplier_controller.go (99%) rename {controllers => internal/controller}/watcherdecisionengine_controller.go (99%) rename {config/webhook => internal/watcher}/.keep (100%) rename {pkg => internal}/watcher/constants.go (100%) rename {pkg => internal}/watcher/dbpurgecronjob.go (100%) rename {pkg => internal}/watcher/dbsync.go (100%) rename {pkg => internal}/watcher/volumes.go (100%) rename {pkg => internal}/watcherapi/statefulset.go (98%) rename {pkg => internal}/watcherapplier/statefulset.go (98%) rename {pkg => internal}/watcherdecisionengine/statefulset.go (98%) create mode 100644 internal/webhook/v1beta1/watcher_webhook.go create mode 100644 internal/webhook/v1beta1/watcherapi_webhook.go create mode 100644 internal/webhook/v1beta1/watcherapplier_webhook.go create mode 100644 internal/webhook/v1beta1/watcherdecisionengine_webhook.go delete mode 100644 main.go delete mode 100644 pkg/watcher/.keep rename {tests => test}/functional/base_test.go (100%) rename {tests => test}/functional/sample_test.go (100%) rename {tests => test}/functional/suite_test.go (94%) rename {tests => test}/functional/watcher_controller_test.go (99%) rename {tests => test}/functional/watcher_test_data.go (98%) rename {tests => test}/functional/watcher_webhook_test.go (100%) rename {tests => test}/functional/watcherapi_controller_test.go (100%) rename {tests => test}/functional/watcherapplier_controller_test.go (100%) rename {tests => test}/functional/watcherdecisionengine_controller_test.go (100%) rename {tests => test}/kuttl/test-suites/default/common/cleanup-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/common/cleanup-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/common/cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/common/deploy-with-defaults.yaml (100%) rename {tests => test}/kuttl/test-suites/default/config.yaml (75%) rename {tests => test}/kuttl/test-suites/default/deps/infra.yaml (100%) rename {tests => test}/kuttl/test-suites/default/deps/keystone.yaml (100%) rename {tests => test}/kuttl/test-suites/default/deps/kustomization.yaml (100%) rename {tests => test}/kuttl/test-suites/default/deps/namespace.yaml (100%) rename {tests => test}/kuttl/test-suites/default/deps/telemetry.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/00-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/01-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/01-deploy-with-defaults.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/02-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/02-scale-up-watcher-api.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/03-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/03-scale-down-watcher-api.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/04-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/04-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/04-scale-down-zero-watcher-api.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/05-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/05-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-api-scaling/05-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-cinder/00-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-cinder/01-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-cinder/01-deploy-watcher-no-cinder.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-cinder/02-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-cinder/02-deploy-cinder.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-cinder/03-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-cinder/03-remove-cinder.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-cinder/04-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-cinder/04-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-notification/00-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-notification/01-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-notification/01-deploy-with-notification.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-notification/02-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-notification/02-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/00-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/01-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/01-deploy-with-tlse.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/02-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/02-change-public-svc-certificate.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/03-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/03-change-internal-svc-certificate.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/04-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/04-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/05-clenaup-certs.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls-certs-change/05-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/00-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/01-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/01-deploy-with-tlse.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/02-assert-mtls.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/02-patch-mtls.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/03-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/03-disable-podlevel-tls.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/04-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/04-deploy-without-route.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/05-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/05-disable-tls.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/06-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/06-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/06-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/07-cleanup-certs.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-tls/07-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-topology/00-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-topology/01-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-topology/01-deploy-with-topology.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-topology/02-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-topology/02-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher-topology/02-errors.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/00-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/01-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/01-deploy-with-defaults.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/02-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/03-precreate-mariadbaccount.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/04-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/04-deploy-with-precreated-account.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/05-assert.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/05-cleanup-watcher.yaml (100%) rename {tests => test}/kuttl/test-suites/default/watcher/05-errors.yaml (100%) diff --git a/.ci-operator.yaml b/.ci-operator.yaml index 1a05e606..df7900c6 100644 --- a/.ci-operator.yaml +++ b/.ci-operator.yaml @@ -1,4 +1,4 @@ build_root_image: name: tools namespace: openstack-k8s-operators - tag: ci-build-root-golang-1.24-sdk-1.31 + tag: ci-build-root-golang-1.24-sdk-1.41.1 diff --git a/.github/workflows/build-watcher-operator.yaml b/.github/workflows/build-watcher-operator.yaml index 1230047b..94b591a9 100644 --- a/.github/workflows/build-watcher-operator.yaml +++ b/.github/workflows/build-watcher-operator.yaml @@ -16,7 +16,7 @@ jobs: with: operator_name: watcher go_version: 1.24.x - operator_sdk_version: 1.31.0 + operator_sdk_version: 1.41.1 secrets: IMAGENAMESPACE: ${{ secrets.IMAGENAMESPACE }} QUAY_USERNAME: ${{ secrets.QUAY_USERNAME }} diff --git a/.github/workflows/force-bump-pr-manual.yaml b/.github/workflows/force-bump-pr-manual.yaml index 4f06d612..fc8f7b7a 100644 --- a/.github/workflows/force-bump-pr-manual.yaml +++ b/.github/workflows/force-bump-pr-manual.yaml @@ -9,6 +9,6 @@ jobs: with: operator_name: watcher branch_name: ${{ github.ref_name }} - custom_image: quay.io/openstack-k8s-operators/openstack-k8s-operators-ci-build-tools:golang-1.24-sdk-1.31 + custom_image: quay.io/openstack-k8s-operators/openstack-k8s-operators-ci-build-tools:golang-1.24-sdk-1.41.1 secrets: FORCE_BUMP_PULL_REQUEST_PAT: ${{ secrets.FORCE_BUMP_PULL_REQUEST_PAT }} diff --git a/.github/workflows/force-bump-pr-scheduled.yaml b/.github/workflows/force-bump-pr-scheduled.yaml index d492a380..20fd740c 100644 --- a/.github/workflows/force-bump-pr-scheduled.yaml +++ b/.github/workflows/force-bump-pr-scheduled.yaml @@ -10,6 +10,6 @@ jobs: uses: openstack-k8s-operators/openstack-k8s-operators-ci/.github/workflows/force-bump-branches.yaml@main with: operator_name: watcher - custom_image: quay.io/openstack-k8s-operators/openstack-k8s-operators-ci-build-tools:golang-1.24-sdk-1.31 + custom_image: quay.io/openstack-k8s-operators/openstack-k8s-operators-ci-build-tools:golang-1.24-sdk-1.41.1 secrets: FORCE_BUMP_PULL_REQUEST_PAT: ${{ secrets.FORCE_BUMP_PULL_REQUEST_PAT }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5caf6e02..93beb387 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -79,7 +79,7 @@ repos: # E012: here doc didn't end before EOF - repo: https://github.com/golangci/golangci-lint - rev: v2.4.0 + rev: v2.6.1 hooks: - id: golangci-lint-full args: ["-v"] diff --git a/.zuul.yaml b/.zuul.yaml index 73bdbf82..46812cd8 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -138,6 +138,7 @@ A zuul job building content from OpenDev epoxy release. parent: openstack-meta-content-provider vars: + cifmw_install_yamls_sdk_version: v1.41.1 cifmw_bop_openstack_release: epoxy cifmw_bop_dlrn_baseurl: "https://trunk.rdoproject.org/centos9-epoxy" cifmw_repo_setup_branch: epoxy @@ -208,6 +209,7 @@ nodeset: centos-stream-10-vexxhost parent: openstack-meta-content-provider vars: + cifmw_install_yamls_sdk_version: v1.41.1 cifmw_bop_openstack_release: master cifmw_bop_dlrn_baseurl: "https://trunk.rdoproject.org/centos10-master" cifmw_repo_setup_branch: master diff --git a/Dockerfile b/Dockerfile index df357fe5..825dff0b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ RUN mkdir -p ${DEST_ROOT}/usr/local/bin/ RUN if [ ! -f $CACHITO_ENV_FILE ]; then go mod download ; fi # Build manager -RUN if [ -f $CACHITO_ENV_FILE ] ; then source $CACHITO_ENV_FILE ; fi ; env ${GO_BUILD_EXTRA_ENV_ARGS} go build ${GO_BUILD_EXTRA_ARGS} -a -o ${DEST_ROOT}/manager main.go +RUN if [ -f $CACHITO_ENV_FILE ] ; then source $CACHITO_ENV_FILE ; fi ; env ${GO_BUILD_EXTRA_ENV_ARGS} go build ${GO_BUILD_EXTRA_ARGS} -a -o ${DEST_ROOT}/manager cmd/main.go RUN cp -r templates ${DEST_ROOT}/templates diff --git a/Makefile b/Makefile index c6bd88db..1418419a 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ endif # Set the Operator SDK version to use. By default, what is installed on the system is used. # This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. -OPERATOR_SDK_VERSION ?= v1.31.0 +OPERATOR_SDK_VERSION ?= v1.41.1 # Image URL to use all building/pushing image targets DEFAULT_IMG ?= quay.io/openstack-k8s-operators/watcher-operator:latest @@ -146,14 +146,14 @@ PROC_CMD = --procs ${PROCS} .PHONY: test test: manifests generate fmt vet envtest ginkgo ## Run tests. OPERATOR_TEMPLATES="$(PWD)/templates" \ - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" $(GINKGO) --trace --cover --coverpkg=../../pkg/watcher,../../controllers,../../api/v1beta1 --coverprofile cover.out --covermode=atomic ${PROC_CMD} $(GINKGO_ARGS) ./tests/... + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" $(GINKGO) --trace --cover --coverpkg=../../internal/watcher,../../internal/controller,../../api/v1beta1 --coverprofile cover.out --covermode=atomic ${PROC_CMD} $(GINKGO_ARGS) ./test/... ##@ Build .PHONY: build build: generate fmt vet ## Build manager binary. - go build -o bin/manager main.go + go build -o bin/manager cmd/main.go .PHONY: run run: export METRICS_PORT?=24604 @@ -161,7 +161,7 @@ run: export HEALTH_PORT?=24605 run: export PPROF_PORT?=8082 run: export ENABLE_WEBHOOKS?=false run: manifests generate fmt vet ## Run a controller from your host. - go run ./main.go -metrics-bind-address ":$(METRICS_PORT)" -health-probe-bind-address ":$(HEALTH_PORT)" -pprof-bind-address ":$(PPROF_PORT)" + go run ./cmd/main.go -metrics-bind-address ":$(METRICS_PORT)" -health-probe-bind-address ":$(HEALTH_PORT)" -pprof-bind-address ":$(PPROF_PORT)" # Extra vars which will be passed to the Docker-build @@ -212,7 +212,7 @@ ENVTEST ?= $(LOCALBIN)/setup-envtest GINKGO ?= $(LOCALBIN)/ginkgo ## Tool Versions -KUSTOMIZE_VERSION ?= v3.8.7 +KUSTOMIZE_VERSION ?= v5.6.0 CONTROLLER_TOOLS_VERSION ?= v0.18.0 SETUP_ENVTEST_VERSION ?= release-0.22 @@ -391,6 +391,10 @@ watcher: export WATCHER_DECISION_ENGINE_IMAGE=${WATCHER_DECISION_ENGINE_CI_IMAGE watcher: export WATCHER_APPLIER_IMAGE=${WATCHER_APPLIER_CI_IMAGE} watcher: export CATALOG_IMG=${CATALOG_IMAGE} watcher: ## Install watcher operator via olm + # explicitly to delete any running watcher-operator deployments from openstack-operator here as + # label selectors can change and installing a service catalog/index like this alongside + # openstack-operator (what CI appears to do?) is not recommended + oc delete deployment watcher-operator-controller-manager -n openstack-operators --ignore-not-found=true bash ci/olm.sh oc apply -f ci/olm.yaml timeout 300s bash -c "while ! (oc get csv -n openshift-operators -l operators.coreos.com/cluster-observability-operator.openshift-operators -o jsonpath='{.items[*].status.phase}' | grep Succeeded); do sleep 10; done" @@ -424,7 +428,7 @@ watcher_cleanup: ## Cleaning watcher operator via olm KUTTL_SUITE ?= default KUTTL_NAMESPACE ?= watcher-kuttl-$(KUTTL_SUITE) -KUTTL_SUITE_DIR ?= tests/kuttl/test-suites/$(KUTTL_SUITE) +KUTTL_SUITE_DIR ?= test/kuttl/test-suites/$(KUTTL_SUITE) .PHONY: stop_watcher_integrated stop_watcher_integrated: diff --git a/PROJECT b/PROJECT index 35d7fd46..e0311a9b 100644 --- a/PROJECT +++ b/PROJECT @@ -4,7 +4,7 @@ # More info: https://book.kubebuilder.io/reference/project-config.html domain: openstack.org layout: -- go.kubebuilder.io/v3 +- go.kubebuilder.io/v4 plugins: manifests.sdk.operatorframework.io/v2: {} scorecard.sdk.operatorframework.io/v2: {} diff --git a/api/v1beta1/common_types.go b/api/v1beta1/common_types.go index 487baa96..09a711a7 100644 --- a/api/v1beta1/common_types.go +++ b/api/v1beta1/common_types.go @@ -147,7 +147,7 @@ type PasswordSelector struct { Service *string `json:"service"` } -// WatcherSubCrsCommon +// WatcherSubCrsCommon defines the common fields for Watcher sub-CRs type WatcherSubCrsCommon struct { // +kubebuilder:validation:Optional // The service specific Container Image URL (will be set to environmental default if empty) @@ -189,6 +189,7 @@ type WatcherSubCrsTemplate struct { TopologyRef *topologyv1.TopoRef `json:"topologyRef,omitempty"` } +// WatcherImages defines the container images for all Watcher services type WatcherImages struct { // +kubebuilder:validation:Required // APIContainerImageURL @@ -203,6 +204,7 @@ type WatcherImages struct { ApplierContainerImageURL string `json:"applierContainerImageURL"` } +// Default sets default values for WatcherImages based on the provided defaults func (r *WatcherImages) Default(defaults WatcherDefaults) { if r.APIContainerImageURL == "" { r.APIContainerImageURL = defaults.APIContainerImageURL @@ -215,8 +217,7 @@ func (r *WatcherImages) Default(defaults WatcherDefaults) { } } -// SetupDefaults - initializes any CRD field defaults based on environment variables (the defaulting mechanism itself is implemented via webhooks) - +// SetupDefaults initializes any CRD field defaults based on environment variables (the defaulting mechanism itself is implemented via webhooks) func SetupDefaults() { // Acquire environmental defaults and initialize Watcher defaults with them watcherDefaults := WatcherDefaults{ diff --git a/api/v1beta1/common_webhook.go b/api/v1beta1/common_webhook.go deleted file mode 100644 index 01fcc55e..00000000 --- a/api/v1beta1/common_webhook.go +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1beta1 - -import ctrl "sigs.k8s.io/controller-runtime" - -func (r *Watcher) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} diff --git a/api/v1beta1/conditions.go b/api/v1beta1/conditions.go index 3aaa2114..afd64224 100644 --- a/api/v1beta1/conditions.go +++ b/api/v1beta1/conditions.go @@ -5,7 +5,7 @@ import "github.com/openstack-k8s-operators/lib-common/modules/common/condition" const ( // WatcherRabbitMQTransportURLReadyCondition - WatcherRabbitMQTransportURLReadyCondition condition.Type = "WatcherRabbitMQTransportURLReady" - // WatcherNotificationsBusTransportURLReadyCondition - + // WatcherNotificationTransportURLReadyCondition indicates whether the Watcher notification transport URL is ready WatcherNotificationTransportURLReadyCondition condition.Type = "WatcherNotificationTransportURLReady" // WatcherAPIReadyCondition - WatcherAPIReadyCondition condition.Type = "WatcherAPIReady" diff --git a/api/v1beta1/watcher_types.go b/api/v1beta1/watcher_types.go index ee6e927c..aace7d54 100644 --- a/api/v1beta1/watcher_types.go +++ b/api/v1beta1/watcher_types.go @@ -63,6 +63,7 @@ type WatcherStatus struct { DecisionEngineServiceReadyCount int32 `json:"decisionengineServiceReadyCount,omitempty"` } +// WatcherDBPurge defines the parameters for the Watcher database purging cron job type WatcherDBPurge struct { // +kubebuilder:validation:Optional // +kubebuilder:default="0 1 * * *" @@ -117,8 +118,8 @@ func (instance Watcher) RbacResourceName() string { } // IsReady returns true if the ReadyCondition is true -func (r *Watcher) IsReady() bool { - return r.Status.Conditions.IsTrue(condition.ReadyCondition) +func (instance *Watcher) IsReady() bool { + return instance.Status.Conditions.IsTrue(condition.ReadyCondition) } func init() { diff --git a/api/v1beta1/watcher_webhook.go b/api/v1beta1/watcher_webhook.go index 3e472513..b6971327 100644 --- a/api/v1beta1/watcher_webhook.go +++ b/api/v1beta1/watcher_webhook.go @@ -42,13 +42,12 @@ var watcherDefaults WatcherDefaults // log is for logging in this package. var watcherlog = logf.Log.WithName("watcher-resource") +// SetupWatcherDefaults initializes the Watcher defaults for the webhook func SetupWatcherDefaults(defaults WatcherDefaults) { watcherDefaults = defaults watcherlog.Info("Watcher defaults initialized", "defaults", defaults) } -//+kubebuilder:webhook:path=/mutate-watcher-openstack-org-v1beta1-watcher,mutating=true,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watchers,verbs=create;update,versions=v1beta1,name=mwatcher.kb.io,admissionReviewVersions=v1 - var _ webhook.Defaulter = &Watcher{} // Default implements webhook.Defaulter so a webhook will be registered for the type @@ -68,8 +67,6 @@ func (spec *WatcherSpecCore) Default() { // no validations . Placeholder for defaulting webhook integrated in the OpenStackControlPlane } -//+kubebuilder:webhook:path=/validate-watcher-openstack-org-v1beta1-watcher,mutating=false,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watchers,verbs=create;update,versions=v1beta1,name=vwatcher.kb.io,admissionReviewVersions=v1 - var _ webhook.Validator = &Watcher{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type @@ -88,17 +85,17 @@ func (r *Watcher) ValidateCreate() (admission.Warnings, error) { } // ValidateCreate validates the WatcherSpec during the webhook invocation. -func (r *WatcherSpec) ValidateCreate(basePath *field.Path, namespace string) field.ErrorList { - return r.WatcherSpecCore.ValidateCreate(basePath, namespace) +func (spec *WatcherSpec) ValidateCreate(basePath *field.Path, namespace string) field.ErrorList { + return spec.WatcherSpecCore.ValidateCreate(basePath, namespace) } // ValidateCreate validates the WatcherSpecCore during the webhook invocation. It is // expected to be called by the validation webhook in the higher level meta // operator -func (r *WatcherSpecCore) ValidateCreate(basePath *field.Path, namespace string) field.ErrorList { +func (spec *WatcherSpecCore) ValidateCreate(basePath *field.Path, namespace string) field.ErrorList { var allErrs field.ErrorList - if *r.DatabaseInstance == "" || r.DatabaseInstance == nil { + if *spec.DatabaseInstance == "" || spec.DatabaseInstance == nil { allErrs = append( allErrs, field.Invalid( @@ -106,7 +103,7 @@ func (r *WatcherSpecCore) ValidateCreate(basePath *field.Path, namespace string) ) } - if *r.RabbitMqClusterName == "" || r.RabbitMqClusterName == nil { + if *spec.RabbitMqClusterName == "" || spec.RabbitMqClusterName == nil { allErrs = append( allErrs, field.Invalid( @@ -114,7 +111,7 @@ func (r *WatcherSpecCore) ValidateCreate(basePath *field.Path, namespace string) ) } - allErrs = append(allErrs, r.ValidateWatcherTopology(basePath, namespace)...) + allErrs = append(allErrs, spec.ValidateWatcherTopology(basePath, namespace)...) return allErrs } @@ -140,18 +137,18 @@ func (r *Watcher) ValidateUpdate(old runtime.Object) (admission.Warnings, error) } -// ValidateCreate validates the WatcherSpec during the webhook invocation. -func (r *WatcherSpec) ValidateUpdate(old WatcherSpec, basePath *field.Path, namespace string) field.ErrorList { - return r.WatcherSpecCore.ValidateUpdate(old.WatcherSpecCore, basePath, namespace) +// ValidateUpdate validates the WatcherSpec during the webhook update invocation. +func (spec *WatcherSpec) ValidateUpdate(old WatcherSpec, basePath *field.Path, namespace string) field.ErrorList { + return spec.WatcherSpecCore.ValidateUpdate(old.WatcherSpecCore, basePath, namespace) } // ValidateUpdate validates the WatcherSpecCore during the webhook invocation. It is // expected to be called by the validation webhook in the higher level meta // operator -func (r *WatcherSpecCore) ValidateUpdate(old WatcherSpecCore, basePath *field.Path, namespace string) field.ErrorList { +func (spec *WatcherSpecCore) ValidateUpdate(old WatcherSpecCore, basePath *field.Path, namespace string) field.ErrorList { var allErrs field.ErrorList - if *r.DatabaseInstance == "" || r.DatabaseInstance == nil { + if *spec.DatabaseInstance == "" || spec.DatabaseInstance == nil { allErrs = append( allErrs, field.Invalid( @@ -159,7 +156,7 @@ func (r *WatcherSpecCore) ValidateUpdate(old WatcherSpecCore, basePath *field.Pa ) } - if *r.RabbitMqClusterName == "" || r.RabbitMqClusterName == nil { + if *spec.RabbitMqClusterName == "" || spec.RabbitMqClusterName == nil { allErrs = append( allErrs, field.Invalid( @@ -167,7 +164,7 @@ func (r *WatcherSpecCore) ValidateUpdate(old WatcherSpecCore, basePath *field.Pa ) } - allErrs = append(allErrs, r.ValidateWatcherTopology(basePath, namespace)...) + allErrs = append(allErrs, spec.ValidateWatcherTopology(basePath, namespace)...) return allErrs } diff --git a/api/v1beta1/watcherapi_types.go b/api/v1beta1/watcherapi_types.go index 1622c4cd..00edd68a 100644 --- a/api/v1beta1/watcherapi_types.go +++ b/api/v1beta1/watcherapi_types.go @@ -138,8 +138,8 @@ type WatcherAPIList struct { } // IsReady returns true if the ReadyCondition is true -func (r *WatcherAPI) IsReady() bool { - return r.Status.Conditions.IsTrue(condition.ReadyCondition) +func (instance *WatcherAPI) IsReady() bool { + return instance.Status.Conditions.IsTrue(condition.ReadyCondition) } func init() { diff --git a/api/v1beta1/watcherapi_webhook.go b/api/v1beta1/watcherapi_webhook.go index 5a5cc86d..d9996565 100644 --- a/api/v1beta1/watcherapi_webhook.go +++ b/api/v1beta1/watcherapi_webhook.go @@ -20,7 +20,6 @@ import ( topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -29,16 +28,8 @@ import ( // log is for logging in this package. var watcherapilog = logf.Log.WithName("watcherapi-resource") -func (r *WatcherAPI) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - // TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -//+kubebuilder:webhook:path=/mutate-watcher-openstack-org-v1beta1-watcherapi,mutating=true,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherapis,verbs=create;update,versions=v1beta1,name=mwatcherapi.kb.io,admissionReviewVersions=v1 - var _ webhook.Defaulter = &WatcherAPI{} // Default implements webhook.Defaulter so a webhook will be registered for the type @@ -49,7 +40,6 @@ func (r *WatcherAPI) Default() { } // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -//+kubebuilder:webhook:path=/validate-watcher-openstack-org-v1beta1-watcherapi,mutating=false,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherapis,verbs=create;update,versions=v1beta1,name=vwatcherapi.kb.io,admissionReviewVersions=v1 var _ webhook.Validator = &WatcherAPI{} diff --git a/api/v1beta1/watcherapplier_types.go b/api/v1beta1/watcherapplier_types.go index 3cb02b8f..68e85a27 100644 --- a/api/v1beta1/watcherapplier_types.go +++ b/api/v1beta1/watcherapplier_types.go @@ -76,7 +76,7 @@ type WatcherApplierStatus struct { LastAppliedTopology *topologyv1.TopoRef `json:"lastAppliedTopology,omitempty"` } -// WatcherApplierTemplatce defines the input parameters specified by the user to +// WatcherApplierTemplate defines the input parameters specified by the user to // create a WatcherApplier via higher level CRDs. type WatcherApplierTemplate struct { WatcherSubCrsTemplate `json:",inline"` @@ -104,8 +104,8 @@ type WatcherApplier struct { } // IsReady returns true if the ReadyCondition is true -func (r *WatcherApplier) IsReady() bool { - return r.Status.Conditions.IsTrue(condition.ReadyCondition) +func (instance *WatcherApplier) IsReady() bool { + return instance.Status.Conditions.IsTrue(condition.ReadyCondition) } //+kubebuilder:object:root=true diff --git a/api/v1beta1/watcherapplier_webhook.go b/api/v1beta1/watcherapplier_webhook.go index 858811b7..0adf3934 100644 --- a/api/v1beta1/watcherapplier_webhook.go +++ b/api/v1beta1/watcherapplier_webhook.go @@ -20,7 +20,6 @@ import ( topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -29,16 +28,8 @@ import ( // log is for logging in this package. var watcherapplierlog = logf.Log.WithName("watcherapplier-resource") -func (r *WatcherApplier) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - // TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -//+kubebuilder:webhook:path=/mutate-watcher-openstack-org-v1beta1-watcherapplier,mutating=true,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherappliers,verbs=create;update,versions=v1beta1,name=mwatcherapplier.kb.io,admissionReviewVersions=v1 - var _ webhook.Defaulter = &WatcherApplier{} // Default implements webhook.Defaulter so a webhook will be registered for the type @@ -49,7 +40,6 @@ func (r *WatcherApplier) Default() { } // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -//+kubebuilder:webhook:path=/validate-watcher-openstack-org-v1beta1-watcherapplier,mutating=false,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherappliers,verbs=create;update,versions=v1beta1,name=vwatcherapplier.kb.io,admissionReviewVersions=v1 var _ webhook.Validator = &WatcherApplier{} diff --git a/api/v1beta1/watcherdecisionengine_types.go b/api/v1beta1/watcherdecisionengine_types.go index 1a0a380f..d65f0d62 100644 --- a/api/v1beta1/watcherdecisionengine_types.go +++ b/api/v1beta1/watcherdecisionengine_types.go @@ -110,8 +110,8 @@ type WatcherDecisionEngineList struct { } // IsReady returns true if the ReadyCondition is true -func (r *WatcherDecisionEngine) IsReady() bool { - return r.Status.Conditions.IsTrue(condition.ReadyCondition) +func (instance *WatcherDecisionEngine) IsReady() bool { + return instance.Status.Conditions.IsTrue(condition.ReadyCondition) } func init() { diff --git a/api/v1beta1/watcherdecisionengine_webhook.go b/api/v1beta1/watcherdecisionengine_webhook.go index a7959211..cedce4eb 100644 --- a/api/v1beta1/watcherdecisionengine_webhook.go +++ b/api/v1beta1/watcherdecisionengine_webhook.go @@ -20,7 +20,6 @@ import ( topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -29,16 +28,8 @@ import ( // log is for logging in this package. var watcherdecisionenginelog = logf.Log.WithName("watcherdecisionengine-resource") -func (r *WatcherDecisionEngine) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - // TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -//+kubebuilder:webhook:path=/mutate-watcher-openstack-org-v1beta1-watcherdecisionengine,mutating=true,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherdecisionengines,verbs=create;update,versions=v1beta1,name=mwatcherdecisionengine.kb.io,admissionReviewVersions=v1 - var _ webhook.Defaulter = &WatcherDecisionEngine{} // Default implements webhook.Defaulter so a webhook will be registered for the type @@ -49,7 +40,6 @@ func (r *WatcherDecisionEngine) Default() { } // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -//+kubebuilder:webhook:path=/validate-watcher-openstack-org-v1beta1-watcherdecisionengine,mutating=false,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherdecisionengines,verbs=create;update,versions=v1beta1,name=vwatcherdecisionengine.kb.io,admissionReviewVersions=v1 var _ webhook.Validator = &WatcherDecisionEngine{} diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 00000000..3c39da29 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,307 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package main is the entry point for the watcher-operator controller manager. +package main + +import ( + "crypto/tls" + "flag" + "os" + "path/filepath" + + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) + // to ensure that exec-entrypoint and run can make use of them. + _ "k8s.io/client-go/plugin/pkg/client/auth" + + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/certwatcher" + "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/metrics/filters" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" + "github.com/openstack-k8s-operators/watcher-operator/internal/controller" + webhookv1beta1 "github.com/openstack-k8s-operators/watcher-operator/internal/webhook/v1beta1" + // +kubebuilder:scaffold:imports + routev1 "github.com/openshift/api/route/v1" + memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1" + rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" + topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1" + keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" + "github.com/openstack-k8s-operators/lib-common/modules/common/operator" + mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" + "k8s.io/client-go/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client/config" +) + +var ( + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") +) + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + + utilruntime.Must(watcherv1beta1.AddToScheme(scheme)) + utilruntime.Must(mariadbv1.AddToScheme(scheme)) + utilruntime.Must(rabbitmqv1.AddToScheme(scheme)) + utilruntime.Must(keystonev1.AddToScheme(scheme)) + utilruntime.Must(memcachedv1.AddToScheme(scheme)) + utilruntime.Must(routev1.AddToScheme(scheme)) + utilruntime.Must(topologyv1.AddToScheme(scheme)) + //+kubebuilder:scaffold:scheme +} + +// nolint:gocyclo +func main() { + var metricsAddr string + var metricsCertPath, metricsCertName, metricsCertKey string + var webhookCertPath, webhookCertName, webhookCertKey string + var enableLeaderElection bool + var probeAddr string + var secureMetrics bool + var enableHTTP2 bool + var tlsOpts []func(*tls.Config) + flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ + "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.") + flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.BoolVar(&enableLeaderElection, "leader-elect", false, + "Enable leader election for controller manager. "+ + "Enabling this will ensure there is only one active controller manager.") + flag.BoolVar(&secureMetrics, "metrics-secure", true, + "If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.") + flag.StringVar(&webhookCertPath, "webhook-cert-path", "", "The directory that contains the webhook certificate.") + flag.StringVar(&webhookCertName, "webhook-cert-name", "tls.crt", "The name of the webhook certificate file.") + flag.StringVar(&webhookCertKey, "webhook-cert-key", "tls.key", "The name of the webhook key file.") + flag.StringVar(&metricsCertPath, "metrics-cert-path", "", + "The directory that contains the metrics server certificate.") + flag.StringVar(&metricsCertName, "metrics-cert-name", "tls.crt", "The name of the metrics server certificate file.") + flag.StringVar(&metricsCertKey, "metrics-cert-key", "tls.key", "The name of the metrics server key file.") + flag.BoolVar(&enableHTTP2, "enable-http2", false, + "If set, HTTP/2 will be enabled for the metrics and webhook servers") + opts := zap.Options{ + Development: true, + } + opts.BindFlags(flag.CommandLine) + flag.Parse() + + ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + + // if the enable-http2 flag is false (the default), http/2 should be disabled + // due to its vulnerabilities. More specifically, disabling http/2 will + // prevent from being vulnerable to the HTTP/2 Stream Cancellation and + // Rapid Reset CVEs. For more information see: + // - https://github.com/advisories/GHSA-qppj-fm5r-hxr3 + // - https://github.com/advisories/GHSA-4374-p667-p6c8 + disableHTTP2 := func(c *tls.Config) { + setupLog.Info("disabling http/2") + c.NextProtos = []string{"http/1.1"} + } + + if !enableHTTP2 { + tlsOpts = append(tlsOpts, disableHTTP2) + } + + // Create watchers for metrics and webhooks certificates + var metricsCertWatcher, webhookCertWatcher *certwatcher.CertWatcher + + // Initial webhook TLS options + webhookTLSOpts := tlsOpts + + if len(webhookCertPath) > 0 { + setupLog.Info("Initializing webhook certificate watcher using provided certificates", + "webhook-cert-path", webhookCertPath, "webhook-cert-name", webhookCertName, "webhook-cert-key", webhookCertKey) + + var err error + webhookCertWatcher, err = certwatcher.New( + filepath.Join(webhookCertPath, webhookCertName), + filepath.Join(webhookCertPath, webhookCertKey), + ) + if err != nil { + setupLog.Error(err, "Failed to initialize webhook certificate watcher") + os.Exit(1) + } + + webhookTLSOpts = append(webhookTLSOpts, func(config *tls.Config) { + config.GetCertificate = webhookCertWatcher.GetCertificate + }) + } + + webhookServer := webhook.NewServer(webhook.Options{ + TLSOpts: webhookTLSOpts, + }) + + // Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server. + // More info: + // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/server + // - https://book.kubebuilder.io/reference/metrics.html + metricsServerOptions := metricsserver.Options{ + BindAddress: metricsAddr, + SecureServing: secureMetrics, + TLSOpts: tlsOpts, + } + + if secureMetrics { + // FilterProvider is used to protect the metrics endpoint with authn/authz. + // These configurations ensure that only authorized users and service accounts + // can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info: + // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/filters#WithAuthenticationAndAuthorization + metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization + } + + // If the certificate is not specified, controller-runtime will automatically + // generate self-signed certificates for the metrics server. While convenient for development and testing, + // this setup is not recommended for production. + // + // TODO(user): If you enable certManager, uncomment the following lines: + // - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates + // managed by cert-manager for the metrics server. + // - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification. + if len(metricsCertPath) > 0 { + setupLog.Info("Initializing metrics certificate watcher using provided certificates", + "metrics-cert-path", metricsCertPath, "metrics-cert-name", metricsCertName, "metrics-cert-key", metricsCertKey) + + var err error + metricsCertWatcher, err = certwatcher.New( + filepath.Join(metricsCertPath, metricsCertName), + filepath.Join(metricsCertPath, metricsCertKey), + ) + if err != nil { + setupLog.Error(err, "to initialize metrics certificate watcher", "error", err) + os.Exit(1) + } + + metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) { + config.GetCertificate = metricsCertWatcher.GetCertificate + }) + } + + // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily + // when the Manager ends. This requires the binary to immediately end when the + // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly + // speeds up voluntary leader transitions as the new leader don't have to wait + // LeaseDuration time first. + // + // In the default scaffold provided, the program ends immediately after + // the manager stops, so would be fine to enable this option. However, + // if you are doing or is intended to do any operation such as perform cleanups + // after the manager stops then its usage might be unsafe. + // LeaderElectionReleaseOnCancel: true, + options := ctrl.Options{ + Scheme: scheme, + Metrics: metricsServerOptions, + WebhookServer: webhookServer, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "5049980f.openstack.org", + } + + // apply common openstack operator manager options + err := operator.SetManagerOptions(&options, setupLog) + if err != nil { + setupLog.Error(err, "unable to set manager options") + os.Exit(1) + } + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) + if err != nil { + setupLog.Error(err, "unable to start manager") + os.Exit(1) + } + + cfg, err := config.GetConfig() + if err != nil { + setupLog.Error(err, "") + os.Exit(1) + } + kclient, err := kubernetes.NewForConfig(cfg) + if err != nil { + setupLog.Error(err, "") + os.Exit(1) + } + if err != nil { + setupLog.Error(err, "unable to start manager") + os.Exit(1) + } + + reconcilers := controller.NewReconcilers(mgr, kclient) + err = reconcilers.Setup(mgr, setupLog) + if err != nil { + os.Exit(1) + } + + watcherv1beta1.SetupDefaults() + + // nolint:goconst + checker := healthz.Ping + if os.Getenv("ENABLE_WEBHOOKS") != "false" { + if err := webhookv1beta1.SetupWatcherAPIWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "WatcherAPI") + os.Exit(1) + } + if err := webhookv1beta1.SetupWatcherWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "Watcher") + os.Exit(1) + } + if err := webhookv1beta1.SetupWatcherDecisionEngineWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "WatcherDecisionEngine") + os.Exit(1) + } + if err := webhookv1beta1.SetupWatcherApplierWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "WatcherApplier") + os.Exit(1) + } + checker = mgr.GetWebhookServer().StartedChecker() + } + // +kubebuilder:scaffold:builder + + if metricsCertWatcher != nil { + setupLog.Info("Adding metrics certificate watcher to manager") + if err := mgr.Add(metricsCertWatcher); err != nil { + setupLog.Error(err, "unable to add metrics certificate watcher to manager") + os.Exit(1) + } + } + + if webhookCertWatcher != nil { + setupLog.Info("Adding webhook certificate watcher to manager") + if err := mgr.Add(webhookCertWatcher); err != nil { + setupLog.Error(err, "unable to add webhook certificate watcher to manager") + os.Exit(1) + } + } + + if err := mgr.AddHealthzCheck("healthz", checker); err != nil { + setupLog.Error(err, "unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", checker); err != nil { + setupLog.Error(err, "unable to set up ready check") + os.Exit(1) + } + + setupLog.Info("starting manager") + if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + setupLog.Error(err, "problem running manager") + os.Exit(1) + } +} diff --git a/config/certmanager/certificate-metrics.yaml b/config/certmanager/certificate-metrics.yaml new file mode 100644 index 00000000..96d057fd --- /dev/null +++ b/config/certmanager/certificate-metrics.yaml @@ -0,0 +1,20 @@ +# The following manifests contain a self-signed issuer CR and a metrics certificate CR. +# More document can be found at https://docs.cert-manager.io +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/name: watcher-operator + app.kubernetes.io/managed-by: kustomize + name: metrics-certs # this name should match the one appeared in kustomizeconfig.yaml + namespace: system +spec: + dnsNames: + # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize + # replacements in the config/default/kustomization.yaml file. + - SERVICE_NAME.SERVICE_NAMESPACE.svc + - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: metrics-server-cert diff --git a/config/certmanager/certificate-webhook.yaml b/config/certmanager/certificate-webhook.yaml new file mode 100644 index 00000000..b1e1b61b --- /dev/null +++ b/config/certmanager/certificate-webhook.yaml @@ -0,0 +1,20 @@ +# The following manifests contain a self-signed issuer CR and a certificate CR. +# More document can be found at https://docs.cert-manager.io +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/name: watcher-operator + app.kubernetes.io/managed-by: kustomize + name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml + namespace: system +spec: + # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize + # replacements in the config/default/kustomization.yaml file. + dnsNames: + - SERVICE_NAME.SERVICE_NAMESPACE.svc + - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: webhook-server-cert diff --git a/config/certmanager/certificate.yaml b/config/certmanager/certificate.yaml deleted file mode 100644 index 9d66cb99..00000000 --- a/config/certmanager/certificate.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# The following manifests contain a self-signed issuer CR and a certificate CR. -# More document can be found at https://docs.cert-manager.io -# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes. -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - labels: - app.kubernetes.io/name: issuer - app.kubernetes.io/instance: selfsigned-issuer - app.kubernetes.io/component: certificate - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator - app.kubernetes.io/managed-by: kustomize - name: selfsigned-issuer - namespace: system -spec: - selfSigned: {} ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - labels: - app.kubernetes.io/name: certificate - app.kubernetes.io/instance: serving-cert - app.kubernetes.io/component: certificate - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator - app.kubernetes.io/managed-by: kustomize - name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml - namespace: system -spec: - # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize - dnsNames: - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local - issuerRef: - kind: Issuer - name: selfsigned-issuer - secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize diff --git a/config/certmanager/issuer.yaml b/config/certmanager/issuer.yaml new file mode 100644 index 00000000..aae343dc --- /dev/null +++ b/config/certmanager/issuer.yaml @@ -0,0 +1,13 @@ +# The following manifest contains a self-signed issuer CR. +# More information can be found at https://docs.cert-manager.io +# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes. +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/name: watcher-operator + app.kubernetes.io/managed-by: kustomize + name: selfsigned-issuer + namespace: system +spec: + selfSigned: {} diff --git a/config/certmanager/kustomization.yaml b/config/certmanager/kustomization.yaml index bebea5a5..fcb7498e 100644 --- a/config/certmanager/kustomization.yaml +++ b/config/certmanager/kustomization.yaml @@ -1,5 +1,7 @@ resources: -- certificate.yaml +- issuer.yaml +- certificate-webhook.yaml +- certificate-metrics.yaml configurations: - kustomizeconfig.yaml diff --git a/config/certmanager/kustomizeconfig.yaml b/config/certmanager/kustomizeconfig.yaml index e631f777..cf6f89e8 100644 --- a/config/certmanager/kustomizeconfig.yaml +++ b/config/certmanager/kustomizeconfig.yaml @@ -1,4 +1,4 @@ -# This configuration is for teaching kustomize how to update name ref and var substitution +# This configuration is for teaching kustomize how to update name ref substitution nameReference: - kind: Issuer group: cert-manager.io @@ -6,11 +6,3 @@ nameReference: - kind: Certificate group: cert-manager.io path: spec/issuerRef/name - -varReference: -- kind: Certificate - group: cert-manager.io - path: spec/commonName -- kind: Certificate - group: cert-manager.io - path: spec/dnsNames diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 9980823e..2a0a03c4 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -6,26 +6,14 @@ resources: - bases/watcher.openstack.org_watchers.yaml - bases/watcher.openstack.org_watcherdecisionengines.yaml - bases/watcher.openstack.org_watcherappliers.yaml -#+kubebuilder:scaffold:crdkustomizeresource +# +kubebuilder:scaffold:crdkustomizeresource patches: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD -#- path: patches/webhook_in_watchers.yaml -#- path: patches/webhook_in_watcherdecisionengines.yaml -#- path: patches/webhook_in_watcherappliers.yaml -#+kubebuilder:scaffold:crdkustomizewebhookpatch - -# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. -# patches here are for enabling the CA injection for each CRD -#- path: patches/cainjection_in_watcherapis.yaml -#- path: patches/cainjection_in_watchers.yaml -#- path: patches/cainjection_in_watcherdecisionengines.yaml -#- path: patches/cainjection_in_watcherappliers.yaml -#+kubebuilder:scaffold:crdkustomizecainjectionpatch +# +kubebuilder:scaffold:crdkustomizewebhookpatch # [WEBHOOK] To enable webhook, uncomment the following section # the following config is for teaching kustomize how to do kustomization for CRDs. - -configurations: -- kustomizeconfig.yaml +#configurations: +#- kustomizeconfig.yaml diff --git a/config/crd/patches/cainjection_in_watcherappliers.yaml b/config/crd/patches/cainjection_in_watcherappliers.yaml deleted file mode 100644 index 45ee2897..00000000 --- a/config/crd/patches/cainjection_in_watcherappliers.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: watcherappliers.watcher.openstack.org diff --git a/config/crd/patches/cainjection_in_watcherdecisionengines.yaml b/config/crd/patches/cainjection_in_watcherdecisionengines.yaml deleted file mode 100644 index a1a7871c..00000000 --- a/config/crd/patches/cainjection_in_watcherdecisionengines.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: watcherdecisionengines.watcher.openstack.org diff --git a/config/crd/patches/cainjection_in_watchers.yaml b/config/crd/patches/cainjection_in_watchers.yaml deleted file mode 100644 index d14dca86..00000000 --- a/config/crd/patches/cainjection_in_watchers.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: watchers.watcher.openstack.org diff --git a/config/crd/patches/webhook_in_watcherappliers.yaml b/config/crd/patches/webhook_in_watcherappliers.yaml deleted file mode 100644 index cdc0a38c..00000000 --- a/config/crd/patches/webhook_in_watcherappliers.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: watcherappliers.watcher.openstack.org -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/crd/patches/webhook_in_watcherdecisionengines.yaml b/config/crd/patches/webhook_in_watcherdecisionengines.yaml deleted file mode 100644 index e39f0c64..00000000 --- a/config/crd/patches/webhook_in_watcherdecisionengines.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: watcherdecisionengines.watcher.openstack.org -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/crd/patches/webhook_in_watchers.yaml b/config/crd/patches/webhook_in_watchers.yaml deleted file mode 100644 index 49797346..00000000 --- a/config/crd/patches/webhook_in_watchers.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: watchers.watcher.openstack.org -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/default/cert_metrics_manager_patch.yaml b/config/default/cert_metrics_manager_patch.yaml new file mode 100644 index 00000000..d9750155 --- /dev/null +++ b/config/default/cert_metrics_manager_patch.yaml @@ -0,0 +1,30 @@ +# This patch adds the args, volumes, and ports to allow the manager to use the metrics-server certs. + +# Add the volumeMount for the metrics-server certs +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + mountPath: /tmp/k8s-metrics-server/metrics-certs + name: metrics-certs + readOnly: true + +# Add the --metrics-cert-path argument for the metrics server +- op: add + path: /spec/template/spec/containers/0/args/- + value: --metrics-cert-path=/tmp/k8s-metrics-server/metrics-certs + +# Add the metrics-server certs volume configuration +- op: add + path: /spec/template/spec/volumes/- + value: + name: metrics-certs + secret: + secretName: metrics-server-cert + optional: false + items: + - key: ca.crt + path: ca.crt + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index c3f02b57..eb8079da 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -25,121 +25,212 @@ resources: #- ../certmanager # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. #- ../prometheus +# [METRICS] Expose the controller manager metrics service. +- metrics_service.yaml +# [NETWORK POLICY] Protect the /metrics endpoint and Webhook Server with NetworkPolicy. +# Only Pod(s) running a namespace labeled with 'metrics: enabled' will be able to gather the metrics. +# Only CR(s) which requires webhooks and are applied on namespaces labeled with 'webhooks: enabled' will +# be able to communicate with the Webhook Server. +#- ../network-policy +# Uncomment the patches line if you enable Metrics patches: -# Protect the /metrics endpoint by putting it behind auth. -# If you want your controller-manager to expose the /metrics -# endpoint w/o any authn/z, please comment the following line. -- path: manager_auth_proxy_patch.yaml +# Injects our custom images (ENV variable settings) +- path: manager_default_images.yaml +# [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443. +# More info: https://book.kubebuilder.io/reference/metrics +- path: manager_metrics_patch.yaml + target: + kind: Deployment + +# Uncomment the patches line if you enable Metrics and CertManager +# [METRICS-WITH-CERTS] To enable metrics protected with certManager, uncomment the following line. +# This patch will protect the metrics with certManager self-signed certs. +#- path: cert_metrics_manager_patch.yaml +# target: +# kind: Deployment # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml - path: manager_webhook_patch.yaml - -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -#- path: webhookcainjection_patch.yaml - -# Injects our custom images (ENV variable settings) -- path: manager_default_images.yaml + target: + kind: Deployment # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. # Uncomment the following replacements to add the cert-manager CA injection annotations #replacements: -# - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldPath: .metadata.namespace # namespace of the certificate CR -# targets: -# - select: -# kind: ValidatingWebhookConfiguration -# fieldPaths: -# - .metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# create: true -# - select: -# kind: MutatingWebhookConfiguration -# fieldPaths: -# - .metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# create: true -# - select: -# kind: CustomResourceDefinition -# fieldPaths: -# - .metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# create: true -# - source: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldPath: .metadata.name -# targets: -# - select: -# kind: ValidatingWebhookConfiguration -# fieldPaths: -# - .metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 1 -# create: true -# - select: -# kind: MutatingWebhookConfiguration -# fieldPaths: -# - .metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 1 -# create: true -# - select: -# kind: CustomResourceDefinition -# fieldPaths: -# - .metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 1 -# create: true -# - source: # Add cert-manager annotation to the webhook Service -# kind: Service -# version: v1 -# name: webhook-service -# fieldPath: .metadata.name # namespace of the service -# targets: -# - select: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# fieldPaths: -# - .spec.dnsNames.0 -# - .spec.dnsNames.1 -# options: -# delimiter: '.' -# index: 0 -# create: true -# - source: -# kind: Service -# version: v1 -# name: webhook-service -# fieldPath: .metadata.namespace # namespace of the service -# targets: -# - select: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# fieldPaths: -# - .spec.dnsNames.0 -# - .spec.dnsNames.1 -# options: -# delimiter: '.' -# index: 1 -# create: true +# - source: # Uncomment the following block to enable certificates for metrics +# kind: Service +# version: v1 +# name: controller-manager-metrics-service +# fieldPath: metadata.name +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: metrics-certs +# fieldPaths: +# - spec.dnsNames.0 +# - spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 0 +# create: true +# - select: # Uncomment the following to set the Service name for TLS config in Prometheus ServiceMonitor +# kind: ServiceMonitor +# group: monitoring.coreos.com +# version: v1 +# name: controller-manager-metrics-monitor +# fieldPaths: +# - spec.endpoints.0.tlsConfig.serverName +# options: +# delimiter: '.' +# index: 0 +# create: true +# +# - source: +# kind: Service +# version: v1 +# name: controller-manager-metrics-service +# fieldPath: metadata.namespace +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: metrics-certs +# fieldPaths: +# - spec.dnsNames.0 +# - spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 1 +# create: true +# - select: # Uncomment the following to set the Service namespace for TLS in Prometheus ServiceMonitor +# kind: ServiceMonitor +# group: monitoring.coreos.com +# version: v1 +# name: controller-manager-metrics-monitor +# fieldPaths: +# - spec.endpoints.0.tlsConfig.serverName +# options: +# delimiter: '.' +# index: 1 +# create: true +# +# - source: # Uncomment the following block if you have any webhook +# kind: Service +# version: v1 +# name: webhook-service +# fieldPath: .metadata.name # Name of the service +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPaths: +# - .spec.dnsNames.0 +# - .spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 0 +# create: true +# - source: +# kind: Service +# version: v1 +# name: webhook-service +# fieldPath: .metadata.namespace # Namespace of the service +# targets: +# - select: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPaths: +# - .spec.dnsNames.0 +# - .spec.dnsNames.1 +# options: +# delimiter: '.' +# index: 1 +# create: true +# +# - source: # Uncomment the following block if you have a ValidatingWebhook (--programmatic-validation) +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # This name should match the one in certificate.yaml +# fieldPath: .metadata.namespace # Namespace of the certificate CR +# targets: +# - select: +# kind: ValidatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 0 +# create: true +# - source: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.name +# targets: +# - select: +# kind: ValidatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 1 +# create: true +# +# - source: # Uncomment the following block if you have a DefaultingWebhook (--defaulting ) +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.namespace # Namespace of the certificate CR +# targets: +# - select: +# kind: MutatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 0 +# create: true +# - source: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.name +# targets: +# - select: +# kind: MutatingWebhookConfiguration +# fieldPaths: +# - .metadata.annotations.[cert-manager.io/inject-ca-from] +# options: +# delimiter: '/' +# index: 1 +# create: true +# +# - source: # Uncomment the following block if you have a ConversionWebhook (--conversion) +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.namespace # Namespace of the certificate CR +# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD. +# +kubebuilder:scaffold:crdkustomizecainjectionns +# - source: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert +# fieldPath: .metadata.name +# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD. +# +kubebuilder:scaffold:crdkustomizecainjectionname diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml deleted file mode 100644 index d12870ed..00000000 --- a/config/default/manager_auth_proxy_patch.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# This patch inject a sidecar container which is a HTTP proxy for the -# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: kube-rbac-proxy - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - "ALL" - image: quay.io/openstack-k8s-operators/kube-rbac-proxy:v0.16.0 - args: - - "--secure-listen-address=0.0.0.0:8443" - - "--upstream=http://127.0.0.1:8080/" - - "--logtostderr=true" - - "--v=0" - ports: - - containerPort: 8443 - protocol: TCP - name: https - resources: - limits: - cpu: 500m - memory: 128Mi - requests: - cpu: 5m - memory: 64Mi - - name: manager - args: - - "--health-probe-bind-address=:8081" - - "--metrics-bind-address=127.0.0.1:8080" - - "--leader-elect" diff --git a/config/default/manager_config_patch.yaml b/config/default/manager_config_patch.yaml deleted file mode 100644 index f6f58916..00000000 --- a/config/default/manager_config_patch.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager diff --git a/config/default/manager_metrics_patch.yaml b/config/default/manager_metrics_patch.yaml new file mode 100644 index 00000000..2aaef653 --- /dev/null +++ b/config/default/manager_metrics_patch.yaml @@ -0,0 +1,4 @@ +# This patch adds the args to allow exposing the metrics endpoint using HTTPS +- op: add + path: /spec/template/spec/containers/0/args/0 + value: --metrics-bind-address=:8443 diff --git a/config/default/manager_webhook_patch.yaml b/config/default/manager_webhook_patch.yaml index 738de350..963c8a4c 100644 --- a/config/default/manager_webhook_patch.yaml +++ b/config/default/manager_webhook_patch.yaml @@ -1,23 +1,31 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: manager - ports: - - containerPort: 9443 - name: webhook-server - protocol: TCP - volumeMounts: - - mountPath: /tmp/k8s-webhook-server/serving-certs - name: cert - readOnly: true - volumes: - - name: cert - secret: - defaultMode: 420 - secretName: webhook-server-cert +# This patch ensures the webhook certificates are properly mounted in the manager container. +# It configures the necessary arguments, volumes, volume mounts, and container ports. + +# Add the --webhook-cert-path argument for configuring the webhook certificate path +- op: add + path: /spec/template/spec/containers/0/args/- + value: --webhook-cert-path=/tmp/k8s-webhook-server/serving-certs + +# Add the volumeMount for the webhook certificates +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + mountPath: /tmp/k8s-webhook-server/serving-certs + name: webhook-certs + readOnly: true + +# Add the port configuration for the webhook server +- op: add + path: /spec/template/spec/containers/0/ports/- + value: + containerPort: 9443 + name: webhook-server + protocol: TCP + +# Add the volume configuration for the webhook certificates +- op: add + path: /spec/template/spec/volumes/- + value: + name: webhook-certs + secret: + secretName: webhook-server-cert diff --git a/config/rbac/auth_proxy_service.yaml b/config/default/metrics_service.yaml similarity index 64% rename from config/rbac/auth_proxy_service.yaml rename to config/default/metrics_service.yaml index 94c22a65..7be00645 100644 --- a/config/rbac/auth_proxy_service.yaml +++ b/config/default/metrics_service.yaml @@ -3,6 +3,7 @@ kind: Service metadata: labels: control-plane: controller-manager + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-service namespace: system @@ -11,6 +12,7 @@ spec: - name: https port: 8443 protocol: TCP - targetPort: https + targetPort: 8443 selector: - openstack.org/operator-name: watcher + control-plane: controller-manager + app.kubernetes.io/name: watcher-operator diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml deleted file mode 100644 index 771ab2db..00000000 --- a/config/default/webhookcainjection_patch.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# This patch add annotation to admission webhook config and -# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. -apiVersion: admissionregistration.k8s.io/v1 -kind: MutatingWebhookConfiguration -metadata: - labels: - app.kubernetes.io/name: mutatingwebhookconfiguration - app.kubernetes.io/instance: mutating-webhook-configuration - app.kubernetes.io/component: webhook - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator - app.kubernetes.io/managed-by: kustomize - name: mutating-webhook-configuration - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) ---- -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - labels: - app.kubernetes.io/name: validatingwebhookconfiguration - app.kubernetes.io/instance: validating-webhook-configuration - app.kubernetes.io/component: webhook - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator - app.kubernetes.io/managed-by: kustomize - name: validating-webhook-configuration - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 9a3ee151..b8e8bf2c 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -3,6 +3,7 @@ kind: Namespace metadata: labels: control-plane: controller-manager + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: system --- @@ -13,12 +14,13 @@ metadata: namespace: system labels: control-plane: controller-manager - openstack.org/operator-name: watcher + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize spec: selector: matchLabels: - openstack.org/operator-name: watcher + control-plane: controller-manager + app.kubernetes.io/name: watcher-operator replicas: 1 template: metadata: @@ -26,7 +28,7 @@ spec: kubectl.kubernetes.io/default-container: manager labels: control-plane: controller-manager - openstack.org/operator-name: watcher + app.kubernetes.io/name: watcher-operator spec: # TODO(user): Uncomment the following code to configure the nodeAffinity expression # according to the platforms which are supported by your solution. @@ -49,21 +51,21 @@ spec: # values: # - linux securityContext: + # Projects are configured by default to adhere to the "restricted" Pod Security Standards. + # This ensures that deployments meet the highest security requirements for Kubernetes. + # For more details, see: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted runAsNonRoot: true - # TODO(user): For common cases that do not require escalating privileges - # it is recommended to ensure that all your Pods/Containers are restrictive. - # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted - # Please uncomment the following code if your project does NOT have to work on old Kubernetes - # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). - # seccompProfile: - # type: RuntimeDefault + seccompProfile: + type: RuntimeDefault containers: - command: - /manager args: - - --leader-elect + - --leader-elect + - --health-probe-bind-address=:8081 image: controller:latest name: manager + ports: [] securityContext: allowPrivilegeEscalation: false capabilities: @@ -90,5 +92,7 @@ spec: requests: cpu: 10m memory: 64Mi + volumeMounts: [] + volumes: [] serviceAccountName: controller-manager terminationGracePeriodSeconds: 10 diff --git a/config/manifests/bases/watcher-operator.clusterserviceversion.yaml b/config/manifests/bases/watcher-operator.clusterserviceversion.yaml index e9252bf4..0e5f30ed 100644 --- a/config/manifests/bases/watcher-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/watcher-operator.clusterserviceversion.yaml @@ -82,6 +82,7 @@ spec: - name: Watcher Operator url: https://github.com/openstack-k8s-operators/watcher-operator maturity: beta + minKubeVersion: 0.0.0 provider: name: Red Hat Inc. url: https://redhat.com/ diff --git a/config/network-policy/allow-metrics-traffic.yaml b/config/network-policy/allow-metrics-traffic.yaml new file mode 100644 index 00000000..a8819be2 --- /dev/null +++ b/config/network-policy/allow-metrics-traffic.yaml @@ -0,0 +1,27 @@ +# This NetworkPolicy allows ingress traffic +# with Pods running on namespaces labeled with 'metrics: enabled'. Only Pods on those +# namespaces are able to gather data from the metrics endpoint. +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/name: watcher-operator + app.kubernetes.io/managed-by: kustomize + name: allow-metrics-traffic + namespace: system +spec: + podSelector: + matchLabels: + control-plane: controller-manager + app.kubernetes.io/name: watcher-operator + policyTypes: + - Ingress + ingress: + # This allows ingress traffic from any namespace with the label metrics: enabled + - from: + - namespaceSelector: + matchLabels: + metrics: enabled # Only from namespaces with this label + ports: + - port: 8443 + protocol: TCP diff --git a/config/network-policy/allow-webhook-traffic.yaml b/config/network-policy/allow-webhook-traffic.yaml new file mode 100644 index 00000000..509f37dd --- /dev/null +++ b/config/network-policy/allow-webhook-traffic.yaml @@ -0,0 +1,27 @@ +# This NetworkPolicy allows ingress traffic to your webhook server running +# as part of the controller-manager from specific namespaces and pods. CR(s) which uses webhooks +# will only work when applied in namespaces labeled with 'webhook: enabled' +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/name: watcher-operator + app.kubernetes.io/managed-by: kustomize + name: allow-webhook-traffic + namespace: system +spec: + podSelector: + matchLabels: + control-plane: controller-manager + app.kubernetes.io/name: watcher-operator + policyTypes: + - Ingress + ingress: + # This allows ingress traffic from any namespace with the label webhook: enabled + - from: + - namespaceSelector: + matchLabels: + webhook: enabled # Only from namespaces with this label + ports: + - port: 443 + protocol: TCP diff --git a/config/network-policy/kustomization.yaml b/config/network-policy/kustomization.yaml new file mode 100644 index 00000000..0872bee1 --- /dev/null +++ b/config/network-policy/kustomization.yaml @@ -0,0 +1,3 @@ +resources: +- allow-webhook-traffic.yaml +- allow-metrics-traffic.yaml diff --git a/config/prometheus/kustomization.yaml b/config/prometheus/kustomization.yaml index ed137168..fdc5481b 100644 --- a/config/prometheus/kustomization.yaml +++ b/config/prometheus/kustomization.yaml @@ -1,2 +1,11 @@ resources: - monitor.yaml + +# [PROMETHEUS-WITH-CERTS] The following patch configures the ServiceMonitor in ../prometheus +# to securely reference certificates created and managed by cert-manager. +# Additionally, ensure that you uncomment the [METRICS WITH CERTMANAGER] patch under config/default/kustomization.yaml +# to mount the "metrics-server-cert" secret in the Manager Deployment. +#patches: +# - path: monitor_tls_patch.yaml +# target: +# kind: ServiceMonitor diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml index 916797e9..bdec4067 100644 --- a/config/prometheus/monitor.yaml +++ b/config/prometheus/monitor.yaml @@ -4,17 +4,24 @@ kind: ServiceMonitor metadata: labels: control-plane: controller-manager + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-monitor namespace: system spec: endpoints: - path: /metrics - port: https + port: https # Ensure this is the name of the port that exposes HTTPS metrics scheme: https bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token tlsConfig: + # TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables + # certificate verification, exposing the system to potential man-in-the-middle attacks. + # For production environments, it is recommended to use cert-manager for automatic TLS certificate management. + # To apply this configuration, enable cert-manager and use the patch located at config/prometheus/servicemonitor_tls_patch.yaml, + # which securely references the certificate from the 'metrics-server-cert' secret. insecureSkipVerify: true selector: matchLabels: - openstack.org/operator-name: watcher + control-plane: controller-manager + app.kubernetes.io/name: watcher-operator diff --git a/config/prometheus/monitor_tls_patch.yaml b/config/prometheus/monitor_tls_patch.yaml new file mode 100644 index 00000000..5bf84ce0 --- /dev/null +++ b/config/prometheus/monitor_tls_patch.yaml @@ -0,0 +1,19 @@ +# Patch for Prometheus ServiceMonitor to enable secure TLS configuration +# using certificates managed by cert-manager +- op: replace + path: /spec/endpoints/0/tlsConfig + value: + # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize + serverName: SERVICE_NAME.SERVICE_NAMESPACE.svc + insecureSkipVerify: false + ca: + secret: + name: metrics-server-cert + key: ca.crt + cert: + secret: + name: metrics-server-cert + key: tls.crt + keySecret: + name: metrics-server-cert + key: tls.key diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index b5c5bb28..88b06101 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -9,16 +9,28 @@ resources: - role_binding.yaml - leader_election_role.yaml - leader_election_role_binding.yaml -# Comment the following 4 lines if you want to disable -# the auth proxy (https://github.com/brancz/kube-rbac-proxy) -# which protects your /metrics endpoint. -- auth_proxy_service.yaml -- auth_proxy_role.yaml -- auth_proxy_role_binding.yaml -- auth_proxy_client_clusterrole.yaml -# For each CRD, "Editor" and "Viewer" roles are scaffolded by +# The following RBAC configurations are used to protect +# the metrics endpoint with authn/authz. These configurations +# ensure that only authorized users and service accounts +# can access the metrics endpoint. Comment the following +# permissions if you want to disable this protection. +# More info: https://book.kubebuilder.io/reference/metrics.html +- metrics_auth_role.yaml +- metrics_auth_role_binding.yaml +- metrics_reader_role.yaml +# For each CRD, "Admin", "Editor" and "Viewer" roles are scaffolded by # default, aiding admins in cluster management. Those roles are -# not used by the Project itself. You can comment the following lines +# not used by the watcher-operator itself. You can comment the following lines # if you do not want those helpers be installed with your Project. +- watcherapplier_admin_role.yaml +- watcherapplier_editor_role.yaml +- watcherapplier_viewer_role.yaml +- watcherdecisionengine_admin_role.yaml +- watcherdecisionengine_editor_role.yaml +- watcherdecisionengine_viewer_role.yaml +- watcher_admin_role.yaml +- watcher_editor_role.yaml +- watcher_viewer_role.yaml +- watcherapi_admin_role.yaml - watcherapi_editor_role.yaml - watcherapi_viewer_role.yaml diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac/metrics_auth_role.yaml similarity index 68% rename from config/rbac/auth_proxy_role.yaml rename to config/rbac/metrics_auth_role.yaml index 0c72e500..32d2e4ec 100644 --- a/config/rbac/auth_proxy_role.yaml +++ b/config/rbac/metrics_auth_role.yaml @@ -1,10 +1,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - labels: - app.kubernetes.io/name: watcher-operator - app.kubernetes.io/managed-by: kustomize - name: proxy-role + name: metrics-auth-role rules: - apiGroups: - authentication.k8s.io diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/metrics_auth_role_binding.yaml similarity index 60% rename from config/rbac/auth_proxy_role_binding.yaml rename to config/rbac/metrics_auth_role_binding.yaml index c7ee0e4c..e775d67f 100644 --- a/config/rbac/auth_proxy_role_binding.yaml +++ b/config/rbac/metrics_auth_role_binding.yaml @@ -1,14 +1,11 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - labels: - app.kubernetes.io/name: watcher-operator - app.kubernetes.io/managed-by: kustomize - name: proxy-rolebinding + name: metrics-auth-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: proxy-role + name: metrics-auth-role subjects: - kind: ServiceAccount name: controller-manager diff --git a/config/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/metrics_reader_role.yaml similarity index 60% rename from config/rbac/auth_proxy_client_clusterrole.yaml rename to config/rbac/metrics_reader_role.yaml index 428431cb..51a75db4 100644 --- a/config/rbac/auth_proxy_client_clusterrole.yaml +++ b/config/rbac/metrics_reader_role.yaml @@ -1,9 +1,6 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - labels: - app.kubernetes.io/name: watcher-operator - app.kubernetes.io/managed-by: kustomize name: metrics-reader rules: - nonResourceURLs: diff --git a/config/rbac/watcher_admin_role.yaml b/config/rbac/watcher_admin_role.yaml new file mode 100644 index 00000000..160e0723 --- /dev/null +++ b/config/rbac/watcher_admin_role.yaml @@ -0,0 +1,27 @@ +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants full permissions ('*') over watcher.openstack.org. +# This role is intended for users authorized to modify roles and bindings within the cluster, +# enabling them to delegate specific permissions to other users or groups as needed. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: watcher-operator + app.kubernetes.io/managed-by: kustomize + name: watcher-admin-role +rules: +- apiGroups: + - watcher.openstack.org + resources: + - watchers + verbs: + - '*' +- apiGroups: + - watcher.openstack.org + resources: + - watchers/status + verbs: + - get diff --git a/config/rbac/watcher_editor_role.yaml b/config/rbac/watcher_editor_role.yaml index d5ce7f30..0c675d7e 100644 --- a/config/rbac/watcher_editor_role.yaml +++ b/config/rbac/watcher_editor_role.yaml @@ -1,13 +1,15 @@ -# permissions for end users to edit watchers. +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants permissions to create, update, and delete resources within the watcher.openstack.org. +# This role is intended for users who need to manage these resources +# but should not control RBAC or manage permissions for others. + apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: watcher-editor-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: watcher-editor-role rules: diff --git a/config/rbac/watcher_viewer_role.yaml b/config/rbac/watcher_viewer_role.yaml index e44e246e..56f95d66 100644 --- a/config/rbac/watcher_viewer_role.yaml +++ b/config/rbac/watcher_viewer_role.yaml @@ -1,13 +1,15 @@ -# permissions for end users to view watchers. +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants read-only access to watcher.openstack.org resources. +# This role is intended for users who need visibility into these resources +# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. + apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: watcher-viewer-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: watcher-viewer-role rules: diff --git a/config/rbac/watcherapi_admin_role.yaml b/config/rbac/watcherapi_admin_role.yaml new file mode 100644 index 00000000..c7c2e10c --- /dev/null +++ b/config/rbac/watcherapi_admin_role.yaml @@ -0,0 +1,27 @@ +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants full permissions ('*') over watcher.openstack.org. +# This role is intended for users authorized to modify roles and bindings within the cluster, +# enabling them to delegate specific permissions to other users or groups as needed. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: watcher-operator + app.kubernetes.io/managed-by: kustomize + name: watcherapi-admin-role +rules: +- apiGroups: + - watcher.openstack.org + resources: + - watcherapis + verbs: + - '*' +- apiGroups: + - watcher.openstack.org + resources: + - watcherapis/status + verbs: + - get diff --git a/config/rbac/watcherapi_editor_role.yaml b/config/rbac/watcherapi_editor_role.yaml index 95c489c2..e02c2440 100644 --- a/config/rbac/watcherapi_editor_role.yaml +++ b/config/rbac/watcherapi_editor_role.yaml @@ -1,4 +1,10 @@ -# permissions for end users to edit watcherapis. +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants permissions to create, update, and delete resources within the watcher.openstack.org. +# This role is intended for users who need to manage these resources +# but should not control RBAC or manage permissions for others. + apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/config/rbac/watcherapi_viewer_role.yaml b/config/rbac/watcherapi_viewer_role.yaml index 66ff5c9d..ac02da9e 100644 --- a/config/rbac/watcherapi_viewer_role.yaml +++ b/config/rbac/watcherapi_viewer_role.yaml @@ -1,4 +1,10 @@ -# permissions for end users to view watcherapis. +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants read-only access to watcher.openstack.org resources. +# This role is intended for users who need visibility into these resources +# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. + apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/config/rbac/watcherapplier_admin_role.yaml b/config/rbac/watcherapplier_admin_role.yaml new file mode 100644 index 00000000..5a7da263 --- /dev/null +++ b/config/rbac/watcherapplier_admin_role.yaml @@ -0,0 +1,27 @@ +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants full permissions ('*') over watcher.openstack.org. +# This role is intended for users authorized to modify roles and bindings within the cluster, +# enabling them to delegate specific permissions to other users or groups as needed. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: watcher-operator + app.kubernetes.io/managed-by: kustomize + name: watcherapplier-admin-role +rules: +- apiGroups: + - watcher.openstack.org + resources: + - watcherappliers + verbs: + - '*' +- apiGroups: + - watcher.openstack.org + resources: + - watcherappliers/status + verbs: + - get diff --git a/config/rbac/watcherapplier_editor_role.yaml b/config/rbac/watcherapplier_editor_role.yaml index 0eb856fe..a5dc57f9 100644 --- a/config/rbac/watcherapplier_editor_role.yaml +++ b/config/rbac/watcherapplier_editor_role.yaml @@ -1,13 +1,15 @@ -# permissions for end users to edit watcherappliers. +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants permissions to create, update, and delete resources within the watcher.openstack.org. +# This role is intended for users who need to manage these resources +# but should not control RBAC or manage permissions for others. + apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: watcherapplier-editor-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: watcherapplier-editor-role rules: diff --git a/config/rbac/watcherapplier_viewer_role.yaml b/config/rbac/watcherapplier_viewer_role.yaml index e532b0a6..711c5879 100644 --- a/config/rbac/watcherapplier_viewer_role.yaml +++ b/config/rbac/watcherapplier_viewer_role.yaml @@ -1,13 +1,15 @@ -# permissions for end users to view watcherappliers. +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants read-only access to watcher.openstack.org resources. +# This role is intended for users who need visibility into these resources +# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. + apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: watcherapplier-viewer-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: watcherapplier-viewer-role rules: diff --git a/config/rbac/watcherdecisionengine_admin_role.yaml b/config/rbac/watcherdecisionengine_admin_role.yaml new file mode 100644 index 00000000..6c2848e9 --- /dev/null +++ b/config/rbac/watcherdecisionengine_admin_role.yaml @@ -0,0 +1,27 @@ +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants full permissions ('*') over watcher.openstack.org. +# This role is intended for users authorized to modify roles and bindings within the cluster, +# enabling them to delegate specific permissions to other users or groups as needed. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: watcher-operator + app.kubernetes.io/managed-by: kustomize + name: watcherdecisionengine-admin-role +rules: +- apiGroups: + - watcher.openstack.org + resources: + - watcherdecisionengines + verbs: + - '*' +- apiGroups: + - watcher.openstack.org + resources: + - watcherdecisionengines/status + verbs: + - get diff --git a/config/rbac/watcherdecisionengine_editor_role.yaml b/config/rbac/watcherdecisionengine_editor_role.yaml index 1186c37a..d62772ad 100644 --- a/config/rbac/watcherdecisionengine_editor_role.yaml +++ b/config/rbac/watcherdecisionengine_editor_role.yaml @@ -1,13 +1,15 @@ -# permissions for end users to edit watcherdecisionengines. +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants permissions to create, update, and delete resources within the watcher.openstack.org. +# This role is intended for users who need to manage these resources +# but should not control RBAC or manage permissions for others. + apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: watcherdecisionengine-editor-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: watcherdecisionengine-editor-role rules: diff --git a/config/rbac/watcherdecisionengine_viewer_role.yaml b/config/rbac/watcherdecisionengine_viewer_role.yaml index 0bf3d0f5..690f2c8a 100644 --- a/config/rbac/watcherdecisionengine_viewer_role.yaml +++ b/config/rbac/watcherdecisionengine_viewer_role.yaml @@ -1,13 +1,15 @@ -# permissions for end users to view watcherdecisionengines. +# This rule is not used by the project watcher-operator itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants read-only access to watcher.openstack.org resources. +# This role is intended for users who need visibility into these resources +# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. + apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: - app.kubernetes.io/name: clusterrole - app.kubernetes.io/instance: watcherdecisionengine-viewer-role - app.kubernetes.io/component: rbac - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: watcherdecisionengine-viewer-role rules: diff --git a/config/scorecard/kustomization.yaml b/config/scorecard/kustomization.yaml index a9a84a85..54e8aa50 100644 --- a/config/scorecard/kustomization.yaml +++ b/config/scorecard/kustomization.yaml @@ -1,16 +1,18 @@ resources: - bases/config.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization patches: - path: patches/basic.config.yaml target: group: scorecard.operatorframework.io - version: v1alpha3 kind: Configuration name: config + version: v1alpha3 - path: patches/olm.config.yaml target: group: scorecard.operatorframework.io - version: v1alpha3 kind: Configuration name: config -#+kubebuilder:scaffold:patches + version: v1alpha3 +# +kubebuilder:scaffold:patches diff --git a/config/scorecard/patches/basic.config.yaml b/config/scorecard/patches/basic.config.yaml index fd6200ae..8237b70d 100644 --- a/config/scorecard/patches/basic.config.yaml +++ b/config/scorecard/patches/basic.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - basic-check-spec - image: quay.io/operator-framework/scorecard-test:v1.37.0 + image: quay.io/operator-framework/scorecard-test:v1.41.1 labels: suite: basic test: basic-check-spec-test diff --git a/config/scorecard/patches/olm.config.yaml b/config/scorecard/patches/olm.config.yaml index a547ce21..416660a7 100644 --- a/config/scorecard/patches/olm.config.yaml +++ b/config/scorecard/patches/olm.config.yaml @@ -4,7 +4,7 @@ entrypoint: - scorecard-test - olm-bundle-validation - image: quay.io/operator-framework/scorecard-test:v1.37.0 + image: quay.io/operator-framework/scorecard-test:v1.41.1 labels: suite: olm test: olm-bundle-validation-test @@ -14,7 +14,7 @@ entrypoint: - scorecard-test - olm-crds-have-validation - image: quay.io/operator-framework/scorecard-test:v1.37.0 + image: quay.io/operator-framework/scorecard-test:v1.41.1 labels: suite: olm test: olm-crds-have-validation-test @@ -24,7 +24,7 @@ entrypoint: - scorecard-test - olm-crds-have-resources - image: quay.io/operator-framework/scorecard-test:v1.37.0 + image: quay.io/operator-framework/scorecard-test:v1.41.1 labels: suite: olm test: olm-crds-have-resources-test @@ -34,7 +34,7 @@ entrypoint: - scorecard-test - olm-spec-descriptors - image: quay.io/operator-framework/scorecard-test:v1.37.0 + image: quay.io/operator-framework/scorecard-test:v1.41.1 labels: suite: olm test: olm-spec-descriptors-test @@ -44,7 +44,7 @@ entrypoint: - scorecard-test - olm-status-descriptors - image: quay.io/operator-framework/scorecard-test:v1.37.0 + image: quay.io/operator-framework/scorecard-test:v1.41.1 labels: suite: olm test: olm-status-descriptors-test diff --git a/config/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml index 25e21e3c..206316e5 100644 --- a/config/webhook/kustomizeconfig.yaml +++ b/config/webhook/kustomizeconfig.yaml @@ -1,4 +1,4 @@ -# the following config is for teaching kustomize where to look at when substituting vars. +# the following config is for teaching kustomize where to look at when substituting nameReference. # It requires kustomize v2.1.0 or newer to work properly. nameReference: - kind: Service @@ -20,6 +20,3 @@ namespace: group: admissionregistration.k8s.io path: webhooks/clientConfig/service/namespace create: true - -varReference: -- path: metadata/annotations diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index f8cc82ab..281377fa 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -12,7 +12,7 @@ webhooks: namespace: system path: /mutate-watcher-openstack-org-v1beta1-watcher failurePolicy: Fail - name: mwatcher.kb.io + name: mwatcher-v1beta1.kb.io rules: - apiGroups: - watcher.openstack.org @@ -32,7 +32,7 @@ webhooks: namespace: system path: /mutate-watcher-openstack-org-v1beta1-watcherapi failurePolicy: Fail - name: mwatcherapi.kb.io + name: mwatcherapi-v1beta1.kb.io rules: - apiGroups: - watcher.openstack.org @@ -52,7 +52,7 @@ webhooks: namespace: system path: /mutate-watcher-openstack-org-v1beta1-watcherapplier failurePolicy: Fail - name: mwatcherapplier.kb.io + name: mwatcherapplier-v1beta1.kb.io rules: - apiGroups: - watcher.openstack.org @@ -72,7 +72,7 @@ webhooks: namespace: system path: /mutate-watcher-openstack-org-v1beta1-watcherdecisionengine failurePolicy: Fail - name: mwatcherdecisionengine.kb.io + name: mwatcherdecisionengine-v1beta1.kb.io rules: - apiGroups: - watcher.openstack.org @@ -98,7 +98,7 @@ webhooks: namespace: system path: /validate-watcher-openstack-org-v1beta1-watcher failurePolicy: Fail - name: vwatcher.kb.io + name: vwatcher-v1beta1.kb.io rules: - apiGroups: - watcher.openstack.org @@ -118,7 +118,7 @@ webhooks: namespace: system path: /validate-watcher-openstack-org-v1beta1-watcherapi failurePolicy: Fail - name: vwatcherapi.kb.io + name: vwatcherapi-v1beta1.kb.io rules: - apiGroups: - watcher.openstack.org @@ -138,7 +138,7 @@ webhooks: namespace: system path: /validate-watcher-openstack-org-v1beta1-watcherapplier failurePolicy: Fail - name: vwatcherapplier.kb.io + name: vwatcherapplier-v1beta1.kb.io rules: - apiGroups: - watcher.openstack.org @@ -158,7 +158,7 @@ webhooks: namespace: system path: /validate-watcher-openstack-org-v1beta1-watcherdecisionengine failurePolicy: Fail - name: vwatcherdecisionengine.kb.io + name: vwatcherdecisionengine-v1beta1.kb.io rules: - apiGroups: - watcher.openstack.org diff --git a/config/webhook/service.yaml b/config/webhook/service.yaml index befaa384..b1245f64 100644 --- a/config/webhook/service.yaml +++ b/config/webhook/service.yaml @@ -1,13 +1,8 @@ - apiVersion: v1 kind: Service metadata: labels: - app.kubernetes.io/name: service - app.kubernetes.io/instance: webhook-service - app.kubernetes.io/component: webhook - app.kubernetes.io/created-by: watcher-operator - app.kubernetes.io/part-of: watcher-operator + app.kubernetes.io/name: watcher-operator app.kubernetes.io/managed-by: kustomize name: webhook-service namespace: system @@ -17,4 +12,5 @@ spec: protocol: TCP targetPort: 9443 selector: - openstack.org/operator-name: watcher + control-plane: controller-manager + app.kubernetes.io/name: watcher-operator diff --git a/go.mod b/go.mod index 89a5885c..aa8f3b3c 100644 --- a/go.mod +++ b/go.mod @@ -25,13 +25,19 @@ require ( require ( github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.1 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect @@ -40,12 +46,15 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/google/cel-go v0.20.1 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/gophercloud/gophercloud/v2 v2.8.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/imdario/mergo v0.3.16 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.7 // indirect @@ -61,8 +70,19 @@ require ( github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect github.com/rabbitmq/cluster-operator/v2 v2.16.0 // indirect + github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/pflag v1.0.7 // indirect + github.com/stoewer/go-strcase v1.2.0 // indirect github.com/x448/float16 v0.8.4 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/sdk v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect @@ -77,11 +97,18 @@ require ( golang.org/x/time v0.12.0 // indirect golang.org/x/tools v0.36.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/grpc v1.71.1 // indirect google.golang.org/protobuf v1.36.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/apiextensions-apiserver v0.33.2 // indirect + k8s.io/apiserver v0.33.2 // indirect + k8s.io/component-base v0.33.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250902184714-7fc278399c7f // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect diff --git a/go.sum b/go.sum index 35b6e2fa..06805af9 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,18 @@ github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -14,6 +23,8 @@ github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= @@ -24,8 +35,11 @@ github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZ github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE= github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= @@ -44,6 +58,8 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= +github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -58,8 +74,12 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gophercloud/gophercloud/v2 v2.8.0 h1:of2+8tT6+FbEYHfYC8GBu8TXJNsXYSNm9KuvpX7Neqo= github.com/gophercloud/gophercloud/v2 v2.8.0/go.mod h1:Ki/ILhYZr/5EPebrPL9Ej+tUg4lqx71/YH2JWVeU+Qk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= @@ -129,10 +149,17 @@ github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzM github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= @@ -147,6 +174,26 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -204,6 +251,12 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24= +google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -213,6 +266,9 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/api v0.31.13 h1:sco9Cq2pY4Ysv9qZiWzcR97MmA/35nwYQ/VCTzOcWmc= @@ -221,14 +277,20 @@ k8s.io/apiextensions-apiserver v0.31.13 h1:8xtWKVpV/YbYX0UX2k6w+cgxfxKhX0UNGuo/V k8s.io/apiextensions-apiserver v0.31.13/go.mod h1:zxpMLWXBxnJqKUIruJ+ulP+Xlfe5lPZPxq1z0cLwA2U= k8s.io/apimachinery v0.31.13 h1:rkG0EiBkBkEzURo/8dKGx/oBF202Z2LqHuSD8Cm3bG4= k8s.io/apimachinery v0.31.13/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/apiserver v0.31.13 h1:Ke9/X2m3vHSgsminpAbUxULDNMbvAfjrRX73Gqx6CZc= +k8s.io/apiserver v0.31.13/go.mod h1:5nBPhL2g7am/CS+/OI5A6+olEbo0C7tQ8QNDODLd+WY= k8s.io/client-go v0.31.13 h1:Q0LG51uFbzNd9fzIj5ilA0Sm1wUholHvDaNwVKzqdCA= k8s.io/client-go v0.31.13/go.mod h1:UB4yTzQeRAv+vULOKp2jdqA5LSwV55bvc3RQ5tM48LM= +k8s.io/component-base v0.31.13 h1:/uVLq7yHk9azReqeCFAZSr/8NXydzpz7yDZ6p/yiwBQ= +k8s.io/component-base v0.31.13/go.mod h1:uMXtKNyDqeNdZYL6SRCr9wB6FutL9pOlQmkK2dRVAKQ= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250627150254-e9823e99808e h1:UGI9rv1A2cV87NhXr4s+AUBxIuoo/SME/IyJ3b6KztE= k8s.io/kube-openapi v0.0.0-20250627150254-e9823e99808e/go.mod h1:GLOk5B+hDbRROvt0X2+hqX64v/zO3vXN7J78OUmBSKw= k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0= k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/controller-runtime v0.19.7 h1:DLABZfMr20A+AwCZOHhcbcu+TqBXnJZaVBri9K3EO48= sigs.k8s.io/controller-runtime v0.19.7/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= diff --git a/hack/stop_integrated_watcher.sh b/hack/stop_integrated_watcher.sh index fddbc6f0..ef949c1a 100755 --- a/hack/stop_integrated_watcher.sh +++ b/hack/stop_integrated_watcher.sh @@ -6,8 +6,16 @@ WATCHER_CSV_NAME="$(oc get csv -n openstack-operators -l operators.coreos.com/wa if [ -z ${WATCHER_CSV_NAME} ]; then OPENSTACK_CSV_NAME="$(oc get csv -n openstack-operators -l operators.coreos.com/openstack-operator.openstack-operators -o name)" if [ -n "{OPENSTACK_CSV_NAME}" ]; then + WATCHER_POD_NAME="$(oc get pod -n openstack-operators -o name | grep watcher-operator-controller-manager || true)" + OPENSTACK_OPERATOR_POD_NAME="$(oc get pod -n openstack-operators -o name | grep openstack-operator-controller-operator || true)" oc patch "${OPENSTACK_CSV_NAME}" -n openstack-operators --type=json -p="[{'op': 'replace', 'path': '/spec/install/spec/deployments/0/spec/replicas', 'value': 0}]" + if [ -n "${OPENSTACK_OPERATOR_POD_NAME}" ]; then + oc wait --for=delete "${OPENSTACK_OPERATOR_POD_NAME}" -n openstack-operators --timeout=60s + fi oc scale --replicas=0 -n openstack-operators deploy/watcher-operator-controller-manager + if [ -n "${WATCHER_POD_NAME}" ]; then + oc wait --for=delete "${WATCHER_POD_NAME}" -n openstack-operators --timeout=60s + fi else echo "Openstack operator is not installed" fi diff --git a/controllers/watcher_common.go b/internal/controller/watcher_common.go similarity index 99% rename from controllers/watcher_common.go rename to internal/controller/watcher_common.go index ab8a9e59..3cb88b61 100644 --- a/controllers/watcher_common.go +++ b/internal/controller/watcher_common.go @@ -1,5 +1,5 @@ -// Package controllers contains the Kubernetes controllers for managing Watcher components -package controllers +// Package controller contains the Kubernetes controllers for managing Watcher components +package controller import ( "context" diff --git a/controllers/watcher_controller.go b/internal/controller/watcher_controller.go similarity index 99% rename from controllers/watcher_controller.go rename to internal/controller/watcher_controller.go index dbf8577a..9c02e7b4 100644 --- a/controllers/watcher_controller.go +++ b/internal/controller/watcher_controller.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package controllers +package controller import ( "context" @@ -54,7 +54,7 @@ import ( watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" - "github.com/openstack-k8s-operators/watcher-operator/pkg/watcher" + "github.com/openstack-k8s-operators/watcher-operator/internal/watcher" k8s_errors "k8s.io/apimachinery/pkg/api/errors" ) diff --git a/controllers/watcherapi_controller.go b/internal/controller/watcherapi_controller.go similarity index 99% rename from controllers/watcherapi_controller.go rename to internal/controller/watcherapi_controller.go index 8001a295..f2e38822 100644 --- a/controllers/watcherapi_controller.go +++ b/internal/controller/watcherapi_controller.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package controllers +package controller import ( "context" @@ -48,8 +48,8 @@ import ( mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" - "github.com/openstack-k8s-operators/watcher-operator/pkg/watcher" - "github.com/openstack-k8s-operators/watcher-operator/pkg/watcherapi" + "github.com/openstack-k8s-operators/watcher-operator/internal/watcher" + "github.com/openstack-k8s-operators/watcher-operator/internal/watcherapi" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" diff --git a/controllers/watcherapplier_controller.go b/internal/controller/watcherapplier_controller.go similarity index 99% rename from controllers/watcherapplier_controller.go rename to internal/controller/watcherapplier_controller.go index f8c8267b..aece0d3b 100644 --- a/controllers/watcherapplier_controller.go +++ b/internal/controller/watcherapplier_controller.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package controllers +package controller import ( "context" @@ -46,8 +46,8 @@ import ( mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" - "github.com/openstack-k8s-operators/watcher-operator/pkg/watcher" - "github.com/openstack-k8s-operators/watcher-operator/pkg/watcherapplier" + "github.com/openstack-k8s-operators/watcher-operator/internal/watcher" + "github.com/openstack-k8s-operators/watcher-operator/internal/watcherapplier" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" diff --git a/controllers/watcherdecisionengine_controller.go b/internal/controller/watcherdecisionengine_controller.go similarity index 99% rename from controllers/watcherdecisionengine_controller.go rename to internal/controller/watcherdecisionengine_controller.go index 784af315..9bb31712 100644 --- a/controllers/watcherdecisionengine_controller.go +++ b/internal/controller/watcherdecisionengine_controller.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package controllers +package controller import ( "context" @@ -45,8 +45,8 @@ import ( "github.com/openstack-k8s-operators/lib-common/modules/common/util" mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" - "github.com/openstack-k8s-operators/watcher-operator/pkg/watcher" - "github.com/openstack-k8s-operators/watcher-operator/pkg/watcherdecisionengine" + "github.com/openstack-k8s-operators/watcher-operator/internal/watcher" + "github.com/openstack-k8s-operators/watcher-operator/internal/watcherdecisionengine" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" diff --git a/config/webhook/.keep b/internal/watcher/.keep similarity index 100% rename from config/webhook/.keep rename to internal/watcher/.keep diff --git a/pkg/watcher/constants.go b/internal/watcher/constants.go similarity index 100% rename from pkg/watcher/constants.go rename to internal/watcher/constants.go diff --git a/pkg/watcher/dbpurgecronjob.go b/internal/watcher/dbpurgecronjob.go similarity index 100% rename from pkg/watcher/dbpurgecronjob.go rename to internal/watcher/dbpurgecronjob.go diff --git a/pkg/watcher/dbsync.go b/internal/watcher/dbsync.go similarity index 100% rename from pkg/watcher/dbsync.go rename to internal/watcher/dbsync.go diff --git a/pkg/watcher/volumes.go b/internal/watcher/volumes.go similarity index 100% rename from pkg/watcher/volumes.go rename to internal/watcher/volumes.go diff --git a/pkg/watcherapi/statefulset.go b/internal/watcherapi/statefulset.go similarity index 98% rename from pkg/watcherapi/statefulset.go rename to internal/watcherapi/statefulset.go index 4381c1a0..455e644d 100644 --- a/pkg/watcherapi/statefulset.go +++ b/internal/watcherapi/statefulset.go @@ -18,7 +18,7 @@ import ( "k8s.io/utils/ptr" watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" - watcher "github.com/openstack-k8s-operators/watcher-operator/pkg/watcher" + watcher "github.com/openstack-k8s-operators/watcher-operator/internal/watcher" ) const ( diff --git a/pkg/watcherapplier/statefulset.go b/internal/watcherapplier/statefulset.go similarity index 98% rename from pkg/watcherapplier/statefulset.go rename to internal/watcherapplier/statefulset.go index 6db44f02..f133fffb 100644 --- a/pkg/watcherapplier/statefulset.go +++ b/internal/watcherapplier/statefulset.go @@ -12,7 +12,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" - watcher "github.com/openstack-k8s-operators/watcher-operator/pkg/watcher" + watcher "github.com/openstack-k8s-operators/watcher-operator/internal/watcher" "k8s.io/utils/ptr" ) diff --git a/pkg/watcherdecisionengine/statefulset.go b/internal/watcherdecisionengine/statefulset.go similarity index 98% rename from pkg/watcherdecisionengine/statefulset.go rename to internal/watcherdecisionengine/statefulset.go index 9de2edea..5cd8ebce 100644 --- a/pkg/watcherdecisionengine/statefulset.go +++ b/internal/watcherdecisionengine/statefulset.go @@ -10,7 +10,7 @@ import ( "github.com/openstack-k8s-operators/lib-common/modules/common/affinity" "github.com/openstack-k8s-operators/lib-common/modules/common/env" watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" - "github.com/openstack-k8s-operators/watcher-operator/pkg/watcher" + "github.com/openstack-k8s-operators/watcher-operator/internal/watcher" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/internal/webhook/v1beta1/watcher_webhook.go b/internal/webhook/v1beta1/watcher_webhook.go new file mode 100644 index 00000000..931ca9be --- /dev/null +++ b/internal/webhook/v1beta1/watcher_webhook.go @@ -0,0 +1,133 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1beta1 contains webhook implementations for Watcher API v1beta1 resources. +package v1beta1 + +import ( + "context" + "errors" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" +) + +var ( + // ErrInvalidWatcherType is returned when an object is not of type Watcher + ErrInvalidWatcherType = errors.New("invalid Watcher object type") + // ErrInvalidWatcherAPIType is returned when an object is not of type WatcherAPI + ErrInvalidWatcherAPIType = errors.New("invalid WatcherAPI object type") + // ErrInvalidWatcherApplierType is returned when an object is not of type WatcherApplier + ErrInvalidWatcherApplierType = errors.New("invalid WatcherApplier object type") + // ErrInvalidWatcherDecisionEngineType is returned when an object is not of type WatcherDecisionEngine + ErrInvalidWatcherDecisionEngineType = errors.New("invalid WatcherDecisionEngine object type") +) + +// nolint:unused +// log is for logging in this package. +var watcherlog = logf.Log.WithName("watcher-resource") + +// SetupWatcherWebhookWithManager registers the webhook for Watcher in the manager. +func SetupWatcherWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&watcherv1beta1.Watcher{}). + WithValidator(&WatcherCustomValidator{}). + WithDefaulter(&WatcherCustomDefaulter{}). + Complete() +} + +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + +// +kubebuilder:webhook:path=/mutate-watcher-openstack-org-v1beta1-watcher,mutating=true,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watchers,verbs=create;update,versions=v1beta1,name=mwatcher-v1beta1.kb.io,admissionReviewVersions=v1 + +// WatcherCustomDefaulter struct is responsible for setting default values on the custom resource of the +// Kind Watcher when those are created or updated. +// +// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods, +// as it is used only for temporary operations and does not need to be deeply copied. +type WatcherCustomDefaulter struct { + // TODO(user): Add more fields as needed for defaulting +} + +var _ webhook.CustomDefaulter = &WatcherCustomDefaulter{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind Watcher. +func (d *WatcherCustomDefaulter) Default(_ context.Context, obj runtime.Object) error { + watcher, ok := obj.(*watcherv1beta1.Watcher) + + if !ok { + return fmt.Errorf("%w: expected Watcher but got %T", ErrInvalidWatcherType, obj) + } + watcherlog.Info("Defaulting for Watcher", "name", watcher.GetName()) + + watcher.Default() + + return nil +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +// NOTE: The 'path' attribute must follow a specific pattern and should not be modified directly here. +// Modifying the path for an invalid path can cause API server errors; failing to locate the webhook. +// +kubebuilder:webhook:path=/validate-watcher-openstack-org-v1beta1-watcher,mutating=false,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watchers,verbs=create;update,versions=v1beta1,name=vwatcher-v1beta1.kb.io,admissionReviewVersions=v1 + +// WatcherCustomValidator struct is responsible for validating the Watcher resource +// when it is created, updated, or deleted. +// +// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods, +// as this struct is used only for temporary operations and does not need to be deeply copied. +type WatcherCustomValidator struct { + // TODO(user): Add more fields as needed for validation +} + +var _ webhook.CustomValidator = &WatcherCustomValidator{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type Watcher. +func (v *WatcherCustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + watcher, ok := obj.(*watcherv1beta1.Watcher) + if !ok { + return nil, fmt.Errorf("%w: expected Watcher but got %T", ErrInvalidWatcherType, obj) + } + watcherlog.Info("Validation for Watcher upon creation", "name", watcher.GetName()) + + return watcher.ValidateCreate() +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type Watcher. +func (v *WatcherCustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + watcher, ok := newObj.(*watcherv1beta1.Watcher) + if !ok { + return nil, fmt.Errorf("%w: expected Watcher for newObj but got %T", ErrInvalidWatcherType, newObj) + } + watcherlog.Info("Validation for Watcher upon update", "name", watcher.GetName()) + + return watcher.ValidateUpdate(oldObj) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type Watcher. +func (v *WatcherCustomValidator) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + watcher, ok := obj.(*watcherv1beta1.Watcher) + if !ok { + return nil, fmt.Errorf("%w: expected Watcher but got %T", ErrInvalidWatcherType, obj) + } + watcherlog.Info("Validation for Watcher upon deletion", "name", watcher.GetName()) + + return watcher.ValidateDelete() +} diff --git a/internal/webhook/v1beta1/watcherapi_webhook.go b/internal/webhook/v1beta1/watcherapi_webhook.go new file mode 100644 index 00000000..7ab0009a --- /dev/null +++ b/internal/webhook/v1beta1/watcherapi_webhook.go @@ -0,0 +1,120 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" +) + +// nolint:unused +// log is for logging in this package. +var watcherapilog = logf.Log.WithName("watcherapi-resource") + +// SetupWatcherAPIWebhookWithManager registers the webhook for WatcherAPI in the manager. +func SetupWatcherAPIWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&watcherv1beta1.WatcherAPI{}). + WithValidator(&WatcherAPICustomValidator{}). + WithDefaulter(&WatcherAPICustomDefaulter{}). + Complete() +} + +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + +// +kubebuilder:webhook:path=/mutate-watcher-openstack-org-v1beta1-watcherapi,mutating=true,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherapis,verbs=create;update,versions=v1beta1,name=mwatcherapi-v1beta1.kb.io,admissionReviewVersions=v1 + +// WatcherAPICustomDefaulter struct is responsible for setting default values on the custom resource of the +// Kind WatcherAPI when those are created or updated. +// +// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods, +// as it is used only for temporary operations and does not need to be deeply copied. +type WatcherAPICustomDefaulter struct { + // TODO(user): Add more fields as needed for defaulting +} + +var _ webhook.CustomDefaulter = &WatcherAPICustomDefaulter{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind WatcherAPI. +func (d *WatcherAPICustomDefaulter) Default(_ context.Context, obj runtime.Object) error { + watcherapi, ok := obj.(*watcherv1beta1.WatcherAPI) + + if !ok { + return fmt.Errorf("%w: expected WatcherAPI but got %T", ErrInvalidWatcherAPIType, obj) + } + watcherapilog.Info("Defaulting for WatcherAPI", "name", watcherapi.GetName()) + + watcherapi.Default() + + return nil +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +// NOTE: The 'path' attribute must follow a specific pattern and should not be modified directly here. +// Modifying the path for an invalid path can cause API server errors; failing to locate the webhook. +// +kubebuilder:webhook:path=/validate-watcher-openstack-org-v1beta1-watcherapi,mutating=false,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherapis,verbs=create;update,versions=v1beta1,name=vwatcherapi-v1beta1.kb.io,admissionReviewVersions=v1 + +// WatcherAPICustomValidator struct is responsible for validating the WatcherAPI resource +// when it is created, updated, or deleted. +// +// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods, +// as this struct is used only for temporary operations and does not need to be deeply copied. +type WatcherAPICustomValidator struct { + // TODO(user): Add more fields as needed for validation +} + +var _ webhook.CustomValidator = &WatcherAPICustomValidator{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type WatcherAPI. +func (v *WatcherAPICustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + watcherapi, ok := obj.(*watcherv1beta1.WatcherAPI) + if !ok { + return nil, fmt.Errorf("%w: expected WatcherAPI but got %T", ErrInvalidWatcherAPIType, obj) + } + watcherapilog.Info("Validation for WatcherAPI upon creation", "name", watcherapi.GetName()) + + return watcherapi.ValidateCreate() +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type WatcherAPI. +func (v *WatcherAPICustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + watcherapi, ok := newObj.(*watcherv1beta1.WatcherAPI) + if !ok { + return nil, fmt.Errorf("%w: expected WatcherAPI for newObj but got %T", ErrInvalidWatcherAPIType, newObj) + } + watcherapilog.Info("Validation for WatcherAPI upon update", "name", watcherapi.GetName()) + + return watcherapi.ValidateUpdate(oldObj) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type WatcherAPI. +func (v *WatcherAPICustomValidator) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + watcherapi, ok := obj.(*watcherv1beta1.WatcherAPI) + if !ok { + return nil, fmt.Errorf("%w: expected WatcherAPI but got %T", ErrInvalidWatcherAPIType, obj) + } + watcherapilog.Info("Validation for WatcherAPI upon deletion", "name", watcherapi.GetName()) + + return watcherapi.ValidateDelete() +} diff --git a/internal/webhook/v1beta1/watcherapplier_webhook.go b/internal/webhook/v1beta1/watcherapplier_webhook.go new file mode 100644 index 00000000..578382d7 --- /dev/null +++ b/internal/webhook/v1beta1/watcherapplier_webhook.go @@ -0,0 +1,120 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" +) + +// nolint:unused +// log is for logging in this package. +var watcherapplierlog = logf.Log.WithName("watcherapplier-resource") + +// SetupWatcherApplierWebhookWithManager registers the webhook for WatcherApplier in the manager. +func SetupWatcherApplierWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&watcherv1beta1.WatcherApplier{}). + WithValidator(&WatcherApplierCustomValidator{}). + WithDefaulter(&WatcherApplierCustomDefaulter{}). + Complete() +} + +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + +// +kubebuilder:webhook:path=/mutate-watcher-openstack-org-v1beta1-watcherapplier,mutating=true,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherappliers,verbs=create;update,versions=v1beta1,name=mwatcherapplier-v1beta1.kb.io,admissionReviewVersions=v1 + +// WatcherApplierCustomDefaulter struct is responsible for setting default values on the custom resource of the +// Kind WatcherApplier when those are created or updated. +// +// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods, +// as it is used only for temporary operations and does not need to be deeply copied. +type WatcherApplierCustomDefaulter struct { + // TODO(user): Add more fields as needed for defaulting +} + +var _ webhook.CustomDefaulter = &WatcherApplierCustomDefaulter{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind WatcherApplier. +func (d *WatcherApplierCustomDefaulter) Default(_ context.Context, obj runtime.Object) error { + watcherapplier, ok := obj.(*watcherv1beta1.WatcherApplier) + + if !ok { + return fmt.Errorf("%w: expected WatcherApplier but got %T", ErrInvalidWatcherApplierType, obj) + } + watcherapplierlog.Info("Defaulting for WatcherApplier", "name", watcherapplier.GetName()) + + watcherapplier.Default() + + return nil +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +// NOTE: The 'path' attribute must follow a specific pattern and should not be modified directly here. +// Modifying the path for an invalid path can cause API server errors; failing to locate the webhook. +// +kubebuilder:webhook:path=/validate-watcher-openstack-org-v1beta1-watcherapplier,mutating=false,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherappliers,verbs=create;update,versions=v1beta1,name=vwatcherapplier-v1beta1.kb.io,admissionReviewVersions=v1 + +// WatcherApplierCustomValidator struct is responsible for validating the WatcherApplier resource +// when it is created, updated, or deleted. +// +// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods, +// as this struct is used only for temporary operations and does not need to be deeply copied. +type WatcherApplierCustomValidator struct { + // TODO(user): Add more fields as needed for validation +} + +var _ webhook.CustomValidator = &WatcherApplierCustomValidator{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type WatcherApplier. +func (v *WatcherApplierCustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + watcherapplier, ok := obj.(*watcherv1beta1.WatcherApplier) + if !ok { + return nil, fmt.Errorf("%w: expected WatcherApplier but got %T", ErrInvalidWatcherApplierType, obj) + } + watcherapplierlog.Info("Validation for WatcherApplier upon creation", "name", watcherapplier.GetName()) + + return watcherapplier.ValidateCreate() +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type WatcherApplier. +func (v *WatcherApplierCustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + watcherapplier, ok := newObj.(*watcherv1beta1.WatcherApplier) + if !ok { + return nil, fmt.Errorf("%w: expected WatcherApplier for newObj but got %T", ErrInvalidWatcherApplierType, newObj) + } + watcherapplierlog.Info("Validation for WatcherApplier upon update", "name", watcherapplier.GetName()) + + return watcherapplier.ValidateUpdate(oldObj) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type WatcherApplier. +func (v *WatcherApplierCustomValidator) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + watcherapplier, ok := obj.(*watcherv1beta1.WatcherApplier) + if !ok { + return nil, fmt.Errorf("%w: expected WatcherApplier but got %T", ErrInvalidWatcherApplierType, obj) + } + watcherapplierlog.Info("Validation for WatcherApplier upon deletion", "name", watcherapplier.GetName()) + + return watcherapplier.ValidateDelete() +} diff --git a/internal/webhook/v1beta1/watcherdecisionengine_webhook.go b/internal/webhook/v1beta1/watcherdecisionengine_webhook.go new file mode 100644 index 00000000..36cfd39a --- /dev/null +++ b/internal/webhook/v1beta1/watcherdecisionengine_webhook.go @@ -0,0 +1,120 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" +) + +// nolint:unused +// log is for logging in this package. +var watcherdecisionenginelog = logf.Log.WithName("watcherdecisionengine-resource") + +// SetupWatcherDecisionEngineWebhookWithManager registers the webhook for WatcherDecisionEngine in the manager. +func SetupWatcherDecisionEngineWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&watcherv1beta1.WatcherDecisionEngine{}). + WithValidator(&WatcherDecisionEngineCustomValidator{}). + WithDefaulter(&WatcherDecisionEngineCustomDefaulter{}). + Complete() +} + +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + +// +kubebuilder:webhook:path=/mutate-watcher-openstack-org-v1beta1-watcherdecisionengine,mutating=true,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherdecisionengines,verbs=create;update,versions=v1beta1,name=mwatcherdecisionengine-v1beta1.kb.io,admissionReviewVersions=v1 + +// WatcherDecisionEngineCustomDefaulter struct is responsible for setting default values on the custom resource of the +// Kind WatcherDecisionEngine when those are created or updated. +// +// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods, +// as it is used only for temporary operations and does not need to be deeply copied. +type WatcherDecisionEngineCustomDefaulter struct { + // TODO(user): Add more fields as needed for defaulting +} + +var _ webhook.CustomDefaulter = &WatcherDecisionEngineCustomDefaulter{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind WatcherDecisionEngine. +func (d *WatcherDecisionEngineCustomDefaulter) Default(_ context.Context, obj runtime.Object) error { + watcherdecisionengine, ok := obj.(*watcherv1beta1.WatcherDecisionEngine) + + if !ok { + return fmt.Errorf("%w: expected WatcherDecisionEngine but got %T", ErrInvalidWatcherDecisionEngineType, obj) + } + watcherdecisionenginelog.Info("Defaulting for WatcherDecisionEngine", "name", watcherdecisionengine.GetName()) + + watcherdecisionengine.Default() + + return nil +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +// NOTE: The 'path' attribute must follow a specific pattern and should not be modified directly here. +// Modifying the path for an invalid path can cause API server errors; failing to locate the webhook. +// +kubebuilder:webhook:path=/validate-watcher-openstack-org-v1beta1-watcherdecisionengine,mutating=false,failurePolicy=fail,sideEffects=None,groups=watcher.openstack.org,resources=watcherdecisionengines,verbs=create;update,versions=v1beta1,name=vwatcherdecisionengine-v1beta1.kb.io,admissionReviewVersions=v1 + +// WatcherDecisionEngineCustomValidator struct is responsible for validating the WatcherDecisionEngine resource +// when it is created, updated, or deleted. +// +// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods, +// as this struct is used only for temporary operations and does not need to be deeply copied. +type WatcherDecisionEngineCustomValidator struct { + // TODO(user): Add more fields as needed for validation +} + +var _ webhook.CustomValidator = &WatcherDecisionEngineCustomValidator{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type WatcherDecisionEngine. +func (v *WatcherDecisionEngineCustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + watcherdecisionengine, ok := obj.(*watcherv1beta1.WatcherDecisionEngine) + if !ok { + return nil, fmt.Errorf("%w: expected WatcherDecisionEngine but got %T", ErrInvalidWatcherDecisionEngineType, obj) + } + watcherdecisionenginelog.Info("Validation for WatcherDecisionEngine upon creation", "name", watcherdecisionengine.GetName()) + + return watcherdecisionengine.ValidateCreate() +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type WatcherDecisionEngine. +func (v *WatcherDecisionEngineCustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + watcherdecisionengine, ok := newObj.(*watcherv1beta1.WatcherDecisionEngine) + if !ok { + return nil, fmt.Errorf("%w: expected WatcherDecisionEngine for newObj but got %T", ErrInvalidWatcherDecisionEngineType, newObj) + } + watcherdecisionenginelog.Info("Validation for WatcherDecisionEngine upon update", "name", watcherdecisionengine.GetName()) + + return watcherdecisionengine.ValidateUpdate(oldObj) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type WatcherDecisionEngine. +func (v *WatcherDecisionEngineCustomValidator) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + watcherdecisionengine, ok := obj.(*watcherv1beta1.WatcherDecisionEngine) + if !ok { + return nil, fmt.Errorf("%w: expected WatcherDecisionEngine but got %T", ErrInvalidWatcherDecisionEngineType, obj) + } + watcherdecisionenginelog.Info("Validation for WatcherDecisionEngine upon deletion", "name", watcherdecisionengine.GetName()) + + return watcherdecisionengine.ValidateDelete() +} diff --git a/main.go b/main.go deleted file mode 100644 index 776010c2..00000000 --- a/main.go +++ /dev/null @@ -1,214 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package main is the entry point for the Watcher operator -package main - -import ( - "crypto/tls" - "flag" - "os" - "strings" - - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) - // to ensure that exec-entrypoint and run can make use of them. - "k8s.io/client-go/kubernetes" - _ "k8s.io/client-go/plugin/pkg/client/auth" - - routev1 "github.com/openshift/api/route/v1" - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - clientgoscheme "k8s.io/client-go/kubernetes/scheme" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client/config" - "sigs.k8s.io/controller-runtime/pkg/healthz" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" - "sigs.k8s.io/controller-runtime/pkg/webhook" - - memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1" - rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" - topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1" - keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" - "github.com/openstack-k8s-operators/lib-common/modules/common/operator" - mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" - - watcherv1beta1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" - "github.com/openstack-k8s-operators/watcher-operator/controllers" - //+kubebuilder:scaffold:imports -) - -var ( - scheme = runtime.NewScheme() - setupLog = ctrl.Log.WithName("setup") -) - -func init() { - utilruntime.Must(clientgoscheme.AddToScheme(scheme)) - - utilruntime.Must(watcherv1beta1.AddToScheme(scheme)) - utilruntime.Must(mariadbv1.AddToScheme(scheme)) - utilruntime.Must(rabbitmqv1.AddToScheme(scheme)) - utilruntime.Must(keystonev1.AddToScheme(scheme)) - utilruntime.Must(memcachedv1.AddToScheme(scheme)) - utilruntime.Must(routev1.AddToScheme(scheme)) - utilruntime.Must(topologyv1.AddToScheme(scheme)) - //+kubebuilder:scaffold:scheme -} - -func main() { - var metricsAddr string - var enableLeaderElection bool - var probeAddr string - var pprofBindAddress string - var webhookPort int - var secureMetrics bool - var enableHTTP2 bool - flag.StringVar(&metricsAddr, "metrics-bind-address", ":33080", "The address the metric endpoint binds to.") - flag.StringVar(&probeAddr, "health-probe-bind-address", ":33081", "The address the probe endpoint binds to.") - flag.StringVar(&pprofBindAddress, "pprof-bind-address", "", "The address the pprof endpoint binds to. Set to empty to disable pprof.") - flag.IntVar(&webhookPort, "webhook-bind-address", 9443, "The port the webhook server binds to.") - flag.BoolVar(&enableLeaderElection, "leader-elect", false, - "Enable leader election for controller manager. "+ - "Enabling this will ensure there is only one active controller manager.") - flag.BoolVar(&secureMetrics, "metrics-secure", false, - "If set the metrics endpoint is served securely") - flag.BoolVar(&enableHTTP2, "enable-http2", false, - "If set, HTTP/2 will be enabled for the metrics and webhook servers") - opts := zap.Options{ - Development: true, - } - opts.BindFlags(flag.CommandLine) - flag.Parse() - - ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) - - // if the enable-http2 flag is false (the default), http/2 should be disabled - // due to its vulnerabilities. More specifically, disabling http/2 will - // prevent from being vulnerable to the HTTP/2 Stream Cancellation and - // Rapid Reset CVEs. For more information see: - // - https://github.com/advisories/GHSA-qppj-fm5r-hxr3 - // - https://github.com/advisories/GHSA-4374-p667-p6c8 - disableHTTP2 := func(c *tls.Config) { - setupLog.Info("disabling http/2") - c.NextProtos = []string{"http/1.1"} - } - - tlsOpts := []func(*tls.Config){} - if !enableHTTP2 { - tlsOpts = append(tlsOpts, disableHTTP2) - } - - webhookServer := webhook.NewServer(webhook.Options{ - Port: webhookPort, - TLSOpts: tlsOpts, - }) - - options := ctrl.Options{ - Scheme: scheme, - Metrics: metricsserver.Options{ - BindAddress: metricsAddr, - SecureServing: secureMetrics, - TLSOpts: tlsOpts, - }, - WebhookServer: webhookServer, - HealthProbeBindAddress: probeAddr, - LeaderElection: enableLeaderElection, - LeaderElectionID: "5049980f.openstack.org", - PprofBindAddress: pprofBindAddress, - // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily - // when the Manager ends. This requires the binary to immediately end when the - // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly - // speeds up voluntary leader transitions as the new leader don't have to wait - // LeaseDuration time first. - // - // In the default scaffold provided, the program ends immediately after - // the manager stops, so would be fine to enable this option. However, - // if you are doing or is intended to do any operation such as perform cleanups - // after the manager stops then its usage might be unsafe. - // LeaderElectionReleaseOnCancel: true, - } - - err := operator.SetManagerOptions(&options, setupLog) - if err != nil { - setupLog.Error(err, "unable to set manager options") - os.Exit(1) - } - - mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) - if err != nil { - setupLog.Error(err, "unable to start manager") - os.Exit(1) - } - - cfg, err := config.GetConfig() - if err != nil { - setupLog.Error(err, "") - os.Exit(1) - } - kclient, err := kubernetes.NewForConfig(cfg) - if err != nil { - setupLog.Error(err, "") - os.Exit(1) - } - - reconcilers := controllers.NewReconcilers(mgr, kclient) - err = reconcilers.Setup(mgr, setupLog) - if err != nil { - os.Exit(1) - } - - // Acquire environmental defaults and initialize operator defaults with them - watcherv1beta1.SetupDefaults() - - checker := healthz.Ping - // Setup webhooks if requested - - if strings.ToLower(os.Getenv("ENABLE_WEBHOOKS")) != "false" { - - if err = (&watcherv1beta1.Watcher{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "Watcher") - os.Exit(1) - } - if err = (&watcherv1beta1.WatcherAPI{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "WatcherAPI") - os.Exit(1) - } - if err = (&watcherv1beta1.WatcherApplier{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "WatcherApplier") - os.Exit(1) - } - if err = (&watcherv1beta1.WatcherDecisionEngine{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "WatcherDecisionEngine") - os.Exit(1) - } - checker = mgr.GetWebhookServer().StartedChecker() - } - if err := mgr.AddHealthzCheck("healthz", checker); err != nil { - setupLog.Error(err, "unable to set up health check") - os.Exit(1) - } - if err := mgr.AddReadyzCheck("readyz", checker); err != nil { - setupLog.Error(err, "unable to set up ready check") - os.Exit(1) - } - - setupLog.Info("starting manager") - if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { - setupLog.Error(err, "problem running manager") - os.Exit(1) - } -} diff --git a/pkg/watcher/.keep b/pkg/watcher/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/functional/base_test.go b/test/functional/base_test.go similarity index 100% rename from tests/functional/base_test.go rename to test/functional/base_test.go diff --git a/tests/functional/sample_test.go b/test/functional/sample_test.go similarity index 100% rename from tests/functional/sample_test.go rename to test/functional/sample_test.go diff --git a/tests/functional/suite_test.go b/test/functional/suite_test.go similarity index 94% rename from tests/functional/suite_test.go rename to test/functional/suite_test.go index 4cb05f98..68e540f4 100644 --- a/tests/functional/suite_test.go +++ b/test/functional/suite_test.go @@ -36,7 +36,8 @@ import ( test "github.com/openstack-k8s-operators/lib-common/modules/test" mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" watcherv1 "github.com/openstack-k8s-operators/watcher-operator/api/v1beta1" - "github.com/openstack-k8s-operators/watcher-operator/controllers" + controllers "github.com/openstack-k8s-operators/watcher-operator/internal/controller" + webhookv1beta1 "github.com/openstack-k8s-operators/watcher-operator/internal/webhook/v1beta1" corev1 "k8s.io/api/core/v1" infra_test "github.com/openstack-k8s-operators/infra-operator/apis/test/helpers" @@ -191,13 +192,13 @@ var _ = BeforeSuite(func() { watcherv1.SetupDefaults() - err = (&watcherv1.Watcher{}).SetupWebhookWithManager(k8sManager) + err = webhookv1beta1.SetupWatcherWebhookWithManager(k8sManager) Expect(err).NotTo(HaveOccurred()) - err = (&watcherv1.WatcherAPI{}).SetupWebhookWithManager(k8sManager) + err = webhookv1beta1.SetupWatcherAPIWebhookWithManager(k8sManager) Expect(err).NotTo(HaveOccurred()) - err = (&watcherv1.WatcherDecisionEngine{}).SetupWebhookWithManager(k8sManager) + err = webhookv1beta1.SetupWatcherDecisionEngineWebhookWithManager(k8sManager) Expect(err).NotTo(HaveOccurred()) - err = (&watcherv1.WatcherApplier{}).SetupWebhookWithManager(k8sManager) + err = webhookv1beta1.SetupWatcherApplierWebhookWithManager(k8sManager) Expect(err).NotTo(HaveOccurred()) go func() { diff --git a/tests/functional/watcher_controller_test.go b/test/functional/watcher_controller_test.go similarity index 99% rename from tests/functional/watcher_controller_test.go rename to test/functional/watcher_controller_test.go index 700db4cc..076bc1b2 100644 --- a/tests/functional/watcher_controller_test.go +++ b/test/functional/watcher_controller_test.go @@ -727,7 +727,7 @@ var _ = Describe("Watcher controller", func() { Expect(err).To(HaveOccurred()) Expect(err.Error()).To( ContainSubstring( - "admission webhook \"vwatcher.kb.io\" denied the request: " + + "admission webhook \"vwatcher-v1beta1.kb.io\" denied the request: " + "Watcher.watcher.openstack.org \"watcher\" is invalid: " + "spec.databaseInstance: Invalid value: \"\": " + "databaseInstance field should not be empty"), @@ -758,7 +758,7 @@ var _ = Describe("Watcher controller", func() { Expect(err).To(HaveOccurred()) Expect(err.Error()).To( ContainSubstring( - "admission webhook \"vwatcher.kb.io\" denied the request: " + + "admission webhook \"vwatcher-v1beta1.kb.io\" denied the request: " + "Watcher.watcher.openstack.org \"watcher\" is invalid: " + "spec.topologyRef.namespace: Invalid value: \"namespace\": " + "Customizing namespace field is not supported"), @@ -788,7 +788,7 @@ var _ = Describe("Watcher controller", func() { Expect(err).To(HaveOccurred()) Expect(err.Error()).To( ContainSubstring( - "admission webhook \"vwatcher.kb.io\" denied the request: " + + "admission webhook \"vwatcher-v1beta1.kb.io\" denied the request: " + "Watcher.watcher.openstack.org \"watcher\" is invalid: " + "spec.rabbitMqClusterName: Invalid value: \"\": " + "rabbitMqClusterName field should not be empty"), diff --git a/tests/functional/watcher_test_data.go b/test/functional/watcher_test_data.go similarity index 98% rename from tests/functional/watcher_test_data.go rename to test/functional/watcher_test_data.go index da55a427..e6701af4 100644 --- a/tests/functional/watcher_test_data.go +++ b/test/functional/watcher_test_data.go @@ -20,7 +20,7 @@ package functional import ( "fmt" - "github.com/openstack-k8s-operators/watcher-operator/pkg/watcher" + "github.com/openstack-k8s-operators/watcher-operator/internal/watcher" "k8s.io/apimachinery/pkg/types" ) diff --git a/tests/functional/watcher_webhook_test.go b/test/functional/watcher_webhook_test.go similarity index 100% rename from tests/functional/watcher_webhook_test.go rename to test/functional/watcher_webhook_test.go diff --git a/tests/functional/watcherapi_controller_test.go b/test/functional/watcherapi_controller_test.go similarity index 100% rename from tests/functional/watcherapi_controller_test.go rename to test/functional/watcherapi_controller_test.go diff --git a/tests/functional/watcherapplier_controller_test.go b/test/functional/watcherapplier_controller_test.go similarity index 100% rename from tests/functional/watcherapplier_controller_test.go rename to test/functional/watcherapplier_controller_test.go diff --git a/tests/functional/watcherdecisionengine_controller_test.go b/test/functional/watcherdecisionengine_controller_test.go similarity index 100% rename from tests/functional/watcherdecisionengine_controller_test.go rename to test/functional/watcherdecisionengine_controller_test.go diff --git a/tests/kuttl/test-suites/default/common/cleanup-assert.yaml b/test/kuttl/test-suites/default/common/cleanup-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/common/cleanup-assert.yaml rename to test/kuttl/test-suites/default/common/cleanup-assert.yaml diff --git a/tests/kuttl/test-suites/default/common/cleanup-errors.yaml b/test/kuttl/test-suites/default/common/cleanup-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/common/cleanup-errors.yaml rename to test/kuttl/test-suites/default/common/cleanup-errors.yaml diff --git a/tests/kuttl/test-suites/default/common/cleanup-watcher.yaml b/test/kuttl/test-suites/default/common/cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/common/cleanup-watcher.yaml rename to test/kuttl/test-suites/default/common/cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/common/deploy-with-defaults.yaml b/test/kuttl/test-suites/default/common/deploy-with-defaults.yaml similarity index 100% rename from tests/kuttl/test-suites/default/common/deploy-with-defaults.yaml rename to test/kuttl/test-suites/default/common/deploy-with-defaults.yaml diff --git a/tests/kuttl/test-suites/default/config.yaml b/test/kuttl/test-suites/default/config.yaml similarity index 75% rename from tests/kuttl/test-suites/default/config.yaml rename to test/kuttl/test-suites/default/config.yaml index 65e3755f..74e5b207 100644 --- a/tests/kuttl/test-suites/default/config.yaml +++ b/test/kuttl/test-suites/default/config.yaml @@ -8,7 +8,7 @@ timeout: 300 parallel: 1 skipDelete: true testDirs: - - tests/kuttl/test-suites/default/ + - test/kuttl/test-suites/default/ suppress: - events -artifactsDir: tests/kuttl/test-suites/default/output +artifactsDir: test/kuttl/test-suites/default/output diff --git a/tests/kuttl/test-suites/default/deps/infra.yaml b/test/kuttl/test-suites/default/deps/infra.yaml similarity index 100% rename from tests/kuttl/test-suites/default/deps/infra.yaml rename to test/kuttl/test-suites/default/deps/infra.yaml diff --git a/tests/kuttl/test-suites/default/deps/keystone.yaml b/test/kuttl/test-suites/default/deps/keystone.yaml similarity index 100% rename from tests/kuttl/test-suites/default/deps/keystone.yaml rename to test/kuttl/test-suites/default/deps/keystone.yaml diff --git a/tests/kuttl/test-suites/default/deps/kustomization.yaml b/test/kuttl/test-suites/default/deps/kustomization.yaml similarity index 100% rename from tests/kuttl/test-suites/default/deps/kustomization.yaml rename to test/kuttl/test-suites/default/deps/kustomization.yaml diff --git a/tests/kuttl/test-suites/default/deps/namespace.yaml b/test/kuttl/test-suites/default/deps/namespace.yaml similarity index 100% rename from tests/kuttl/test-suites/default/deps/namespace.yaml rename to test/kuttl/test-suites/default/deps/namespace.yaml diff --git a/tests/kuttl/test-suites/default/deps/telemetry.yaml b/test/kuttl/test-suites/default/deps/telemetry.yaml similarity index 100% rename from tests/kuttl/test-suites/default/deps/telemetry.yaml rename to test/kuttl/test-suites/default/deps/telemetry.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/00-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/00-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/00-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/00-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/01-assert.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/01-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/01-assert.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/01-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/01-deploy-with-defaults.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/01-deploy-with-defaults.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/01-deploy-with-defaults.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/01-deploy-with-defaults.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/02-assert.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/02-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/02-assert.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/02-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/02-scale-up-watcher-api.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/02-scale-up-watcher-api.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/02-scale-up-watcher-api.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/02-scale-up-watcher-api.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/03-assert.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/03-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/03-assert.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/03-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/03-scale-down-watcher-api.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/03-scale-down-watcher-api.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/03-scale-down-watcher-api.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/03-scale-down-watcher-api.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/04-assert.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/04-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/04-assert.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/04-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/04-errors.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/04-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/04-errors.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/04-errors.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/04-scale-down-zero-watcher-api.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/04-scale-down-zero-watcher-api.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/04-scale-down-zero-watcher-api.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/04-scale-down-zero-watcher-api.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/05-assert.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/05-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/05-assert.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/05-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/05-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/05-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/05-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/05-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-api-scaling/05-errors.yaml b/test/kuttl/test-suites/default/watcher-api-scaling/05-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-api-scaling/05-errors.yaml rename to test/kuttl/test-suites/default/watcher-api-scaling/05-errors.yaml diff --git a/tests/kuttl/test-suites/default/watcher-cinder/00-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-cinder/00-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-cinder/00-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-cinder/00-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-cinder/01-assert.yaml b/test/kuttl/test-suites/default/watcher-cinder/01-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-cinder/01-assert.yaml rename to test/kuttl/test-suites/default/watcher-cinder/01-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-cinder/01-deploy-watcher-no-cinder.yaml b/test/kuttl/test-suites/default/watcher-cinder/01-deploy-watcher-no-cinder.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-cinder/01-deploy-watcher-no-cinder.yaml rename to test/kuttl/test-suites/default/watcher-cinder/01-deploy-watcher-no-cinder.yaml diff --git a/tests/kuttl/test-suites/default/watcher-cinder/02-assert.yaml b/test/kuttl/test-suites/default/watcher-cinder/02-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-cinder/02-assert.yaml rename to test/kuttl/test-suites/default/watcher-cinder/02-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-cinder/02-deploy-cinder.yaml b/test/kuttl/test-suites/default/watcher-cinder/02-deploy-cinder.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-cinder/02-deploy-cinder.yaml rename to test/kuttl/test-suites/default/watcher-cinder/02-deploy-cinder.yaml diff --git a/tests/kuttl/test-suites/default/watcher-cinder/03-assert.yaml b/test/kuttl/test-suites/default/watcher-cinder/03-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-cinder/03-assert.yaml rename to test/kuttl/test-suites/default/watcher-cinder/03-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-cinder/03-remove-cinder.yaml b/test/kuttl/test-suites/default/watcher-cinder/03-remove-cinder.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-cinder/03-remove-cinder.yaml rename to test/kuttl/test-suites/default/watcher-cinder/03-remove-cinder.yaml diff --git a/tests/kuttl/test-suites/default/watcher-cinder/04-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-cinder/04-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-cinder/04-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-cinder/04-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-cinder/04-errors.yaml b/test/kuttl/test-suites/default/watcher-cinder/04-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-cinder/04-errors.yaml rename to test/kuttl/test-suites/default/watcher-cinder/04-errors.yaml diff --git a/tests/kuttl/test-suites/default/watcher-notification/00-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-notification/00-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-notification/00-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-notification/00-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-notification/01-assert.yaml b/test/kuttl/test-suites/default/watcher-notification/01-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-notification/01-assert.yaml rename to test/kuttl/test-suites/default/watcher-notification/01-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-notification/01-deploy-with-notification.yaml b/test/kuttl/test-suites/default/watcher-notification/01-deploy-with-notification.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-notification/01-deploy-with-notification.yaml rename to test/kuttl/test-suites/default/watcher-notification/01-deploy-with-notification.yaml diff --git a/tests/kuttl/test-suites/default/watcher-notification/02-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-notification/02-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-notification/02-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-notification/02-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-notification/02-errors.yaml b/test/kuttl/test-suites/default/watcher-notification/02-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-notification/02-errors.yaml rename to test/kuttl/test-suites/default/watcher-notification/02-errors.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/00-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/00-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/00-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/00-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/01-assert.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/01-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/01-assert.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/01-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/01-deploy-with-tlse.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/01-deploy-with-tlse.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/01-deploy-with-tlse.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/01-deploy-with-tlse.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/02-assert.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/02-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/02-assert.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/02-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/02-change-public-svc-certificate.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/02-change-public-svc-certificate.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/02-change-public-svc-certificate.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/02-change-public-svc-certificate.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/03-assert.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/03-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/03-assert.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/03-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/03-change-internal-svc-certificate.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/03-change-internal-svc-certificate.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/03-change-internal-svc-certificate.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/03-change-internal-svc-certificate.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/04-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/04-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/04-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/04-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/04-errors.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/04-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/04-errors.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/04-errors.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/05-clenaup-certs.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/05-clenaup-certs.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/05-clenaup-certs.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/05-clenaup-certs.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls-certs-change/05-errors.yaml b/test/kuttl/test-suites/default/watcher-tls-certs-change/05-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls-certs-change/05-errors.yaml rename to test/kuttl/test-suites/default/watcher-tls-certs-change/05-errors.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/00-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-tls/00-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/00-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-tls/00-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/01-assert.yaml b/test/kuttl/test-suites/default/watcher-tls/01-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/01-assert.yaml rename to test/kuttl/test-suites/default/watcher-tls/01-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/01-deploy-with-tlse.yaml b/test/kuttl/test-suites/default/watcher-tls/01-deploy-with-tlse.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/01-deploy-with-tlse.yaml rename to test/kuttl/test-suites/default/watcher-tls/01-deploy-with-tlse.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/02-assert-mtls.yaml b/test/kuttl/test-suites/default/watcher-tls/02-assert-mtls.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/02-assert-mtls.yaml rename to test/kuttl/test-suites/default/watcher-tls/02-assert-mtls.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/02-patch-mtls.yaml b/test/kuttl/test-suites/default/watcher-tls/02-patch-mtls.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/02-patch-mtls.yaml rename to test/kuttl/test-suites/default/watcher-tls/02-patch-mtls.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/03-assert.yaml b/test/kuttl/test-suites/default/watcher-tls/03-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/03-assert.yaml rename to test/kuttl/test-suites/default/watcher-tls/03-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/03-disable-podlevel-tls.yaml b/test/kuttl/test-suites/default/watcher-tls/03-disable-podlevel-tls.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/03-disable-podlevel-tls.yaml rename to test/kuttl/test-suites/default/watcher-tls/03-disable-podlevel-tls.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/04-assert.yaml b/test/kuttl/test-suites/default/watcher-tls/04-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/04-assert.yaml rename to test/kuttl/test-suites/default/watcher-tls/04-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/04-deploy-without-route.yaml b/test/kuttl/test-suites/default/watcher-tls/04-deploy-without-route.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/04-deploy-without-route.yaml rename to test/kuttl/test-suites/default/watcher-tls/04-deploy-without-route.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/05-assert.yaml b/test/kuttl/test-suites/default/watcher-tls/05-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/05-assert.yaml rename to test/kuttl/test-suites/default/watcher-tls/05-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/05-disable-tls.yaml b/test/kuttl/test-suites/default/watcher-tls/05-disable-tls.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/05-disable-tls.yaml rename to test/kuttl/test-suites/default/watcher-tls/05-disable-tls.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/06-assert.yaml b/test/kuttl/test-suites/default/watcher-tls/06-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/06-assert.yaml rename to test/kuttl/test-suites/default/watcher-tls/06-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/06-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-tls/06-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/06-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-tls/06-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/06-errors.yaml b/test/kuttl/test-suites/default/watcher-tls/06-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/06-errors.yaml rename to test/kuttl/test-suites/default/watcher-tls/06-errors.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/07-cleanup-certs.yaml b/test/kuttl/test-suites/default/watcher-tls/07-cleanup-certs.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/07-cleanup-certs.yaml rename to test/kuttl/test-suites/default/watcher-tls/07-cleanup-certs.yaml diff --git a/tests/kuttl/test-suites/default/watcher-tls/07-errors.yaml b/test/kuttl/test-suites/default/watcher-tls/07-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-tls/07-errors.yaml rename to test/kuttl/test-suites/default/watcher-tls/07-errors.yaml diff --git a/tests/kuttl/test-suites/default/watcher-topology/00-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-topology/00-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-topology/00-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-topology/00-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-topology/01-assert.yaml b/test/kuttl/test-suites/default/watcher-topology/01-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-topology/01-assert.yaml rename to test/kuttl/test-suites/default/watcher-topology/01-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-topology/01-deploy-with-topology.yaml b/test/kuttl/test-suites/default/watcher-topology/01-deploy-with-topology.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-topology/01-deploy-with-topology.yaml rename to test/kuttl/test-suites/default/watcher-topology/01-deploy-with-topology.yaml diff --git a/tests/kuttl/test-suites/default/watcher-topology/02-assert.yaml b/test/kuttl/test-suites/default/watcher-topology/02-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-topology/02-assert.yaml rename to test/kuttl/test-suites/default/watcher-topology/02-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher-topology/02-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher-topology/02-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-topology/02-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher-topology/02-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher-topology/02-errors.yaml b/test/kuttl/test-suites/default/watcher-topology/02-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher-topology/02-errors.yaml rename to test/kuttl/test-suites/default/watcher-topology/02-errors.yaml diff --git a/tests/kuttl/test-suites/default/watcher/00-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher/00-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/00-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher/00-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher/01-assert.yaml b/test/kuttl/test-suites/default/watcher/01-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/01-assert.yaml rename to test/kuttl/test-suites/default/watcher/01-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher/01-deploy-with-defaults.yaml b/test/kuttl/test-suites/default/watcher/01-deploy-with-defaults.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/01-deploy-with-defaults.yaml rename to test/kuttl/test-suites/default/watcher/01-deploy-with-defaults.yaml diff --git a/tests/kuttl/test-suites/default/watcher/02-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher/02-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/02-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher/02-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher/03-precreate-mariadbaccount.yaml b/test/kuttl/test-suites/default/watcher/03-precreate-mariadbaccount.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/03-precreate-mariadbaccount.yaml rename to test/kuttl/test-suites/default/watcher/03-precreate-mariadbaccount.yaml diff --git a/tests/kuttl/test-suites/default/watcher/04-assert.yaml b/test/kuttl/test-suites/default/watcher/04-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/04-assert.yaml rename to test/kuttl/test-suites/default/watcher/04-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher/04-deploy-with-precreated-account.yaml b/test/kuttl/test-suites/default/watcher/04-deploy-with-precreated-account.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/04-deploy-with-precreated-account.yaml rename to test/kuttl/test-suites/default/watcher/04-deploy-with-precreated-account.yaml diff --git a/tests/kuttl/test-suites/default/watcher/05-assert.yaml b/test/kuttl/test-suites/default/watcher/05-assert.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/05-assert.yaml rename to test/kuttl/test-suites/default/watcher/05-assert.yaml diff --git a/tests/kuttl/test-suites/default/watcher/05-cleanup-watcher.yaml b/test/kuttl/test-suites/default/watcher/05-cleanup-watcher.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/05-cleanup-watcher.yaml rename to test/kuttl/test-suites/default/watcher/05-cleanup-watcher.yaml diff --git a/tests/kuttl/test-suites/default/watcher/05-errors.yaml b/test/kuttl/test-suites/default/watcher/05-errors.yaml similarity index 100% rename from tests/kuttl/test-suites/default/watcher/05-errors.yaml rename to test/kuttl/test-suites/default/watcher/05-errors.yaml