diff --git a/.github/actions/deploy-lifecycle-manager-e2e/action.yml b/.github/actions/deploy-lifecycle-manager-e2e/action.yml index ae6aaaf286..393b77d759 100644 --- a/.github/actions/deploy-lifecycle-manager-e2e/action.yml +++ b/.github/actions/deploy-lifecycle-manager-e2e/action.yml @@ -80,9 +80,28 @@ runs: cat requeue-interval-patch.yaml kustomize edit add patch --path requeue-interval-patch.yaml --kind Deployment popd + - name: Patch KLM deployment for watcher zero downtime + if: ${{matrix.e2e-test == 'watcher-zero-downtime'}} + working-directory: lifecycle-manager + shell: bash + run: | + pushd config/watcher_local_test + echo \ + "- op: replace + path: /spec/template/spec/containers/0/args/16 + value: --kyma-requeue-success-interval=10s + - op: add + path: /spec/template/spec/containers/0/args/- + value: --istio-gateway-cert-switch-before-expiration-time=58m30s + - op: add + path: /spec/template/spec/containers/0/args/- + value: --istio-gateway-secret-requeue-success-interval=6s" >> requeue-interval-patch.yaml + cat requeue-interval-patch.yaml + kustomize edit add patch --path requeue-interval-patch.yaml --kind Deployment + popd - name: Patch CA certificate renewBefore - if: ${{matrix.e2e-test == 'ca-certificate-rotation' || - matrix.e2e-test == 'istio-gateway-secret-rotation'}} + if: ${{matrix.e2e-test == 'legacy-istio-gateway-secret-rotation' || + matrix.e2e-test == 'watcher-zero-downtime'}} working-directory: lifecycle-manager shell: bash run: | @@ -97,6 +116,19 @@ runs: cat certificate_renewal.yaml kustomize edit add patch --path certificate_renewal.yaml --kind Certificate --group cert-manager.io --version v1 --name watcher-serving popd + - name: Use legacy istio gateway secret rotation strategy + if: ${{matrix.e2e-test == 'legacy-istio-gateway-secret-rotation'}} + working-directory: lifecycle-manager + shell: bash + run: | + pushd config/watcher_local_test + echo \ + "- op: add + path: /spec/template/spec/containers/0/args/- + value: --legacy-strategy-for-istio-gateway-secret=true" >> legacy-secret-rotation.yaml + cat legacy-secret-rotation.yaml + kustomize edit add patch --path legacy-secret-rotation.yaml --kind Deployment + popd - name: Create and use maintenance window policy if: ${{matrix.e2e-test == 'maintenance-windows' || matrix.e2e-test == 'maintenance-windows-initial-installation' || @@ -141,9 +173,6 @@ runs: echo "Maintenance window policy:" cat ./maintenance_windows/policy.json - - cd watcher_local_test - kustomize edit add component ../maintenance_windows - name: Deploy LM local testing kustomize uses: ./lifecycle-manager/.github/actions/deploy-lifecycle-manager with: @@ -151,13 +180,6 @@ runs: klm_image_repo: ${{ inputs.klm_image_repo }} - name: Expose Metrics Endpoint working-directory: lifecycle-manager - if: ${{ matrix.e2e-test == 'kyma-metrics' || - matrix.e2e-test == 'module-status-decoupling-with-statefulset' || - matrix.e2e-test == 'module-status-decoupling-with-deployment' || - matrix.e2e-test == 'purge-metrics' || - matrix.e2e-test == 'self-signed-certificate-rotation' || - matrix.e2e-test == 'mandatory-module-metrics' || - matrix.e2e-test == 'mandatory-module-metrics-with-old-naming-pattern'}} shell: bash run: | kubectl patch svc klm-controller-manager-metrics -p '{"spec": {"type": "LoadBalancer"}}' -n kcp-system diff --git a/.github/actions/deploy-template-operator-with-modulereleasemeta/action.yml b/.github/actions/deploy-template-operator-with-modulereleasemeta/action.yml index 4afbbd5738..d2ac0cea34 100644 --- a/.github/actions/deploy-template-operator-with-modulereleasemeta/action.yml +++ b/.github/actions/deploy-template-operator-with-modulereleasemeta/action.yml @@ -21,7 +21,8 @@ runs: - name: Create and apply Template Operator ModuleTemplate from the latest release working-directory: template-operator if: ${{ matrix.e2e-test != 'mandatory-module' && - matrix.e2e-test != 'mandatory-module-metrics' + matrix.e2e-test != 'mandatory-module-metrics' && + matrix.e2e-test != 'watcher-zero-downtime' }} shell: bash run: | @@ -32,7 +33,8 @@ runs: - name: Create and apply Template Operator ModuleTemplate with ModuleDeploymentNameInOlderVersion working-directory: template-operator if: ${{ matrix.e2e-test != 'mandatory-module' && - matrix.e2e-test != 'mandatory-module-metrics' + matrix.e2e-test != 'mandatory-module-metrics' && + matrix.e2e-test != 'watcher-zero-downtime' }} shell: bash run: | @@ -42,7 +44,8 @@ runs: - name: Create and apply Template Operator ModuleTemplate with ModuleDeploymentNameInNewerVersion working-directory: template-operator if: ${{ matrix.e2e-test != 'mandatory-module' && - matrix.e2e-test != 'mandatory-module-metrics' + matrix.e2e-test != 'mandatory-module-metrics' && + matrix.e2e-test != 'watcher-zero-downtime' }} shell: bash run: | diff --git a/.github/workflows/check-manifests-changes.yml b/.github/workflows/check-manifests-changes.yml new file mode 100644 index 0000000000..a928ea7ba1 --- /dev/null +++ b/.github/workflows/check-manifests-changes.yml @@ -0,0 +1,123 @@ +name: "Check If Manifests Change" + +env: + PR_CACHE_KEY: pr-manifests-${{ github.run_id }}-${{ github.run_attempt }} + MAIN_CACHE_KEY: main-manifests-${{ github.run_id }}-${{ github.run_attempt }} + +on: + pull_request_target: + +jobs: + create-pr-manifests: + runs-on: ubuntu-latest + steps: + - name: Checkout PR branch + uses: actions/checkout@v4 + + - name: Create manifests on PR branch + run: | + make dry-run-control-plane + mkdir -p ./cache/pr + mv ./dry-run/manifests.yaml ./cache/pr/manifests.yaml + + - name: Save PR manifests in cache + uses: actions/cache@v3 + with: + path: ./cache/pr/ + key: ${{ env.PR_CACHE_KEY }} + + create-main-manifests: + runs-on: ubuntu-latest + steps: + - name: Checkout main branch + uses: actions/checkout@v4 + with: + ref: main + + - name: Create manifests on main branch + run: | + make dry-run-control-plane + mkdir -p ./cache/main + mv ./dry-run/manifests.yaml ./cache/main/manifests.yaml + + - name: Save main manifests in cache + uses: actions/cache@v3 + with: + path: ./cache/main/ + key: ${{ env.MAIN_CACHE_KEY }} + + diff-manifests: + needs: + - create-pr-manifests + - create-main-manifests + runs-on: ubuntu-latest + steps: + - name: Restore PR manifests from cache + uses: actions/cache@v3 + with: + path: ./cache/pr/ + key: ${{ env.PR_CACHE_KEY }} + + - name: Restore main manifests from cache + uses: actions/cache@v3 + with: + path: ./cache/main/ + key: ${{ env.MAIN_CACHE_KEY }} + + - name: Compare Manifests + id: compare-manifests + run: | + set +e + DIFF_OUTPUT=$(diff ./cache/pr/manifests.yaml ./cache/main/manifests.yaml) + EXIT_CODE=$? + if [[ $EXIT_CODE != 0 ]]; then + echo "❌ Detected differences in manifest outputs!" + echo "$DIFF_OUTPUT" + echo "manifests_diff_detected=true" >> $GITHUB_OUTPUT + else + echo "✅ No differences in manifest outputs detected." + echo "manifests_diff_detected=false" >> $GITHUB_OUTPUT + fi + exit 0 + + - name: Add PR Comment if Manifest Differences Detected + if: steps.compare-manifests.outputs.manifests_diff_detected == 'true' + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: "❌ **Manifests created with 'make dry-run-control-plane' changed!** Please make sure to check if changes are needed in related repositories like management-plane-charts, runtime-watchter, etc.." + }); + github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + labels: ["manifests-diff"] + }); + + - name: Remove 'manifests-diff' Label if No Differences + if: steps.compare-manifests.outputs.manifests_diff_detected == 'false' + uses: actions/github-script@v7 + with: + script: | + const labelName = 'manifests-diff'; + const { data: labels } = await github.rest.issues.listLabelsOnIssue({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + }); + if (labels.some(label => label.name === labelName)) { + console.log(`Label "${labelName}" found, removing it.`); + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + name: labelName, + }); + } else { + console.log(`Label "${labelName}" not found, skipping removal.`); + } + diff --git a/.github/workflows/check-pipeline-changes.yml b/.github/workflows/check-pipeline-changes.yml new file mode 100644 index 0000000000..bd348d177a --- /dev/null +++ b/.github/workflows/check-pipeline-changes.yml @@ -0,0 +1,87 @@ +name: "Check Pipeline Changes" + +on: + pull_request_target: + +jobs: + check-pipeline-changes: + runs-on: ubuntu-latest + steps: + - name: Get list of changed files + id: changed-files + uses: actions/github-script@v7 + with: + script: | + const { data: files } = await github.rest.pulls.listFiles({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + }); + // Define the pipeline-related paths to watch + const pathsToCheck = [ + ".github/actions", + ".github/workflows/test-e2e.yml", + ".github/workflows/test-e2e-with-modulereleasemeta.yml", + ".github/scripts", + "scripts/tests", + "versions.yaml" + ]; + + const pipelineFiles = files.filter(file => + pathsToCheck.some(path => file.filename === path || file.filename.startsWith(path + '/')) + ); + core.setOutput('pipelineFiles', pipelineFiles.map(file => file.filename).join(',')); + + - name: Evaluate Pipeline Changes + id: eval-changes + run: | + echo "Changed pipeline-related files:" + echo "${{ steps.changed-files.outputs.pipelineFiles }}" | tr ',' '\n' + if [ -n "${{ steps.changed-files.outputs.pipelineFiles }}" ]; then + echo "⚠️ Pipeline-related changes detected!" + echo "pipeline_changed=true" >> $GITHUB_OUTPUT + else + echo "✅ No pipeline-related changes detected." + echo "pipeline_changed=false" >> $GITHUB_OUTPUT + fi + + - name: Add PR Comment & Label if Pipeline Changes Detected + if: steps.eval-changes.outputs.pipeline_changed == 'true' + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: "⚠️ **Pipeline-related file changes detected!** Please review if related updates (e.g. manifest generation or workflow adjustments) are required." + }); + github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + labels: ["pipeline-changed"] + }); + + - name: Remove 'pipeline-changed' Label if No Changes Detected + if: steps.eval-changes.outputs.pipeline_changed == 'false' + uses: actions/github-script@v7 + with: + script: | + const labelName = 'pipeline-changed'; + const { data: labels } = await github.rest.issues.listLabelsOnIssue({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + }); + if (labels.some(label => label.name === labelName)) { + console.log(`Label "${labelName}" found, removing it.`); + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + name: labelName, + }); + } else { + console.log(`Label "${labelName}" not found, skipping removal.`); + } diff --git a/.github/workflows/test-e2e-with-modulereleasemeta.yml b/.github/workflows/test-e2e-with-modulereleasemeta.yml index 89b49ef491..e19bb7e99a 100644 --- a/.github/workflows/test-e2e-with-modulereleasemeta.yml +++ b/.github/workflows/test-e2e-with-modulereleasemeta.yml @@ -54,8 +54,7 @@ jobs: - modulereleasemeta-module-upgrade-new-version - unmanage-module - skip-manifest-reconciliation - - ca-certificate-rotation - - istio-gateway-secret-rotation + - legacy-istio-gateway-secret-rotation - self-signed-certificate-rotation - mandatory-module - mandatory-module-metrics @@ -70,6 +69,7 @@ jobs: - maintenance-windows - maintenance-windows-initial-installation - maintenance-windows-skip + - watcher-zero-downtime runs-on: ubuntu-latest timeout-minutes: 20 diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 7dbdf594a9..98770c3012 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -55,8 +55,7 @@ jobs: - unmanage-module - module-install-by-version - skip-manifest-reconciliation - - ca-certificate-rotation - - istio-gateway-secret-rotation + - legacy-istio-gateway-secret-rotation - self-signed-certificate-rotation - mandatory-module-with-old-naming-pattern - mandatory-module-metrics-with-old-naming-pattern diff --git a/.golangci.yaml b/.golangci.yaml index dc487c7f74..2e51a71891 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -134,6 +134,8 @@ linters-settings: alias: watcherctrl - pkg: github.com/kyma-project/lifecycle-manager/internal/gatewaysecret/client alias: gatewaysecretclient + - pkg: github.com/kyma-project/lifecycle-manager/internal/gatewaysecret/handler + alias: gatewaysecrethandler ireturn: allow: - anon diff --git a/.run/Launch KLM locally.run.xml b/.run/Launch KLM locally.run.xml index bc93d15202..682d67f8c9 100644 --- a/.run/Launch KLM locally.run.xml +++ b/.run/Launch KLM locally.run.xml @@ -2,7 +2,7 @@ - + diff --git a/.vscode/tasks.json b/.vscode/tasks.json index fd0692612c..41f0de1574 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -117,7 +117,6 @@ "module-upgrade-new-version", "unmanage-module", "skip-manifest-reconciliation", - "ca-certificate-rotation", "self-signed-certificate-rotation", "mandatory-module", "mandatory-module-metrics", diff --git a/Dockerfile b/Dockerfile index be10ef7c3a..c6a9151ae7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM golang:1.23.5-alpine as builder +FROM golang:1.23.6-alpine as builder WORKDIR /lifecycle-manager # Copy the Go Modules manifests diff --git a/PROJECT b/PROJECT index 5f67eae77c..25e67a803b 100644 --- a/PROJECT +++ b/PROJECT @@ -10,19 +10,6 @@ plugins: projectName: operator repo: github.com/kyma-project/lifecycle-manager resources: -- api: - crdVersion: v1 - namespaced: true - domain: kyma-project.io - group: operator - kind: Manifest - path: github.com/kyma-project/module-manager/api/v1beta1 - version: v1beta1 - webhooks: - conversion: true - defaulting: true - validation: true - webhookVersion: v1 - api: crdVersion: v1 namespaced: true @@ -110,10 +97,12 @@ resources: - api: crdVersion: v1 namespaced: true - controller: true domain: kyma-project.io group: operator - kind: SyncResource - path: github.com/kyma-project/lifecycle-manager/api/v1alpha1 - version: v1alpha1 + kind: ModuleReleaseMeta + path: github.com/kyma-project/lifecycle-manager/api/v1beta2 + version: v1beta2 + webhooks: + conversion: true + webhookVersion: v1 version: "3" diff --git a/api/go.mod b/api/go.mod index 055262fe36..1378e0a0e9 100644 --- a/api/go.mod +++ b/api/go.mod @@ -1,12 +1,12 @@ module github.com/kyma-project/lifecycle-manager/api -go 1.23.5 +go 1.23.6 require ( github.com/Masterminds/semver/v3 v3.3.1 github.com/stretchr/testify v1.10.0 - k8s.io/apimachinery v0.32.1 - sigs.k8s.io/controller-runtime v0.20.1 + k8s.io/apimachinery v0.32.2 + sigs.k8s.io/controller-runtime v0.20.2 ) require github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -14,7 +14,7 @@ require github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // in require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -32,7 +32,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/x448/float16 v0.8.4 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect @@ -43,8 +42,8 @@ require ( google.golang.org/protobuf v1.35.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.32.0 // indirect - k8s.io/client-go v0.32.0 // indirect + k8s.io/api v0.32.2 // indirect + k8s.io/client-go v0.32.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect diff --git a/api/go.sum b/api/go.sum index f718530f81..4db8cc16a5 100644 --- a/api/go.sum +++ b/api/go.sum @@ -6,8 +6,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/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/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= @@ -57,10 +57,10 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= -github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= -github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= -github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= +github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw= +github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -132,22 +132,22 @@ 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.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= -k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= -k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0= -k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw= -k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs= -k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= -k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= +k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= +k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= +k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw= +k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto= +k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= +k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= +k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= 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-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE= -sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= +sigs.k8s.io/controller-runtime v0.20.2 h1:/439OZVxoEc02psi1h4QO3bHzTgu49bb347Xp4gW1pc= +sigs.k8s.io/controller-runtime v0.20.2/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= diff --git a/api/shared/operator_labels.go b/api/shared/operator_labels.go index 8931a22951..2780b20d0e 100644 --- a/api/shared/operator_labels.go +++ b/api/shared/operator_labels.go @@ -47,8 +47,7 @@ const ( GlobalAccountIDLabel = KymaGroup + Separator + "global-account-id" RegionLabel = KymaGroup + Separator + "region" PlatformRegionLabel = KymaGroup + Separator + "platform-region" - // to be confirmed https://github.com/kyma-project/kyma/issues/18611#issuecomment-2441158676 - PlanLabel = KymaGroup + Separator + "broker-plan-name" + PlanLabel = KymaGroup + Separator + "broker-plan-name" EnableLabelValue = "true" DisableLabelValue = "false" diff --git a/api/v1beta2/kyma_types.go b/api/v1beta2/kyma_types.go index 631169ad99..176f57dadd 100644 --- a/api/v1beta2/kyma_types.go +++ b/api/v1beta2/kyma_types.go @@ -452,7 +452,6 @@ func (kyma *Kyma) GetPlatformRegion() string { return kyma.Labels[shared.PlatformRegionLabel] } -// to be confirmed https://github.com/kyma-project/kyma/issues/18611#issuecomment-2441158676 func (kyma *Kyma) GetPlan() string { return kyma.Labels[shared.PlanLabel] } diff --git a/cmd/main.go b/cmd/main.go index 9402dc3258..f14ef0734c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -81,7 +81,6 @@ const ( maintenanceWindowPolicyName = "policy" maintenanceWindowPoliciesDirectory = "/etc/maintenance-policy" - minMaintenanceWindowSize = 20 * time.Minute ) var ( @@ -144,31 +143,12 @@ func pprofStartServer(addr string, timeout time.Duration, setupLog logr.Logger) } } -//nolint:funlen // setupManager is a main function that sets up the manager func setupManager(flagVar *flags.FlagVar, cacheOptions cache.Options, scheme *machineryruntime.Scheme, - setupLog logr.Logger, + logger logr.Logger, ) { - config := ctrl.GetConfigOrDie() - config.QPS = float32(flagVar.ClientQPS) - config.Burst = flagVar.ClientBurst - - mgr, err := ctrl.NewManager( - config, ctrl.Options{ - Scheme: scheme, - Metrics: metricsserver.Options{ - BindAddress: flagVar.MetricsAddr, - }, - HealthProbeBindAddress: flagVar.ProbeAddr, - LeaderElection: flagVar.EnableLeaderElection, - LeaderElectionID: "893110f7.kyma-project.io", - LeaseDuration: &flagVar.LeaderElectionLeaseDuration, - RenewDeadline: &flagVar.LeaderElectionRenewDeadline, - RetryPeriod: &flagVar.LeaderElectionRetryPeriod, - Cache: cacheOptions, - }, - ) + mgr, err := configManager(flagVar, cacheOptions, scheme) if err != nil { - setupLog.Error(err, "unable to start manager") + logger.Error(err, "unable to start manager") os.Exit(bootstrapFailedExitCode) } kcpRestConfig := mgr.GetConfig() @@ -180,13 +160,13 @@ func setupManager(flagVar *flags.FlagVar, cacheOptions cache.Options, scheme *ma var options ctrlruntime.Options if flagVar.EnableKcpWatcher { if skrWebhookManager, err = createSkrWebhookManager(mgr, skrContextProvider, flagVar); err != nil { - setupLog.Error(err, "failed to create skr webhook manager") + logger.Error(err, "failed to create skr webhook manager") os.Exit(bootstrapFailedExitCode) } - setupKcpWatcherReconciler(mgr, options, eventRecorder, flagVar, setupLog) + setupKcpWatcherReconciler(mgr, options, eventRecorder, flagVar, logger) err = istiogatewaysecret.SetupReconciler(mgr, flagVar, options) if err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Istio") + logger.Error(err, "unable to create controller", "controller", "Istio") os.Exit(bootstrapFailedExitCode) } } @@ -195,44 +175,80 @@ func setupManager(flagVar *flags.FlagVar, cacheOptions cache.Options, scheme *ma descriptorProvider := provider.NewCachedDescriptorProvider() kymaMetrics := metrics.NewKymaMetrics(sharedMetrics) mandatoryModulesMetrics := metrics.NewMandatoryModulesMetrics() + maintenanceWindow := initMaintenanceWindow(flagVar.MinMaintenanceWindowSize, logger) - maintenanceWindow, err := maintenancewindows.InitializeMaintenanceWindow(setupLog, - maintenanceWindowPoliciesDirectory, - maintenanceWindowPolicyName, - // align the configuration values before rollout - // https://github.com/kyma-project/lifecycle-manager/issues/2165 - true, - minMaintenanceWindowSize) - if err != nil { - setupLog.Error(err, "unable to set maintenance windows policy") - } setupKymaReconciler(mgr, descriptorProvider, skrContextProvider, eventRecorder, flagVar, options, skrWebhookManager, - kymaMetrics, setupLog, maintenanceWindow) - setupManifestReconciler(mgr, flagVar, options, sharedMetrics, mandatoryModulesMetrics, setupLog, + kymaMetrics, logger, maintenanceWindow) + setupManifestReconciler(mgr, flagVar, options, sharedMetrics, mandatoryModulesMetrics, logger, eventRecorder) - setupMandatoryModuleReconciler(mgr, descriptorProvider, flagVar, options, mandatoryModulesMetrics, setupLog) - setupMandatoryModuleDeletionReconciler(mgr, descriptorProvider, eventRecorder, flagVar, options, setupLog) + setupMandatoryModuleReconciler(mgr, descriptorProvider, flagVar, options, mandatoryModulesMetrics, logger) + setupMandatoryModuleDeletionReconciler(mgr, descriptorProvider, eventRecorder, flagVar, options, logger) if flagVar.EnablePurgeFinalizer { - setupPurgeReconciler(mgr, skrContextProvider, eventRecorder, flagVar, options, setupLog) + setupPurgeReconciler(mgr, skrContextProvider, eventRecorder, flagVar, options, logger) } if flagVar.EnableWebhooks { // enable conversion webhook for CRDs here - setupLog.Info("currently no configured webhooks") + logger.Info("currently no configured webhooks") } - addHealthChecks(mgr, setupLog) + addHealthChecks(mgr, logger) - go cleanupStoredVersions(flagVar.DropCrdStoredVersionMap, mgr, setupLog) - go scheduleMetricsCleanup(kymaMetrics, flagVar.MetricsCleanupIntervalInMinutes, mgr, setupLog) + go cleanupStoredVersions(flagVar.DropCrdStoredVersionMap, mgr, logger) + go scheduleMetricsCleanup(kymaMetrics, flagVar.MetricsCleanupIntervalInMinutes, mgr, logger) if err = mgr.Start(ctrl.SetupSignalHandler()); err != nil { - setupLog.Error(err, "problem running manager") + logger.Error(err, "problem running manager") os.Exit(runtimeProblemExitCode) } } +func initMaintenanceWindow(minWindowSize time.Duration, logger logr.Logger) maintenancewindows.MaintenanceWindow { + maintenanceWindowsMetrics := metrics.NewMaintenanceWindowMetrics() + maintenanceWindow, err := maintenancewindows.InitializeMaintenanceWindow(logger, + maintenanceWindowPoliciesDirectory, + maintenanceWindowPolicyName, + minWindowSize) + if err != nil { + maintenanceWindowsMetrics.RecordConfigReadSuccess(false) + logger.Error(err, "unable to set maintenance windows policy") + } else { + maintenanceWindowsMetrics.RecordConfigReadSuccess(true) + } + return maintenanceWindow +} + +//nolint:ireturn // the implementation is not a part of the public API +func configManager(flagVar *flags.FlagVar, cacheOptions cache.Options, + scheme *machineryruntime.Scheme, +) (manager.Manager, error) { + config := ctrl.GetConfigOrDie() + + config.QPS = float32(flagVar.ClientQPS) + config.Burst = flagVar.ClientBurst + + mgr, err := ctrl.NewManager( + config, ctrl.Options{ + Scheme: scheme, + Metrics: metricsserver.Options{ + BindAddress: flagVar.MetricsAddr, + }, + HealthProbeBindAddress: flagVar.ProbeAddr, + LeaderElection: flagVar.EnableLeaderElection, + LeaderElectionID: "893110f7.kyma-project.io", + LeaseDuration: &flagVar.LeaderElectionLeaseDuration, + RenewDeadline: &flagVar.LeaderElectionRenewDeadline, + RetryPeriod: &flagVar.LeaderElectionRetryPeriod, + Cache: cacheOptions, + }, + ) + if err != nil { + return nil, fmt.Errorf("unable to create manager: %w", err) + } + return mgr, nil +} + func addHealthChecks(mgr manager.Manager, setupLog logr.Logger) { // +kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { @@ -287,7 +303,7 @@ func scheduleMetricsCleanup(kymaMetrics *metrics.KymaMetrics, cleanupIntervalInM func setupKymaReconciler(mgr ctrl.Manager, descriptorProvider *provider.CachedDescriptorProvider, skrContextFactory remote.SkrContextProvider, event event.Event, flagVar *flags.FlagVar, options ctrlruntime.Options, skrWebhookManager *watcher.SKRWebhookManifestManager, kymaMetrics *metrics.KymaMetrics, - setupLog logr.Logger, maintenanceWindow *maintenancewindows.MaintenanceWindow, + setupLog logr.Logger, maintenanceWindow maintenancewindows.MaintenanceWindow, ) { options.RateLimiter = internal.RateLimiter(flagVar.FailureBaseDelay, flagVar.FailureMaxDelay, flagVar.RateLimiterFrequency, flagVar.RateLimiterBurst) diff --git a/config/certmanager/kustomization.yaml b/config/certmanager/kustomization.yaml index bebea5a595..34e7e5b126 100644 --- a/config/certmanager/kustomization.yaml +++ b/config/certmanager/kustomization.yaml @@ -1,5 +1,4 @@ resources: -- certificate.yaml - + - certificate.yaml configurations: -- kustomizeconfig.yaml + - kustomizeconfig.yaml diff --git a/config/control-plane/kustomization.yaml b/config/control-plane/kustomization.yaml index 40d61a3756..915be48adb 100644 --- a/config/control-plane/kustomization.yaml +++ b/config/control-plane/kustomization.yaml @@ -1,42 +1,31 @@ -# WARNING: This is a Kustomization that CANNOT run standalone -# It is meant to be used in conjunction with a control-plane deployment only and has prerequisites that -# need to be explicitly created externally in a centrally managed place (e.g. the kcp-system). -# In fact, in order to avoid conflicts, it even explicitly patches out certain configuration elements. apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization - -namePrefix: klm- #kyma-lifecycle-manager - -# Labels to add to all resources and selectors. +namePrefix: klm- commonLabels: app.kubernetes.io/instance: kcp-lifecycle-manager app.kubernetes.io/name: lifecycle-manager app.kubernetes.io/created-by: argo-cd app.kubernetes.io/part-of: kcp app.kubernetes.io/managed-by: kustomize - images: -- name: europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager - + - name: europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager resources: - ../manager - # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. - ../certmanager - components: - ../crd - - ../rbac/namespace_bindings - # [ISTIO] To enable istio, uncomment all sections with 'ISTIO'. + - ../rbac - ../istio - # [WATCHER] To enable the watcher, uncomment all the sections with [WATCHER] - ../watcher - # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix - ../webhook - # [GRAFANA] To enable grafana, uncomment all sections with 'GRAFANA'. - ../grafana - patches: - - patch: |- + - path: patches/deployment_resources.yaml + - path: patches/unique_deployment_webhook_patch.yaml + - path: patches/unique_certificate_name.yaml # Override certificate name to ensure a unique CM Cert when run with other kubebuilder operators + - target: + kind: Deployment + patch: |- - op: add path: /spec/template/spec/containers/0/args/- value: --in-kcp-mode @@ -64,64 +53,56 @@ patches: - op: add path: /spec/template/spec/containers/0/args/- value: --is-kyma-managed - target: - kind: Deployment - - patch: |- + - target: + kind: ConfigMap + name: dashboard-(overview|status|watcher|mandatory-modules) + version: v1 + patch: |- - op: add path: /metadata/labels value: {} - op: add path: /metadata/labels/grafana_dashboard value: "1" - target: - kind: ConfigMap - name: dashboard-(overview|status|watcher|mandatory-modules) - version: v1 - - path: patches/unique_manager_webhook_patch.yaml - - path: patches/adjust_resources_in_deployment.yaml - # We override the certificate name to ensure that Cert-Manager uses a unique cert in conjunction with other - # kubebuilder operators. - - path: patches/unique_certificate_name.yaml - # Note: Now as the 'patchesJson6902' is deprecated, the direct use of the 'PatchTransformer' is the only way to change a resource namespace to something different from the value configured by the global namespace transformer. transformers: -- |- - apiVersion: builtin - kind: PrefixSuffixTransformer - metadata: - name: add-klm-prefix-to-resources - prefix: klm- - fieldSpecs: - - path: subjects/name - kind: RoleBinding - - path: subjects/name - kind: ClusterRoleBinding -- |- - apiVersion: builtin - kind: NamespaceTransformer - metadata: - name: add-resources-to-kcp-system - namespace: kcp-system - unsetOnly: true - setRoleBindingSubjects: allServiceAccounts -- |- - apiVersion: builtin - kind: AnnotationsTransformer - metadata: - name: add-ca-inject-annotation - annotations: - cert-manager.io/inject-ca-from: kcp-system/klm-controller-manager-webhook-serving - fieldSpecs: - - kind: CustomResourceDefinition - path: metadata/annotations -- |- - apiVersion: builtin - kind: PatchTransformer - metadata: - name: fix-cert-dns-names - patch: '[{"op": "replace", "path": "/spec/dnsNames/0", "value": "klm-webhook-service.kcp-system.svc"}, {"op": "replace", "path": "/spec/dnsNames/1", "value": "klm-webhook-service.kcp-system.svc.cluster.local"}]' - target: - kind: Certificate - name: klm-controller-manager-webhook-serving - version: v1 - group: cert-manager.io + - |- + apiVersion: builtin + kind: PrefixSuffixTransformer + metadata: + name: add-klm-prefix-to-resources + prefix: klm- + fieldSpecs: + - path: subjects/name + kind: RoleBinding + - path: subjects/name + kind: ClusterRoleBinding + - |- + apiVersion: builtin + kind: NamespaceTransformer + metadata: + name: add-resources-to-kcp-system + namespace: kcp-system + unsetOnly: true + setRoleBindingSubjects: allServiceAccounts + - |- + apiVersion: builtin + kind: AnnotationsTransformer + metadata: + name: add-ca-inject-annotation + annotations: + cert-manager.io/inject-ca-from: kcp-system/klm-controller-manager-webhook-serving + fieldSpecs: + - kind: CustomResourceDefinition + path: metadata/annotations + - |- + apiVersion: builtin + kind: PatchTransformer + metadata: + name: fix-cert-dns-names + patch: '[{"op": "replace", "path": "/spec/dnsNames/0", "value": "klm-webhook-service.kcp-system.svc"}, {"op": "replace", "path": "/spec/dnsNames/1", "value": "klm-webhook-service.kcp-system.svc.cluster.local"}]' + target: + kind: Certificate + name: klm-controller-manager-webhook-serving + version: v1 + group: cert-manager.io diff --git a/config/control-plane/patches/adjust_resources_in_deployment.yaml b/config/control-plane/patches/deployment_resources.yaml similarity index 55% rename from config/control-plane/patches/adjust_resources_in_deployment.yaml rename to config/control-plane/patches/deployment_resources.yaml index bc1694d98f..a2d67f9f90 100644 --- a/config/control-plane/patches/adjust_resources_in_deployment.yaml +++ b/config/control-plane/patches/deployment_resources.yaml @@ -1,5 +1,3 @@ -# 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: @@ -14,4 +12,4 @@ spec: memory: 4000Mi requests: cpu: 1000m - memory: 1000Mi \ No newline at end of file + memory: 1000Mi diff --git a/config/control-plane/patches/secured_manager_auth_proxy.yaml b/config/control-plane/patches/secured_manager_auth_proxy.yaml deleted file mode 100644 index b1dd3ca9bb..0000000000 --- a/config/control-plane/patches/secured_manager_auth_proxy.yaml +++ /dev/null @@ -1,36 +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 -spec: - template: - spec: - containers: - - name: kube-rbac-proxy - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 - args: - - "--insecure-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: 512Mi - requests: - cpu: 5m - memory: 64Mi - - name: manager - args: - - "--health-probe-bind-address=:8081" - - "--metrics-bind-address=127.0.0.1:8080" - - "--leader-elect" - - "--k8s-client-qps=150" - - "--k8s-client-burst=150" - - "--max-concurrent-reconciles=20" diff --git a/config/control-plane/patches/unique_certificate_name.yaml b/config/control-plane/patches/unique_certificate_name.yaml index bf53cdf233..08c73fb4f9 100644 --- a/config/control-plane/patches/unique_certificate_name.yaml +++ b/config/control-plane/patches/unique_certificate_name.yaml @@ -3,4 +3,4 @@ kind: Certificate metadata: name: controller-manager-webhook-serving # this name should match the one appeared in kustomizeconfig.yaml spec: - secretName: klm-controller-manager-webhook # this secret will not be prefixed, since it's not managed by kustomize \ No newline at end of file + secretName: klm-controller-manager-webhook # secretName will not be prefixed, since it's not managed by kustomize diff --git a/config/control-plane/patches/unique_manager_webhook_patch.yaml b/config/control-plane/patches/unique_deployment_webhook_patch.yaml similarity index 100% rename from config/control-plane/patches/unique_manager_webhook_patch.yaml rename to config/control-plane/patches/unique_deployment_webhook_patch.yaml diff --git a/config/crd/kustomizeconfig.yaml b/config/crd/kustomizeconfig.yaml index ec5c150a9d..b7b511d07d 100644 --- a/config/crd/kustomizeconfig.yaml +++ b/config/crd/kustomizeconfig.yaml @@ -1,19 +1,17 @@ -# This file is for teaching kustomize how to substitute name and namespace reference in CRD +# Configure name and namespace reference substitution in CRDs nameReference: -- kind: Service - version: v1 - fieldSpecs: + - kind: Service + version: v1 + fieldSpecs: + - kind: CustomResourceDefinition + version: v1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/name +namespace: - kind: CustomResourceDefinition version: v1 group: apiextensions.k8s.io - path: spec/conversion/webhook/clientConfig/service/name - -namespace: -- kind: CustomResourceDefinition - version: v1 - group: apiextensions.k8s.io - path: spec/conversion/webhook/clientConfig/service/namespace - create: false - + path: spec/conversion/webhook/clientConfig/service/namespace + create: false varReference: -- path: metadata/annotations + - path: metadata/annotations diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 1dd1cb0bae..6b4f8d0091 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -1,10 +1,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization - -# Value of this field is prepended to the names of all resources namePrefix: klm- - -# Labels to add to all resources and selectors. commonLabels: app.kubernetes.io/component: lifecycle-manager.kyma-project.io app.kubernetes.io/instance: kcp-lifecycle-manager-main @@ -12,56 +8,43 @@ commonLabels: app.kubernetes.io/created-by: kustomize app.kubernetes.io/managed-by: kustomize app.kubernetes.io/part-of: manual-deployment - - patches: -- path: manager_webhook_patch.yaml - + - path: patches/deployment_webhook.yaml resources: -- ../manager -- ../certmanager -- namespace_create.yaml - + - ../manager + - ../certmanager + - namespace.yaml components: - ../crd - - ../rbac/cluster_bindings - # [ISTIO] To enable istio, uncomment all sections with 'ISTIO'. - #- ../istio - # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in - # crd/kustomization.yaml + - ../rbac - ../webhook - # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. - #- ../prometheus - # [GRAFANA] To generate configmap for provision grafana dashboard - #- ../grafana - transformers: -- |- - apiVersion: builtin - kind: NamespaceTransformer - metadata: - name: adds-resources-to-kcp-system - namespace: kcp-system - unsetOnly: true - setRoleBindingSubjects: allServiceAccounts -- |- - apiVersion: builtin - kind: AnnotationsTransformer - metadata: - name: add-ca-inject-annotation - annotations: - cert-manager.io/inject-ca-from: kcp-system/klm-controller-manager-webhook-serving - fieldSpecs: - - kind: CustomResourceDefinition - path: metadata/annotations -- |- - apiVersion: builtin - kind: PatchTransformer - metadata: - name: fix-cert-dns-names - patch: '[{"op": "replace", "path": "/spec/dnsNames/0", "value": "klm-webhook-service.kcp-system.svc"}, {"op": "replace", "path": "/spec/dnsNames/1", "value": "klm-webhook-service.kcp-system.svc.cluster.local"}]' - target: - kind: Certificate - name: klm-controller-manager-webhook-serving - version: v1 - group: cert-manager.io + - |- + apiVersion: builtin + kind: NamespaceTransformer + metadata: + name: adds-resources-to-kcp-system + namespace: kcp-system + unsetOnly: true + setRoleBindingSubjects: allServiceAccounts + - |- + apiVersion: builtin + kind: AnnotationsTransformer + metadata: + name: add-ca-inject-annotation + annotations: + cert-manager.io/inject-ca-from: kcp-system/klm-controller-manager-webhook-serving + fieldSpecs: + - kind: CustomResourceDefinition + path: metadata/annotations + - |- + apiVersion: builtin + kind: PatchTransformer + metadata: + name: fix-cert-dns-names + patch: '[{"op": "replace", "path": "/spec/dnsNames/0", "value": "klm-webhook-service.kcp-system.svc"}, {"op": "replace", "path": "/spec/dnsNames/1", "value": "klm-webhook-service.kcp-system.svc.cluster.local"}]' + target: + kind: Certificate + name: klm-controller-manager-webhook-serving + version: v1 + group: cert-manager.io diff --git a/config/default/namespace_create.yaml b/config/default/namespace.yaml similarity index 68% rename from config/default/namespace_create.yaml rename to config/default/namespace.yaml index 38c7c7022c..a33da52528 100644 --- a/config/default/namespace_create.yaml +++ b/config/default/namespace.yaml @@ -1,4 +1,4 @@ apiVersion: v1 kind: Namespace metadata: - name: kcp-system \ No newline at end of file + name: kcp-system diff --git a/config/default/manager_webhook_patch.yaml b/config/default/patches/deployment_webhook.yaml similarity index 100% rename from config/default/manager_webhook_patch.yaml rename to config/default/patches/deployment_webhook.yaml diff --git a/config/grafana/overview.json b/config/grafana/overview.json index e8bea48b09..796a2e7612 100644 --- a/config/grafana/overview.json +++ b/config/grafana/overview.json @@ -77,7 +77,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 5, "points": false, "renderer": "flot", @@ -215,7 +215,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 5, "points": false, "renderer": "flot", @@ -315,7 +315,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 5, "points": false, "renderer": "flot", @@ -596,7 +596,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 2, "points": false, "renderer": "flot", @@ -699,7 +699,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 5, "points": false, "renderer": "flot", @@ -813,7 +813,7 @@ "showThresholdMarkers": true, "text": {} }, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "targets": [ { "datasource": { @@ -1167,7 +1167,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 5, "points": false, "renderer": "flot", @@ -1277,7 +1277,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 5, "points": false, "renderer": "flot", @@ -1387,7 +1387,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 5, "points": false, "renderer": "flot", @@ -1500,7 +1500,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 5, "points": false, "renderer": "flot", @@ -1622,7 +1622,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 2, "points": false, "renderer": "flot", @@ -1730,7 +1730,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 2, "points": false, "renderer": "flot", @@ -1826,7 +1826,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 2, "points": false, "renderer": "flot", @@ -1920,7 +1920,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.29", + "pluginVersion": "7.5.35", "pointradius": 2, "points": false, "renderer": "flot", @@ -1977,6 +1977,100 @@ "align": false, "alignLevel": null } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 110 + }, + "id": 84, + "panels": [], + "title": "Maintenance Windows", + "type": "row" + }, + { + "datasource": null, + "description": "Indicates whether the KLM successfully read the maintenance policy file from the mounted ConfigMap.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "from": "", + "id": 1, + "text": "Failed", + "to": "", + "type": 1, + "value": "0" + }, + { + "from": "", + "id": 2, + "text": "Success", + "to": "", + "type": 1, + "value": "1" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 111 + }, + "id": 86, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "7.5.35", + "targets": [ + { + "exemplar": true, + "expr": "maintenance_window_config_read_success", + "format": "time_series", + "interval": "", + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Maintenance Window Configuration Read Status", + "type": "stat" } ], "refresh": "", diff --git a/config/istio/commonlabels_override.yaml b/config/istio/commonlabels_override.yaml index f11a704f31..754834e22f 100644 --- a/config/istio/commonlabels_override.yaml +++ b/config/istio/commonlabels_override.yaml @@ -1,8 +1,7 @@ # This is an extension to builtin commonLabels, # reference https://github.com/kubernetes-sigs/kustomize/blob/master/api/konfig/builtinpluginconsts/commonlabels.go - commonLabels: - path: spec/selector/matchLabels create: true version: v1beta1 - kind: AuthorizationPolicy \ No newline at end of file + kind: AuthorizationPolicy diff --git a/config/istio/ap.yaml b/config/istio/endpoints_authorization_policy.yaml similarity index 61% rename from config/istio/ap.yaml rename to config/istio/endpoints_authorization_policy.yaml index 961eb76d99..2642097ac8 100644 --- a/config/istio/ap.yaml +++ b/config/istio/endpoints_authorization_policy.yaml @@ -5,13 +5,13 @@ metadata: spec: action: ALLOW rules: - - to: - - operation: - paths: - - /metrics - - /v1* - - /convert* - - /mutate* + - to: + - operation: + paths: + - /metrics + - /v1* + - /convert* + - /mutate* selector: matchLabels: app.kubernetes.io/component: lifecycle-manager.kyma-project.io diff --git a/config/istio/kustomization.yaml b/config/istio/kustomization.yaml index 5ef5308a6f..e793b3f558 100644 --- a/config/istio/kustomization.yaml +++ b/config/istio/kustomization.yaml @@ -1,15 +1,11 @@ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component - -configurations: -- commonlabels_override.yaml - -resources: -- ap.yaml - generatorOptions: disableNameSuffixHash: true - +configurations: + - commonlabels_override.yaml +resources: + - endpoints_authorization_policy.yaml patches: - - path: patches/istio_deployment_labels.yaml - - path: patches/exclude_webhook_port.yaml + - path: patches/deployment_istio_inject.yaml + - path: patches/deployment_exclude_webhook_port.yaml diff --git a/config/istio/patches/exclude_webhook_port.yaml b/config/istio/patches/deployment_exclude_webhook_port.yaml similarity index 100% rename from config/istio/patches/exclude_webhook_port.yaml rename to config/istio/patches/deployment_exclude_webhook_port.yaml diff --git a/config/istio/patches/istio_deployment_labels.yaml b/config/istio/patches/deployment_istio_inject.yaml similarity index 100% rename from config/istio/patches/istio_deployment_labels.yaml rename to config/istio/patches/deployment_istio_inject.yaml diff --git a/config/maintenance_windows/kustomization.yaml b/config/maintenance_windows/kustomization.yaml index 1312778007..d8bd295964 100644 --- a/config/maintenance_windows/kustomization.yaml +++ b/config/maintenance_windows/kustomization.yaml @@ -1,21 +1,17 @@ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component - +generatorOptions: + disableNameSuffixHash: true configMapGenerator: - name: maintenance-config files: - policy.json - -generatorOptions: - disableNameSuffixHash: true - patches: - path: patches/volume_mount.yaml target: kind: Deployment name: klm-controller-manager namespace: kcp-system - transformers: - |- apiVersion: builtin diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 00ae86ff75..1bfbb27603 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,14 +1,11 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization - -resources: -- manager.yaml -- metrics_service.yaml - generatorOptions: disableNameSuffixHash: true - +resources: + - manager.yaml + - metrics_service.yaml images: -- name: controller - newName: europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager - newTag: latest + - name: controller + newName: europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager + newTag: latest diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 5ee4ac62a8..65943d24dd 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -44,8 +44,6 @@ spec: port: 8081 initialDelaySeconds: 5 periodSeconds: 10 - # TODO(user): Configure the resources accordingly based on the project requirements. - # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ resources: limits: memory: 1024Mi diff --git a/config/rbac/namespace_bindings/watcher_certmanager_role.yaml b/config/rbac/certmanager_role.yaml similarity index 92% rename from config/rbac/namespace_bindings/watcher_certmanager_role.yaml rename to config/rbac/certmanager_role.yaml index 05b512e6a5..cbe291686a 100644 --- a/config/rbac/namespace_bindings/watcher_certmanager_role.yaml +++ b/config/rbac/certmanager_role.yaml @@ -3,7 +3,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - name: controller-manager-watcher-certmanager + name: controller-manager-certmanager namespace: istio-system rules: - apiGroups: diff --git a/config/rbac/namespace_bindings/watcher_certmanager_role_binding.yaml b/config/rbac/certmanager_role_binding.yaml similarity index 69% rename from config/rbac/namespace_bindings/watcher_certmanager_role_binding.yaml rename to config/rbac/certmanager_role_binding.yaml index e587e35a2c..740e088df3 100644 --- a/config/rbac/namespace_bindings/watcher_certmanager_role_binding.yaml +++ b/config/rbac/certmanager_role_binding.yaml @@ -1,12 +1,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: controller-manager-watcher-certmanager + name: controller-manager-certmanager namespace: istio-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: controller-manager-watcher-certmanager + name: controller-manager-certmanager subjects: - kind: ServiceAccount name: controller-manager diff --git a/config/rbac/cluster_bindings/clusterrole_binding.yaml b/config/rbac/cluster_bindings/clusterrole_binding.yaml deleted file mode 100644 index bb7720d18e..0000000000 --- a/config/rbac/cluster_bindings/clusterrole_binding.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: controller-manager -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: controller-manager -subjects: -- kind: ServiceAccount - name: controller-manager diff --git a/config/rbac/cluster_bindings/kustomization.yaml b/config/rbac/cluster_bindings/kustomization.yaml deleted file mode 100644 index 70e3bb3228..0000000000 --- a/config/rbac/cluster_bindings/kustomization.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -components: - - ../common - -resources: - # All RBAC will be applied under this service account in - # the deployment namespace. You may comment out this resource - # if your manager will use a service account that exists at - # runtime. Be sure to update RoleBinding and ClusterRoleBinding - # subjects if changing service account names. - - clusterrole_binding.yaml - - metrics_clusterrole_binding.yaml diff --git a/config/rbac/cluster_bindings/metrics_clusterrole_binding.yaml b/config/rbac/cluster_bindings/metrics_clusterrole_binding.yaml deleted file mode 100644 index 89fdcd6dc8..0000000000 --- a/config/rbac/cluster_bindings/metrics_clusterrole_binding.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: controller-manager-metrics -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: controller-manager-metrics -subjects: - - kind: ServiceAccount - name: controller-manager diff --git a/config/rbac/common/crd_clusterrole.yaml b/config/rbac/common/crd_clusterrole.yaml deleted file mode 100644 index e483d9702c..0000000000 --- a/config/rbac/common/crd_clusterrole.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: controller-manager-crds -rules: -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - list - - watch -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions/status - verbs: - - update diff --git a/config/rbac/common/kustomization.yaml b/config/rbac/common/kustomization.yaml deleted file mode 100644 index e6453c1ea1..0000000000 --- a/config/rbac/common/kustomization.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -resources: - # All RBAC will be applied under this service account in - # the deployment namespace. You may comment out this resource - # if your manager will use a service account that exists at - # runtime. Be sure to update RoleBinding and ClusterRoleBinding - # subjects if changing service account names. - - service_account.yaml - - role.yaml - - leader_election_role.yaml - - leader_election_role_binding.yaml - - crd_clusterrole.yaml - - crd_clusterrole_binding.yaml \ No newline at end of file diff --git a/config/rbac/common/leader_election_role.yaml b/config/rbac/common/leader_election_role.yaml deleted file mode 100644 index cb31f01120..0000000000 --- a/config/rbac/common/leader_election_role.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# permissions to do leader election. -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: controller-manager-leader-election -rules: -- apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - events - verbs: - - create - - patch diff --git a/config/rbac/common/role.yaml b/config/rbac/common/role.yaml deleted file mode 100644 index f56a3db68c..0000000000 --- a/config/rbac/common/role.yaml +++ /dev/null @@ -1,203 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: controller-manager -rules: -- apiGroups: - - "" - resources: - - configmaps - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - events - verbs: - - create - - get - - list - - patch - - watch -- apiGroups: - - "" - resources: - - secrets - verbs: - - create - - delete - - get - - list - - update - - watch -- apiGroups: - - "" - resources: - - services - verbs: - - get - - list - - watch -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - list - - watch -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions/status - verbs: - - update -- apiGroups: - - cert-manager.io - resources: - - certificates - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - cert-manager.io - resources: - - issuers - verbs: - - get - - list - - watch -- apiGroups: - - networking.istio.io - resources: - - gateways - verbs: - - get - - list -- apiGroups: - - networking.istio.io - resources: - - virtualservices - verbs: - - create - - delete - - get - - list - - update -- apiGroups: - - operator.kyma-project.io - resources: - - kymas - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - operator.kyma-project.io - resources: - - kymas/finalizers - verbs: - - update -- apiGroups: - - operator.kyma-project.io - resources: - - kymas/status - verbs: - - get - - patch - - update - - watch -- apiGroups: - - operator.kyma-project.io - resources: - - manifests - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - operator.kyma-project.io - resources: - - manifests/finalizers - verbs: - - update -- apiGroups: - - operator.kyma-project.io - resources: - - manifests/status - verbs: - - get - - patch - - update -- apiGroups: - - operator.kyma-project.io - resources: - - modulereleasemetas - verbs: - - get - - list - - watch -- apiGroups: - - operator.kyma-project.io - resources: - - moduletemplates - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - operator.kyma-project.io - resources: - - moduletemplates/finalizers - verbs: - - update -- apiGroups: - - operator.kyma-project.io - resources: - - watchers - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - operator.kyma-project.io - resources: - - watchers/finalizers - verbs: - - update -- apiGroups: - - operator.kyma-project.io - resources: - - watchers/status - verbs: - - get - - patch - - update diff --git a/config/rbac/crd_cluster_role.yaml b/config/rbac/crd_cluster_role.yaml new file mode 100644 index 0000000000..fca7d63863 --- /dev/null +++ b/config/rbac/crd_cluster_role.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: controller-manager-crds +rules: + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions/status + verbs: + - update diff --git a/config/rbac/common/crd_clusterrole_binding.yaml b/config/rbac/crd_cluster_role_binding.yaml similarity index 100% rename from config/rbac/common/crd_clusterrole_binding.yaml rename to config/rbac/crd_cluster_role_binding.yaml diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml new file mode 100644 index 0000000000..63394c4b96 --- /dev/null +++ b/config/rbac/kustomization.yaml @@ -0,0 +1,12 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component +resources: + - service_account.yaml + - manager_role.yaml + - manager_role_binding.yaml + - leader_election_role.yaml + - leader_election_role_binding.yaml + - crd_cluster_role.yaml + - crd_cluster_role_binding.yaml + - certmanager_role.yaml + - certmanager_role_binding.yaml diff --git a/config/rbac/leader_election_role.yaml b/config/rbac/leader_election_role.yaml new file mode 100644 index 0000000000..ffa61e3756 --- /dev/null +++ b/config/rbac/leader_election_role.yaml @@ -0,0 +1,37 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: controller-manager-leader-election +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/config/rbac/common/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml similarity index 100% rename from config/rbac/common/leader_election_role_binding.yaml rename to config/rbac/leader_election_role_binding.yaml diff --git a/config/rbac/manager_role.yaml b/config/rbac/manager_role.yaml new file mode 100644 index 0000000000..8ad0ad7d7d --- /dev/null +++ b/config/rbac/manager_role.yaml @@ -0,0 +1,180 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: controller-manager + namespace: kcp-system +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - list + - patch + - watch + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - update + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - cert-manager.io + resources: + - certificates + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - cert-manager.io + resources: + - issuers + verbs: + - get + - list + - watch + - apiGroups: + - networking.istio.io + resources: + - gateways + verbs: + - get + - list + - apiGroups: + - networking.istio.io + resources: + - virtualservices + verbs: + - create + - delete + - get + - list + - update + - apiGroups: + - operator.kyma-project.io + resources: + - kymas + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - operator.kyma-project.io + resources: + - kymas/finalizers + verbs: + - update + - apiGroups: + - operator.kyma-project.io + resources: + - kymas/status + verbs: + - get + - patch + - update + - watch + - apiGroups: + - operator.kyma-project.io + resources: + - manifests + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - operator.kyma-project.io + resources: + - manifests/finalizers + verbs: + - update + - apiGroups: + - operator.kyma-project.io + resources: + - manifests/status + verbs: + - get + - patch + - update + - apiGroups: + - operator.kyma-project.io + resources: + - modulereleasemetas + verbs: + - get + - list + - watch + - apiGroups: + - operator.kyma-project.io + resources: + - moduletemplates + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - operator.kyma-project.io + resources: + - moduletemplates/finalizers + verbs: + - update + - apiGroups: + - operator.kyma-project.io + resources: + - watchers + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - operator.kyma-project.io + resources: + - watchers/finalizers + verbs: + - update + - apiGroups: + - operator.kyma-project.io + resources: + - watchers/status + verbs: + - get + - patch + - update diff --git a/config/rbac/namespace_bindings/role_binding.yaml b/config/rbac/manager_role_binding.yaml similarity index 92% rename from config/rbac/namespace_bindings/role_binding.yaml rename to config/rbac/manager_role_binding.yaml index ca76ff8d92..705eb370e2 100644 --- a/config/rbac/namespace_bindings/role_binding.yaml +++ b/config/rbac/manager_role_binding.yaml @@ -5,7 +5,7 @@ metadata: namespace: kcp-system roleRef: apiGroup: rbac.authorization.k8s.io - kind: ClusterRole + kind: Role name: controller-manager subjects: - kind: ServiceAccount diff --git a/config/rbac/namespace_bindings/istio_namespace_role.yaml b/config/rbac/namespace_bindings/istio_namespace_role.yaml deleted file mode 100644 index 88a81257d1..0000000000 --- a/config/rbac/namespace_bindings/istio_namespace_role.yaml +++ /dev/null @@ -1,34 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: manager-role-istio-namespace - namespace: istio-system -rules: -- apiGroups: - - "" - resources: - - secrets - verbs: - - list - - watch - - create - - delete -- apiGroups: - - cert-manager.io - resources: - - certificates - verbs: - - patch - - list - - watch - - get - - create - - delete -- apiGroups: - - cert-manager.io - resources: - - issuers - verbs: - - list - - watch diff --git a/config/rbac/namespace_bindings/istio_namespace_role_binding.yaml b/config/rbac/namespace_bindings/istio_namespace_role_binding.yaml deleted file mode 100644 index 0f5dd49c78..0000000000 --- a/config/rbac/namespace_bindings/istio_namespace_role_binding.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: manager-rolebinding-istio-namespace - namespace: istio-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: manager-role-istio-namespace -subjects: - - kind: ServiceAccount - name: controller-manager \ No newline at end of file diff --git a/config/rbac/namespace_bindings/kustomization.yaml b/config/rbac/namespace_bindings/kustomization.yaml deleted file mode 100644 index 8e9a9d4f54..0000000000 --- a/config/rbac/namespace_bindings/kustomization.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -components: - - ../common - -resources: - # All RBAC will be applied under this service account in - # the deployment namespace. You may comment out this resource - # if your manager will use a service account that exists at - # runtime. Be sure to update RoleBinding and ClusterRoleBinding - # subjects if changing service account names. - - role_binding.yaml - # Comment the following to disable manifest integration - - watcher_certmanager_role.yaml - - watcher_certmanager_role_binding.yaml diff --git a/config/rbac/namespace_bindings/remote_namespace_role.yaml b/config/rbac/namespace_bindings/remote_namespace_role.yaml deleted file mode 100644 index 4c8e2cc1fc..0000000000 --- a/config/rbac/namespace_bindings/remote_namespace_role.yaml +++ /dev/null @@ -1,42 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: manager-role-remote-namespace - namespace: kyma-system -rules: -- apiGroups: - - operator.kyma-project.io - resources: - - kymas - verbs: - - list - - watch - - delete - - get - - create - - patch - - update -- apiGroups: - - operator.kyma-project.io - resources: - - kymas/finalizers - verbs: - - update -- apiGroups: - - operator.kyma-project.io - resources: - - kymas/status - verbs: - - get - - patch - - update - - watch -- apiGroups: - - operator.kyma-project.io - resources: - - moduletemplates - verbs: - - list - - watch - - delete \ No newline at end of file diff --git a/config/rbac/namespace_bindings/remote_namespace_role_binding.yaml b/config/rbac/namespace_bindings/remote_namespace_role_binding.yaml deleted file mode 100644 index 23c42d6610..0000000000 --- a/config/rbac/namespace_bindings/remote_namespace_role_binding.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: manager-rolebinding-remote-namespace - namespace: kyma-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: manager-role-remote-namespace -subjects: - - kind: ServiceAccount - name: controller-manager \ No newline at end of file diff --git a/config/rbac/common/service_account.yaml b/config/rbac/service_account.yaml similarity index 100% rename from config/rbac/common/service_account.yaml rename to config/rbac/service_account.yaml diff --git a/config/watcher/certificate_setup.yaml b/config/watcher/certificate.yaml similarity index 99% rename from config/watcher/certificate_setup.yaml rename to config/watcher/certificate.yaml index 256ee49e66..679c73f78b 100644 --- a/config/watcher/certificate_setup.yaml +++ b/config/watcher/certificate.yaml @@ -1,7 +1,6 @@ # 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: ClusterIssuer metadata: diff --git a/config/watcher/gateway.yaml b/config/watcher/gateway.yaml index 5eb8034307..ca12fba606 100644 --- a/config/watcher/gateway.yaml +++ b/config/watcher/gateway.yaml @@ -1,4 +1,4 @@ -# Use this Gateway for setup with watcher enabled if there is no istio gateway configured +# Use this Gateway for setup with enabled watcher if there is no istio gateway configured apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: diff --git a/config/watcher/kustomization.yaml b/config/watcher/kustomization.yaml index dc72ac98d9..5acb2daed5 100644 --- a/config/watcher/kustomization.yaml +++ b/config/watcher/kustomization.yaml @@ -1,15 +1,15 @@ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component - -resources: -- operator_v1beta2_watcher.yaml -- gateway.yaml -- certificate_setup.yaml generatorOptions: disableNameSuffixHash: true - +resources: + - certificate.yaml + - gateway.yaml + - kyma_watcher.yaml patches: - - patch: |- + - target: + kind: Deployment + patch: |- - op: add path: /spec/template/spec/containers/0/args/- value: --enable-kcp-watcher @@ -18,12 +18,10 @@ patches: value: --skr-watcher-path=/skr-webhook - op: add path: /spec/template/spec/containers/0/args/- - value: --skr-watcher-image-tag=1.1.10 + value: --skr-watcher-image-tag=1.1.11 - op: add path: /spec/template/spec/containers/0/args/- value: --skr-watcher-image-registry=europe-docker.pkg.dev/kyma-project/prod - op: add path: /spec/template/spec/containers/0/args/- value: --enable-domain-name-pinning=true - target: - kind: Deployment diff --git a/config/watcher/operator_v1beta2_watcher.yaml b/config/watcher/kyma_watcher.yaml similarity index 100% rename from config/watcher/operator_v1beta2_watcher.yaml rename to config/watcher/kyma_watcher.yaml diff --git a/config/watcher_local_test/kustomization.yaml b/config/watcher_local_test/kustomization.yaml index 62a0c27f78..bd53c5aa3f 100644 --- a/config/watcher_local_test/kustomization.yaml +++ b/config/watcher_local_test/kustomization.yaml @@ -1,91 +1,79 @@ -# The main purpose of this dedicated kustomization is to have different configuration for testing the watcher locally. -# Unlike the default setup, it enables the ability to configure additional components -# that we do not want in the default configuration (e.g. vendor-specific gateway implementation) +# Configuration for testing the watcher locally. +# Enables the ability to configure additional components, +# that we do not want in the default configuration (e.g. vendor-specific gateway implementation), # but are necessary for testing the watcher on locally provisioned clusters using k3d. +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +generatorOptions: + disableNameSuffixHash: true resources: -- ../control-plane -# In control-plane we expect a kcp-system and kyma-system namespace to be already present, thus for testing we need to create it -- patches/namespace_create.yaml - -# [WATCHER] To enable the watcher, uncomment all the sections with [WATCHER] -# [ISTIO] To enable istio, uncomment all sections with 'ISTIO'. + - namespace.yaml + - ../control-plane components: - ../istio -# [Maintenance Windows] To enable the maintenance windows policy, uncomment the component below -# - ../maintenance_windows - - -generatorOptions: - disableNameSuffixHash: true - -# Patches enable the local testing mode for the KLM -# and sets the namespace for the watcher resources to `kcp-system`. -# When deployed on KCP it will be set by the default kustomize. + - ../maintenance_windows patches: -- path: patches/adjust_resources_for_local_setup.yaml -- patch: |- - - op: add - path: /spec/template/spec/containers/0/args/- - value: --kyma-requeue-success-interval=20s - - op: add - path: /spec/template/spec/containers/0/args/- - value: --manifest-requeue-success-interval=5s - - op: add - path: /spec/template/spec/containers/0/args/- - value: --log-level=9 - - op: add - path: /spec/template/spec/containers/0/args/- - value: --additional-dns-names=localhost,127.0.0.1,host.k3d.internal - - op: add - path: /spec/template/spec/containers/0/args/- - value: --listener-port-overwrite=9443 - - op: add - path: /spec/template/spec/containers/0/args/- - value: --leader-election-lease-duration=20s - - op: add - path: /spec/template/spec/containers/0/args/- - value: --leader-election-renew-deadline=15s - - op: add - path: /spec/template/spec/containers/0/args/- - value: --leader-election-retry-period=3s - - op: replace - path: /spec/template/spec/containers/0/imagePullPolicy - value: Always - target: - kind: Deployment -- patch: |- - - op: replace - path: /metadata/namespace - value: kcp-system - target: - group: security.istio.io - version: v1beta1 - kind: AuthorizationPolicy - name: controller-manager -- patch: |- - - op: replace - path: /spec/servers/0/hosts/0 - value: "host.k3d.internal" - target: - group: networking.istio.io - version: v1beta1 - kind: Gateway - name: watcher -- patch: |- - - op: replace - path: /spec/dnsNames/0 - value: "localhost" - - op: add - path: /spec/dnsNames/1 - value: "host.k3d.internal" - - op: add - path: /spec/dnsNames/2 - value: "skr.cluster.local" - target: - group: cert-manager.io - version: v1 - kind: Certificate - name: watcher-serving - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization + - path: patches/deployment_resources.yaml + - target: + kind: Deployment + patch: |- + - op: add + path: /spec/template/spec/containers/0/args/- + value: --kyma-requeue-success-interval=20s + - op: add + path: /spec/template/spec/containers/0/args/- + value: --manifest-requeue-success-interval=5s + - op: add + path: /spec/template/spec/containers/0/args/- + value: --log-level=9 + - op: add + path: /spec/template/spec/containers/0/args/- + value: --additional-dns-names=localhost,127.0.0.1,host.k3d.internal + - op: add + path: /spec/template/spec/containers/0/args/- + value: --listener-port-overwrite=9443 + - op: add + path: /spec/template/spec/containers/0/args/- + value: --leader-election-lease-duration=20s + - op: add + path: /spec/template/spec/containers/0/args/- + value: --leader-election-renew-deadline=15s + - op: add + path: /spec/template/spec/containers/0/args/- + value: --leader-election-retry-period=3s + - op: replace + path: /spec/template/spec/containers/0/imagePullPolicy + value: Always + - target: + group: security.istio.io + version: v1beta1 + kind: AuthorizationPolicy + name: controller-manager + patch: |- + - op: replace + path: /metadata/namespace + value: kcp-system + - target: + group: networking.istio.io + version: v1beta1 + kind: Gateway + name: watcher + patch: |- + - op: replace + path: /spec/servers/0/hosts/0 + value: "host.k3d.internal" + - target: + group: cert-manager.io + version: v1 + kind: Certificate + name: watcher-serving + patch: |- + - op: replace + path: /spec/dnsNames/0 + value: "localhost" + - op: add + path: /spec/dnsNames/1 + value: "host.k3d.internal" + - op: add + path: /spec/dnsNames/2 + value: "skr.cluster.local" diff --git a/config/watcher_local_test/namespace.yaml b/config/watcher_local_test/namespace.yaml new file mode 100644 index 0000000000..a33da52528 --- /dev/null +++ b/config/watcher_local_test/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: kcp-system diff --git a/config/watcher_local_test/patches/adjust_resources_for_local_setup.yaml b/config/watcher_local_test/patches/deployment_resources.yaml similarity index 90% rename from config/watcher_local_test/patches/adjust_resources_for_local_setup.yaml rename to config/watcher_local_test/patches/deployment_resources.yaml index 013818ff9b..0b2431abec 100644 --- a/config/watcher_local_test/patches/adjust_resources_for_local_setup.yaml +++ b/config/watcher_local_test/patches/deployment_resources.yaml @@ -13,4 +13,4 @@ spec: memory: 400Mi requests: cpu: 100m - memory: 100Mi \ No newline at end of file + memory: 100Mi diff --git a/config/watcher_local_test/patches/namespace_create.yaml b/config/watcher_local_test/patches/namespace_create.yaml deleted file mode 100644 index 45a073e162..0000000000 --- a/config/watcher_local_test/patches/namespace_create.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: kcp-system ---- -apiVersion: v1 -kind: Namespace -metadata: - name: kyma-system \ No newline at end of file diff --git a/config/webhook/kustomization.yaml b/config/webhook/kustomization.yaml index 4372090bfa..930b03ca77 100644 --- a/config/webhook/kustomization.yaml +++ b/config/webhook/kustomization.yaml @@ -1,16 +1,13 @@ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component - resources: - service.yaml - configurations: - kustomizeconfig.yaml - patches: - - patch: |- + - target: + kind: Deployment + patch: |- - op: add path: /spec/template/spec/containers/0/args/- value: --enable-webhooks=true - target: - kind: Deployment \ No newline at end of file diff --git a/go.mod b/go.mod index a3cdc8725f..58c1f22bf2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/kyma-project/lifecycle-manager -go 1.23.5 +go 1.23.6 replace ( github.com/kyma-project/lifecycle-manager/api => ./api @@ -9,7 +9,7 @@ replace ( require ( github.com/Masterminds/semver/v3 v3.3.1 - github.com/cert-manager/cert-manager v1.16.3 + github.com/cert-manager/cert-manager v1.17.1 github.com/go-logr/logr v1.4.2 github.com/go-logr/zapr v1.3.0 github.com/golang/mock v1.6.0 @@ -21,38 +21,39 @@ require ( github.com/kyma-project/runtime-watcher/listener v0.0.0-20240502124257-9d96561ef070 github.com/onsi/ginkgo/v2 v2.22.2 github.com/onsi/gomega v1.36.2 - github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/client_golang v1.21.0 github.com/stretchr/testify v1.10.0 go.uber.org/zap v1.27.0 - golang.org/x/sync v0.10.0 - golang.org/x/time v0.9.0 - k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - ocm.software/ocm v0.19.1 - sigs.k8s.io/controller-runtime v0.20.1 + golang.org/x/sync v0.11.0 + golang.org/x/time v0.10.0 + k8s.io/utils v0.0.0-20241210054802-24370beab758 + ocm.software/ocm v0.20.1 + sigs.k8s.io/controller-runtime v0.20.2 sigs.k8s.io/yaml v1.4.0 ) require ( - istio.io/api v1.24.2 - istio.io/client-go v1.24.2 + istio.io/api v1.24.3 + istio.io/client-go v1.24.3 ) require ( github.com/go-co-op/gocron v1.37.0 github.com/kyma-project/template-operator/api v0.0.0-20240404131948-52c84f14e73c github.com/prometheus/client_model v0.6.1 - k8s.io/api v0.32.1 - k8s.io/apiextensions-apiserver v0.32.1 - k8s.io/apimachinery v0.32.1 - k8s.io/cli-runtime v0.32.1 - k8s.io/client-go v0.32.1 - k8s.io/kubectl v0.32.1 + k8s.io/api v0.32.2 + k8s.io/apiextensions-apiserver v0.32.2 + k8s.io/apimachinery v0.32.2 + k8s.io/cli-runtime v0.32.2 + k8s.io/client-go v0.32.2 + k8s.io/kubectl v0.32.2 ) require ( - cloud.google.com/go/auth v0.10.2 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect + cloud.google.com/go/auth v0.13.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect cloud.google.com/go/compute/metadata v0.6.0 // indirect + dario.cat/mergo v1.0.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.15.2 // indirect @@ -66,8 +67,9 @@ require ( github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.0.0 // indirect + github.com/ProtonMail/go-crypto v1.1.3 // indirect github.com/ThalesIgnite/crypto11 v1.2.5 // indirect github.com/a8m/envsubst v1.4.2 // indirect github.com/alecthomas/participle/v2 v2.1.1 // indirect @@ -84,26 +86,26 @@ require ( github.com/alibabacloud-go/tea-xml v1.1.3 // indirect github.com/aliyun/credentials-go v1.3.10 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2 v1.32.5 // indirect + github.com/aws/aws-sdk-go-v2 v1.33.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect - github.com/aws/aws-sdk-go-v2/config v1.28.5 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.40 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect + github.com/aws/aws-sdk-go-v2/config v1.29.1 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.54 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.52 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24 // indirect - github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.28 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.38.6 // indirect github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.27.2 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.68.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.9 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.73.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.11 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.9 // indirect github.com/aws/smithy-go v1.22.1 // indirect github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20241009180534-e718692eec62 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -115,23 +117,25 @@ require ( github.com/buildkite/roko v1.2.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chai2010/gettext-go v1.0.3 // indirect + github.com/chainguard-dev/git-urls v1.0.2 // indirect github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/cloudflare/cfssl v1.6.5 // indirect github.com/cloudflare/circl v1.5.0 // indirect github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect - github.com/containerd/containerd v1.7.24 // indirect + github.com/containerd/containerd v1.7.25 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect - github.com/containers/image/v5 v5.33.0 // indirect + github.com/containers/image/v5 v5.33.1 // indirect github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect github.com/containers/ocicrypt v1.2.0 // indirect - github.com/containers/storage v1.56.0 // indirect - github.com/coreos/go-oidc/v3 v3.11.0 // indirect + github.com/containers/storage v1.56.1 // indirect + github.com/coreos/go-oidc/v3 v3.12.0 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect - github.com/cyphar/filepath-securejoin v0.3.4 // indirect + github.com/cyphar/filepath-securejoin v0.3.6 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect @@ -147,17 +151,23 @@ require ( github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/elliotchance/orderedmap v1.6.0 // indirect + github.com/elliotchance/orderedmap v1.7.1 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/evanphx/json-patch v5.9.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-chi/chi v4.1.2+incompatible // indirect github.com/go-errors/errors v1.5.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.6.2 // indirect + github.com/go-git/go-git/v5 v5.13.1 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -174,8 +184,8 @@ require ( github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-test/deep v1.1.1 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/goccy/go-json v0.10.3 // indirect - github.com/goccy/go-yaml v1.13.0 // indirect + github.com/goccy/go-json v0.10.4 // indirect + github.com/goccy/go-yaml v1.13.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -183,7 +193,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/certificate-transparency-go v1.2.1 // indirect - github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect + github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-github/v45 v45.2.0 // indirect github.com/google/go-github/v55 v55.0.0 // indirect @@ -194,12 +204,15 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.14.0 // indirect + github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/gowebpki/jcs v1.0.1 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect @@ -207,18 +220,21 @@ require ( github.com/hashicorp/vault-client-go v0.4.3 // indirect github.com/in-toto/in-toto-golang v0.9.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect github.com/jinzhu/copier v0.4.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/pgzip v1.2.6 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/letsencrypt/boulder v0.0.0-20241010192615-6692160cedfa // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/mailru/easyjson v0.7.7 // indirect + github.com/magiconair/properties v1.8.9 // indirect + github.com/mailru/easyjson v0.9.0 // indirect github.com/mandelsoft/filepath v0.0.0-20240223090642-3e2777258aa3 // indirect github.com/mandelsoft/goutils v0.0.0-20241005173814-114fa825bbdc // indirect github.com/mandelsoft/logging v0.0.0-20240618075559-fdca28a87b0a // indirect @@ -227,13 +243,15 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect - github.com/mikefarah/yq/v4 v4.44.5 // indirect + github.com/mikefarah/yq/v4 v4.45.1 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect + github.com/moby/spdystream v0.5.0 // indirect github.com/moby/sys/capability v0.3.0 // indirect github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/sequential v0.6.0 // indirect @@ -244,6 +262,7 @@ require ( github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/mozillazg/docker-credential-acr-helper v0.4.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/oleiade/reflections v1.1.0 // indirect @@ -252,29 +271,32 @@ require ( github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pborman/uuid v1.2.1 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/redis/go-redis/v9 v9.7.0 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.6.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sassoftware/relic v7.2.1+incompatible // indirect - github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect + github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect github.com/segmentio/ksuid v1.0.4 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/shibumi/go-pathspec v1.3.0 // indirect github.com/sigstore/cosign/v2 v2.4.1 // indirect github.com/sigstore/fulcio v1.6.5 // indirect - github.com/sigstore/protobuf-specs v0.3.2 // indirect - github.com/sigstore/rekor v1.3.7 // indirect - github.com/sigstore/sigstore v1.8.10 // indirect + github.com/sigstore/protobuf-specs v0.3.3 // indirect + github.com/sigstore/rekor v1.3.8 // indirect + github.com/sigstore/sigstore v1.8.12 // indirect github.com/sigstore/timestamp-authority v1.2.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/skeema/knownhosts v1.3.0 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect @@ -300,6 +322,7 @@ require ( github.com/vbatts/tar-split v0.11.6 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/go-gitlab v0.112.0 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -307,23 +330,22 @@ require ( github.com/yuin/gopher-lua v1.1.1 // indirect github.com/zeebo/errs v1.4.0 // indirect go.mongodb.org/mongo-driver v1.17.1 // indirect - go.opencensus.io v0.24.0 // 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.33.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect go.opentelemetry.io/otel/metric v1.33.0 // indirect go.opentelemetry.io/otel/sdk v1.33.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/otel/trace v1.33.0 // indirect - go.opentelemetry.io/proto/otlp v1.3.1 // indirect - go.step.sm/crypto v0.54.2 // indirect + go.opentelemetry.io/proto/otlp v1.4.0 // indirect + go.step.sm/crypto v0.56.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.32.0 // indirect - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect + golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect golang.org/x/mod v0.22.0 // indirect golang.org/x/net v0.34.0 // indirect golang.org/x/oauth2 v0.25.0 // indirect @@ -332,26 +354,28 @@ require ( golang.org/x/text v0.21.0 // indirect golang.org/x/tools v0.29.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/api v0.206.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/grpc v1.68.0 // indirect + google.golang.org/api v0.216.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect + google.golang.org/grpc v1.69.4 // indirect google.golang.org/protobuf v1.36.3 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - helm.sh/helm/v3 v3.16.3 // indirect - k8s.io/component-base v0.32.1 // indirect + helm.sh/helm/v3 v3.17.0 // indirect + k8s.io/component-base v0.32.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect oras.land/oras-go v1.2.6 // indirect + oras.land/oras-go/v2 v2.5.0 // indirect sigs.k8s.io/gateway-api v1.1.0 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/kustomize/api v0.18.0 // indirect sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect sigs.k8s.io/release-utils v0.8.5 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect ) diff --git a/go.sum b/go.sum index e844eebfba..ed4d05b166 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,24 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/auth v0.10.2 h1:oKF7rgBfSHdp/kuhXtqU/tNDr0mZqhYbEh+6SiqzkKo= -cloud.google.com/go/auth v0.10.2/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= -cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk= -cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= +cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= +cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= +cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= -cloud.google.com/go/kms v1.20.1 h1:og29Wv59uf2FVaZlesaiDAqHFzHaoUyHI3HYp9VUHVg= -cloud.google.com/go/kms v1.20.1/go.mod h1:LywpNiVCvzYNJWS9JUcGJSVTNSwPwi0vBAotzDqn2nc= +cloud.google.com/go/kms v1.20.4 h1:CJ0hMpOg1ANN9tx/a/GPJ+Uxudy8k6f3fvGFuTHiE5A= +cloud.google.com/go/kms v1.20.4/go.mod h1:gPLsp1r4FblUgBYPOcvI/bUPpdMg2Jm1ZVKU4tQUfcc= cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2 h1:BnG6pr9TTr6CYlrJznYUDj6V7xldD1W+1iXPum0wT/w= cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2/go.mod h1:pK23AUVXuNzzTpfMCA06sxZGeVQ/75FdVtW249de9Uo= cuelang.org/go v0.9.2 h1:pfNiry2PdRBr02G/aKm5k2vhzmqbAOoaB4WurmEbWvs= cuelang.org/go v0.9.2/go.mod h1:qpAYsLOf7gTM1YdEg6cxh553uZ4q9ZDWlPbtZr9q1Wk= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= @@ -33,10 +35,10 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxr github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 h1:DRiANoJTiW6obBQe3SqZizkuV1PEgfiiGivmVocDy64= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0/go.mod h1:qLIye2hwb/ZouqhpSD9Zn3SJipvpEnz1Ywl3VUk9Y0s= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.0 h1:7rKG7UmnrxX4N53TFhkYqjc+kVUZuw0fL8I3Fh+Ld9E= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.0/go.mod h1:Wjo+24QJVhhl/L7jy6w9yzFF2yDOf3cKECAa8ecf9vE= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0 h1:eXnN9kaS8TiDwXjoie3hMRLuwdUBUMW9KRgOqB3mCaw= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.0/go.mod h1:XIpam8wumeZ5rVMuhdDQLMfIPDf1WO3IzrCRO3e3e3o= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -61,21 +63,24 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.1 h1:gUDtaZk8heteyfdmv+pcfHvhR9llnh7c7GMwZ8RVG04= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4= github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= -github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= +github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= @@ -143,52 +148,56 @@ github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6q github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM= github.com/aliyun/credentials-go v1.3.10 h1:45Xxrae/evfzQL9V10zL3xX31eqgLWEaIdCoPipOEQA= github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo= -github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2 v1.33.0 h1:Evgm4DI9imD81V0WwD+TN4DCwjUMdc94TrduMLbgZJs= +github.com/aws/aws-sdk-go-v2 v1.33.0/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc= -github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0= -github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o= -github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg= -github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.40 h1:CbalQNEYQljzAJ+3beY8FQBShdLNLpJzHL4h/5LSFMc= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.40/go.mod h1:1iYVr/urNWuZ7WZ1829FSE7RRTaXvzFdwrEQV8Z40cE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg= +github.com/aws/aws-sdk-go-v2/config v1.29.1 h1:JZhGawAyZ/EuJeBtbQYnaoftczcb2drR2Iq36Wgz4sQ= +github.com/aws/aws-sdk-go-v2/config v1.29.1/go.mod h1:7bR2YD5euaxBhzt2y/oDkt3uNRb6tjFp98GlTFueRwk= +github.com/aws/aws-sdk-go-v2/credentials v1.17.54 h1:4UmqeOqJPvdvASZWrKlhzpRahAulBfyTJQUaYy4+hEI= +github.com/aws/aws-sdk-go-v2/credentials v1.17.54/go.mod h1:RTdfo0P0hbbTxIhmQrOsC/PquBZGabEPnCaxxKRPSnI= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24 h1:5grmdTdMsovn9kPZPI23Hhvp0ZyNm5cRO+IZFIYiAfw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24/go.mod h1:zqi7TVKTswH3Ozq28PkmBmgzG1tona7mo9G2IJg4Cis= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.52 h1:6kI83R98XOnnyzHv9g9KTYXFawMyeQq8NeEERWMAwJk= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.52/go.mod h1:Juj7unpf3CIrWpEyJZhRJ6rJl9IYX7Hd8HOlwaZq/LE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28 h1:igORFSiH3bfq4lxKFkTSYDhJEUCYo6C8VKiWJjYwQuQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28/go.mod h1:3So8EA/aAYm36L7XIvCVwLa0s5N0P7o2b1oqnx/2R4g= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28 h1:1mOW9zAUMhTSrMDssEHS/ajx8JcAj/IcftzcmNlmVLI= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28/go.mod h1:kGlXVIWDfvt2Ox5zEaNglmq0hXPHgQFNMix33Tw22jA= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24 h1:JX70yGKLj25+lMC5Yyh8wBtvB01GDilyRuJvXJ4piD0= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24/go.mod h1:+Ln60j9SUTD0LEwnhEB0Xhg61DHqplBrbZpLgyjoEHg= -github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 h1:zg+3FGHA0PBs0KM25qE/rOf2o5zsjNa1g/Qq83+SDI0= -github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6/go.mod h1:ZSq54Z9SIsOTf1Efwgw1msilSs4XVEfVQiP9nYVnKpM= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.28 h1:7kpeALOUeThs2kEjlAxlADAVfxKmkYAedlpZ3kdoSJ4= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.28/go.mod h1:pyaOYEdp1MJWgtXLy6q80r3DhsVdOIOZNB9hdTcJIvI= +github.com/aws/aws-sdk-go-v2/service/ecr v1.38.6 h1:0aXmaDSg7/UN5gX+gG2ecw9DAnoEcE3nQfhhcUMPlBA= +github.com/aws/aws-sdk-go-v2/service/ecr v1.38.6/go.mod h1:fKviTTmQsNmJIdfc3m4tKAhBQQjeivCegNxvATPINFg= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.27.2 h1:Zru9Iy2JPM5+uRnFnoqeOZzi8JIVIHJ0ua6JdeDHcyg= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.27.2/go.mod h1:PtQC3XjutCYFCn1+i8+wtpDaXvEK+vXF2gyLIKAmh4A= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5 h1:gvZOjQKPxFXy1ft3QnEyXmT+IqneM9QAUWlM3r0mfqw= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5/go.mod h1:DLWnfvIcm9IET/mmjdxeXbBKmTCm0ZB8p1za9BVteM8= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5 h1:P1doBzv5VEg1ONxnJss1Kh5ZG/ewoIE4MQtKKc6Crgg= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5/go.mod h1:NOP+euMW7W3Ukt28tAxPuoWao4rhhqJD3QEBk7oCg7w= -github.com/aws/aws-sdk-go-v2/service/kms v1.37.5 h1:5dQJ6Q5QrQOqZxXjSbRXukBqU8Pgu6Ro6Qqtyd8yiz4= -github.com/aws/aws-sdk-go-v2/service/kms v1.37.5/go.mod h1:A9vfQcNHVBCE7ZZN6H+UUJpXtbH26Vv6L7Zhk5nIJAY= -github.com/aws/aws-sdk-go-v2/service/s3 v1.68.0 h1:bFpcqdwtAEsgpZXvkTxIThFQx/EM0oV6kXmfFIGjxME= -github.com/aws/aws-sdk-go-v2/service/s3 v1.68.0/go.mod h1:ralv4XawHjEMaHOWnTFushl0WRqim/gQWesAMF6hTow= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.2 h1:e6um6+DWYQP1XCa+E9YVtG/9v1qk5lyAOelMOVwSyO8= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.2/go.mod h1:dIW8puxSbYLSPv/ju0d9A3CpwXdtqvJtYKDMVmPLOWE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9 h1:TQmKDyETFGiXVhZfQ/I0cCFziqqX58pi4tKJGYGFSz0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9/go.mod h1:HVLPK2iHQBUx7HfZeOQSEu3v2ubZaAY2YPbAm5/WUyY= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.9 h1:2aInXbh02XsbO0KobPGMNXyv2QP73VDKsWPNJARj/+4= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.9/go.mod h1:dgXS1i+HgWnYkPXqNoPIPKeUsUUYHaUbThC90aDnNiE= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.8 h1:KbLZjYqhQ9hyB4HwXiheiflTlYQa0+Fz0Ms/rh5f3mk= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.8/go.mod h1:ANs9kBhK4Ghj9z1W+bsr3WsNaPF71qkgd6eE6Ekol/Y= +github.com/aws/aws-sdk-go-v2/service/s3 v1.73.2 h1:F3h8VYq9ZLBXYurmwrT8W0SPhgCcU0q+0WZJfT1dFt0= +github.com/aws/aws-sdk-go-v2/service/s3 v1.73.2/go.mod h1:jGJ/v7FIi7Ys9t54tmEFnrxuaWeJLpwNgKp2DXAVhOU= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.11 h1:kuIyu4fTT38Kj7YCC7ouNbVZSSpqkZ+LzIfhCr6Dg+I= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.11/go.mod h1:Ro744S4fKiCCuZECXgOi760TiYylUM8ZBf6OGiZzJtY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10 h1:l+dgv/64iVlQ3WsBbnn+JSbkj01jIi+SM0wYsj3y/hY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.10/go.mod h1:Fzsj6lZEb8AkTE5S68OhcbBqeWPsR8RnGuKPr8Todl8= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.9 h1:BRVDbewN6VZcwr+FBOszDKvYeXY1kJ+GGMCcpghlw0U= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.9/go.mod h1:f6vjfZER1M17Fokn0IzssOTMT2N8ZSq+7jnNF0tArvw= github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20241009180534-e718692eec62 h1:T5b8GwBFIlqQzAbqTNcyLvzcAvJ09MXrF6zyUlIic8A= @@ -225,14 +234,17 @@ github.com/buildkite/interpolate v0.1.4 h1:qacB5WR+7+Ol1xiJ4xZajHh/CGDdhcMesXR+V github.com/buildkite/interpolate v0.1.4/go.mod h1:dHnrwHew5O8VNOAgMDpwRlFnhL5VSN6M1bHVmRZ9Ccc= github.com/buildkite/roko v1.2.0 h1:hbNURz//dQqNl6Eo9awjQOVOZwSDJ8VEbBDxSfT9rGQ= github.com/buildkite/roko v1.2.0/go.mod h1:23R9e6nHxgedznkwwfmqZ6+0VJZJZ2Sg/uVcp2cP46I= -github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cert-manager/cert-manager v1.16.3 h1:seEF5eidFaeduaCuM85PFEuzH/1X/HOV5Y8zDQrHgpc= -github.com/cert-manager/cert-manager v1.16.3/go.mod h1:6JQ/GAZ6dH+erqS1BbaqorPy8idJzCtWFUmJQBTjo6Q= +github.com/cert-manager/cert-manager v1.17.1 h1:Aig+lWMoLsmpGd9TOlTvO4t0Ah3D+/vGB37x/f+ZKt0= +github.com/cert-manager/cert-manager v1.17.1/go.mod h1:zeG4D+AdzqA7hFMNpYCJgcQ2VOfFNBa+Jzm3kAwiDU4= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.3 h1:9liNh8t+u26xl5ddmWLmsOsdNLwkdRTg5AG+JnTiM80= +github.com/chai2010/gettext-go v1.0.3/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/chainguard-dev/git-urls v1.0.2 h1:pSpT7ifrpc5X55n4aTTm7FFUE+ZQHKiqpiwNkJrVcKQ= +github.com/chainguard-dev/git-urls v1.0.2/go.mod h1:rbGgj10OS7UgZlbzdUQIQpT0k/D4+An04HJY7Ol+Y/o= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -245,7 +257,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/cloudflare/cfssl v1.6.5 h1:46zpNkm6dlNkMZH/wMW22ejih6gIaJbzL2du6vD7ZeI= github.com/cloudflare/cfssl v1.6.5/go.mod h1:Bk1si7sq8h2+yVEDrFJiz3d7Aw+pfjjJSZVaD+Taky4= -github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys= github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -258,10 +269,10 @@ github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= -github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA= -github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= -github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= -github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/containerd v1.7.25 h1:khEQOAXOEJalRO228yzVsuASLH42vT7DIo9Ss+9SMFQ= +github.com/containerd/containerd v1.7.25/go.mod h1:tWfHzVI0azhw4CT2vaIjsb2CoV4LJ9PrMPaULAr21Ok= +github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= +github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= @@ -275,16 +286,16 @@ github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9 github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= -github.com/containers/image/v5 v5.33.0 h1:6oPEFwTurf7pDTGw7TghqGs8K0+OvPtY/UyzU0B2DfE= -github.com/containers/image/v5 v5.33.0/go.mod h1:T7HpASmvnp2H1u4cyckMvCzLuYgpD18dSmabSw0AcHk= +github.com/containers/image/v5 v5.33.1 h1:nTWKwxAlY0aJrilvvhssqssJVnley6VqxkLiLzTEYIs= +github.com/containers/image/v5 v5.33.1/go.mod h1:/FJiLlvVbeBxWNMPVPPIWJxHTAzwBoFvyN0a51zo1CE= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM= github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U= -github.com/containers/storage v1.56.0 h1:DZ9KSkj6M2tvj/4bBoaJu3QDHRl35BwsZ4kmLJS97ZI= -github.com/containers/storage v1.56.0/go.mod h1:c6WKowcAlED/DkWGNuL9bvGYqIWCVy7isRMdCSKWNjk= -github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI= -github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= +github.com/containers/storage v1.56.1 h1:gDZj/S6Zxus4Xx42X6iNB3ODXuh0qoOdH/BABfrvcKo= +github.com/containers/storage v1.56.1/go.mod h1:c6WKowcAlED/DkWGNuL9bvGYqIWCVy7isRMdCSKWNjk= +github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= +github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -293,8 +304,8 @@ github.com/creack/pty v1.1.19 h1:tUN6H7LWqNx4hQVxomd0CVsDwaDr9gaRQaI4GpSmrsA= github.com/creack/pty v1.1.19/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM= github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= -github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= -github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= +github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= +github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -345,21 +356,26 @@ github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= -github.com/elliotchance/orderedmap v1.6.0 h1:xjn+kbbKXeDq6v9RVE+WYwRbYfAZKvlWfcJNxM8pvEw= -github.com/elliotchance/orderedmap v1.6.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= +github.com/elazarl/goproxy v1.2.3 h1:xwIyKHbaP5yfT6O9KIeYJR5549MXRQkoQMRXGztz8YQ= +github.com/elazarl/goproxy v1.2.3/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64= +github.com/elliotchance/orderedmap v1.7.1 h1:8SR2DB391dw0HVI9572ElrY+KU0Q89OCXYwWZx7aAZc= +github.com/elliotchance/orderedmap v1.7.1/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/proto v1.12.1 h1:6n/Z2pZAnBwuhU66Gs8160B8rrrYKo7h2F2sCOnNceE= github.com/emicklei/proto v1.12.1/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/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/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -371,8 +387,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= @@ -381,12 +397,22 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= +github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= +github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M= +github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= @@ -444,10 +470,10 @@ github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/goccy/go-yaml v1.13.0 h1:0Wtp0FZLd7Sm8gERmR9S6Iczzb3vItJj7NaHmFg8pTs= -github.com/goccy/go-yaml v1.13.0/go.mod h1:IjYwxUiJDoqpx2RmbdjMUceGHZwYLon3sfOGl5Hi9lc= +github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= +github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.13.3 h1:IXRULR8mAa0MXQobzzp0VOfMUJ8EnaQ4x3jhf7S0/nI= +github.com/goccy/go-yaml v1.13.3/go.mod h1:IjYwxUiJDoqpx2RmbdjMUceGHZwYLon3sfOGl5Hi9lc= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -463,7 +489,6 @@ github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17w github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -479,9 +504,7 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -493,15 +516,13 @@ github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76 github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.2.1 h1:4iW/NwzqOqYEEoCBEFP+jPbBXbLqMpq3CifMyOnDUME= github.com/google/certificate-transparency-go v1.2.1/go.mod h1:bvn/ytAccv+I6+DGkqpvSsEdiVGramgaSC6RD3tEmeE= -github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= -github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -528,17 +549,16 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcgTJZStM= -github.com/google/trillian v1.6.1 h1:jWU5BGz24GQ5IsHNr+qbmISLkt+73jLv8BOIPN8RtD4= -github.com/google/trillian v1.6.1/go.mod h1:TvwtNkJViJgWZ5VmAMXDwsTjzPBHaPjQO85Kt37JPmM= +github.com/google/trillian v1.7.1 h1:+zX8jLM3524bAMPS+VxaDIDgsMv3/ty6DuLWerHXcek= +github.com/google/trillian v1.7.1/go.mod h1:E1UMAHqpZCA8AQdrKdWmHmtUfSeiD0sDWD1cv00Xa+c= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= -github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= -github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= +github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= +github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= @@ -546,14 +566,17 @@ github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkM github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gowebpki/jcs v1.0.1 h1:Qjzg8EOkrOTuWP7DqQ1FbYtcpEbeTzUoTN9bptp8FOU= github.com/gowebpki/jcs v1.0.1/go.mod h1:CID1cNZ+sHp1CCpAR8mPf6QRtagFBgPJE0FCUQ6+BrI= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= @@ -596,6 +619,8 @@ github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY= github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc= @@ -626,6 +651,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= @@ -658,10 +685,10 @@ github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTRe github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mandelsoft/filepath v0.0.0-20240223090642-3e2777258aa3 h1:oo9nIgnyiBgYPbcZslRT4y29siuL5EoNJ/t1tr0xEVQ= github.com/mandelsoft/filepath v0.0.0-20240223090642-3e2777258aa3/go.mod h1:LxhqC7khDoRENwooP6f/vWvia9ivj6TqLYrR39zqkN0= github.com/mandelsoft/goutils v0.0.0-20241005173814-114fa825bbdc h1:706IHCvAg6DjmG4cQ24CRNpvNVJ8+KQkcGEdQiLyJbU= @@ -687,8 +714,8 @@ github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/mikefarah/yq/v4 v4.44.5 h1:/Xm1dM1BfyDJMg+yIpnl2AgpmLFQg3Lcm/kuyYgHEXE= -github.com/mikefarah/yq/v4 v4.44.5/go.mod h1:rpn3xGVz+2pDuLJTlCvzatCwTmmUeHcm7MbkbtHdvkc= +github.com/mikefarah/yq/v4 v4.45.1 h1:EW+HjKEVa55pUYFJseEHEHdQ0+ulunY+q42zF3M7ZaQ= +github.com/mikefarah/yq/v4 v4.45.1/go.mod h1:djgN2vD749hpjVNGYTShr5Kmv5LYljhCG3lUTuEe3LM= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -704,6 +731,8 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= +github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg= github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= @@ -732,6 +761,8 @@ github.com/mozillazg/docker-credential-acr-helper v0.4.0/go.mod h1:2kiicb3OlPytm github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 h1:Up6+btDp321ZG5/zdSLo48H9Iaq0UQGthrhWC6pCxzE= github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481/go.mod h1:yKZQO8QE2bHlgozqWDiRVqTFlLQSj30K/6SAK8EeYFw= @@ -782,6 +813,8 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= @@ -797,8 +830,8 @@ github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA= +github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -808,8 +841,8 @@ github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQy github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -832,6 +865,7 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= 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 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= @@ -843,41 +877,44 @@ github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGq github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= github.com/sassoftware/relic/v7 v7.6.2 h1:rS44Lbv9G9eXsukknS4mSjIAuuX+lMq/FnStgmZlUv4= github.com/sassoftware/relic/v7 v7.6.2/go.mod h1:kjmP0IBVkJZ6gXeAu35/KCEfca//+PKM6vTAsyDPY+k= -github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA= -github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU= +github.com/secure-systems-lab/go-securesystemslib v0.9.0 h1:rf1HIbL64nUpEIZnjLZ3mcNEL9NBPB0iuVjyxvq3LZc= +github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/woA/peqr+L0joiRXbPpQ042GgJckkFgw= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= github.com/sigstore/cosign/v2 v2.4.1 h1:b8UXEfJFks3hmTwyxrRNrn6racpmccUycBHxDMkEPvU= github.com/sigstore/cosign/v2 v2.4.1/go.mod h1:GvzjBeUKigI+XYnsoVQDmMAsMMc6engxztRSuxE+x9I= github.com/sigstore/fulcio v1.6.5 h1:A9DtV2hmeJ835mtqqxgvV0Sie0HOPKaLPgvFVF4FU7c= github.com/sigstore/fulcio v1.6.5/go.mod h1:wUei0BMnlz5iY10keKAx5FXFGnMX0N25ZSe4jGRA65M= -github.com/sigstore/protobuf-specs v0.3.2 h1:nCVARCN+fHjlNCk3ThNXwrZRqIommIeNKWwQvORuRQo= -github.com/sigstore/protobuf-specs v0.3.2/go.mod h1:RZ0uOdJR4OB3tLQeAyWoJFbNCBFrPQdcokntde4zRBA= -github.com/sigstore/rekor v1.3.7 h1:Z5UW5TmqbTZnyOFkMRfi32q/CWcxK6VuzIkx+33mbq8= -github.com/sigstore/rekor v1.3.7/go.mod h1:TihqJscZ6L6398x68EHY82t0AOnGYfrQ0siXe3WgbR4= -github.com/sigstore/sigstore v1.8.10 h1:r4t+TYzJlG9JdFxMy+um9GZhZ2N1hBTyTex0AHEZxFs= -github.com/sigstore/sigstore v1.8.10/go.mod h1:BekjqxS5ZtHNJC4u3Q3Stvfx2eyisbW/lUZzmPU2u4A= +github.com/sigstore/protobuf-specs v0.3.3 h1:RMZQgXTD/pF7KW6b5NaRLYxFYZ/wzx44PQFXN2PEo5g= +github.com/sigstore/protobuf-specs v0.3.3/go.mod h1:vIhZ6Uor1a38+wvRrKcqL2PtYNlgoIW9lhzYzkyy4EU= +github.com/sigstore/rekor v1.3.8 h1:B8kJI8mpSIXova4Jxa6vXdJyysRxFGsEsLKBDl0rRjA= +github.com/sigstore/rekor v1.3.8/go.mod h1:/dHFYKSuxEygfDRnEwyJ+ZD6qoVYNXQdi1mJrKvKWsI= +github.com/sigstore/sigstore v1.8.12 h1:S8xMVZbE2z9ZBuQUEG737pxdLjnbOIcFi5v9UFfkJFc= +github.com/sigstore/sigstore v1.8.12/go.mod h1:+PYQAa8rfw0QdPpBcT+Gl3egKD9c+TUgAlF12H3Nmjo= github.com/sigstore/sigstore-go v0.6.1 h1:tGkkv1oDIER+QYU5MrjqlttQOVDWfSkmYwMqkJhB/cg= github.com/sigstore/sigstore-go v0.6.1/go.mod h1:Xe5GHmUeACRFbomUWzVkf/xYCn8xVifb9DgqJrV2dIw= -github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.10 h1:e5GfVngPjGap/N3ODefayt7vKIPS1/v3hWLZ9+4MrN4= -github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.10/go.mod h1:HOr3AdFPKdND2FNl/sUD5ZifPl1OMJvrbf9xIaaWcus= -github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.10 h1:9tZEpfIL/ewAG9G87AHe3aVoy8Ujos2F1qLfCckX6jQ= -github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.10/go.mod h1:VnIAcitund62R45ezK/dtUeEhuRtB3LsAgJ8m0H34zc= -github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.10 h1:Xre51HdjIIaVo5ox5zyL+6h0tkrx7Ke9Neh7fLmmZK0= -github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.10/go.mod h1:VNfdklQDbyGJog8S7apdxiEfmYmCkKyxrsCL9xprkTY= -github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.10 h1:HjfjL3x3dP2kaGqQHVog974cTcKfzFaGjfZyLQ9KXrg= -github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.10/go.mod h1:jaeEjkTW1p3gUyPjz9lTcT4TydCs208FoyAwIs6bIT4= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.12 h1:EC3UmIaa7nV9sCgSpVevmvgvTYTkMqyrRbj5ojPp7tE= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.12/go.mod h1:aw60vs3crnQdM/DYH+yF2P0MVKtItwAX34nuaMrY7Lk= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.12 h1:FPpliDTywSy0woLHMAdmTSZ5IS/lVBZ0dY0I+2HmnSY= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.12/go.mod h1:NkPiz4XA0JcBSXzJUrjMj7Xi7oSTew1Ip3Zmt56mHlw= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.12 h1:kweBChR6M9FEvmxN3BMEcl7SNnwxTwKF7THYFKLOE5U= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.12/go.mod h1:6+d+A6oYt1W5OgtzgEVb21V7tAZ/C2Ihtzc5MNJbayY= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.12 h1:jvY1B9bjP+tKzdKDyuq5K7O19CG2IKzGJNTy5tuL2Gs= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.12/go.mod h1:2uEeOb8xE2RC6OvzxKux1wkS39Zv8gA27z92m49xUTc= github.com/sigstore/timestamp-authority v1.2.3 h1:/4YXCKF/+ZQsad89D0Lj2QIz78s5/aRgLa8Nwq2/Kd4= github.com/sigstore/timestamp-authority v1.2.3/go.mod h1:q2tJKJzP34hLIbVu3Y1A9bBZTBuZ/gEmMN7MtAoGQKI= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= +github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY= @@ -915,11 +952,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -962,6 +999,8 @@ 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/xanzy/go-gitlab v0.112.0 h1:6Z0cqEooCvBMfBIHw+CgO4AKGRV8na/9781xOb0+DKw= github.com/xanzy/go-gitlab v0.112.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1006,8 +1045,8 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/exporters/autoexport v0.46.1 h1:ysCfPZB9AjUlMa1UHYup3c9dAOCMQX/6sxSfPBUoxHw= go.opentelemetry.io/contrib/exporters/autoexport v0.46.1/go.mod h1:ha0aiYm+DOPsLHjh0zoQ8W8sLT+LJ58J3j47lGpSLrU= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 h1:hCq2hNMwsegUvPzI7sPOvtO9cqyy5GbWt/Ybp2xrx8Q= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0/go.mod h1:LqaApwGx/oUmzsbqxkzuBvyoPpkxk3JQWnqfVrJ3wCA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0= 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.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= @@ -1016,10 +1055,10 @@ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 h1:FZ6 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0/go.mod h1:MdEu/mC6j3D+tTEfvI15b5Ci2Fn7NneJ71YMoiS3tpI= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 h1:bflGWrfYyuulcdxf14V6n9+CoQcu5SAAdHmDPAJnlps= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0/go.mod h1:qcTO4xHAxZLaLxPd60TdE88rxtItPHgHWqOhOGRr0as= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0= go.opentelemetry.io/otel/exporters/prometheus v0.44.0 h1:08qeJgaPC0YEBu2PQMbqU3rogTlyzpjhCI2b58Yn00w= @@ -1036,10 +1075,10 @@ go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4Jjx go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= -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.step.sm/crypto v0.54.2 h1:3LSA5nYDQvcd484OSx7xsS3XDqQ7/WZjVqvq0+a0fWc= -go.step.sm/crypto v0.54.2/go.mod h1:1+OjUozd5aA3TkBJfr5Aobd6vNt9F70n1DagcoBh3Pc= +go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg= +go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY= +go.step.sm/crypto v0.56.0 h1:KcFfV76cI9Xaw8bdSc9x55skyuSdcHcTdL37vvVZnvY= +go.step.sm/crypto v0.56.0/go.mod h1:snWNloxY9s1W+HsFqcviq55nvzbqqX6LxVt0Vktv5mw= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= @@ -1060,18 +1099,17 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -1096,7 +1134,6 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= @@ -1104,9 +1141,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= @@ -1125,8 +1160,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1144,6 +1179,7 @@ golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1155,8 +1191,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1168,9 +1202,7 @@ golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= @@ -1182,15 +1214,13 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= -golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1214,37 +1244,31 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/api v0.206.0 h1:A27GClesCSheW5P2BymVHjpEeQ2XHH8DI8Srs2HI2L8= -google.golang.org/api v0.206.0/go.mod h1:BtB8bfjTYIrai3d8UyvPmV9REGgox7coh+ZRwm0b+W8= +google.golang.org/api v0.216.0 h1:xnEHy+xWFrtYInWPy8OdGFsyIfWJjtVnO39g7pz2BFY= +google.golang.org/api v0.216.0/go.mod h1:K9wzQMvWi47Z9IU7OgdOofvZuw75Ge3PPITImZR/UyI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28 h1:KJjNNclfpIkVqrZlTWcgOOaVQ00LdBnoEaRfkUx760s= -google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:mt9/MofW7AWQ+Gy179ChOnvmJatV8YHUmrcedo9CIFI= -google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= -google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= +google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb h1:B7GIB7sr443wZ/EAEl7VZjmh1V6qzkt5V+RYcUYtS1U= +google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb/go.mod h1:E5//3O5ZIG2l71Xnt+P/CYUY8Bxs8E7WMoZ9tlcMbAY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4= google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= -google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= @@ -1255,6 +1279,7 @@ gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9a gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -1274,6 +1299,8 @@ gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1287,40 +1314,42 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -helm.sh/helm/v3 v3.16.3 h1:kb8bSxMeRJ+knsK/ovvlaVPfdis0X3/ZhYCSFRP+YmY= -helm.sh/helm/v3 v3.16.3/go.mod h1:zeVWGDR4JJgiRbT3AnNsjYaX8OTJlIE9zC+Q7F7iUSU= +helm.sh/helm/v3 v3.17.0 h1:DUD4AGdNVn7PSTYfxe1gmQG7s18QeWv/4jI9TubnhT0= +helm.sh/helm/v3 v3.17.0/go.mod h1:Mo7eGyKPPHlS0Ml67W8z/lbkox/gD9Xt1XpD6bxvZZA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -istio.io/api v1.24.2 h1:jYjcN6Iq0RPtQj/3KMFsybxmfqmjGN/dxhL7FGJEdIM= -istio.io/api v1.24.2/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= -istio.io/client-go v1.24.2 h1:JTTfBV6dv+AAW+AfccyrdX4T1f9CpsXd1Yzo1s/IYAI= -istio.io/client-go v1.24.2/go.mod h1:dgZ9EmJzh1EECzf6nQhwNL4R6RvlyeH/RXeNeNp/MRg= -k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc= -k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k= -k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw= -k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto= -k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs= -k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/cli-runtime v0.32.1 h1:19nwZPlYGJPUDbhAxDIS2/oydCikvKMHsxroKNGA2mM= -k8s.io/cli-runtime v0.32.1/go.mod h1:NJPbeadVFnV2E7B7vF+FvU09mpwYlZCu8PqjzfuOnkY= -k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU= -k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg= -k8s.io/component-base v0.32.1 h1:/5IfJ0dHIKBWysGV0yKTFfacZ5yNV1sulPh3ilJjRZk= -k8s.io/component-base v0.32.1/go.mod h1:j1iMMHi/sqAHeG5z+O9BFNCF698a1u0186zkjMZQ28w= +istio.io/api v1.24.3 h1:iwWWPM0uEQ+oxRHvIWoB8MQ4bjF3dRQj+M5IDVczg0M= +istio.io/api v1.24.3/go.mod h1:MQnRok7RZ20/PE56v0LxmoWH0xVxnCQPNuf9O7PAN1I= +istio.io/client-go v1.24.3 h1:TB8IcM3yyMCDzKRJo0YfFOUGNQmkhwH/JE/Yr3lzVAk= +istio.io/client-go v1.24.3/go.mod h1:zSyw/c4luKQKosFIHQaWAQOA0c3bODu4SahQCAMlKA4= +k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= +k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= +k8s.io/apiextensions-apiserver v0.32.2 h1:2YMk285jWMk2188V2AERy5yDwBYrjgWYggscghPCvV4= +k8s.io/apiextensions-apiserver v0.32.2/go.mod h1:GPwf8sph7YlJT3H6aKUWtd0E+oyShk/YHWQHf/OOgCA= +k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= +k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/cli-runtime v0.32.2 h1:aKQR4foh9qeyckKRkNXUccP9moxzffyndZAvr+IXMks= +k8s.io/cli-runtime v0.32.2/go.mod h1:a/JpeMztz3xDa7GCyyShcwe55p8pbcCVQxvqZnIwXN8= +k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= +k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= +k8s.io/component-base v0.32.2 h1:1aUL5Vdmu7qNo4ZsE+569PV5zFatM9hl+lb3dEea2zU= +k8s.io/component-base v0.32.2/go.mod h1:PXJ61Vx9Lg+P5mS8TLd7bCIr+eMJRQTyXe8KvkrvJq0= 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-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= -k8s.io/kubectl v0.32.1 h1:/btLtXLQUU1rWx8AEvX9jrb9LaI6yeezt3sFALhB8M8= -k8s.io/kubectl v0.32.1/go.mod h1:sezNuyWi1STk4ZNPVRIFfgjqMI6XMf+oCVLjZen/pFQ= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -ocm.software/ocm v0.19.1 h1:sWcQB+G9zcURqZfKvTnAfeA+rcDwlbI222o/fPkm6ls= -ocm.software/ocm v0.19.1/go.mod h1:JCGMa/y8PPXvRhD+8SnnNHco4aAXMaXxiJKe8gyRHTQ= +k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg= +k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= +k8s.io/kubectl v0.32.2 h1:TAkag6+XfSBgkqK9I7ZvwtF0WVtUAvK8ZqTt+5zi1Us= +k8s.io/kubectl v0.32.2/go.mod h1:+h/NQFSPxiDZYX/WZaWw9fwYezGLISP0ud8nQKg+3g8= +k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= +k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +ocm.software/ocm v0.20.1 h1:fHqczw6vrXh6l/c65NvqqgNXcmYWqb254C45DiQoftM= +ocm.software/ocm v0.20.1/go.mod h1:dmB8RhgfWZKMhU7KBe3QAyUNjfhMYdFklw0/mQ+gAzU= oras.land/oras-go v1.2.6 h1:z8cmxQXBU8yZ4mkytWqXfo6tZcamPwjsuxYU81xJ8Lk= oras.land/oras-go v1.2.6/go.mod h1:OVPc1PegSEe/K8YiLfosrlqlqTN9PUyFvOw5Y9gwrT8= -sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE= -sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= +oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c= +oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg= +sigs.k8s.io/controller-runtime v0.20.2 h1:/439OZVxoEc02psi1h4QO3bHzTgu49bb347Xp4gW1pc= +sigs.k8s.io/controller-runtime v0.20.2/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM= sigs.k8s.io/gateway-api v1.1.0/go.mod h1:ZH4lHrL2sDi0FHZ9jjneb8kKnGzFWyrTya35sWUTrRs= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= @@ -1331,8 +1360,8 @@ sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= sigs.k8s.io/release-utils v0.8.5 h1:FUtFqEAN621gSXv0L7kHyWruBeS7TUU9aWf76olX7uQ= sigs.k8s.io/release-utils v0.8.5/go.mod h1:qsm5bdxdgoHkD8HsXpgme2/c3mdsNaiV53Sz2HmKeJA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk= +sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= software.sslmate.com/src/go-pkcs12 v0.5.0 h1:EC6R394xgENTpZ4RltKydeDUjtlM5drOYIG9c6TVj2M= diff --git a/internal/controller/istiogatewaysecret/controller.go b/internal/controller/istiogatewaysecret/controller.go index 4e22d6393b..1adae8028a 100644 --- a/internal/controller/istiogatewaysecret/controller.go +++ b/internal/controller/istiogatewaysecret/controller.go @@ -11,6 +11,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "github.com/kyma-project/lifecycle-manager/pkg/log" + "github.com/kyma-project/lifecycle-manager/pkg/queue" ) var ErrSecretNotFound = errors.New("root secret not found") @@ -25,12 +26,14 @@ type ( type Reconciler struct { getRootSecret GetterFunc handler Handler + intervals queue.RequeueIntervals } -func NewReconciler(getSecretFunc GetterFunc, handler Handler) *Reconciler { +func NewReconciler(getSecretFunc GetterFunc, handler Handler, intervals queue.RequeueIntervals) *Reconciler { return &Reconciler{ getRootSecret: getSecretFunc, handler: handler, + intervals: intervals, } } @@ -42,13 +45,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu return ctrl.Result{}, fmt.Errorf("failed to get istio gateway root secret: %w", err) } if rootSecret == nil { - return ctrl.Result{}, ErrSecretNotFound + return ctrl.Result{Requeue: true, RequeueAfter: r.intervals.Error}, ErrSecretNotFound } err = r.handler.ManageGatewaySecret(ctx, rootSecret) if err != nil { - return ctrl.Result{}, fmt.Errorf("failed to manage gateway secret: %w", err) + return ctrl.Result{Requeue: true, RequeueAfter: r.intervals.Error}, + fmt.Errorf("failed to manage gateway secret: %w", err) } - return ctrl.Result{}, nil + return ctrl.Result{Requeue: true, RequeueAfter: r.intervals.Success}, nil } diff --git a/internal/controller/istiogatewaysecret/controller_test.go b/internal/controller/istiogatewaysecret/controller_test.go index 0af19ae1b6..dcf9689a69 100644 --- a/internal/controller/istiogatewaysecret/controller_test.go +++ b/internal/controller/istiogatewaysecret/controller_test.go @@ -12,6 +12,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "github.com/kyma-project/lifecycle-manager/internal/controller/istiogatewaysecret" + "github.com/kyma-project/lifecycle-manager/pkg/queue" ) func TestReconcile_WhenGetSecretFuncReturnsError_ReturnError(t *testing.T) { @@ -20,7 +21,7 @@ func TestReconcile_WhenGetSecretFuncReturnsError_ReturnError(t *testing.T) { return nil, errors.New("some-error") } mockHandler := &mockHandler{} - reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, mockHandler) + reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, mockHandler, queue.RequeueIntervals{}) // ACT _, err := reconciler.Reconcile(context.TODO(), ctrl.Request{}) @@ -36,7 +37,7 @@ func TestReconcile_WhenGetSecretFuncReturnsNoErrorAndSecretIsNil_ReturnError(t * return nil, nil } mockHandler := &mockHandler{} - reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, mockHandler) + reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, mockHandler, queue.RequeueIntervals{}) // ACT _, err := reconciler.Reconcile(context.TODO(), ctrl.Request{}) @@ -56,7 +57,7 @@ func TestReconcile_WhenGetSecretFuncIsCalled_IsCalledWithRequestNamespacedName(t assert.Equal(t, request.Name, name.Name) return nil, nil } - reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, &mockHandler{}) + reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, &mockHandler{}, queue.RequeueIntervals{}) // ACT // ASSERT @@ -70,7 +71,7 @@ func TestReconcile_WhenGetSecretFuncReturnsSecret_HandlerManageGatewaySecretIsCa return secret, nil } mockHandler := &mockHandler{} - reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, mockHandler) + reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, mockHandler, queue.RequeueIntervals{}) // ACT _, err := reconciler.Reconcile(context.TODO(), ctrl.Request{}) @@ -87,7 +88,7 @@ func TestReconcile_WhenHandlerManageGatewaySecretReturnsError_ReturnError(t *tes return secret, nil } mockHandler := &mockHandler{err: errors.New("some-error")} - reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, mockHandler) + reconciler := istiogatewaysecret.NewReconciler(stubGetterFunc, mockHandler, queue.RequeueIntervals{}) // ACT _, err := reconciler.Reconcile(context.TODO(), ctrl.Request{}) diff --git a/internal/controller/istiogatewaysecret/setup.go b/internal/controller/istiogatewaysecret/setup.go index 94af8cc825..5d7bc389a1 100644 --- a/internal/controller/istiogatewaysecret/setup.go +++ b/internal/controller/istiogatewaysecret/setup.go @@ -16,8 +16,11 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret" + "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret/cabundle" gatewaysecretclient "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret/client" + "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret/legacy" "github.com/kyma-project/lifecycle-manager/internal/pkg/flags" + "github.com/kyma-project/lifecycle-manager/pkg/queue" ) const ( @@ -25,21 +28,30 @@ const ( kcpRootSecretName = "klm-watcher" ) -var errCouldNotGetLastModifiedAt = errors.New("getting lastModifiedAt time failed") +var errCouldNotGetTimeFromAnnotation = errors.New("getting time from annotation failed") func SetupReconciler(mgr ctrl.Manager, flagVar *flags.FlagVar, options ctrlruntime.Options) error { options.MaxConcurrentReconciles = flagVar.MaxConcurrentWatcherReconciles clnt := gatewaysecretclient.NewGatewaySecretRotationClient(mgr.GetConfig()) - var parseLastModifiedFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret) (time.Time, error) { - if gwSecretLastModifiedAtValue, ok := secret.Annotations[shared.LastModifiedAtAnnotation]; ok { - if gwSecretLastModifiedAt, err := time.Parse(time.RFC3339, gwSecretLastModifiedAtValue); err == nil { - return gwSecretLastModifiedAt, nil + var parseLastModifiedFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret, + annotation string, + ) (time.Time, error) { + if strValue, ok := secret.Annotations[annotation]; ok { + if time, err := time.Parse(time.RFC3339, strValue); err == nil { + return time, nil } } - return time.Time{}, errCouldNotGetLastModifiedAt + return time.Time{}, fmt.Errorf("%w: %s", errCouldNotGetTimeFromAnnotation, annotation) + } + + var handler gatewaysecret.Handler + if flagVar.UseLegacyStrategyForIstioGatewaySecret { + handler = legacy.NewGatewaySecretHandler(clnt, parseLastModifiedFunc) + } else { + handler = cabundle.NewGatewaySecretHandler(clnt, parseLastModifiedFunc, + flagVar.IstioGatewayCertSwitchBeforeExpirationTime) } - handler := gatewaysecret.NewGatewaySecretHandler(clnt, parseLastModifiedFunc) var getSecretFunc GetterFunc = func(ctx context.Context, name types.NamespacedName) (*apicorev1.Secret, error) { secret := &apicorev1.Secret{} @@ -51,7 +63,10 @@ func SetupReconciler(mgr ctrl.Manager, flagVar *flags.FlagVar, options ctrlrunti return secret, nil } - return NewReconciler(getSecretFunc, handler).setupWithManager(mgr, options) + return NewReconciler(getSecretFunc, handler, queue.RequeueIntervals{ + Success: flagVar.IstioGatewaySecretRequeueSuccessInterval, + Error: flagVar.IstioGatewaySecretRequeueErrInterval, + }).setupWithManager(mgr, options) } func (r *Reconciler) setupWithManager(mgr ctrl.Manager, opts ctrlruntime.Options) error { diff --git a/internal/controller/kyma/controller.go b/internal/controller/kyma/controller.go index 1b70afcc2b..789cc69f6e 100644 --- a/internal/controller/kyma/controller.go +++ b/internal/controller/kyma/controller.go @@ -75,21 +75,6 @@ type Reconciler struct { TemplateLookup *templatelookup.TemplateLookup } -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=kymas,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=kymas/status,verbs=get;update;patch;watch -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=kymas/finalizers,verbs=update -// +kubebuilder:rbac:groups="",resources=services,verbs=get;list;watch -// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch;get;list;watch -// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch -// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=moduletemplates,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=modulereleasemetas,verbs=get;list;watch -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=moduletemplates/finalizers,verbs=update -// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch -// +kubebuilder:rbac:groups=cert-manager.io,resources=issuers,verbs=get;list;watch -// +kubebuilder:rbac:groups=cert-manager.io,resources=certificates,verbs=get;list;create;update;delete;patch;watch -// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions/status,verbs=update - func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { logger := logf.FromContext(ctx) logger.V(log.DebugLevel).Info("Kyma reconciliation started") @@ -274,9 +259,15 @@ func (r *Reconciler) syncStatusToRemote(ctx context.Context, kcpKyma *v1beta2.Ky if err != nil { return fmt.Errorf("failed to get skrContext: %w", err) } - if err := skrContext.SynchronizeKyma(ctx, kcpKyma, remoteKyma); err != nil { - return fmt.Errorf("sync run failure: %w", err) + + if err := skrContext.SynchronizeKymaMetadata(ctx, kcpKyma, remoteKyma); err != nil { + return fmt.Errorf("failed to sync SKR Kyma CR Metadata: %w", err) } + + if err := skrContext.SynchronizeKymaStatus(ctx, kcpKyma, remoteKyma); err != nil { + return fmt.Errorf("failed to sync SKR Kyma CR Status: %w", err) + } + return nil } diff --git a/internal/controller/manifest/controller.go b/internal/controller/manifest/controller.go index afa47768ed..d1346b3475 100644 --- a/internal/controller/manifest/controller.go +++ b/internal/controller/manifest/controller.go @@ -11,10 +11,6 @@ import ( "github.com/kyma-project/lifecycle-manager/pkg/queue" ) -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=manifests,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=manifests/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=manifests/finalizers,verbs=update - func NewReconciler(mgr manager.Manager, requeueIntervals queue.RequeueIntervals, manifestMetrics *metrics.ManifestMetrics, mandatoryModulesMetrics *metrics.MandatoryModulesMetrics, manifestClient declarativev2.ManifestAPIClient, diff --git a/internal/controller/watcher/controller.go b/internal/controller/watcher/controller.go index 2695f85ea0..88b72c35e6 100644 --- a/internal/controller/watcher/controller.go +++ b/internal/controller/watcher/controller.go @@ -63,14 +63,6 @@ type Reconciler struct { queue.RequeueIntervals } -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=watchers,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=watchers/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=watchers/finalizers,verbs=update -// +kubebuilder:rbac:groups=networking.istio.io,resources=virtualservices,verbs=get;list;create;update;delete -// +kubebuilder:rbac:groups=networking.istio.io,resources=gateways,verbs=list;get; -// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;delete -// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete - func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { logger := logf.FromContext(ctx).WithName(req.NamespacedName.String()) logger.V(log.DebugLevel).Info("Reconciliation loop starting") diff --git a/internal/declarative/v2/default_transforms.go b/internal/declarative/v2/default_transforms.go index 42dc06a496..edacb77868 100644 --- a/internal/declarative/v2/default_transforms.go +++ b/internal/declarative/v2/default_transforms.go @@ -31,7 +31,7 @@ func DisclaimerTransform(_ context.Context, _ Object, resources []*unstructured. func KymaComponentTransform(_ context.Context, obj Object, resources []*unstructured.Unstructured) error { for _, resource := range resources { - resource.SetLabels(collections.MergeMaps(resource.GetLabels(), map[string]string{ + resource.SetLabels(collections.MergeMapsSilent(resource.GetLabels(), map[string]string{ "app.kubernetes.io/component": obj.GetName(), "app.kubernetes.io/part-of": "Kyma", })) @@ -41,11 +41,11 @@ func KymaComponentTransform(_ context.Context, obj Object, resources []*unstruct func ManagedByOwnedBy(_ context.Context, obj Object, resources []*unstructured.Unstructured) error { for _, resource := range resources { - resource.SetLabels(collections.MergeMaps(resource.GetLabels(), map[string]string{ + resource.SetLabels(collections.MergeMapsSilent(resource.GetLabels(), map[string]string{ shared.ManagedBy: shared.ManagedByLabelValue, })) - resource.SetAnnotations(collections.MergeMaps(resource.GetAnnotations(), map[string]string{ + resource.SetAnnotations(collections.MergeMapsSilent(resource.GetAnnotations(), map[string]string{ shared.OwnedByAnnotation: fmt.Sprintf(OwnedByFormat, obj.GetNamespace(), obj.GetName()), })) } diff --git a/internal/declarative/v2/reconciler.go b/internal/declarative/v2/reconciler.go index eb08a33845..f9f0eaa3a3 100644 --- a/internal/declarative/v2/reconciler.go +++ b/internal/declarative/v2/reconciler.go @@ -7,7 +7,6 @@ import ( "time" apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/cli-runtime/pkg/resource" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -52,14 +51,15 @@ func NewFromManager(mgr manager.Manager, requeueIntervals queue.RequeueIntervals reconciler.RequeueIntervals = requeueIntervals reconciler.specResolver = specResolver reconciler.manifestClient = manifestAPIClient - reconciler.managedLabelRemovalService = labelsremoval.NewManagedLabelRemovalService(manifestAPIClient) + reconciler.managedLabelRemovalService = labelsremoval.NewManagedByLabelRemovalService(manifestAPIClient) reconciler.Options = DefaultOptions().Apply(WithManager(mgr)).Apply(options...) return reconciler } -type ManagedLabelRemoval interface { - RemoveManagedLabel(ctx context.Context, - manifest *v1beta2.Manifest, skrClient client.Client, defaultCR *unstructured.Unstructured, +type ManagedByLabelRemoval interface { + RemoveManagedByLabel(ctx context.Context, + manifest *v1beta2.Manifest, + skrClient client.Client, ) error } @@ -77,7 +77,7 @@ type Reconciler struct { MandatoryModuleMetrics *metrics.MandatoryModulesMetrics specResolver SpecResolver manifestClient ManifestAPIClient - managedLabelRemovalService ManagedLabelRemoval + managedLabelRemovalService ManagedByLabelRemoval } //nolint:funlen,cyclop,gocognit // Declarative pkg will be removed soon @@ -123,7 +123,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu return r.cleanupManifest(ctx, manifest, manifestStatus, metrics.ManifestUnmanagedUpdate, nil) } - if controllerutil.ContainsFinalizer(manifest, labelsremoval.LabelRemovalFinalizer) { + if controllerutil.ContainsFinalizer(manifest, finalizer.LabelRemovalFinalizer) { return r.handleLabelsRemovalFinalizer(ctx, skrClient, manifest) } @@ -222,16 +222,11 @@ func recordMandatoryModuleState(manifest *v1beta2.Manifest, r *Reconciler) { func (r *Reconciler) handleLabelsRemovalFinalizer(ctx context.Context, skrClient client.Client, manifest *v1beta2.Manifest, ) (ctrl.Result, error) { - defaultCR, err := modulecr.NewClient(skrClient).GetCR(ctx, manifest) + err := r.managedLabelRemovalService.RemoveManagedByLabel(ctx, manifest, skrClient) if err != nil { return ctrl.Result{}, err } - if err := r.managedLabelRemovalService.RemoveManagedLabel(ctx, manifest, skrClient, - defaultCR); err != nil { - return ctrl.Result{}, err - } - r.ManifestMetrics.RecordRequeueReason(metrics.ManifestResourcesLabelRemoval, queue.IntendedRequeue) return ctrl.Result{Requeue: true}, nil } diff --git a/internal/gatewaysecret/cabundle/handler.go b/internal/gatewaysecret/cabundle/handler.go new file mode 100644 index 0000000000..6dd3b85283 --- /dev/null +++ b/internal/gatewaysecret/cabundle/handler.go @@ -0,0 +1,150 @@ +package cabundle + +import ( + "context" + "errors" + "slices" + "time" + + certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" + apicorev1 "k8s.io/api/core/v1" + apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyma-project/lifecycle-manager/api/shared" + "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret" + "github.com/kyma-project/lifecycle-manager/pkg/util" +) + +var ErrCACertificateNotReady = errors.New("watcher-serving ca certificate is not ready") + +const ( + caBundleTempCertKey = "temp.ca.crt" + CurrentCAExpirationAnnotation = "currentCAExpiration" +) + +type Handler struct { + client gatewaysecret.Client + parseTimeFromAnnotationFunc gatewaysecret.TimeParserFunc + switchCertBeforeExpirationTime time.Duration +} + +func NewGatewaySecretHandler(client gatewaysecret.Client, timeParserFunc gatewaysecret.TimeParserFunc, + switchCertBeforeExpirationTime time.Duration, +) *Handler { + return &Handler{ + client: client, + parseTimeFromAnnotationFunc: timeParserFunc, + switchCertBeforeExpirationTime: switchCertBeforeExpirationTime, + } +} + +func (h *Handler) ManageGatewaySecret(ctx context.Context, rootSecret *apicorev1.Secret) error { + caCert, err := h.client.GetWatcherServingCert(ctx) + if err != nil { + return err + } + if caCert.Status.NotBefore == nil || caCert.Status.NotAfter == nil { + return ErrCACertificateNotReady + } + + gwSecret, err := h.client.GetGatewaySecret(ctx) + if util.IsNotFound(err) { + return h.createGatewaySecretFromRootSecret(ctx, rootSecret, caCert) + } else if err != nil { + return err + } + + // this is for the case when we switch existing secret from legacy to new rotation mechanism + bootstrapLegacyGatewaySecret(gwSecret, rootSecret, caCert) + + if h.requiresBundling(gwSecret, caCert) { + bundleCACrt(gwSecret, rootSecret) + setLastModifiedToNow(gwSecret) + } + if h.requiresCertSwitching(gwSecret) { + switchCertificate(gwSecret, rootSecret) + setCurrentCAExpiration(gwSecret, caCert) + } + return h.client.UpdateGatewaySecret(ctx, gwSecret) +} + +func (h *Handler) createGatewaySecretFromRootSecret(ctx context.Context, rootSecret *apicorev1.Secret, + caCert *certmanagerv1.Certificate, +) error { + newSecret := &apicorev1.Secret{ + TypeMeta: apimetav1.TypeMeta{ + Kind: gatewaysecret.SecretKind, + APIVersion: apicorev1.SchemeGroupVersion.String(), + }, + ObjectMeta: apimetav1.ObjectMeta{ + Name: shared.GatewaySecretName, + Namespace: shared.IstioNamespace, + }, + } + + newSecret.Data = make(map[string][]byte) + newSecret.Data[gatewaysecret.TLSCrt] = rootSecret.Data[gatewaysecret.TLSCrt] + newSecret.Data[gatewaysecret.TLSKey] = rootSecret.Data[gatewaysecret.TLSKey] + newSecret.Data[gatewaysecret.CACrt] = rootSecret.Data[gatewaysecret.CACrt] + + newSecret.Data[caBundleTempCertKey] = rootSecret.Data[gatewaysecret.CACrt] + setLastModifiedToNow(newSecret) + setCurrentCAExpiration(newSecret, caCert) + + return h.client.CreateGatewaySecret(ctx, newSecret) +} + +func (h *Handler) requiresBundling(gwSecret *apicorev1.Secret, caCert *certmanagerv1.Certificate) bool { + // If the last modified time of the gateway secret is after the notBefore time of the CA certificate, + // then we don't need to update the gateway secret + if lastModified, err := h.parseTimeFromAnnotationFunc(gwSecret, shared.LastModifiedAtAnnotation); err == nil { + if lastModified.After(caCert.Status.NotBefore.Time) { + return false + } + } + return true +} + +func (h *Handler) requiresCertSwitching(gwSecret *apicorev1.Secret) bool { + // If the current CA is about to expire, then we need to switch the certificate and private key + caExpirationTime, err := h.parseTimeFromAnnotationFunc(gwSecret, CurrentCAExpirationAnnotation) + return err != nil || time.Now().After(caExpirationTime.Add(-h.switchCertBeforeExpirationTime)) +} + +func bootstrapLegacyGatewaySecret(gwSecret *apicorev1.Secret, rootSecret *apicorev1.Secret, + caCert *certmanagerv1.Certificate, +) { + if _, ok := gwSecret.Annotations[CurrentCAExpirationAnnotation]; !ok { + setCurrentCAExpiration(gwSecret, caCert) + } + if _, ok := gwSecret.Data[caBundleTempCertKey]; !ok { + gwSecret.Data[caBundleTempCertKey] = rootSecret.Data[gatewaysecret.CACrt] + } +} + +func setLastModifiedToNow(secret *apicorev1.Secret) { + if secret.Annotations == nil { + secret.Annotations = make(map[string]string) + } + secret.Annotations[shared.LastModifiedAtAnnotation] = apimetav1.Now().Format(time.RFC3339) +} + +func setCurrentCAExpiration(secret *apicorev1.Secret, caCert *certmanagerv1.Certificate) { + if secret.Annotations == nil { + secret.Annotations = make(map[string]string) + } + secret.Annotations[CurrentCAExpirationAnnotation] = caCert.Status.NotAfter.Time.Format(time.RFC3339) +} + +func bundleCACrt(gatewaySecret *apicorev1.Secret, rootSecret *apicorev1.Secret) { + gatewaySecret.Data[gatewaysecret.CACrt] = slices.Clone(rootSecret.Data[gatewaysecret.CACrt]) + gatewaySecret.Data[gatewaysecret.CACrt] = append(gatewaySecret.Data[gatewaysecret.CACrt], + gatewaySecret.Data[caBundleTempCertKey]...) + + gatewaySecret.Data[caBundleTempCertKey] = rootSecret.Data[gatewaysecret.CACrt] +} + +func switchCertificate(gatewaySecret *apicorev1.Secret, rootSecret *apicorev1.Secret) { + gatewaySecret.Data[gatewaysecret.TLSCrt] = rootSecret.Data[gatewaysecret.TLSCrt] + gatewaySecret.Data[gatewaysecret.TLSKey] = rootSecret.Data[gatewaysecret.TLSKey] +} diff --git a/internal/gatewaysecret/cabundle/handler_test.go b/internal/gatewaysecret/cabundle/handler_test.go new file mode 100644 index 0000000000..bf27fafca1 --- /dev/null +++ b/internal/gatewaysecret/cabundle/handler_test.go @@ -0,0 +1,320 @@ +package cabundle_test + +import ( + "context" + "errors" + "testing" + "time" + + certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + apicorev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyma-project/lifecycle-manager/api/shared" + "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret" + "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret/cabundle" + "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret/testutils" +) + +const gatewaySwitchCertBeforeExpirationTime = 1 * time.Hour + +func TestManageGatewaySecret_WhenGetWatcherServingCertReturnsError_ReturnsError(t *testing.T) { + // ARRANGE + mockClient := &testutils.ClientMock{} + someError := errors.New("some-error") + mockClient.On("GetWatcherServingCert", mock.Anything).Return(nil, someError) + + handler := cabundle.NewGatewaySecretHandler(mockClient, nil, gatewaySwitchCertBeforeExpirationTime) + + // ACT + err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) + + // ASSERT + require.Error(t, err) + require.ErrorIs(t, err, someError) + mockClient.AssertNumberOfCalls(t, "GetWatcherServingCert", 1) +} + +func TestManageGatewaySecret_WhenGetWatcherServingCertReturnsIncompleteStatus_ReturnsError(t *testing.T) { + // ARRANGE + mockClient := &testutils.ClientMock{} + mockClient.On("GetWatcherServingCert", mock.Anything).Return(&certmanagerv1.Certificate{ + Status: certmanagerv1.CertificateStatus{}, + }, nil) + + handler := cabundle.NewGatewaySecretHandler(mockClient, nil, gatewaySwitchCertBeforeExpirationTime) + + // ACT + err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) + + // ASSERT + require.Error(t, err) + require.ErrorIs(t, err, cabundle.ErrCACertificateNotReady) + mockClient.AssertNumberOfCalls(t, "GetWatcherServingCert", 1) +} + +func TestManageGatewaySecret_WhenGetGatewaySecretReturnsError_ReturnsError(t *testing.T) { + // ARRANGE + mockClient := &testutils.ClientMock{} + mockClient.On("GetWatcherServingCert", mock.Anything).Return(getActiveCertificate(), nil) + someError := errors.New("some-error") + mockClient.On("GetGatewaySecret", mock.Anything).Return(nil, someError) + + handler := cabundle.NewGatewaySecretHandler(mockClient, nil, gatewaySwitchCertBeforeExpirationTime) + + // ACT + err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) + + // ASSERT + require.Error(t, err) + require.ErrorIs(t, err, someError) + mockClient.AssertNumberOfCalls(t, "GetWatcherServingCert", 1) + mockClient.AssertNumberOfCalls(t, "GetGatewaySecret", 1) +} + +func TestManageGatewaySecret_WhenGetGatewaySecretReturnsNotFoundError_CreatesGatewaySecretFromRootSecret(t *testing.T) { + // ARRANGE + mockClient := &testutils.ClientMock{} + mockClient.On("GetWatcherServingCert", mock.Anything).Return(getActiveCertificate(), nil) + mockClient.On("GetGatewaySecret", mock.Anything).Return(nil, notFoundError()) + mockClient.On("CreateGatewaySecret", mock.Anything, mock.Anything).Return(nil) + rootSecret := &apicorev1.Secret{ + Data: map[string][]byte{ + "tls.crt": []byte("value1"), + "tls.key": []byte("value2"), + "ca.crt": []byte("value3"), + }, + } + handler := cabundle.NewGatewaySecretHandler(mockClient, nil, gatewaySwitchCertBeforeExpirationTime) + + // ACT + err := handler.ManageGatewaySecret(context.TODO(), rootSecret) + + // ASSERT + require.NoError(t, err) + mockClient.AssertNumberOfCalls(t, "GetGatewaySecret", 1) + mockClient.AssertNumberOfCalls(t, "CreateGatewaySecret", 1) + + expectedNamespace := "istio-system" + expectedName := "klm-istio-gateway" + mockClient.AssertCalled(t, "CreateGatewaySecret", mock.Anything, mock.MatchedBy( + func(secret *apicorev1.Secret) bool { + return secret.ObjectMeta.Name == expectedName && + secret.ObjectMeta.Namespace == expectedNamespace && + string(secret.Data["tls.crt"]) == string(rootSecret.Data["tls.crt"]) && + string(secret.Data["tls.key"]) == string(rootSecret.Data["tls.key"]) && + string(secret.Data["ca.crt"]) == string(rootSecret.Data["ca.crt"]) && + string(secret.Data["temp.ca.crt"]) == string(rootSecret.Data["ca.crt"]) && + secret.Annotations[shared.LastModifiedAtAnnotation] != "" && + secret.Annotations[cabundle.CurrentCAExpirationAnnotation] != "" + })) +} + +func TestManageGatewaySecret_WhenGetGatewaySecretReturnsNotFoundErrorAndCreationFailed_ReturnError(t *testing.T) { + // ARRANGE + mockClient := &testutils.ClientMock{} + mockClient.On("GetWatcherServingCert", mock.Anything).Return(getActiveCertificate(), nil) + mockClient.On("GetGatewaySecret", mock.Anything).Return(nil, notFoundError()) + expectedError := errors.New("some-error") + mockClient.On("CreateGatewaySecret", mock.Anything, mock.Anything).Return(expectedError) + + handler := cabundle.NewGatewaySecretHandler(mockClient, nil, gatewaySwitchCertBeforeExpirationTime) + + // ACT + err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) + + // ASSERT + require.Error(t, err) + require.ErrorIs(t, err, expectedError) + mockClient.AssertNumberOfCalls(t, "GetGatewaySecret", 1) + mockClient.AssertNumberOfCalls(t, "CreateGatewaySecret", 1) +} + +func TestManageGatewaySecret_WhenLegacySecret_BootstrapsLegacyGatewaySecret(t *testing.T) { + // ARRANGE + mockClient := &testutils.ClientMock{} + mockClient.On("GetWatcherServingCert", mock.Anything).Return(getActiveCertificate(), nil) + mockClient.On("GetGatewaySecret", mock.Anything).Return(&apicorev1.Secret{ + Data: map[string][]byte{ + "tls.crt": []byte("value1"), + "tls.key": []byte("value2"), + "ca.crt": []byte("value3"), + }, + }, nil) + mockClient.On("UpdateGatewaySecret", mock.Anything, mock.Anything).Return(nil) + timeParserFunction := getTimeParserFunction(false, false) + handler := cabundle.NewGatewaySecretHandler(mockClient, timeParserFunction, gatewaySwitchCertBeforeExpirationTime) + rootSecret := &apicorev1.Secret{ + Data: map[string][]byte{ + "tls.crt": []byte("value1"), + "tls.key": []byte("value2"), + "ca.crt": []byte("value3"), + }, + } + + // ACT + err := handler.ManageGatewaySecret(context.TODO(), rootSecret) + + // ASSERT + require.NoError(t, err) + mockClient.AssertNumberOfCalls(t, "UpdateGatewaySecret", 1) + mockClient.AssertCalled(t, "UpdateGatewaySecret", mock.Anything, mock.MatchedBy( + func(secret *apicorev1.Secret) bool { + return secret.Annotations[cabundle.CurrentCAExpirationAnnotation] != "" && + string(secret.Data["temp.ca.crt"]) == "value3" + })) +} + +//nolint:dupl // the tests may contain similar code but they test different scenarios +func TestManageGatewaySecret_WhenRequiresBundling_BundlesGatewaySecretWithRootSecretCA(t *testing.T) { + // ARRANGE + mockClient := &testutils.ClientMock{} + mockClient.On("GetWatcherServingCert", mock.Anything).Return(getActiveCertificate(), nil) + mockClient.On("GetGatewaySecret", mock.Anything).Return(&apicorev1.Secret{ + Data: map[string][]byte{ + "tls.crt": []byte("value1"), + "tls.key": []byte("value2"), + "ca.crt": []byte("value3"), + "temp.ca.crt": []byte("value3"), + }, + }, nil) + mockClient.On("UpdateGatewaySecret", mock.Anything, mock.Anything).Return(nil) + timeParserFunction := getTimeParserFunction(true, false) + handler := cabundle.NewGatewaySecretHandler(mockClient, timeParserFunction, gatewaySwitchCertBeforeExpirationTime) + rootSecret := &apicorev1.Secret{ + Data: map[string][]byte{ + "tls.crt": []byte("new-value1"), + "tls.key": []byte("new-value2"), + "ca.crt": []byte("new-value3"), + }, + } + + // ACT + err := handler.ManageGatewaySecret(context.TODO(), rootSecret) + + // ASSERT + require.NoError(t, err) + mockClient.AssertNumberOfCalls(t, "UpdateGatewaySecret", 1) + mockClient.AssertCalled(t, "UpdateGatewaySecret", mock.Anything, mock.MatchedBy( + func(secret *apicorev1.Secret) bool { + return string(secret.Data["tls.crt"]) == "value1" && + string(secret.Data["tls.key"]) == "value2" && + string(secret.Data["ca.crt"]) == "new-value3value3" && + string(secret.Data["temp.ca.crt"]) == "new-value3" + })) +} + +func TestManageGatewaySecret_WhenUpdateSecretFails_ReturnsError(t *testing.T) { + // ARRANGE + mockClient := &testutils.ClientMock{} + mockClient.On("GetWatcherServingCert", mock.Anything).Return(getActiveCertificate(), nil) + mockClient.On("GetGatewaySecret", mock.Anything).Return(&apicorev1.Secret{ + Data: map[string][]byte{ + "tls.crt": []byte("value1"), + "tls.key": []byte("value2"), + "ca.crt": []byte("value3"), + "temp.ca.crt": []byte("value3"), + }, + }, nil) + expectedError := errors.New("some-error") + mockClient.On("UpdateGatewaySecret", mock.Anything, mock.Anything).Return(expectedError) + timeParserFunction := getTimeParserFunction(true, false) + handler := cabundle.NewGatewaySecretHandler(mockClient, timeParserFunction, gatewaySwitchCertBeforeExpirationTime) + rootSecret := &apicorev1.Secret{ + Data: map[string][]byte{ + "tls.crt": []byte("new-value1"), + "tls.key": []byte("new-value2"), + "ca.crt": []byte("new-value3"), + }, + } + + // ACT + err := handler.ManageGatewaySecret(context.TODO(), rootSecret) + + // ASSERT + require.Error(t, err) + require.ErrorIs(t, err, expectedError) + mockClient.AssertNumberOfCalls(t, "GetWatcherServingCert", 1) + mockClient.AssertNumberOfCalls(t, "UpdateGatewaySecret", 1) +} + +//nolint:dupl // the tests may contain similar code but they test different scenarios +func TestManageGatewaySecret_WhenRequiresCertSwitching_SwitchesTLSCertAndKeyWithRootSecret(t *testing.T) { + // ARRANGE + mockClient := &testutils.ClientMock{} + mockClient.On("GetWatcherServingCert", mock.Anything).Return(getActiveCertificate(), nil) + mockClient.On("GetGatewaySecret", mock.Anything).Return(&apicorev1.Secret{ + Data: map[string][]byte{ + "tls.crt": []byte("value1"), + "tls.key": []byte("value2"), + "ca.crt": []byte("new-value3value3"), + "temp.ca.crt": []byte("new-value3"), + }, + }, nil) + mockClient.On("UpdateGatewaySecret", mock.Anything, mock.Anything).Return(nil) + timeParserFunction := getTimeParserFunction(false, true) + handler := cabundle.NewGatewaySecretHandler(mockClient, timeParserFunction, gatewaySwitchCertBeforeExpirationTime) + rootSecret := &apicorev1.Secret{ + Data: map[string][]byte{ + "tls.crt": []byte("new-value1"), + "tls.key": []byte("new-value2"), + "ca.crt": []byte("new-value3"), + }, + } + + // ACT + err := handler.ManageGatewaySecret(context.TODO(), rootSecret) + + // ASSERT + require.NoError(t, err) + mockClient.AssertNumberOfCalls(t, "UpdateGatewaySecret", 1) + mockClient.AssertCalled(t, "UpdateGatewaySecret", mock.Anything, mock.MatchedBy( + func(secret *apicorev1.Secret) bool { + return string(secret.Data["tls.crt"]) == "new-value1" && + string(secret.Data["tls.key"]) == "new-value2" && + string(secret.Data["ca.crt"]) == "new-value3value3" && + string(secret.Data["temp.ca.crt"]) == "new-value3" + })) +} + +func getActiveCertificate() *certmanagerv1.Certificate { + return &certmanagerv1.Certificate{ + Status: certmanagerv1.CertificateStatus{ + NotBefore: &apimetav1.Time{ + Time: time.Now().Add(-1 * time.Hour), + }, + NotAfter: &apimetav1.Time{ + Time: time.Now().Add(2 * time.Hour), + }, + }, + } +} + +func getTimeParserFunction(bundlingRequired, certSwitchRequired bool) gatewaysecret.TimeParserFunc { + var lastModifiedAt, currentCAExpiration time.Time + + if bundlingRequired { + lastModifiedAt = time.Now().Add(-2 * time.Hour) + } else { + lastModifiedAt = time.Now() + } + if certSwitchRequired { + currentCAExpiration = time.Now().Add(30 * time.Minute) + } else { + currentCAExpiration = time.Now().Add(2 * time.Hour) + } + + return func(secret *apicorev1.Secret, annotation string) (time.Time, error) { + if annotation == shared.LastModifiedAtAnnotation { + return lastModifiedAt, nil + } + return currentCAExpiration, nil + } +} + +func notFoundError() error { + return apierrors.NewNotFound(apicorev1.Resource("secrets"), "not-found") +} diff --git a/internal/gatewaysecret/handler.go b/internal/gatewaysecret/handler.go index c0c7052ad8..dd954077fc 100644 --- a/internal/gatewaysecret/handler.go +++ b/internal/gatewaysecret/handler.go @@ -6,10 +6,13 @@ import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" apicorev1 "k8s.io/api/core/v1" - apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) - "github.com/kyma-project/lifecycle-manager/api/shared" - "github.com/kyma-project/lifecycle-manager/pkg/util" +const ( + TLSCrt = "tls.crt" + TLSKey = "tls.key" + CACrt = "ca.crt" + SecretKind = "Secret" ) type Client interface { @@ -19,91 +22,8 @@ type Client interface { UpdateGatewaySecret(ctx context.Context, secret *apicorev1.Secret) error } -type TimeParserFunc func(secret *apicorev1.Secret) (time.Time, error) - -type Handler struct { - client Client - parseLastModifiedTime TimeParserFunc -} - -func NewGatewaySecretHandler(client Client, timeParserFunc TimeParserFunc) *Handler { - return &Handler{ - client: client, - parseLastModifiedTime: timeParserFunc, - } -} - -const ( - tlsCrt = "tls.crt" - tlsKey = "tls.key" - caCrt = "ca.crt" - secretKind = "Secret" -) - -func (h *Handler) ManageGatewaySecret(ctx context.Context, rootSecret *apicorev1.Secret) error { - gwSecret, err := h.client.GetGatewaySecret(ctx) - if util.IsNotFound(err) { - return h.createGatewaySecretFromRootSecret(ctx, rootSecret) - } else if err != nil { - return err - } - - caCert, err := h.client.GetWatcherServingCert(ctx) - if err != nil { - return err - } - - if h.requiresUpdate(gwSecret, caCert) { - copyDataFromRootSecret(gwSecret, rootSecret) - setLastModifiedToNow(gwSecret) - - return h.client.UpdateGatewaySecret(ctx, gwSecret) - } - - return nil -} - -func (h *Handler) createGatewaySecretFromRootSecret(ctx context.Context, rootSecret *apicorev1.Secret) error { - newSecret := &apicorev1.Secret{ - TypeMeta: apimetav1.TypeMeta{ - Kind: secretKind, - APIVersion: apicorev1.SchemeGroupVersion.String(), - }, - ObjectMeta: apimetav1.ObjectMeta{ - Name: shared.GatewaySecretName, - Namespace: shared.IstioNamespace, - }, - } - - copyDataFromRootSecret(newSecret, rootSecret) - setLastModifiedToNow(newSecret) - - return h.client.CreateGatewaySecret(ctx, newSecret) -} - -func (h *Handler) requiresUpdate(gwSecret *apicorev1.Secret, caCert *certmanagerv1.Certificate) bool { - // If the last modified time of the gateway secret is after the notBefore time of the CA certificate, - // then we don't need to update the gateway secret - if lastModified, err := h.parseLastModifiedTime(gwSecret); err == nil { - if caCert.Status.NotBefore != nil && lastModified.After(caCert.Status.NotBefore.Time) { - return false - } - } - return true -} - -func setLastModifiedToNow(secret *apicorev1.Secret) { - if secret.Annotations == nil { - secret.Annotations = make(map[string]string) - } - secret.Annotations[shared.LastModifiedAtAnnotation] = apimetav1.Now().Format(time.RFC3339) -} +type TimeParserFunc func(secret *apicorev1.Secret, annotation string) (time.Time, error) -func copyDataFromRootSecret(secret *apicorev1.Secret, rootSecret *apicorev1.Secret) { - if secret.Data == nil { - secret.Data = make(map[string][]byte) - } - secret.Data[tlsCrt] = rootSecret.Data[tlsCrt] - secret.Data[tlsKey] = rootSecret.Data[tlsKey] - secret.Data[caCrt] = rootSecret.Data[caCrt] +type Handler interface { + ManageGatewaySecret(ctx context.Context, rootSecret *apicorev1.Secret) error } diff --git a/internal/gatewaysecret/legacy/handler.go b/internal/gatewaysecret/legacy/handler.go new file mode 100644 index 0000000000..73e5a96eae --- /dev/null +++ b/internal/gatewaysecret/legacy/handler.go @@ -0,0 +1,94 @@ +package legacy + +import ( + "context" + "time" + + certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" + apicorev1 "k8s.io/api/core/v1" + apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyma-project/lifecycle-manager/api/shared" + "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret" + "github.com/kyma-project/lifecycle-manager/pkg/util" +) + +type Handler struct { + client gatewaysecret.Client + parseLastModifiedTime gatewaysecret.TimeParserFunc +} + +func NewGatewaySecretHandler(client gatewaysecret.Client, timeParserFunc gatewaysecret.TimeParserFunc) *Handler { + return &Handler{ + client: client, + parseLastModifiedTime: timeParserFunc, + } +} + +func (h *Handler) ManageGatewaySecret(ctx context.Context, rootSecret *apicorev1.Secret) error { + gwSecret, err := h.client.GetGatewaySecret(ctx) + if util.IsNotFound(err) { + return h.createGatewaySecretFromRootSecret(ctx, rootSecret) + } else if err != nil { + return err + } + + caCert, err := h.client.GetWatcherServingCert(ctx) + if err != nil { + return err + } + + if h.requiresUpdate(gwSecret, caCert) { + copyDataFromRootSecret(gwSecret, rootSecret) + setLastModifiedToNow(gwSecret) + + return h.client.UpdateGatewaySecret(ctx, gwSecret) + } + + return nil +} + +func (h *Handler) createGatewaySecretFromRootSecret(ctx context.Context, rootSecret *apicorev1.Secret) error { + newSecret := &apicorev1.Secret{ + TypeMeta: apimetav1.TypeMeta{ + Kind: gatewaysecret.SecretKind, + APIVersion: apicorev1.SchemeGroupVersion.String(), + }, + ObjectMeta: apimetav1.ObjectMeta{ + Name: shared.GatewaySecretName, + Namespace: shared.IstioNamespace, + }, + } + + copyDataFromRootSecret(newSecret, rootSecret) + setLastModifiedToNow(newSecret) + + return h.client.CreateGatewaySecret(ctx, newSecret) +} + +func (h *Handler) requiresUpdate(gwSecret *apicorev1.Secret, caCert *certmanagerv1.Certificate) bool { + // If the last modified time of the gateway secret is after the notBefore time of the CA certificate, + // then we don't need to update the gateway secret + if lastModified, err := h.parseLastModifiedTime(gwSecret, shared.LastModifiedAtAnnotation); err == nil { + if caCert.Status.NotBefore != nil && lastModified.After(caCert.Status.NotBefore.Time) { + return false + } + } + return true +} + +func setLastModifiedToNow(secret *apicorev1.Secret) { + if secret.Annotations == nil { + secret.Annotations = make(map[string]string) + } + secret.Annotations[shared.LastModifiedAtAnnotation] = apimetav1.Now().Format(time.RFC3339) +} + +func copyDataFromRootSecret(secret *apicorev1.Secret, rootSecret *apicorev1.Secret) { + if secret.Data == nil { + secret.Data = make(map[string][]byte) + } + secret.Data[gatewaysecret.TLSCrt] = rootSecret.Data[gatewaysecret.TLSCrt] + secret.Data[gatewaysecret.TLSKey] = rootSecret.Data[gatewaysecret.TLSKey] + secret.Data[gatewaysecret.CACrt] = rootSecret.Data[gatewaysecret.CACrt] +} diff --git a/internal/gatewaysecret/handler_test.go b/internal/gatewaysecret/legacy/handler_test.go similarity index 86% rename from internal/gatewaysecret/handler_test.go rename to internal/gatewaysecret/legacy/handler_test.go index 17ccc316a2..49c746783b 100644 --- a/internal/gatewaysecret/handler_test.go +++ b/internal/gatewaysecret/legacy/handler_test.go @@ -1,4 +1,4 @@ -package gatewaysecret_test +package legacy_test import ( "context" @@ -15,15 +15,17 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret" + "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret/legacy" + "github.com/kyma-project/lifecycle-manager/internal/gatewaysecret/testutils" ) func TestManageGatewaySecret_WhenGetGatewaySecretReturnsError_ReturnsError(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} someError := errors.New("some-error") mockClient.On("GetGatewaySecret", mock.Anything).Return(nil, someError) - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, nil) + handler := legacy.NewGatewaySecretHandler(mockClient, nil) // ACT err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) @@ -36,7 +38,7 @@ func TestManageGatewaySecret_WhenGetGatewaySecretReturnsError_ReturnsError(t *te func TestManageGatewaySecret_WhenGetGatewaySecretReturnsNotFoundError_CreatesGatewaySecretFromRootSecret(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} mockClient.On("GetGatewaySecret", mock.Anything).Return(nil, notFoundError()) mockClient.On("CreateGatewaySecret", mock.Anything, mock.Anything).Return(nil) rootSecret := &apicorev1.Secret{ @@ -46,7 +48,7 @@ func TestManageGatewaySecret_WhenGetGatewaySecretReturnsNotFoundError_CreatesGat "ca.crt": []byte("value3"), }, } - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, nil) + handler := legacy.NewGatewaySecretHandler(mockClient, nil) // ACT err := handler.ManageGatewaySecret(context.TODO(), rootSecret) @@ -70,12 +72,12 @@ func TestManageGatewaySecret_WhenGetGatewaySecretReturnsNotFoundError_CreatesGat func TestManageGatewaySecret_WhenGetGatewaySecretReturnsNotFoundErrorAndCreationFailed_ReturnError(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} mockClient.On("GetGatewaySecret", mock.Anything).Return(nil, notFoundError()) expectedError := errors.New("some-error") mockClient.On("CreateGatewaySecret", mock.Anything, mock.Anything).Return(expectedError) - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, nil) + handler := legacy.NewGatewaySecretHandler(mockClient, nil) // ACT err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) @@ -89,11 +91,11 @@ func TestManageGatewaySecret_WhenGetGatewaySecretReturnsNotFoundErrorAndCreation func TestManageGatewaySecret_WhenGetGatewaySecretReturnsNotFoundError_CreatesGatewaySecretWithLastModifiedAnnotation(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} mockClient.On("GetGatewaySecret", mock.Anything).Return(nil, notFoundError()) mockClient.On("CreateGatewaySecret", mock.Anything, mock.Anything).Return(nil) - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, nil) + handler := legacy.NewGatewaySecretHandler(mockClient, nil) // ACT err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) @@ -110,12 +112,12 @@ func TestManageGatewaySecret_WhenGetGatewaySecretReturnsNotFoundError_CreatesGat func TestManageGatewaySecret_WhenWatcherServingCertReturnsError_ReturnsError(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} mockClient.On("GetGatewaySecret", mock.Anything).Return(&apicorev1.Secret{}, nil) expectedError := errors.New("some-error") mockClient.On("GetWatcherServingCert", mock.Anything).Return(nil, expectedError) - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, nil) + handler := legacy.NewGatewaySecretHandler(mockClient, nil) // ACT err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) @@ -129,7 +131,7 @@ func TestManageGatewaySecret_WhenWatcherServingCertReturnsError_ReturnsError(t * func TestManageGatewaySecret_WhenRequiresUpdate_UpdatesGatewaySecretWithRootSecretData(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} mockClient.On("GetGatewaySecret", mock.Anything).Return(&apicorev1.Secret{}, nil) cert := &certmanagerv1.Certificate{ Status: certmanagerv1.CertificateStatus{ @@ -140,10 +142,12 @@ func TestManageGatewaySecret_WhenRequiresUpdate_UpdatesGatewaySecretWithRootSecr } mockClient.On("GetWatcherServingCert", mock.Anything).Return(cert, nil) mockClient.On("UpdateGatewaySecret", mock.Anything, mock.Anything).Return(nil) - var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret) (time.Time, error) { + var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret, + annotation string, + ) (time.Time, error) { return time.Now(), nil } - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, mockFunc) + handler := legacy.NewGatewaySecretHandler(mockClient, mockFunc) rootSecret := &apicorev1.Secret{ Data: map[string][]byte{ "tls.crt": []byte("value1"), @@ -168,7 +172,7 @@ func TestManageGatewaySecret_WhenRequiresUpdate_UpdatesGatewaySecretWithRootSecr func TestManageGatewaySecret_WhenRequiresUpdate_UpdatesGatewaySecretWithUpdatedModifiedNowAnnotation(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} originalTime := time.Now().Add(-time.Hour) gwSecret := &apicorev1.Secret{ ObjectMeta: apimetav1.ObjectMeta{ @@ -187,10 +191,12 @@ func TestManageGatewaySecret_WhenRequiresUpdate_UpdatesGatewaySecretWithUpdatedM } mockClient.On("GetWatcherServingCert", mock.Anything).Return(cert, nil) mockClient.On("UpdateGatewaySecret", mock.Anything, mock.Anything).Return(nil) - var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret) (time.Time, error) { + var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret, + annotation string, + ) (time.Time, error) { return time.Now(), nil } - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, mockFunc) + handler := legacy.NewGatewaySecretHandler(mockClient, mockFunc) // ACT err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) @@ -212,7 +218,7 @@ func TestManageGatewaySecret_WhenRequiresUpdate_UpdatesGatewaySecretWithUpdatedM func TestManageGatewaySecret_WhenRequiresUpdateAndUpdateFails_ReturnsError(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} mockClient.On("GetGatewaySecret", mock.Anything).Return(&apicorev1.Secret{}, nil) cert := &certmanagerv1.Certificate{ Status: certmanagerv1.CertificateStatus{ @@ -224,10 +230,12 @@ func TestManageGatewaySecret_WhenRequiresUpdateAndUpdateFails_ReturnsError(t *te mockClient.On("GetWatcherServingCert", mock.Anything).Return(cert, nil) expectedError := errors.New("some-error") mockClient.On("UpdateGatewaySecret", mock.Anything, mock.Anything).Return(expectedError) - var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret) (time.Time, error) { + var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret, + annotation string, + ) (time.Time, error) { return time.Now(), nil } - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, mockFunc) + handler := legacy.NewGatewaySecretHandler(mockClient, mockFunc) // ACT err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) @@ -241,7 +249,7 @@ func TestManageGatewaySecret_WhenRequiresUpdateAndUpdateFails_ReturnsError(t *te func TestManageGatewaySecret_WhenRequiresUpdateIsFalse_DoesNotUpdateGatewaySecret(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} mockClient.On("GetGatewaySecret", mock.Anything).Return(&apicorev1.Secret{}, nil) cert := &certmanagerv1.Certificate{ Status: certmanagerv1.CertificateStatus{ @@ -252,10 +260,12 @@ func TestManageGatewaySecret_WhenRequiresUpdateIsFalse_DoesNotUpdateGatewaySecre } mockClient.On("GetWatcherServingCert", mock.Anything).Return(cert, nil) mockClient.On("UpdateGatewaySecret", mock.Anything, mock.Anything).Return(nil) - var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret) (time.Time, error) { + var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret, + annotation string, + ) (time.Time, error) { return time.Now(), nil } - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, mockFunc) + handler := legacy.NewGatewaySecretHandler(mockClient, mockFunc) // ACT err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) @@ -267,7 +277,7 @@ func TestManageGatewaySecret_WhenRequiresUpdateIsFalse_DoesNotUpdateGatewaySecre func TestManageGatewaySecret_WhenTimeParserFuncReturnsError_UpdatesGatewaySecret(t *testing.T) { // ARRANGE - mockClient := &ClientMock{} + mockClient := &testutils.ClientMock{} mockClient.On("GetGatewaySecret", mock.Anything).Return(&apicorev1.Secret{}, nil) cert := &certmanagerv1.Certificate{ Status: certmanagerv1.CertificateStatus{ @@ -278,12 +288,14 @@ func TestManageGatewaySecret_WhenTimeParserFuncReturnsError_UpdatesGatewaySecret } mockClient.On("GetWatcherServingCert", mock.Anything).Return(cert, nil) mockClient.On("UpdateGatewaySecret", mock.Anything, mock.Anything).Return(nil) - var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret) (time.Time, error) { + var mockFunc gatewaysecret.TimeParserFunc = func(secret *apicorev1.Secret, + annotation string, + ) (time.Time, error) { return time.Time{}, errors.New("some-error") } - handler := gatewaysecret.NewGatewaySecretHandler(mockClient, mockFunc) + handler := legacy.NewGatewaySecretHandler(mockClient, mockFunc) - // ACT + // ACT″ err := handler.ManageGatewaySecret(context.TODO(), &apicorev1.Secret{}) // ASSERT diff --git a/internal/gatewaysecret/mock_Client_test.go b/internal/gatewaysecret/testutils/mock_Client.go similarity index 99% rename from internal/gatewaysecret/mock_Client_test.go rename to internal/gatewaysecret/testutils/mock_Client.go index bb54f2243b..d609fc10c9 100644 --- a/internal/gatewaysecret/mock_Client_test.go +++ b/internal/gatewaysecret/testutils/mock_Client.go @@ -1,6 +1,6 @@ // Code generated by mockery v2.50.0. DO NOT EDIT. -package gatewaysecret_test +package testutils import ( context "context" diff --git a/internal/maintenancewindows/maintenance_window.go b/internal/maintenancewindows/maintenance_window.go index 09e08f7a3d..4e881c0afa 100644 --- a/internal/maintenancewindows/maintenance_window.go +++ b/internal/maintenancewindows/maintenance_window.go @@ -12,7 +12,10 @@ import ( "github.com/kyma-project/lifecycle-manager/maintenancewindows/resolver" ) -var ErrNoMaintenanceWindowPolicyConfigured = errors.New("no maintenance window policy configured") +var ( + ErrNoMaintenanceWindowPolicyConfigured = errors.New("no maintenance window policy configured") + ErrPolicyFileNotFound = errors.New("maintenance window policy file not found") +) type MaintenanceWindowPolicy interface { Resolve(runtime *resolver.Runtime, opts ...interface{}) (*resolver.ResolvedWindow, error) @@ -22,41 +25,44 @@ type MaintenanceWindow struct { // make this private once we refactor the API // https://github.com/kyma-project/lifecycle-manager/issues/2190 MaintenanceWindowPolicy MaintenanceWindowPolicy - ongoing resolver.OngoingWindow minDuration resolver.MinWindowSize } func InitializeMaintenanceWindow(log logr.Logger, policiesDirectory, policyName string, - ongoingWindow bool, minWindowSize time.Duration, -) (*MaintenanceWindow, error) { +) (MaintenanceWindow, error) { if err := os.Setenv(resolver.PolicyPathENV, policiesDirectory); err != nil { - return nil, fmt.Errorf("failed to set the policy path env variable, %w", err) + return MaintenanceWindow{ + MaintenanceWindowPolicy: nil, + }, fmt.Errorf("failed to set the policy path env variable, %w", err) } policyFilePath := fmt.Sprintf("%s/%s.json", policiesDirectory, policyName) if !MaintenancePolicyFileExists(policyFilePath) { - log.Info("maintenance windows policy file does not exist") - return &MaintenanceWindow{ + log.Error(ErrPolicyFileNotFound, "maintenance windows policy file does not exist") + return MaintenanceWindow{ MaintenanceWindowPolicy: nil, - }, nil + }, fmt.Errorf("maintenance windows policy file does not exist, %w", ErrPolicyFileNotFound) } maintenancePolicyPool, err := resolver.GetMaintenancePolicyPool() if err != nil { - return nil, fmt.Errorf("failed to get maintenance policy pool, %w", err) + return MaintenanceWindow{ + MaintenanceWindowPolicy: nil, + }, fmt.Errorf("failed to get maintenance policy pool, %w", err) } maintenancePolicy, err := resolver.GetMaintenancePolicy(maintenancePolicyPool, policyName) if err != nil { - return nil, fmt.Errorf("failed to get maintenance window policy, %w", err) + return MaintenanceWindow{ + MaintenanceWindowPolicy: nil, + }, fmt.Errorf("failed to get maintenance window policy, %w", err) } - return &MaintenanceWindow{ + return MaintenanceWindow{ MaintenanceWindowPolicy: maintenancePolicy, - ongoing: resolver.OngoingWindow(ongoingWindow), minDuration: resolver.MinWindowSize(minWindowSize), }, nil } @@ -103,7 +109,7 @@ func (mw MaintenanceWindow) IsActive(kyma *v1beta2.Kyma) (bool, error) { } resolvedWindow, err := mw.MaintenanceWindowPolicy.Resolve(runtime, - mw.ongoing, + resolver.OngoingWindow(true), mw.minDuration) if err != nil { return false, err diff --git a/internal/maintenancewindows/maintenance_window_test.go b/internal/maintenancewindows/maintenance_window_test.go index 4dad868728..baf2149f20 100644 --- a/internal/maintenancewindows/maintenance_window_test.go +++ b/internal/maintenancewindows/maintenance_window_test.go @@ -30,36 +30,33 @@ func TestMaintenancePolicyFileExists_FileExists(t *testing.T) { require.True(t, got) } -func TestInitializeMaintenanceWindowsPolicy_FileNotExist_NoError(t *testing.T) { +func TestInitializeMaintenanceWindowsPolicy_FileNotExist(t *testing.T) { got, err := maintenancewindows.InitializeMaintenanceWindow(logr.Logger{}, "testdata", "policy-1", - true, 20*time.Minute) require.Nil(t, got.MaintenanceWindowPolicy) - require.NoError(t, err) + require.ErrorContains(t, err, maintenancewindows.ErrPolicyFileNotFound.Error()) } -func TestInitializeMaintenanceWindowsPolicy_DirectoryNotExist_NoError(t *testing.T) { +func TestInitializeMaintenanceWindowsPolicy_DirectoryNotExist(t *testing.T) { got, err := maintenancewindows.InitializeMaintenanceWindow(logr.Logger{}, "files", "policy", - true, 20*time.Minute) require.Nil(t, got.MaintenanceWindowPolicy) - require.NoError(t, err) + require.ErrorContains(t, err, maintenancewindows.ErrPolicyFileNotFound.Error()) } func TestInitializeMaintenanceWindowsPolicy_InvalidPolicy(t *testing.T) { got, err := maintenancewindows.InitializeMaintenanceWindow(logr.Logger{}, "testdata", "invalid-policy", - true, 20*time.Minute) - require.Nil(t, got) + require.Nil(t, got.MaintenanceWindowPolicy) require.ErrorContains(t, err, "failed to get maintenance window policy") } @@ -67,7 +64,6 @@ func TestInitializeMaintenanceWindowsPolicy_WhenFileExists_CorrectPolicyIsRead(t got, err := maintenancewindows.InitializeMaintenanceWindow(logr.Logger{}, "testdata", "policy", - true, 20*time.Minute) require.NoError(t, err) @@ -321,7 +317,9 @@ func Test_IsActive_Returns_False_And_Error_WhenNoPolicyConfigured(t *testing.T) type maintenanceWindowInactiveStub struct{} -func (s maintenanceWindowInactiveStub) Resolve(runtime *resolver.Runtime, opts ...interface{}) (*resolver.ResolvedWindow, error) { +func (s maintenanceWindowInactiveStub) Resolve(runtime *resolver.Runtime, + opts ...interface{}, +) (*resolver.ResolvedWindow, error) { return &resolver.ResolvedWindow{ Begin: time.Now().Add(1 * time.Hour), End: time.Now().Add(2 * time.Hour), @@ -330,7 +328,9 @@ func (s maintenanceWindowInactiveStub) Resolve(runtime *resolver.Runtime, opts . type maintenanceWindowActiveStub struct{} -func (s maintenanceWindowActiveStub) Resolve(runtime *resolver.Runtime, opts ...interface{}) (*resolver.ResolvedWindow, error) { +func (s maintenanceWindowActiveStub) Resolve(runtime *resolver.Runtime, opts ...interface{}) (*resolver.ResolvedWindow, + error, +) { return &resolver.ResolvedWindow{ Begin: time.Now().Add(-1 * time.Hour), End: time.Now().Add(1 * time.Hour), @@ -339,7 +339,9 @@ func (s maintenanceWindowActiveStub) Resolve(runtime *resolver.Runtime, opts ... type maintenanceWindowErrorStub struct{} -func (s maintenanceWindowErrorStub) Resolve(runtime *resolver.Runtime, opts ...interface{}) (*resolver.ResolvedWindow, error) { +func (s maintenanceWindowErrorStub) Resolve(runtime *resolver.Runtime, opts ...interface{}) (*resolver.ResolvedWindow, + error, +) { return &resolver.ResolvedWindow{}, errors.New("test error") } @@ -347,7 +349,9 @@ type maintenanceWindowRuntimeArgStub struct { receivedRuntime *resolver.Runtime } -func (s maintenanceWindowRuntimeArgStub) Resolve(runtime *resolver.Runtime, opts ...interface{}) (*resolver.ResolvedWindow, error) { +func (s maintenanceWindowRuntimeArgStub) Resolve(runtime *resolver.Runtime, + opts ...interface{}, +) (*resolver.ResolvedWindow, error) { *s.receivedRuntime = *runtime return &resolver.ResolvedWindow{}, nil diff --git a/internal/manifest/finalizer/handler.go b/internal/manifest/finalizer/handler.go index b73130e3fd..dae0697fa2 100644 --- a/internal/manifest/finalizer/handler.go +++ b/internal/manifest/finalizer/handler.go @@ -10,7 +10,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/internal/manifest/labelsremoval" "github.com/kyma-project/lifecycle-manager/pkg/util" ) @@ -19,11 +18,12 @@ var ErrRequeueRequired = errors.New("requeue required") const ( DefaultFinalizer = "declarative.kyma-project.io/finalizer" CustomResourceManagerFinalizer = "resource.kyma-project.io/finalizer" + LabelRemovalFinalizer = "label-removal-finalizer" ) // RemoveRequiredFinalizers removes preconfigured finalizers, but not include CustomResourceManagerFinalizer. func RemoveRequiredFinalizers(manifest *v1beta2.Manifest) bool { - finalizersToRemove := []string{DefaultFinalizer, labelsremoval.LabelRemovalFinalizer} + finalizersToRemove := []string{DefaultFinalizer, LabelRemovalFinalizer} finalizerRemoved := false for _, f := range finalizersToRemove { @@ -46,7 +46,7 @@ func RemoveAllFinalizers(manifest *v1beta2.Manifest) bool { func FinalizersUpdateRequired(manifest *v1beta2.Manifest) bool { defaultFinalizerAdded := controllerutil.AddFinalizer(manifest, DefaultFinalizer) - labelRemovalFinalizerAdded := controllerutil.AddFinalizer(manifest, labelsremoval.LabelRemovalFinalizer) + labelRemovalFinalizerAdded := controllerutil.AddFinalizer(manifest, LabelRemovalFinalizer) return defaultFinalizerAdded || labelRemovalFinalizerAdded } diff --git a/internal/manifest/labelsremoval/labels_removal.go b/internal/manifest/labelsremoval/labels_removal.go index 5e397c1cb9..5493ade7f6 100644 --- a/internal/manifest/labelsremoval/labels_removal.go +++ b/internal/manifest/labelsremoval/labels_removal.go @@ -2,6 +2,7 @@ package labelsremoval import ( "context" + "errors" "fmt" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -11,37 +12,43 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/internal/manifest/finalizer" + "github.com/kyma-project/lifecycle-manager/internal/manifest/modulecr" ) -const LabelRemovalFinalizer = "label-removal-finalizer" - type ManifestAPIClient interface { UpdateManifest(ctx context.Context, manifest *v1beta2.Manifest) error } -type ManagedLabelRemovalService struct { +type ManagedByLabelRemovalService struct { manifestClient ManifestAPIClient } -func NewManagedLabelRemovalService(manifestClient ManifestAPIClient) *ManagedLabelRemovalService { - return &ManagedLabelRemovalService{ +func NewManagedByLabelRemovalService(manifestClient ManifestAPIClient) *ManagedByLabelRemovalService { + return &ManagedByLabelRemovalService{ manifestClient: manifestClient, } } -func (l *ManagedLabelRemovalService) RemoveManagedLabel(ctx context.Context, - manifest *v1beta2.Manifest, skrClient client.Client, defaultCR *unstructured.Unstructured, +func (l *ManagedByLabelRemovalService) RemoveManagedByLabel(ctx context.Context, + manifest *v1beta2.Manifest, + skrClient client.Client, ) error { - if err := HandleLabelsRemovalFromResources(ctx, manifest, skrClient, defaultCR); err != nil { - return err + resourcesError := removeFromSyncedResources(ctx, manifest, skrClient) + defaultCRError := removeFromDefaultCR(ctx, manifest, skrClient) + + if resourcesError != nil || defaultCRError != nil { + return fmt.Errorf("failed to remove %s label from one or more resources: %w", + shared.ManagedBy, + errors.Join(resourcesError, defaultCRError)) } - controllerutil.RemoveFinalizer(manifest, LabelRemovalFinalizer) + controllerutil.RemoveFinalizer(manifest, finalizer.LabelRemovalFinalizer) return l.manifestClient.UpdateManifest(ctx, manifest) } -func HandleLabelsRemovalFromResources(ctx context.Context, manifestCR *v1beta2.Manifest, - skrClient client.Client, defaultCR *unstructured.Unstructured, +func removeFromSyncedResources(ctx context.Context, manifestCR *v1beta2.Manifest, + skrClient client.Client, ) error { for _, res := range manifestCR.Status.Synced { objectKey := client.ObjectKey{ @@ -54,19 +61,33 @@ func HandleLabelsRemovalFromResources(ctx context.Context, manifestCR *v1beta2.M return fmt.Errorf("failed to get resource, %w", err) } - if IsManagedLabelRemoved(obj) { - if err := skrClient.Update(ctx, obj); err != nil { - return fmt.Errorf("failed to update object: %w", err) - } + if err := removeFromObject(ctx, obj, skrClient); err != nil { + return err } } - if defaultCR == nil { + return nil +} + +func removeFromDefaultCR(ctx context.Context, + manifest *v1beta2.Manifest, + skrClient client.Client, +) error { + if manifest.Spec.Resource == nil { return nil } - if IsManagedLabelRemoved(defaultCR) { - if err := skrClient.Update(ctx, defaultCR); err != nil { + defaultCR, err := modulecr.NewClient(skrClient).GetCR(ctx, manifest) + if err != nil { + return fmt.Errorf("failed to get default CR, %w", err) + } + + return removeFromObject(ctx, defaultCR, skrClient) +} + +func removeFromObject(ctx context.Context, obj *unstructured.Unstructured, skrClient client.Client) error { + if removeManagedLabel(obj) { + if err := skrClient.Update(ctx, obj); err != nil { return fmt.Errorf("failed to update object: %w", err) } } @@ -87,7 +108,7 @@ func constructResource(resource shared.Resource) *unstructured.Unstructured { return obj } -func IsManagedLabelRemoved(resource *unstructured.Unstructured) bool { +func removeManagedLabel(resource *unstructured.Unstructured) bool { labels := resource.GetLabels() _, managedByLabelExists := labels[shared.ManagedBy] if managedByLabelExists { diff --git a/internal/manifest/labelsremoval/labels_removal_test.go b/internal/manifest/labelsremoval/labels_removal_test.go index ec0f458818..ddc21d042e 100644 --- a/internal/manifest/labelsremoval/labels_removal_test.go +++ b/internal/manifest/labelsremoval/labels_removal_test.go @@ -2,8 +2,10 @@ package labelsremoval_test import ( "context" + "errors" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -15,34 +17,10 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" "github.com/kyma-project/lifecycle-manager/internal/manifest/labelsremoval" - "github.com/kyma-project/lifecycle-manager/internal/manifest/manifestclient" "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" ) -func Test_needsUpdateAfterLabelRemoval_WhenLabelsAreEmpty(t *testing.T) { - emptyLabels := map[string]string{} - res := &unstructured.Unstructured{} - res.SetLabels(emptyLabels) - actual := labelsremoval.IsManagedLabelRemoved(res) - - require.False(t, actual) - require.Equal(t, emptyLabels, res.GetLabels()) -} - -func Test_needsUpdateAfterLabelRemoval_WhenManagedByLabel(t *testing.T) { - labels := map[string]string{ - shared.ManagedBy: shared.ManagedByLabelValue, - } - expectedLabels := map[string]string{} - res := &unstructured.Unstructured{} - res.SetLabels(labels) - actual := labelsremoval.IsManagedLabelRemoved(res) - - require.True(t, actual) - require.Equal(t, expectedLabels, res.GetLabels()) -} - -func Test_handleLabelsRemovalFromResources_WhenManifestResourcesHaveLabels(t *testing.T) { +func Test_RemoveManagedByLabel_WhenManifestResourcesHaveLabels(t *testing.T) { gvk := schema.GroupVersionKind{ Group: "test-group", Version: "v1", @@ -105,8 +83,11 @@ func Test_handleLabelsRemovalFromResources_WhenManifestResourcesHaveLabels(t *te err := v1beta2.AddToScheme(scheme) require.NoError(t, err) fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(objs...).Build() + manifestClient := manifestClientStub{} + + service := labelsremoval.NewManagedByLabelRemovalService(&manifestClient) - err = labelsremoval.HandleLabelsRemovalFromResources(context.TODO(), manifest, fakeClient, nil) + err = service.RemoveManagedByLabel(context.TODO(), manifest, fakeClient) require.NoError(t, err) firstObj, secondObj := &unstructured.Unstructured{}, &unstructured.Unstructured{} @@ -121,29 +102,20 @@ func Test_handleLabelsRemovalFromResources_WhenManifestResourcesHaveLabels(t *te secondObj) require.NoError(t, err) require.Empty(t, secondObj.GetLabels()) -} -func Test_handleLabelsRemovalFromResources_WhenManifestResourcesAreNilAndNoDefaultCR(t *testing.T) { - manifest := builder.NewManifestBuilder().Build() + assert.True(t, manifestClient.called) +} +func Test_RemoveManagedByLabel_WhenManifestResourceCannotBeFetched(t *testing.T) { scheme := machineryruntime.NewScheme() err := v1beta2.AddToScheme(scheme) require.NoError(t, err) - fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build() - - err = labelsremoval.HandleLabelsRemovalFromResources(context.TODO(), manifest, fakeClient, nil) - - require.NoError(t, err) -} - -func Test_handleLabelsRemovalFromResources_WhenManifestResourcesAndDefaultCRHaveLabels(t *testing.T) { gvk := schema.GroupVersionKind{ Group: "test-group", Version: "v1", Kind: "TestKind", } - status := shared.Status{ Synced: []shared.Resource{ { @@ -159,20 +131,22 @@ func Test_handleLabelsRemovalFromResources_WhenManifestResourcesAndDefaultCRHave } manifest := builder.NewManifestBuilder().WithStatus(status).Build() - objs := []client.Object{ - &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": gvk.GroupVersion().String(), - "kind": gvk.Kind, - "version": gvk.Version, - }, - }, + fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build() + manifestClient := manifestClientStub{} + + svc := labelsremoval.NewManagedByLabelRemovalService(&manifestClient) + + err = svc.RemoveManagedByLabel(context.TODO(), manifest, fakeClient) + require.ErrorContains(t, err, "failed to get resource") + assert.False(t, manifestClient.called) +} + +func Test_RemoveManagedByLabel_WhenDefaultCRHasLabels(t *testing.T) { + gvk := schema.GroupVersionKind{ + Group: "test-group", + Version: "v1", + Kind: "TestKind", } - objs[0].SetName("test-resource-1") - objs[0].SetNamespace("test-1") - objs[0].SetLabels(map[string]string{ - "operator.kyma-project.io/managed-by": "kyma", - }) defaultCR := &unstructured.Unstructured{} defaultCR.SetName("default-cr") @@ -181,36 +155,61 @@ func Test_handleLabelsRemovalFromResources_WhenManifestResourcesAndDefaultCRHave defaultCR.SetLabels(map[string]string{ "operator.kyma-project.io/managed-by": "kyma", }) - - objs = append(objs, defaultCR) + objs := []client.Object{defaultCR} scheme := machineryruntime.NewScheme() err := v1beta2.AddToScheme(scheme) require.NoError(t, err) fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(objs...).Build() + manifest := builder.NewManifestBuilder().WithResource(defaultCR).Build() + manifestClient := manifestClientStub{} - err = labelsremoval.HandleLabelsRemovalFromResources(context.TODO(), manifest, fakeClient, - defaultCR) + service := labelsremoval.NewManagedByLabelRemovalService(&manifestClient) - require.NoError(t, err) + err = service.RemoveManagedByLabel(context.TODO(), manifest, fakeClient) - firstObj := &unstructured.Unstructured{} - firstObj.SetGroupVersionKind(gvk) - err = fakeClient.Get(context.TODO(), client.ObjectKey{Name: "test-resource-1", Namespace: "test-1"}, - firstObj) require.NoError(t, err) - require.Empty(t, firstObj.GetLabels()) + err = fakeClient.Get(context.TODO(), + client.ObjectKey{Name: "default-cr", Namespace: "default-ns"}, + defaultCR) require.NoError(t, err) - require.Empty(t, defaultCR.GetLabels()) + assert.Empty(t, defaultCR.GetLabels()) } -func Test_RemoveManagedLabel_WhenErrorIsReturned(t *testing.T) { +func Test_RemoveManagedByLabel_WhenDefaultCRCannotBeFetched(t *testing.T) { + gvk := schema.GroupVersionKind{ + Group: "test-group", + Version: "v1", + Kind: "TestKind", + } + + defaultCR := &unstructured.Unstructured{} + defaultCR.SetName("default-cr") + defaultCR.SetNamespace("default-ns") + defaultCR.SetGroupVersionKind(gvk) + defaultCR.SetLabels(map[string]string{ + "operator.kyma-project.io/managed-by": "kyma", + }) + scheme := machineryruntime.NewScheme() err := v1beta2.AddToScheme(scheme) require.NoError(t, err) + fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build() + manifest := builder.NewManifestBuilder().WithResource(defaultCR).Build() + manifestClient := manifestClientStub{} + + service := labelsremoval.NewManagedByLabelRemovalService(&manifestClient) + + err = service.RemoveManagedByLabel(context.TODO(), manifest, fakeClient) + + require.ErrorContains(t, err, "failed to get default CR") + assert.False(t, manifestClient.called) +} + +func Test_RemoveManagedByLabel_WhenObjCannotBeUpdated(t *testing.T) { gvk := schema.GroupVersionKind{ Group: "test-group", Version: "v1", @@ -229,18 +228,57 @@ func Test_RemoveManagedLabel_WhenErrorIsReturned(t *testing.T) { }, }, } + + objs := []client.Object{ + &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": gvk.GroupVersion().String(), + "kind": gvk.Kind, + "version": gvk.Version, + }, + }, + } + objs[0].SetName("test-resource-1") + objs[0].SetNamespace("test-1") + objs[0].SetLabels(map[string]string{ + "operator.kyma-project.io/managed-by": "kyma", + }) + + scheme := machineryruntime.NewScheme() + err := v1beta2.AddToScheme(scheme) + require.NoError(t, err) + fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(objs...).Build() + manifest := builder.NewManifestBuilder().WithStatus(status).Build() + manifestClient := manifestClientStub{} + + service := labelsremoval.NewManagedByLabelRemovalService(&manifestClient) + + err = service.RemoveManagedByLabel(context.TODO(), manifest, errorClientStub{fakeClient: fakeClient}) + + require.ErrorContains(t, err, "failed to update object") + require.ErrorContains(t, err, "test error") +} + +func Test_RemoveManagedByLabel_WhenManifestResourcesAreNilAndNoDefaultCR(t *testing.T) { + manifest := builder.NewManifestBuilder().Build() + + scheme := machineryruntime.NewScheme() + err := v1beta2.AddToScheme(scheme) + require.NoError(t, err) fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build() + manifestClient := manifestClientStub{} - manifestClnt := manifestclient.NewManifestClient(nil, fakeClient) - svc := labelsremoval.NewManagedLabelRemovalService(manifestClnt) + service := labelsremoval.NewManagedByLabelRemovalService(&manifestClient) - err = svc.RemoveManagedLabel(context.TODO(), manifest, fakeClient, nil) - require.ErrorContains(t, err, "failed to get resource") + err = service.RemoveManagedByLabel(context.TODO(), manifest, fakeClient) + + require.NoError(t, err) + assert.True(t, manifestClient.called) } -func Test_RemoveManagedLabel_WhenFinalizerIsRemoved(t *testing.T) { +func Test_RemoveManagedByLabel_WhenFinalizerIsRemoved(t *testing.T) { scheme := machineryruntime.NewScheme() err := v1beta2.AddToScheme(scheme) require.NoError(t, err) @@ -282,15 +320,37 @@ func Test_RemoveManagedLabel_WhenFinalizerIsRemoved(t *testing.T) { }) fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(manifest).WithObjects(objs...).Build() + manifestClient := manifestClientStub{} + svc := labelsremoval.NewManagedByLabelRemovalService(&manifestClient) - manifestClnt := manifestclient.NewManifestClient(nil, fakeClient) - svc := labelsremoval.NewManagedLabelRemovalService(manifestClnt) + err = svc.RemoveManagedByLabel(context.TODO(), manifest, fakeClient) - err = svc.RemoveManagedLabel(context.TODO(), manifest, fakeClient, nil) require.NoError(t, err) + assert.Empty(t, manifest.GetFinalizers()) + assert.True(t, manifestClient.called) +} - err = fakeClient.Get(context.TODO(), client.ObjectKey{Name: manifest.GetName(), Namespace: manifest.GetNamespace()}, - manifest) - require.NoError(t, err) - require.Empty(t, manifest.GetFinalizers()) +// stubs + +type manifestClientStub struct { + called bool + err error +} + +func (m *manifestClientStub) UpdateManifest(ctx context.Context, manifest *v1beta2.Manifest) error { + m.called = true + return m.err +} + +type errorClientStub struct { + client.Client + fakeClient client.Client +} + +func (e errorClientStub) Update(_ context.Context, _ client.Object, _ ...client.UpdateOption) error { + return errors.New("test error") +} + +func (e errorClientStub) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { + return e.fakeClient.Get(ctx, key, obj, opts...) } diff --git a/internal/manifest/modulecr/client.go b/internal/manifest/modulecr/client.go index 2d80a8a6a0..0b8ce7fb7d 100644 --- a/internal/manifest/modulecr/client.go +++ b/internal/manifest/modulecr/client.go @@ -2,6 +2,7 @@ package modulecr import ( "context" + "errors" "fmt" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -17,6 +18,8 @@ import ( "github.com/kyma-project/lifecycle-manager/pkg/util" ) +var ErrNoResourceDefined = errors.New("no resource defined in the manifest") + type Client struct { client.Client } @@ -30,6 +33,10 @@ func NewClient(client client.Client) *Client { func (c *Client) GetCR(ctx context.Context, manifest *v1beta2.Manifest) (*unstructured.Unstructured, error, ) { + if manifest.Spec.Resource == nil { + return nil, ErrNoResourceDefined + } + resourceCR := &unstructured.Unstructured{} name := manifest.Spec.Resource.GetName() namespace := manifest.Spec.Resource.GetNamespace() @@ -111,7 +118,7 @@ func (c *Client) SyncModuleCR(ctx context.Context, manifest *v1beta2.Manifest) e } resource := manifest.Spec.Resource.DeepCopy() - resource.SetLabels(collections.MergeMaps(resource.GetLabels(), map[string]string{ + resource.SetLabels(collections.MergeMapsSilent(resource.GetLabels(), map[string]string{ shared.ManagedBy: shared.ManagedByLabelValue, })) diff --git a/internal/manifest/skrresources/collector.go b/internal/manifest/skrresources/collector.go new file mode 100644 index 0000000000..f939f7f695 --- /dev/null +++ b/internal/manifest/skrresources/collector.go @@ -0,0 +1,192 @@ +package skrresources + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "os" + "regexp" + "slices" + "strconv" + "strings" + "sync" + "time" + + "github.com/jellydator/ttlcache/v3" + apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + + "github.com/kyma-project/lifecycle-manager/api/shared" + "github.com/kyma-project/lifecycle-manager/internal" + "github.com/kyma-project/lifecycle-manager/internal/manifest/manifestclient" +) + +const ( + knownManagersDefault = string(manifestclient.DefaultFieldOwner) + ";" + + shared.OperatorName + ";" + + "k3s" // Applied in k3s environments. + knownManagersEnvVar = "KLM_EXPERIMENTAL_KNOWN_MANAGERS" + knownManagersRegexp = `^[a-zA-Z][a-zA-Z0-9.:_/-]{1,127}$` + + frequencyLimiterTTLDefault = 60 * 5 // 5 minutes + frequencyLimiterTTLEnvVar = "KLM_EXPERIMENTAL_FREQUENCY_LIMITER_TTL" + frequencyLimiterTTLRegexp = `^[1-9][0-9]{1,3}$` + + managedFieldsAnalysisLabelEnvVar = "KLM_EXPERIMENTAL_MANAGED_FIELDS_ANALYSIS_LABEL" +) + +var ( + allowedManagers = getAllowedManagers() //nolint:gochecknoglobals // list of managers is a global configuration + singletonFrequencyLimiter = newFrequencyLimiter() //nolint:gochecknoglobals // singleton cache is used to prevent emitting the same log multiple times in a short period +) + +type LogCollectorEntry struct { + ObjectName string `json:"objectName"` + ObjectNamespace string `json:"objectNamespace"` + ObjectGVK string `json:"objectGvk"` + ManagedFields []apimetav1.ManagedFieldsEntry `json:"managedFields"` +} + +// Implements skrresources.ManagedFieldsCollector interface, emits the collected data to the log stream. +// The collector is thread-safe. +// The collector is frequency-limited to prevent emitting entries for the same objectKey multiple times in a short time. +type LogCollector struct { + objectKey string + frequencyLimiter *ttlcache.Cache[string, bool] + owner client.FieldOwner + entries []LogCollectorEntry + mu sync.Mutex +} + +func NewLogCollector(key string, owner client.FieldOwner) *LogCollector { + return &LogCollector{ + objectKey: key, + owner: owner, + entries: []LogCollectorEntry{}, + frequencyLimiter: singletonFrequencyLimiter, + } +} + +// safeAddEntry adds a new entry to the collector's entries slice in a thread-safe way. +func (c *LogCollector) safeAddEntry(entry LogCollectorEntry) { + c.mu.Lock() + defer c.mu.Unlock() + c.entries = append(c.entries, entry) +} + +func (c *LogCollector) Collect(ctx context.Context, remoteObj client.Object) { + managedFields := remoteObj.GetManagedFields() + for _, mf := range managedFields { + if isUnknownManager(mf.Manager) { + newEntry := LogCollectorEntry{ + ObjectName: remoteObj.GetName(), + ObjectNamespace: remoteObj.GetNamespace(), + ObjectGVK: remoteObj.GetObjectKind().GroupVersionKind().String(), + ManagedFields: slices.Clone(remoteObj.GetManagedFields()), + } + c.safeAddEntry(newEntry) + return + } + } +} + +func (c *LogCollector) Emit(ctx context.Context) error { + if c.frequencyLimiter.Has(c.objectKey) { + logger := logf.FromContext(ctx, "owner", c.owner) + logger.V(internal.TraceLogLevel).Info("Unknown managers detection skipped (frequency)") + return nil + } + + c.mu.Lock() + defer c.mu.Unlock() + + if len(c.entries) > 0 { + c.frequencyLimiter.Set(c.objectKey, true, ttlcache.DefaultTTL) + + jsonSer, err := json.MarshalIndent(c.entries, "", " ") + if err != nil { + return fmt.Errorf("failed to serialize managed field data: %w", err) + } + logData, err := compressAndBase64(jsonSer) + if err != nil { + return err + } + + logger := logf.FromContext(ctx, "owner", c.owner) + logger.V(internal.TraceLogLevel).Info("Unknown managers detected", "base64gzip", logData) + } + return nil +} + +// compressAndBase64 compresses the input byte slice using gzip and encodes it to base64 so that it can be logged as a string. +func compressAndBase64(in []byte) (string, error) { + var buf bytes.Buffer + archive := gzip.NewWriter(&buf) + + _, err := archive.Write(in) + if err != nil { + return "", fmt.Errorf("failed to write to gzip archive: %w", err) + } + + if err := archive.Close(); err != nil { + return "", fmt.Errorf("failed to close gzip archive: %w", err) + } + + return base64.StdEncoding.EncodeToString(buf.Bytes()), nil +} + +func isUnknownManager(manager string) bool { + return !slices.Contains(allowedManagers, manager) +} + +// allowedManagers returns either a list configured in the KLM_RECONCILECONFIG_KNOWN_MANAGERS environment variable or the default list. +// The values must be separated by semicolons and are case-sensitive! +func getAllowedManagers() []string { + configured := os.Getenv(knownManagersEnvVar) + if configured == "" { + return splitBySemicolons(knownManagersDefault) + } else { + rxp := regexp.MustCompile(knownManagersRegexp) + configuredValues := splitBySemicolons(configured) + res := []string{} + for _, name := range configuredValues { + if rxp.MatchString(name) { + res = append(res, name) + } + } + return res + } +} + +func getFrequencyLimiterTTL() int { + var res int = frequencyLimiterTTLDefault + + if configured := os.Getenv(frequencyLimiterTTLEnvVar); configured != "" { + rxp := regexp.MustCompile(frequencyLimiterTTLRegexp) + if rxp.MatchString(configured) { + if parsed, err := strconv.Atoi(configured); err == nil { + res = parsed + } + } + } + + return res +} + +func newFrequencyLimiter() *ttlcache.Cache[string, bool] { + cache := ttlcache.New(ttlcache.WithTTL[string, bool](time.Duration(getFrequencyLimiterTTL()) * time.Second)) + go cache.Start() + return cache +} + +func splitBySemicolons(value string) []string { + return strings.Split(value, ";") +} + +func getManagedFieldsAnalysisLabel() string { + return os.Getenv(managedFieldsAnalysisLabelEnvVar) +} diff --git a/internal/manifest/skrresources/collector_test.go b/internal/manifest/skrresources/collector_test.go new file mode 100644 index 0000000000..77c8939436 --- /dev/null +++ b/internal/manifest/skrresources/collector_test.go @@ -0,0 +1,83 @@ +package skrresources //nolint:testpackage // testing package internals + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetAllowedManagers(t *testing.T) { + tests := []struct { + name string + envValue string + want []string + }{ + { + name: "default managers", + envValue: "", + want: []string{"declarative.kyma-project.io/applier", "lifecycle-manager", "k3s"}, + }, + { + name: "single manager in env", + envValue: "manager1", + want: []string{"manager1"}, + }, + { + name: "multiple managers in env", + envValue: "manager1;manager2;some-manager:3", + want: []string{"manager1", "manager2", "some-manager:3"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.envValue != "" { + t.Setenv(knownManagersEnvVar, tt.envValue) + } + assert.Equal(t, tt.want, getAllowedManagers()) + }) + } +} + +func TestGetCacheTTL(t *testing.T) { + tests := []struct { + name string + envValue string + want int + }{ + { + name: "default TTL", + envValue: "", + want: 300, + }, + { + name: "custom TTL", + envValue: "123", + want: 123, + }, + { + name: "invalid value is ignored, default TTL is returned", + envValue: "abc", + want: 300, + }, + { + name: "zero is invalid, default TTL is returned", + envValue: "0", + want: 300, + }, + { + name: "Negative value is ignored, default TTL is returned", + envValue: "-123", + want: 300, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.envValue != "" { + t.Setenv(frequencyLimiterTTLEnvVar, tt.envValue) + } + assert.Equal(t, tt.want, getFrequencyLimiterTTL()) + }) + } +} diff --git a/internal/manifest/skrresources/manifestcollector.go b/internal/manifest/skrresources/manifestcollector.go new file mode 100644 index 0000000000..cbfff9323b --- /dev/null +++ b/internal/manifest/skrresources/manifestcollector.go @@ -0,0 +1,61 @@ +package skrresources + +import ( + "context" + + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + "github.com/kyma-project/lifecycle-manager/internal/manifest/manifestclient" +) + +// ManifestLogCollector is a collector for remote Manifest objects. It delegates the calls to the embedded generic collector if collection is enabled for the given Manifest. +type ManifestLogCollector struct { + collector *LogCollector + enabled bool +} + +func NewManifestLogCollector(manifest *v1beta2.Manifest, owner client.FieldOwner) *ManifestLogCollector { + key := "" + enabled := false + if manifest != nil { + key = string(manifest.GetUID()) + enabled = isManifestCollectionEnabled(manifest) + } + return &ManifestLogCollector{ + collector: NewLogCollector(key, manifestclient.DefaultFieldOwner), + enabled: enabled, + } +} + +// Implements the skrresources.ManagedFieldsCollector interface. +func (c *ManifestLogCollector) Collect(ctx context.Context, obj client.Object) { + if c.enabled { + c.collector.Collect(ctx, obj) + } +} + +// Implements the skrresources.ManagedFieldsCollector interface. +func (c *ManifestLogCollector) Emit(ctx context.Context) error { + if c.enabled { + return c.collector.Emit(ctx) + } + return nil +} + +// isManifestCollectionEnabled checks if managed fields detection is enabled for the given manifest. +// The detection is disabled by default, but can be enabled by setting a specific label on the manifest CR. +func isManifestCollectionEnabled(obj *v1beta2.Manifest) bool { + if obj == nil { + return false + } + + configuredLabelName := getManagedFieldsAnalysisLabel() + + if configuredLabelName == "" { + return false + } + + _, found := obj.GetLabels()[configuredLabelName] + return found +} diff --git a/internal/manifest/skrresources/ssa.go b/internal/manifest/skrresources/ssa.go index 8a4aa70e0f..a55e5b821f 100644 --- a/internal/manifest/skrresources/ssa.go +++ b/internal/manifest/skrresources/ssa.go @@ -26,18 +26,28 @@ type SSA interface { Run(ctx context.Context, resourceInfo []*resource.Info) error } +type ManagedFieldsCollector interface { + // Collect collects managed fields data from the single object + Collect(ctx context.Context, obj client.Object) + // Emit emits collected data to some backing store + Emit(ctx context.Context) error +} + type ConcurrentDefaultSSA struct { clnt client.Client owner client.FieldOwner versioner machineryruntime.GroupVersioner converter machineryruntime.ObjectConvertor + collector ManagedFieldsCollector } -func ConcurrentSSA(clnt client.Client, owner client.FieldOwner) *ConcurrentDefaultSSA { +func ConcurrentSSA(clnt client.Client, owner client.FieldOwner, managedFieldsCollector ManagedFieldsCollector) *ConcurrentDefaultSSA { return &ConcurrentDefaultSSA{ - clnt: clnt, owner: owner, + clnt: clnt, + owner: owner, versioner: schema.GroupVersions(clnt.Scheme().PrioritizedVersionsAllGroups()), converter: clnt.Scheme(), + collector: managedFieldsCollector, } } @@ -70,6 +80,9 @@ func (c *ConcurrentDefaultSSA) Run(ctx context.Context, resources []*resource.In return errors.Join(errs...) } logger.V(internal.DebugLogLevel).Info("ServerSideApply finished", "time", ssaFinish) + if err := c.collector.Emit(ctx); err != nil { + logger.V(internal.DebugLogLevel).Error(err, "error emitting data of unknown field managers") + } return nil } @@ -123,6 +136,7 @@ func (c *ConcurrentDefaultSSA) serverSideApplyResourceInfo( ) } + c.collector.Collect(ctx, obj) return nil } diff --git a/internal/manifest/skrresources/ssa_test.go b/internal/manifest/skrresources/ssa_test.go index 308c2a59b7..532a04e2fa 100644 --- a/internal/manifest/skrresources/ssa_test.go +++ b/internal/manifest/skrresources/ssa_test.go @@ -29,6 +29,8 @@ func TestConcurrentSSA(t *testing.T) { fakeClientBuilder := fake.NewClientBuilder().WithRuntimeObjects(pod).Build() _ = fakeClientBuilder.Create(context.Background(), pod) + inactiveCollector := skrresources.NewManifestLogCollector(nil, client.FieldOwner("test")) + type args struct { clnt client.Client owner client.FieldOwner @@ -54,7 +56,7 @@ func TestConcurrentSSA(t *testing.T) { t.Run( testCase.name, func(t *testing.T) { t.Parallel() - ssa := skrresources.ConcurrentSSA(testCase.ssa.clnt, testCase.ssa.owner) + ssa := skrresources.ConcurrentSSA(testCase.ssa.clnt, testCase.ssa.owner, inactiveCollector) if err := ssa.Run(context.Background(), testCase.apply); err != nil { require.ErrorIs(t, err, testCase.err) } diff --git a/internal/manifest/skrresources/sync.go b/internal/manifest/skrresources/sync.go index feae73400a..cd28dcee19 100644 --- a/internal/manifest/skrresources/sync.go +++ b/internal/manifest/skrresources/sync.go @@ -19,7 +19,9 @@ func SyncResources(ctx context.Context, skrClient client.Client, manifest *v1bet ) error { manifestStatus := manifest.GetStatus() - if err := ConcurrentSSA(skrClient, manifestclient.DefaultFieldOwner).Run(ctx, target); err != nil { + managedFieldsCollector := NewManifestLogCollector(manifest, manifestclient.DefaultFieldOwner) + + if err := ConcurrentSSA(skrClient, manifestclient.DefaultFieldOwner, managedFieldsCollector).Run(ctx, target); err != nil { manifest.SetStatus(manifestStatus.WithState(shared.StateError).WithErr(err)) return err } diff --git a/internal/pkg/flags/flags.go b/internal/pkg/flags/flags.go index 4979706e8c..4db872f32f 100644 --- a/internal/pkg/flags/flags.go +++ b/internal/pkg/flags/flags.go @@ -48,6 +48,9 @@ const ( DefaultSelfSignedCertRenewBefore time.Duration = 60 * 24 * time.Hour DefaultSelfSignedCertificateRenewBuffer = 24 * time.Hour DefaultSelfSignedCertKeySize = 4096 + DefaultIstioGatewayCertSwitchBeforeExpirationTime = 24 * time.Hour + DefaultIstioGatewaySecretRequeueSuccessInterval = 5 * time.Minute + DefaultIstioGatewaySecretRequeueErrInterval = 2 * time.Second DefaultRemoteSyncNamespace = shared.DefaultRemoteNamespace DefaultMetricsAddress = ":8080" DefaultProbeAddress = ":8081" @@ -61,6 +64,7 @@ const ( DefaultWatcherResourceLimitsMemory = "200Mi" DefaultDropCrdStoredVersionMap = "Manifest:v1beta1,Watcher:v1beta1,ModuleTemplate:v1beta1,Kyma:v1beta1" DefaultMetricsCleanupIntervalInMinutes = 15 + DefaultMinMaintenanceWindowSize = 20 * time.Minute DefaultLeaderElectionLeaseDuration = 180 * time.Second DefaultLeaderElectionRenewDeadline = 120 * time.Second DefaultLeaderElectionRetryPeriod = 3 * time.Second @@ -217,6 +221,17 @@ func DefineFlagVar() *FlagVar { "The buffer duration to wait before confirm self-signed certificate not renewed") flag.IntVar(&flagVar.SelfSignedCertKeySize, "self-signed-cert-key-size", DefaultSelfSignedCertKeySize, "The key size for the self-signed certificate") + flag.DurationVar(&flagVar.IstioGatewayCertSwitchBeforeExpirationTime, + "istio-gateway-cert-switch-before-expiration-time", DefaultIstioGatewayCertSwitchBeforeExpirationTime, + "Time before the expiration of the current CA certificate when the Gateway certificate should be switched") + flag.DurationVar(&flagVar.IstioGatewaySecretRequeueSuccessInterval, + "istio-gateway-secret-requeue-success-interval", DefaultIstioGatewaySecretRequeueSuccessInterval, + "determines the duration after which the istio gateway secret is enqueued after successful reconciliation.") + flag.DurationVar(&flagVar.IstioGatewaySecretRequeueErrInterval, + "istio-gateway-secret-requeue-error-interval", DefaultIstioGatewaySecretRequeueErrInterval, + "determines the duration after which the istio gateway secret is enqueued after unsuccessful reconciliation.") + flag.BoolVar(&flagVar.UseLegacyStrategyForIstioGatewaySecret, "legacy-strategy-for-istio-gateway-secret", + false, "Use the legacy strategy (with downtime) for the Istio Gateway Secret") flag.BoolVar(&flagVar.IsKymaManaged, "is-kyma-managed", false, "indicates whether Kyma is managed") flag.StringVar(&flagVar.DropCrdStoredVersionMap, "drop-crd-stored-version-map", DefaultDropCrdStoredVersionMap, "Specify the API versions to be dropped from the storage version. The input format should be a "+ @@ -237,6 +252,9 @@ func DefineFlagVar() *FlagVar { flag.IntVar(&flagVar.MetricsCleanupIntervalInMinutes, "metrics-cleanup-interval", DefaultMetricsCleanupIntervalInMinutes, "The interval at which the cleanup of non-existing kyma CRs metrics runs.") + flag.DurationVar(&flagVar.MinMaintenanceWindowSize, "min-maintenance-window-size", + DefaultMinMaintenanceWindowSize, + "The minimum duration of maintenance window required for reconciling modules with downtime.") return flagVar } @@ -277,34 +295,39 @@ type FlagVar struct { // ListenerPortOverwrite is used to enable the user to overwrite the port // used to expose the KCP cluster for the watcher. By default, it will be // fetched from the specified gateway. - ListenerPortOverwrite string - Pprof bool - PprofAddr string - PprofServerTimeout time.Duration - FailureBaseDelay, FailureMaxDelay time.Duration - RateLimiterBurst, RateLimiterFrequency int - CacheSyncTimeout time.Duration - LogLevel int - InKCPMode bool - PurgeFinalizerTimeout time.Duration - SkipPurgingFor string - RemoteSyncNamespace string - CaCertName string - IsKymaManaged bool - SelfSignedCertDuration time.Duration - SelfSignedCertRenewBefore time.Duration - SelfSignedCertRenewBuffer time.Duration - SelfSignedCertKeySize int - DropCrdStoredVersionMap string - WatcherImageTag string - WatcherImageName string - WatcherImageRegistry string - WatcherResourceLimitsMemory string - WatcherResourceLimitsCPU string - WatcherResourcesPath string - MetricsCleanupIntervalInMinutes int - ManifestRequeueJitterProbability float64 - ManifestRequeueJitterPercentage float64 + ListenerPortOverwrite string + Pprof bool + PprofAddr string + PprofServerTimeout time.Duration + FailureBaseDelay, FailureMaxDelay time.Duration + RateLimiterBurst, RateLimiterFrequency int + CacheSyncTimeout time.Duration + LogLevel int + InKCPMode bool + PurgeFinalizerTimeout time.Duration + SkipPurgingFor string + RemoteSyncNamespace string + CaCertName string + IsKymaManaged bool + SelfSignedCertDuration time.Duration + SelfSignedCertRenewBefore time.Duration + SelfSignedCertRenewBuffer time.Duration + SelfSignedCertKeySize int + UseLegacyStrategyForIstioGatewaySecret bool + DropCrdStoredVersionMap string + WatcherImageTag string + WatcherImageName string + WatcherImageRegistry string + WatcherResourceLimitsMemory string + WatcherResourceLimitsCPU string + WatcherResourcesPath string + MetricsCleanupIntervalInMinutes int + ManifestRequeueJitterProbability float64 + ManifestRequeueJitterPercentage float64 + IstioGatewayCertSwitchBeforeExpirationTime time.Duration + IstioGatewaySecretRequeueSuccessInterval time.Duration + IstioGatewaySecretRequeueErrInterval time.Duration + MinMaintenanceWindowSize time.Duration } func (f FlagVar) Validate() error { diff --git a/internal/pkg/flags/flags_test.go b/internal/pkg/flags/flags_test.go index 600cfa5949..6d45e74445 100644 --- a/internal/pkg/flags/flags_test.go +++ b/internal/pkg/flags/flags_test.go @@ -195,6 +195,21 @@ func Test_ConstantFlags(t *testing.T) { constValue: strconv.Itoa(int(DefaultSelfSignedCertKeySize)), expectedValue: "4096", }, + { + constName: "DefaultIstioGatewayCertSwitchBeforeExpirationTime", + constValue: DefaultIstioGatewayCertSwitchBeforeExpirationTime.String(), + expectedValue: (24 * time.Hour).String(), + }, + { + constName: "DefaultIstioGatewaySecretRequeueSuccessInterval", + constValue: DefaultIstioGatewaySecretRequeueSuccessInterval.String(), + expectedValue: (5 * time.Minute).String(), + }, + { + constName: "DefaultIstioGatewaySecretRequeueErrInterval", + constValue: DefaultIstioGatewaySecretRequeueErrInterval.String(), + expectedValue: (2 * time.Second).String(), + }, { constName: "DefaultMetricsAddress", constValue: DefaultMetricsAddress, @@ -250,6 +265,11 @@ func Test_ConstantFlags(t *testing.T) { constValue: DefaultDropCrdStoredVersionMap, expectedValue: "Manifest:v1beta1,Watcher:v1beta1,ModuleTemplate:v1beta1,Kyma:v1beta1", }, + { + constName: "DefaultMinMaintenanceWindowSize", + constValue: DefaultMinMaintenanceWindowSize.String(), + expectedValue: (20 * time.Minute).String(), + }, { constName: "DefaultLeaderElectionLeaseDuration", constValue: DefaultLeaderElectionLeaseDuration.String(), diff --git a/internal/pkg/metrics/maintance_window.go b/internal/pkg/metrics/maintance_window.go new file mode 100644 index 0000000000..b799ef4f30 --- /dev/null +++ b/internal/pkg/metrics/maintance_window.go @@ -0,0 +1,33 @@ +package metrics + +import ( + "github.com/prometheus/client_golang/prometheus" + ctrlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics" +) + +const ( + MetricMaintenanceWindowConfigReadSuccess = "maintenance_window_config_read_success" +) + +type MaintenanceWindowMetrics struct { + ConfigReadSuccessGauge prometheus.Gauge +} + +func NewMaintenanceWindowMetrics() *MaintenanceWindowMetrics { + metrics := &MaintenanceWindowMetrics{ + ConfigReadSuccessGauge: prometheus.NewGauge(prometheus.GaugeOpts{ + Name: MetricMaintenanceWindowConfigReadSuccess, + Help: "Indicates whether the maintenance window configuration was read successfully (1 for success, 0 for failure)", + }), + } + ctrlmetrics.Registry.MustRegister(metrics.ConfigReadSuccessGauge) + return metrics +} + +func (m *MaintenanceWindowMetrics) RecordConfigReadSuccess(success bool) { + value := 0.0 + if success { + value = 1.0 + } + m.ConfigReadSuccessGauge.Set(value) +} diff --git a/internal/pkg/metrics/maintance_window_test.go b/internal/pkg/metrics/maintance_window_test.go new file mode 100644 index 0000000000..b21e6306d4 --- /dev/null +++ b/internal/pkg/metrics/maintance_window_test.go @@ -0,0 +1,35 @@ +package metrics_test + +import ( + "strings" + "testing" + + "github.com/prometheus/client_golang/prometheus/testutil" + + "github.com/kyma-project/lifecycle-manager/internal/pkg/metrics" +) + +func TestMaintenanceWindowMetrics(t *testing.T) { + // Create a new instance of MaintenanceWindowMetrics + maintenanceWindowMetrics := metrics.NewMaintenanceWindowMetrics() + + // Test recording a successful config read + maintenanceWindowMetrics.RecordConfigReadSuccess(true) + if err := testutil.CollectAndCompare(maintenanceWindowMetrics.ConfigReadSuccessGauge, strings.NewReader(` + # HELP maintenance_window_config_read_success Indicates whether the maintenance window configuration was read successfully (1 for success, 0 for failure) + # TYPE maintenance_window_config_read_success gauge + maintenance_window_config_read_success 1 + `)); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } + + // Test recording a failed config read + maintenanceWindowMetrics.RecordConfigReadSuccess(false) + if err := testutil.CollectAndCompare(maintenanceWindowMetrics.ConfigReadSuccessGauge, strings.NewReader(` + # HELP maintenance_window_config_read_success Indicates whether the maintenance window configuration was read successfully (1 for success, 0 for failure) + # TYPE maintenance_window_config_read_success gauge + maintenance_window_config_read_success 0 + `)); err != nil { + t.Errorf("unexpected collecting result:\n%s", err) + } +} diff --git a/internal/remote/crd_upgrade.go b/internal/remote/crd_upgrade.go index 6bf8b57aa4..e453339e29 100644 --- a/internal/remote/crd_upgrade.go +++ b/internal/remote/crd_upgrade.go @@ -87,7 +87,7 @@ func PatchCRD(ctx context.Context, clnt client.Client, crd *apiextensionsv1.Cust crdToApply.Spec.Conversion.Strategy = apiextensionsv1.NoneConverter crdToApply.Spec.Conversion.Webhook = nil - crdToApply.SetLabels(collections.MergeMaps(crdToApply.GetLabels(), map[string]string{ + crdToApply.SetLabels(collections.MergeMapsSilent(crdToApply.GetLabels(), map[string]string{ shared.ManagedBy: shared.ManagedByLabelValue, })) diff --git a/internal/remote/modulereleasemeta_syncworker.go b/internal/remote/modulereleasemeta_syncworker.go index 60d84b9c1f..abdfe59ebe 100644 --- a/internal/remote/modulereleasemeta_syncworker.go +++ b/internal/remote/modulereleasemeta_syncworker.go @@ -114,7 +114,7 @@ func prepareModuleReleaseMetaForSSA(moduleReleaseMeta *v1beta2.ModuleReleaseMeta moduleReleaseMeta.SetResourceVersion("") moduleReleaseMeta.SetUID("") moduleReleaseMeta.SetManagedFields([]apimetav1.ManagedFieldsEntry{}) - moduleReleaseMeta.SetLabels(collections.MergeMaps(moduleReleaseMeta.GetLabels(), map[string]string{ + moduleReleaseMeta.SetLabels(collections.MergeMapsSilent(moduleReleaseMeta.GetLabels(), map[string]string{ shared.ManagedBy: shared.ManagedByLabelValue, })) diff --git a/internal/remote/moduletemplate_syncworker.go b/internal/remote/moduletemplate_syncworker.go index ac41dbc191..ff16218c83 100644 --- a/internal/remote/moduletemplate_syncworker.go +++ b/internal/remote/moduletemplate_syncworker.go @@ -114,7 +114,7 @@ func prepareModuleTemplateForSSA(moduleTemplate *v1beta2.ModuleTemplate, namespa moduleTemplate.SetResourceVersion("") moduleTemplate.SetUID("") moduleTemplate.SetManagedFields([]apimetav1.ManagedFieldsEntry{}) - moduleTemplate.SetLabels(collections.MergeMaps(moduleTemplate.GetLabels(), map[string]string{ + moduleTemplate.SetLabels(collections.MergeMapsSilent(moduleTemplate.GetLabels(), map[string]string{ shared.ManagedBy: shared.ManagedByLabelValue, })) diff --git a/internal/remote/skr_context.go b/internal/remote/skr_context.go index 2bf3dc42a3..d06a70a6bc 100644 --- a/internal/remote/skr_context.go +++ b/internal/remote/skr_context.go @@ -11,6 +11,7 @@ import ( apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/meta" apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -18,16 +19,19 @@ import ( "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" "github.com/kyma-project/lifecycle-manager/internal/event" + "github.com/kyma-project/lifecycle-manager/internal/util/collections" "github.com/kyma-project/lifecycle-manager/pkg/util" ) var ErrNotFoundAndKCPKymaUnderDeleting = errors.New("not found and kcp kyma under deleting") const ( + fieldManager = "kyma-sync-context" + crdInstallation event.Reason = "CRDInstallation" remoteInstallation event.Reason = "RemoteInstallation" - remoteUpdateFailure event.Reason = "RemoteSynchronization" - statusUpdateFailure event.Reason = "UpdateRuntimeStatus" + metadataSyncFailure event.Reason = "MetadataSynchronization" + statusSyncFailure event.Reason = "StatusSynchronization" ) type SkrContext struct { @@ -92,7 +96,7 @@ func (s *SkrContext) CreateKymaNamespace(ctx context.Context) error { patch := client.RawPatch(types.ApplyPatchType, buf.Bytes()) force := true - patchOpts := &client.PatchOptions{Force: &force, FieldManager: "kyma-sync-context"} + patchOpts := &client.PatchOptions{Force: &force, FieldManager: fieldManager} if err := s.Client.Patch(ctx, namespace, patch, patchOpts); err != nil { return fmt.Errorf("failed to ensure remote namespace exists: %w", err) } @@ -159,24 +163,52 @@ func (s *SkrContext) CreateOrFetchKyma( return remoteKyma, nil } -func (s *SkrContext) SynchronizeKyma(ctx context.Context, kcpKyma, remoteKyma *v1beta2.Kyma) error { - if !remoteKyma.GetDeletionTimestamp().IsZero() { +// SynchronizeKymaMetadata synchronizes the metadata to the SKR Kyma CR . +// It sets the required labels and annotations. +func (s *SkrContext) SynchronizeKymaMetadata(ctx context.Context, kcpKyma, skrKyma *v1beta2.Kyma) error { + if !skrKyma.GetDeletionTimestamp().IsZero() { + return nil + } + + changed := syncWatcherLabelsAnnotations(kcpKyma, skrKyma) + if !changed { return nil } - s.syncWatcherLabelsAnnotations(kcpKyma, remoteKyma) - if err := s.Client.Update(ctx, remoteKyma); err != nil { - err = fmt.Errorf("failed to synchronise runtime kyma: %w", err) - s.event.Warning(kcpKyma, remoteUpdateFailure, err) + metadataToSync := &unstructured.Unstructured{} + metadataToSync.SetName(skrKyma.GetName()) + metadataToSync.SetNamespace(skrKyma.GetNamespace()) + metadataToSync.SetGroupVersionKind(kcpKyma.GroupVersionKind()) // use KCP GVK as SKR GVK may not be available + metadataToSync.SetLabels(skrKyma.GetLabels()) + metadataToSync.SetAnnotations(skrKyma.GetAnnotations()) + + forceOwnership := true + err := s.Client.Patch(ctx, + metadataToSync, + client.Apply, + &client.PatchOptions{FieldManager: fieldManager, Force: &forceOwnership}) + if err != nil { + err = fmt.Errorf("failed to synchronise Kyma metadata to SKR: %w", err) + s.event.Warning(kcpKyma, metadataSyncFailure, err) return err } - remoteKyma.Status = kcpKyma.Status - if err := s.Client.Status().Update(ctx, remoteKyma); err != nil { - err = fmt.Errorf("failed to update runtime kyma status: %w", err) - s.event.Warning(kcpKyma, statusUpdateFailure, err) + return nil +} + +// SynchronizeKymaStatus synchronizes the status to the SKR Kyma CR. +func (s *SkrContext) SynchronizeKymaStatus(ctx context.Context, kcpKyma, skrKyma *v1beta2.Kyma) error { + if !skrKyma.GetDeletionTimestamp().IsZero() { + return nil + } + + syncStatus(&kcpKyma.Status, &skrKyma.Status) + if err := s.Client.Status().Update(ctx, skrKyma); err != nil { + err = fmt.Errorf("failed to synchronise Kyma status to SKR: %w", err) + s.event.Warning(kcpKyma, statusSyncFailure, err) return err } + return nil } @@ -202,19 +234,47 @@ func (s *SkrContext) getRemoteKyma(ctx context.Context) (*v1beta2.Kyma, error) { return skrKyma, nil } -// syncWatcherLabelsAnnotations inserts labels into the given KymaCR, which are needed to ensure -// a working e2e-flow for the runtime-watcher. -func (s *SkrContext) syncWatcherLabelsAnnotations(controlPlaneKyma, remoteKyma *v1beta2.Kyma) { - if remoteKyma.Labels == nil { - remoteKyma.Labels = make(map[string]string) - } +// syncWatcherLabelsAnnotations adds required labels and annotations to the skrKyma. +// It returns true if any of the labels or annotations were changed. +func syncWatcherLabelsAnnotations(kcpKyma, skrKyma *v1beta2.Kyma) bool { + labels, labelsChanged := collections.MergeMaps(skrKyma.Labels, map[string]string{ + shared.WatchedByLabel: shared.WatchedByLabelValue, + shared.ManagedBy: shared.ManagedByLabelValue, + }) + skrKyma.Labels = labels + + annotations, annotationsChanged := collections.MergeMaps(skrKyma.Annotations, map[string]string{ + shared.OwnedByAnnotation: fmt.Sprintf(shared.OwnedByFormat, + kcpKyma.GetNamespace(), kcpKyma.GetName()), + }) + skrKyma.Annotations = annotations + + return labelsChanged || annotationsChanged +} + +// syncStatus copies the Kyma status and transofrms it from KCP perspective to SKR perspective. +// E.g., it removes manifest references or changes namespaces. +func syncStatus(kcpStatus, skrStatus *v1beta2.KymaStatus) { + *skrStatus = *kcpStatus.DeepCopy() + + useRemoteNamespaceForModuleTemplates(skrStatus) + removeManifestReference(skrStatus) +} - remoteKyma.Labels[shared.WatchedByLabel] = shared.WatchedByLabelValue - remoteKyma.Labels[shared.ManagedBy] = shared.ManagedByLabelValue +func useRemoteNamespaceForModuleTemplates(status *v1beta2.KymaStatus) { + for i := range status.Modules { + if status.Modules[i].Template == nil { + continue + } + status.Modules[i].Template.Namespace = shared.DefaultRemoteNamespace + } +} - if remoteKyma.Annotations == nil { - remoteKyma.Annotations = make(map[string]string) +func removeManifestReference(status *v1beta2.KymaStatus) { + for i := range status.Modules { + if status.Modules[i].Manifest == nil { + continue + } + status.Modules[i].Manifest = nil } - remoteKyma.Annotations[shared.OwnedByAnnotation] = fmt.Sprintf(shared.OwnedByFormat, - controlPlaneKyma.GetNamespace(), controlPlaneKyma.GetName()) } diff --git a/internal/remote/skr_context_test.go b/internal/remote/skr_context_test.go index af037ae945..677537409d 100644 --- a/internal/remote/skr_context_test.go +++ b/internal/remote/skr_context_test.go @@ -1,21 +1,33 @@ -package remote_test +package remote //nolint:testpackage // testing package internals import ( + "context" + "errors" + "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + machineryruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/internal/remote" - "github.com/kyma-project/lifecycle-manager/pkg/testutils" + "github.com/kyma-project/lifecycle-manager/internal/event" + "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" +) + +const ( + kymaName = "test-name" + kymaNamespace = "test-namespace" ) func TestReplaceWithVirtualKyma(t *testing.T) { t.Parallel() type testKyma struct { - channel string - modules []string + channel string + moduleNames []string } tests := []struct { name string @@ -24,64 +36,392 @@ func TestReplaceWithVirtualKyma(t *testing.T) { expectedKyma testKyma }{ { - "module in kcp Kyma gets replaced with remote Kyma", + "modules in kcp Kyma get replaced with modules in remote Kyma", testKyma{ - channel: "regular", - modules: []string{"module1"}, + channel: "regular", + moduleNames: []string{"module1", "module3"}, }, testKyma{ - channel: "regular", - modules: []string{"module2"}, + channel: "regular", + moduleNames: []string{"module2"}, }, testKyma{ - channel: "regular", - modules: []string{"module1"}, + channel: "regular", + moduleNames: []string{"module1", "module3"}, }, }, { - "channel updated in remoteKyma be the final channel", + "channel in kcp Kym gets replaced with channel in remote Kyma", testKyma{ channel: "regular", - modules: []string{"module1"}, }, testKyma{ channel: "fast", - modules: []string{"module1"}, }, testKyma{ channel: "regular", - modules: []string{"module1"}, }, }, } for _, testCase := range tests { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - kcpKyma := createKyma(testCase.kcpKyma.channel, testCase.kcpKyma.modules) - remoteKyma := createKyma(testCase.remoteKyma.channel, testCase.remoteKyma.modules) - remote.ReplaceSpec(kcpKyma, remoteKyma) + kcpKyma := createKyma(testCase.kcpKyma.channel, testCase.kcpKyma.moduleNames) + remoteKyma := createKyma(testCase.remoteKyma.channel, testCase.remoteKyma.moduleNames) + ReplaceSpec(kcpKyma, remoteKyma) assert.Equal(t, testCase.expectedKyma.channel, kcpKyma.Spec.Channel) var virtualModules []string for _, module := range kcpKyma.Spec.Modules { virtualModules = append(virtualModules, module.Name) } - require.ElementsMatch(t, testCase.expectedKyma.modules, virtualModules) + require.ElementsMatch(t, testCase.expectedKyma.moduleNames, virtualModules) }) } } -func createKyma(channel string, modules []string) *v1beta2.Kyma { - kcpKyma := testutils.NewTestKyma("test-kyma") +func Test_SynchronizeKymaMetadata_SkipsIfSKRKymaIsDeleting(t *testing.T) { + skrKyma := builder.NewKymaBuilder().WithDeletionTimestamp().Build() + kcpKyma := builder.NewKymaBuilder().Build() + + event := &eventStub{} + client := &clientStub{} + skrContext := NewSkrContext(client, event) + + err := skrContext.SynchronizeKymaMetadata(context.Background(), kcpKyma, skrKyma) + + require.NoError(t, err) + assert.False(t, client.called) + assert.False(t, event.called) +} + +func Test_SynchronizeKymaMetadata_Syncs(t *testing.T) { + skrKyma := builder.NewKymaBuilder().Build() + kcpKyma := builder.NewKymaBuilder().Build() + + event := &eventStub{} + client := &clientStub{} + skrContext := NewSkrContext(client, event) + + err := skrContext.SynchronizeKymaMetadata(context.Background(), kcpKyma, skrKyma) + + require.NoError(t, err) + assert.True(t, client.called) + assert.False(t, event.called) +} + +func Test_SynchronizeKymaMetadata_SkipsSyncIfLabelsAndAnnotationsUnchanged(t *testing.T) { + skrKyma := builder.NewKymaBuilder(). + WithLabel(shared.WatchedByLabel, shared.WatchedByLabelValue). + WithLabel(shared.ManagedBy, shared.ManagedByLabelValue). + WithAnnotation(shared.OwnedByAnnotation, fmt.Sprintf(shared.OwnedByFormat, kymaNamespace, kymaName)). + Build() + kcpKyma := builder.NewKymaBuilder().WithName(kymaName).WithNamespace(kymaNamespace).Build() + + event := &eventStub{} + client := &clientStub{} + skrContext := NewSkrContext(client, event) + + err := skrContext.SynchronizeKymaMetadata(context.Background(), kcpKyma, skrKyma) + + require.NoError(t, err) + assert.False(t, client.called) + assert.False(t, event.called) +} + +func Test_SynchronizeKymaMetadata_ErrorsWhenFailedToSync(t *testing.T) { + skrKyma := builder.NewKymaBuilder().Build() + kcpKyma := builder.NewKymaBuilder().Build() + + expectedError := errors.New("test error") + event := &eventStub{} + client := &clientStub{err: expectedError} + skrContext := NewSkrContext(client, event) + + err := skrContext.SynchronizeKymaMetadata(context.Background(), kcpKyma, skrKyma) + + require.ErrorIs(t, err, expectedError) + assert.Contains(t, err.Error(), "failed to synchronise Kyma metadata to SKR") + assert.True(t, client.called) + assert.True(t, event.called) +} + +func Test_SynchronizeKymaStatus_SkipsIfSKRKymaIsDeleting(t *testing.T) { + skrKyma := builder.NewKymaBuilder().WithDeletionTimestamp().Build() + kcpKyma := builder.NewKymaBuilder().Build() + + event := &eventStub{} + statusClient := &statusClient{} + client := &clientStub{status: statusClient} + skrContext := NewSkrContext(client, event) + + err := skrContext.SynchronizeKymaStatus(context.Background(), kcpKyma, skrKyma) + + require.NoError(t, err) + assert.False(t, statusClient.called) + assert.False(t, event.called) +} + +func Test_SynchronizeKymaStatus_Syncs(t *testing.T) { + skrKyma := builder.NewKymaBuilder().Build() + kcpKyma := builder.NewKymaBuilder().Build() + + event := &eventStub{} + statusClient := &statusClient{} + client := &clientStub{status: statusClient} + skrContext := NewSkrContext(client, event) + + err := skrContext.SynchronizeKymaStatus(context.Background(), kcpKyma, skrKyma) + + require.NoError(t, err) + assert.True(t, statusClient.called) + assert.False(t, event.called) +} + +func Test_SynchronizeKymaStatus_ErrorsWhenFailedToSync(t *testing.T) { + skrKyma := builder.NewKymaBuilder().Build() + kcpKyma := builder.NewKymaBuilder().Build() + + expectedError := errors.New("test error") + event := &eventStub{} + statusClient := &statusClient{err: expectedError} + client := &clientStub{status: statusClient} + skrContext := NewSkrContext(client, event) + + err := skrContext.SynchronizeKymaStatus(context.Background(), kcpKyma, skrKyma) + + require.ErrorIs(t, err, expectedError) + assert.Contains(t, err.Error(), "failed to synchronise Kyma status to SKR") + assert.True(t, statusClient.called) + assert.True(t, event.called) +} + +func Test_syncStatus_AssignsRemoteNamespace(t *testing.T) { + skrStatus := &v1beta2.KymaStatus{} + kcpStatus := &v1beta2.KymaStatus{ + Modules: []v1beta2.ModuleStatus{ + { + Name: "module-1", + Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Namespace: "kcp-system", + }, + }, + }, + { + Name: "module-2", + Template: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Namespace: "kcp-system", + }, + }, + }, + { + Name: "module-3", + }, + }, + } + + syncStatus(kcpStatus, skrStatus) + + for _, module := range skrStatus.Modules { + if module.Template == nil { + continue + } + assert.Equal(t, shared.DefaultRemoteNamespace, module.Template.Namespace) + } + + for _, module := range kcpStatus.Modules { + if module.Template == nil { + continue + } + assert.Equal(t, "kcp-system", module.Template.Namespace) + } +} - kcpKyma.Spec.Channel = channel - for _, module := range modules { - kcpKyma.Spec.Modules = append( - kcpKyma.Spec.Modules, v1beta2.Module{ - Name: module, - Channel: v1beta2.DefaultChannel, - Managed: true, - }) +func Test_syncStatus_RemovesManifestReference(t *testing.T) { + skrStatus := &v1beta2.KymaStatus{} + kcpStatus := &v1beta2.KymaStatus{ + Modules: []v1beta2.ModuleStatus{ + { + Name: "module-1", + Manifest: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Namespace: "kcp-system", + }, + }, + }, + { + Name: "module-2", + Manifest: &v1beta2.TrackingObject{ + PartialMeta: v1beta2.PartialMeta{ + Namespace: "kcp-system", + }, + }, + }, + { + Name: "module-3", + }, + }, } - return kcpKyma + + syncStatus(kcpStatus, skrStatus) + + for _, module := range skrStatus.Modules { + assert.Nil(t, module.Manifest) + } + + assert.NotNil(t, kcpStatus.Modules[0].Manifest) + assert.NotNil(t, kcpStatus.Modules[1].Manifest) + assert.Nil(t, kcpStatus.Modules[2].Manifest) +} + +func Test_syncWatcherLabelsAnnotations_AddsLabelsAndAnnotations(t *testing.T) { + skrKyma := builder.NewKymaBuilder().Build() + kcpKyma := builder.NewKymaBuilder().WithName(kymaName).WithNamespace(kymaNamespace).Build() + + changed := syncWatcherLabelsAnnotations(kcpKyma, skrKyma) + + assert.True(t, changed) + assertLabelsAndAnnotations(t, skrKyma) +} + +func Test_syncWatcherLabelsAnnotations_AddsLabels(t *testing.T) { + skrKyma := builder.NewKymaBuilder(). + WithAnnotation(shared.OwnedByAnnotation, fmt.Sprintf(shared.OwnedByFormat, kymaNamespace, kymaName)). + Build() + kcpKyma := builder.NewKymaBuilder().WithName(kymaName).WithNamespace(kymaNamespace).Build() + + changed := syncWatcherLabelsAnnotations(kcpKyma, skrKyma) + + assert.True(t, changed) + assertLabelsAndAnnotations(t, skrKyma) +} + +func Test_syncWatcherLabelsAnnotations_AddsAnnotations(t *testing.T) { + skrKyma := builder.NewKymaBuilder(). + WithLabel(shared.WatchedByLabel, shared.WatchedByLabelValue). + WithLabel(shared.ManagedBy, shared.ManagedByLabelValue). + Build() + kcpKyma := builder.NewKymaBuilder().WithName(kymaName).WithNamespace(kymaNamespace).Build() + + changed := syncWatcherLabelsAnnotations(kcpKyma, skrKyma) + + assert.True(t, changed) + assertLabelsAndAnnotations(t, skrKyma) +} + +func Test_syncWatcherLabelsAnnotations_ChangesAnnotations(t *testing.T) { + skrKyma := builder.NewKymaBuilder(). + WithLabel(shared.WatchedByLabel, shared.WatchedByLabelValue). + WithLabel(shared.ManagedBy, shared.ManagedByLabelValue). + WithAnnotation(shared.OwnedByAnnotation, "foo"). + Build() + kcpKyma := builder.NewKymaBuilder().WithName(kymaName).WithNamespace(kymaNamespace).Build() + + changed := syncWatcherLabelsAnnotations(kcpKyma, skrKyma) + + assert.True(t, changed) + assertLabelsAndAnnotations(t, skrKyma) +} + +func Test_syncWatcherLabelsAnnotations_ChangesLabels(t *testing.T) { + skrKyma := builder.NewKymaBuilder(). + WithLabel(shared.WatchedByLabel, "foo"). + WithLabel(shared.ManagedBy, "bar"). + WithAnnotation(shared.OwnedByAnnotation, fmt.Sprintf(shared.OwnedByFormat, kymaNamespace, kymaName)). + Build() + kcpKyma := builder.NewKymaBuilder().WithName(kymaName).WithNamespace(kymaNamespace).Build() + + changed := syncWatcherLabelsAnnotations(kcpKyma, skrKyma) + + assert.True(t, changed) + assertLabelsAndAnnotations(t, skrKyma) +} + +func Test_syncWatcherLabelsAnnotations_ReturnsFalseIfLabelsAndAnnotationsUnchanged(t *testing.T) { + skrKyma := builder.NewKymaBuilder(). + WithLabel(shared.WatchedByLabel, shared.WatchedByLabelValue). + WithLabel(shared.ManagedBy, shared.ManagedByLabelValue). + WithAnnotation(shared.OwnedByAnnotation, fmt.Sprintf(shared.OwnedByFormat, kymaNamespace, kymaName)). + Build() + kcpKyma := builder.NewKymaBuilder().WithName(kymaName).WithNamespace(kymaNamespace).Build() + + changed := syncWatcherLabelsAnnotations(kcpKyma, skrKyma) + + assert.False(t, changed) + assertLabelsAndAnnotations(t, skrKyma) +} + +// test helpers + +func createKyma(channel string, moduleNames []string) *v1beta2.Kyma { + kyma := builder.NewKymaBuilder(). + WithChannel(channel). + Build() + + modules := []v1beta2.Module{} + for _, moduleName := range moduleNames { + modules = append(modules, v1beta2.Module{ + Name: moduleName, + Channel: v1beta2.DefaultChannel, + Managed: true, + }) + } + + kyma.Spec.Modules = modules + + return kyma +} + +func assertLabelsAndAnnotations(t *testing.T, skrKyma *v1beta2.Kyma) { + t.Helper() + + assert.Equal(t, shared.WatchedByLabelValue, skrKyma.Labels[shared.WatchedByLabel]) + assert.Equal(t, shared.ManagedByLabelValue, skrKyma.Labels[shared.ManagedBy]) + assert.Equal(t, + fmt.Sprintf(shared.OwnedByFormat, kymaNamespace, kymaName), + skrKyma.Annotations[shared.OwnedByAnnotation]) +} + +// test stubs + +type eventStub struct { + event.Event + called bool +} + +func (e *eventStub) Warning(object machineryruntime.Object, reason event.Reason, err error) { + e.called = true +} + +type clientStub struct { + err error + status client.SubResourceWriter + client.Client + called bool +} + +func (c *clientStub) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { + c.called = true + return c.err +} + +func (c *clientStub) Status() client.SubResourceWriter { + return c.status +} + +func (*clientStub) Config() *rest.Config { + return nil +} + +type statusClient struct { + err error + client.SubResourceWriter + called bool +} + +func (s *statusClient) Update(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) error { + s.called = true + return s.err } diff --git a/internal/util/collections/collections.go b/internal/util/collections/collections.go index 6edb0259e6..62edfb10b3 100644 --- a/internal/util/collections/collections.go +++ b/internal/util/collections/collections.go @@ -1,15 +1,26 @@ package collections -func MergeMaps(map1, map2 map[string]string) map[string]string { - mergedMap := make(map[string]string) +// MergeMapsSilent merges map2 into map1. +// It does not indicate if map1 changed. +func MergeMapsSilent(map1, map2 map[string]string) map[string]string { + mergedMap, _ := MergeMaps(map1, map2) + return mergedMap +} - for k, v := range map1 { - mergedMap[k] = v +// MergeMaps merges map2 into map1. +// It returns true if map1 changed. +func MergeMaps(map1, map2 map[string]string) (map[string]string, bool) { + changed := false + if map1 == nil { + map1 = make(map[string]string) } for k, v := range map2 { - mergedMap[k] = v + if map1[k] != v { + map1[k] = v + changed = true + } } - return mergedMap + return map1, changed } diff --git a/internal/util/collections/collections_test.go b/internal/util/collections/collections_test.go index 5632ad24a4..84945700e3 100644 --- a/internal/util/collections/collections_test.go +++ b/internal/util/collections/collections_test.go @@ -8,31 +8,33 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/util/collections" ) -func TestMergeMaps_WhenMapIsEmpty(t *testing.T) { +func TestMergeMapsSilent_WhenMapIsEmpty(t *testing.T) { firstMap := map[string]string{} secondMap := map[string]string{ "key": "value", } - mergedMap := collections.MergeMaps(firstMap, secondMap) + mergedMap := collections.MergeMapsSilent(firstMap, secondMap) + require.Len(t, mergedMap, 1) require.Contains(t, mergedMap, "key") require.Equal(t, "value", mergedMap["key"]) } -func TestMergeMaps_WhenMapIsNil(t *testing.T) { +func TestMergeMapsSilent_WhenMapIsNil(t *testing.T) { var firstMap map[string]string secondMap := map[string]string{ "key": "value", } - mergedMap := collections.MergeMaps(firstMap, secondMap) + mergedMap := collections.MergeMapsSilent(firstMap, secondMap) + require.Len(t, mergedMap, 1) require.Contains(t, mergedMap, "key") require.Equal(t, "value", mergedMap["key"]) } -func TestMergeMaps_WhenBothMapsHaveValues(t *testing.T) { +func TestMergeMapsSilent_WhenBothMapsHaveValues(t *testing.T) { firstMap := map[string]string{ "key1": "value1", } @@ -40,10 +42,98 @@ func TestMergeMaps_WhenBothMapsHaveValues(t *testing.T) { "key2": "value2", } - mergedMap := collections.MergeMaps(firstMap, secondMap) + mergedMap := collections.MergeMapsSilent(firstMap, secondMap) + require.Len(t, mergedMap, 2) require.Contains(t, mergedMap, "key1") require.Equal(t, "value1", mergedMap["key1"]) require.Contains(t, mergedMap, "key2") require.Equal(t, "value2", mergedMap["key2"]) } + +func TestMergeMaps_WhenMapIsNil(t *testing.T) { + var firstMap map[string]string = nil + secondMap := map[string]string{ + "key": "value", + } + + mergedMap, changed := collections.MergeMaps(firstMap, secondMap) + + require.True(t, changed) + require.Len(t, mergedMap, 1) + for k, v := range secondMap { + require.Equal(t, v, mergedMap[k]) + } + require.Nil(t, firstMap) +} + +func TestMergeMaps_WhenMapIsEmpty(t *testing.T) { + firstMap := map[string]string{} + secondMap := map[string]string{ + "key": "value", + } + + mergedMap, changed := collections.MergeMaps(firstMap, secondMap) + + require.True(t, changed) + require.Len(t, mergedMap, 1) + for k, v := range secondMap { + require.Equal(t, v, mergedMap[k]) + } + for k, v := range firstMap { + require.Equal(t, v, mergedMap[k]) + } +} + +func TestMergeMaps_WhenSecondMapIsNil(t *testing.T) { + firstMap := map[string]string{ + "key": "value", + } + var secondMap map[string]string = nil + + mergedMap, changed := collections.MergeMaps(firstMap, secondMap) + + require.False(t, changed) + require.Len(t, mergedMap, 1) + for k, v := range firstMap { + require.Equal(t, v, mergedMap[k]) + } + require.Nil(t, secondMap) +} + +func TestMergeMaps_WhenEntriesDistinct(t *testing.T) { + firstMap := map[string]string{ + "key1": "value1", + } + secondMap := map[string]string{ + "key2": "value2", + } + + mergedMap, changed := collections.MergeMaps(firstMap, secondMap) + + require.Len(t, mergedMap, 2) + require.True(t, changed) + for k, v := range firstMap { + require.Equal(t, v, mergedMap[k]) + } + for k, v := range secondMap { + require.Equal(t, v, mergedMap[k]) + } +} + +func TestMergeMaps_WhenSecondMapOverwritingFirst(t *testing.T) { + firstMap := map[string]string{ + "key1": "value1", + } + secondMap := map[string]string{ + "key1": "value2", + } + + mergedMap, changed := collections.MergeMaps(firstMap, secondMap) + + require.Len(t, mergedMap, 1) + require.True(t, changed) + for k, v := range secondMap { + require.Equal(t, v, mergedMap[k]) + } +} diff --git a/maintenancewindows/go.mod b/maintenancewindows/go.mod index ace3b9e56a..9d82148f82 100644 --- a/maintenancewindows/go.mod +++ b/maintenancewindows/go.mod @@ -1,6 +1,6 @@ module github.com/kyma-project/lifecycle-manager/maintenancewindows -go 1.23.5 +go 1.23.6 require github.com/stretchr/testify v1.10.0 diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy_test.go index 1f04802ea6..8e63bc991b 100644 --- a/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy_test.go +++ b/pkg/templatelookup/moduletemplateinfolookup/by_channel_strategy_test.go @@ -46,9 +46,7 @@ func Test_ByChannelStrategy_Lookup_ReturnsModuleTemplateInfo(t *testing.T) { kyma := builder.NewKymaBuilder().Build() var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil moduleTemplate := builder.NewModuleTemplateBuilder(). - WithName("test-module-regular"). WithModuleName("test-module"). - WithVersion(""). WithChannel("regular"). Build() byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( @@ -67,3 +65,163 @@ func Test_ByChannelStrategy_Lookup_ReturnsModuleTemplateInfo(t *testing.T) { assert.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.ModuleTemplate.Spec.Version) assert.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.ModuleTemplate.Spec.Channel) } + +func Test_ByChannelStrategy_Lookup_ReturnsModuleTemplateInfo_UsingGlobalChannel(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").Enabled().Build() + kyma := builder.NewKymaBuilder().WithChannel("fast").Build() + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithModuleName("test-module"). + WithChannel("fast"). + Build() + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byChannelStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Equal(t, moduleTemplate.Name, moduleTemplateInfo.ModuleTemplate.Name) + assert.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.ModuleTemplate.Spec.ModuleName) + assert.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.ModuleTemplate.Spec.Version) + assert.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.ModuleTemplate.Spec.Channel) +} + +func Test_ByChannelStrategy_Lookup_ReturnsModuleTemplateInfo_UsingDefaultChannel(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").Enabled().Build() + kyma := builder.NewKymaBuilder().Build() + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithModuleName("test-module"). + WithChannel("regular"). + Build() + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byChannelStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Equal(t, moduleTemplate.Name, moduleTemplateInfo.ModuleTemplate.Name) + assert.Equal(t, moduleTemplate.Spec.ModuleName, moduleTemplateInfo.ModuleTemplate.Spec.ModuleName) + assert.Equal(t, moduleTemplate.Spec.Version, moduleTemplateInfo.ModuleTemplate.Spec.Version) + assert.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.ModuleTemplate.Spec.Channel) +} + +func Test_ByChannelStrategy_Lookup_WhenNoModuleTemplateFound(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() + kyma := builder.NewKymaBuilder().Build() + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient(&v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{}, + })) + + moduleTemplateInfo := byChannelStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "no templates were found: for module test-module in channel regular") +} + +func Test_ByChannelStrateg_Lookup_WhenFailedToListModuleTemplates(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() + kyma := builder.NewKymaBuilder().Build() + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(&failedClientStub{}) + + moduleTemplateInfo := byChannelStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "failed to list module templates on lookup") +} + +func Test_ByChannelStrategy_Lookup_WhenMoreThanOneModuleTemplateFound(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() + kyma := builder.NewKymaBuilder().Build() + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + firstModuleTemplate := builder.NewModuleTemplateBuilder(). + WithName("test-module-regular"). + WithModuleName("test-module"). + WithChannel("regular"). + Build() + secondModuleTemplate := builder.NewModuleTemplateBuilder(). + WithName("test-module-regular-2"). + WithModuleName("test-module"). + WithChannel("regular"). + Build() + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *firstModuleTemplate, + *secondModuleTemplate, + }, + }, + )) + + moduleTemplateInfo := byChannelStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "no unique template could be identified: more than one module template found for module: test-module, candidates: [test-module-regular test-module-regular-2]") +} + +func Test_ByChannelStrategy_Lookup_WhenModuleTemplateHasNoChannel(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() + kyma := builder.NewKymaBuilder().Build() + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithModuleName("test-module"). + Build() + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byChannelStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "no templates were found: for module test-module in channel regular") +} + +func Test_ByChannelStrategy_Lookup_WhenModuleTemplateIsMandatory(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() + kyma := builder.NewKymaBuilder().Build() + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithModuleName("test-module"). + WithChannel("regular"). + WithMandatory(true). + Build() + byChannelStrategy := moduletemplateinfolookup.NewByChannelStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byChannelStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "template marked as mandatory: for module test-module in channel regular") +} diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy_test.go index ba6f1469ee..0e1585856b 100644 --- a/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy_test.go +++ b/pkg/templatelookup/moduletemplateinfolookup/by_module_release_meta_strategy_test.go @@ -53,7 +53,6 @@ func Test_ByModuleReleaseMeta_Strategy_Lookup_ReturnsModuleTemplateInfo(t *testi WithName("test-module-1.0.0"). WithModuleName("test-module"). WithVersion("1.0.0"). - WithChannel("none"). Build() byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(fakeClient( &v1beta2.ModuleTemplateList{ @@ -72,6 +71,67 @@ func Test_ByModuleReleaseMeta_Strategy_Lookup_ReturnsModuleTemplateInfo(t *testi assert.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.ModuleTemplate.Spec.Channel) } +func Test_ByModuleReleaseMeta_Strategy_Lookup_WhenGetChannelVersionForModuleReturnsError(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() + kyma := builder.NewKymaBuilder().Build() + moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). + WithModuleName("test-module"). + WithName("test-module"). + WithModuleChannelAndVersions([]v1beta2.ChannelVersionAssignment{ + { + Channel: "regular", + Version: "1.0.0", + }, + }). + Build() + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithName("test-module"). + WithModuleName("test-module"). + WithVersion("1.0.0"). + Build() + byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byMRMStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "failed to get module template: moduletemplates.operator.kyma-project.io \"test-module-1.0.0\" not found") +} + +func Test_ByModuleReleaseMeta_Strategy_Lookup_WhenGetTemplateByVersionReturnsError(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithChannel("regular").Enabled().Build() + kyma := builder.NewKymaBuilder().Build() + moduleReleaseMeta := builder.NewModuleReleaseMetaBuilder(). + WithModuleName("test-module"). + WithName("test-module"). + Build() + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithName("test-module-1.0.0"). + WithModuleName("test-module"). + WithVersion("1.0.0"). + Build() + byMRMStrategy := moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byMRMStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, "no channels found for module: test-module") +} + func fakeClient(mts *v1beta2.ModuleTemplateList) client.Client { scheme := machineryruntime.NewScheme() machineryutilruntime.Must(api.AddToScheme(scheme)) diff --git a/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy_test.go b/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy_test.go index 243d0abd16..597a08781e 100644 --- a/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy_test.go +++ b/pkg/templatelookup/moduletemplateinfolookup/by_version_strategy_test.go @@ -2,9 +2,11 @@ package moduletemplateinfolookup_test import ( "context" + "errors" "testing" "github.com/stretchr/testify/assert" + "sigs.k8s.io/controller-runtime/pkg/client" "github.com/kyma-project/lifecycle-manager/api/v1beta2" "github.com/kyma-project/lifecycle-manager/pkg/templatelookup" @@ -69,6 +71,102 @@ func Test_ByVersion_Strategy_Lookup_ReturnsModuleTemplateInfo(t *testing.T) { assert.Equal(t, moduleTemplate.Spec.Channel, moduleTemplateInfo.ModuleTemplate.Spec.Channel) } +func Test_ByVersion_Strategy_Lookup_WhenMoreThanOneModuleTemplateFound(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithVersion("1.0.0").Enabled().Build() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + firstModuleTemplate := builder.NewModuleTemplateBuilder(). + WithName("test-module-1.0.0"). + WithModuleName("test-module"). + WithVersion("1.0.0"). + WithChannel("none"). + Build() + secondModuleTemplate := builder.NewModuleTemplateBuilder(). + WithName("test-module-1.0.0-duplicate"). + WithModuleName("test-module"). + WithVersion("1.0.0"). + WithChannel("none"). + Build() + + byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *firstModuleTemplate, + *secondModuleTemplate, + }, + }, + )) + + moduleTemplateInfo := byVersionStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "no unique template could be identified: more than one module template found for module: test-module, candidates: [test-module-1.0.0 test-module-1.0.0-duplicate]") +} + +func Test_ByVersion_Strategy_Lookup_WhenFailedToListModuleTemplates(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithVersion("1.0.0").Enabled().Build() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + + byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(&failedClientStub{}) + + moduleTemplateInfo := byVersionStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "failed to list module templates on lookup") +} + +func Test_ByVersion_Strategy_Lookup_WhenNoModuleTemplateFound(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithVersion("1.0.0").Enabled().Build() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + + byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{}, + }, + )) + + moduleTemplateInfo := byVersionStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "no templates were found: for module test-module in version 1.0.0") +} + +func Test_ByVersion_Strategy_Lookup_WhenModuleTemplateIsMandatory(t *testing.T) { + moduleInfo := newModuleInfoBuilder().WithName("test-module").WithVersion("1.0.0").Enabled().Build() + var kyma *v1beta2.Kyma = nil + var moduleReleaseMeta *v1beta2.ModuleReleaseMeta = nil + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithName("test-module-1.0.0"). + WithModuleName("test-module"). + WithVersion("1.0.0"). + WithChannel("none"). + WithMandatory(true). + Build() + + byVersionStrategy := moduletemplateinfolookup.NewByVersionStrategy(fakeClient( + &v1beta2.ModuleTemplateList{ + Items: []v1beta2.ModuleTemplate{ + *moduleTemplate, + }, + }, + )) + + moduleTemplateInfo := byVersionStrategy.Lookup(context.Background(), moduleInfo, kyma, moduleReleaseMeta) + + assert.NotNil(t, moduleTemplateInfo) + assert.Nil(t, moduleTemplateInfo.ModuleTemplate) + assert.ErrorContains(t, moduleTemplateInfo.Err, + "template marked as mandatory: for module test-module in version 1.0.0") +} + type moduleInfoBuilder struct { moduleInfo *templatelookup.ModuleInfo } @@ -104,3 +202,11 @@ func (b moduleInfoBuilder) Enabled() moduleInfoBuilder { func (b moduleInfoBuilder) Build() *templatelookup.ModuleInfo { return b.moduleInfo } + +type failedClientStub struct { + client.Client +} + +func (c *failedClientStub) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { + return errors.New("failed to list module templates") +} diff --git a/pkg/templatelookup/moduletemplateinfolookup/common_test.go b/pkg/templatelookup/moduletemplateinfolookup/common_test.go new file mode 100644 index 0000000000..35c3eec616 --- /dev/null +++ b/pkg/templatelookup/moduletemplateinfolookup/common_test.go @@ -0,0 +1,45 @@ +package moduletemplateinfolookup_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup" + "github.com/kyma-project/lifecycle-manager/pkg/testutils/builder" +) + +func Test_TemplateNameMatch_WhenModuleNameFieldIsMatching(t *testing.T) { + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithModuleName("test-module"). + Build() + + isNameMatching := moduletemplateinfolookup.TemplateNameMatch(moduleTemplate, "test-module") + assert.True(t, isNameMatching) +} + +func Test_TemplateNameMatch_WhenModuleNameFieldIsNotMatching(t *testing.T) { + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithModuleName("test-module"). + Build() + + isNameMatching := moduletemplateinfolookup.TemplateNameMatch(moduleTemplate, "module") + assert.False(t, isNameMatching) +} + +func Test_TemplateNameMatch_WhenNoModuleNameFieldButMatchingLabel(t *testing.T) { + moduleTemplate := builder.NewModuleTemplateBuilder(). + WithLabelModuleName("test-module"). + Build() + + isNameMatching := moduletemplateinfolookup.TemplateNameMatch(moduleTemplate, "test-module") + assert.True(t, isNameMatching) +} + +func Test_TemplateNameMatch_WhenNoModuleNameFieldAndNoMatchingLabel(t *testing.T) { + moduleTemplate := builder.NewModuleTemplateBuilder(). + Build() + + isNameMatching := moduletemplateinfolookup.TemplateNameMatch(moduleTemplate, "test-module") + assert.False(t, isNameMatching) +} diff --git a/pkg/testutils/builder/kyma.go b/pkg/testutils/builder/kyma.go index 219029a1e2..04550b1c22 100644 --- a/pkg/testutils/builder/kyma.go +++ b/pkg/testutils/builder/kyma.go @@ -2,6 +2,7 @@ package builder import ( "fmt" + "time" apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -128,6 +129,12 @@ func (kb KymaBuilder) WithSkipMaintenanceWindows(skip bool) KymaBuilder { return kb } +// WithDeletionTimestamp sets v1beta2.Kyma.ObjectMeta.DeletionTimestamp. +func (kb KymaBuilder) WithDeletionTimestamp() KymaBuilder { + kb.kyma.ObjectMeta.DeletionTimestamp = &apimetav1.Time{Time: time.Now()} + return kb +} + // Build returns the built v1beta2.Kyma. func (kb KymaBuilder) Build() *v1beta2.Kyma { return kb.kyma diff --git a/pkg/testutils/builder/manifest.go b/pkg/testutils/builder/manifest.go index a7170d88dc..ccd0a11cb0 100644 --- a/pkg/testutils/builder/manifest.go +++ b/pkg/testutils/builder/manifest.go @@ -2,6 +2,7 @@ package builder import ( apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "github.com/kyma-project/lifecycle-manager/api/shared" "github.com/kyma-project/lifecycle-manager/api/v1beta2" @@ -91,6 +92,11 @@ func (mb ManifestBuilder) WithFinalizers(finalizers []string) ManifestBuilder { return mb } +func (mb ManifestBuilder) WithResource(resource *unstructured.Unstructured) ManifestBuilder { + mb.manifest.Spec.Resource = resource + return mb +} + // Build returns the built v1beta2.Manifest. func (mb ManifestBuilder) Build() *v1beta2.Manifest { return mb.manifest diff --git a/pkg/testutils/kyma.go b/pkg/testutils/kyma.go index d430ff615e..53c169bb52 100644 --- a/pkg/testutils/kyma.go +++ b/pkg/testutils/kyma.go @@ -28,6 +28,10 @@ var ( ErrModuleMessageInStatusIsIncorrect = errors.New("status.modules.message is incorrect") ) +const ( + FastChannel = "fast" +) + func NewTestKyma(name string) *v1beta2.Kyma { return NewKymaWithSyncLabel(name, ControlPlaneNamespace, v1beta2.DefaultChannel) } diff --git a/pkg/testutils/utils.go b/pkg/testutils/utils.go index c260bc0227..c166215829 100644 --- a/pkg/testutils/utils.go +++ b/pkg/testutils/utils.go @@ -180,3 +180,17 @@ func parseResourcesFromYAML(yamlFilePath string, clnt client.Client) ([]*unstruc } return resources, nil } + +func PatchServiceToTypeLoadBalancer(ctx context.Context, clnt client.Client, serviceName, namespace string) error { + service := &apicorev1.Service{} + if err := clnt.Get(ctx, client.ObjectKey{Name: serviceName, Namespace: namespace}, service); err != nil { + return err + } + + service.Spec.Type = apicorev1.ServiceTypeLoadBalancer + if err := clnt.Update(ctx, service); err != nil { + return err + } + + return nil +} diff --git a/pkg/watcher/skr_webhook_manifest_manager.go b/pkg/watcher/skr_webhook_manifest_manager.go index 4355c81f25..1940b95cbd 100644 --- a/pkg/watcher/skr_webhook_manifest_manager.go +++ b/pkg/watcher/skr_webhook_manifest_manager.go @@ -214,7 +214,7 @@ func (m *SKRWebhookManifestManager) getRawManifestClientObjects(cfg *unstructure resources := make([]client.Object, 0) for _, baseRes := range m.baseResources { resource := baseRes.DeepCopy() - resource.SetLabels(collections.MergeMaps(resource.GetLabels(), map[string]string{ + resource.SetLabels(collections.MergeMapsSilent(resource.GetLabels(), map[string]string{ shared.ManagedBy: shared.ManagedByLabelValue, })) configuredResource, err := configureUnstructuredObject(cfg, resource) diff --git a/pkg/watcher/skr_webhook_resources.go b/pkg/watcher/skr_webhook_resources.go index 49d685f25a..1510875b24 100644 --- a/pkg/watcher/skr_webhook_resources.go +++ b/pkg/watcher/skr_webhook_resources.go @@ -194,7 +194,7 @@ func configureDeployment(cfg *unstructuredResourcesConfig, obj *unstructured.Uns } deployment.Spec.Template.Spec.Containers[0] = serverContainer - deployment.SetLabels(collections.MergeMaps(deployment.GetLabels(), map[string]string{ + deployment.SetLabels(collections.MergeMapsSilent(deployment.GetLabels(), map[string]string{ shared.ManagedBy: shared.ManagedByLabelValue, })) diff --git a/scripts/tests/create_test_clusters.sh b/scripts/tests/create_test_clusters.sh index 68a3145316..35a24184c1 100755 --- a/scripts/tests/create_test_clusters.sh +++ b/scripts/tests/create_test_clusters.sh @@ -54,6 +54,7 @@ else k3d cluster create skr \ -p 10080:80@loadbalancer \ -p 10443:443@loadbalancer \ + -p 2112:2112@loadbalancer \ --k3s-arg --tls-san="skr.cluster.local@server:*" \ --image rancher/k3s:v${K8S_VERSION}-k3s1 \ --k3s-arg --disable="traefik@server:*" \ diff --git a/sec-scanners-config.yaml b/sec-scanners-config.yaml index ef9d2e2e8e..75a3f7fc94 100644 --- a/sec-scanners-config.yaml +++ b/sec-scanners-config.yaml @@ -3,7 +3,7 @@ kind: kcp checkmarxOne: checkmarx_preset: golang protecode: - - europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager:1.2.8 + - europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager:1.3.0 - europe-docker.pkg.dev/kyma-project/prod/lifecycle-manager:latest whitesource: language: golang-mod diff --git a/tests/e2e/Makefile b/tests/e2e/Makefile index bda03c58d1..f331e7b7f6 100644 --- a/tests/e2e/Makefile +++ b/tests/e2e/Makefile @@ -136,11 +136,8 @@ modulereleasemeta-module-upgrade-new-version: module-install-by-version: go test -timeout 20m -ginkgo.v -ginkgo.focus "Module Install By Version" -ca-certificate-rotation: - go test -timeout 20m -ginkgo.v -ginkgo.focus "CA Certificate Rotation" - -istio-gateway-secret-rotation: - go test -timeout 20m -ginkgo.v -ginkgo.focus "Istio Gateway Secret Rotation" +legacy-istio-gateway-secret-rotation: + go test -timeout 20m -ginkgo.v -ginkgo.focus "Legacy Istio Gateway Secret Rotation" self-signed-certificate-rotation: go test -timeout 20m -ginkgo.v -ginkgo.focus "Self Signed Certificate Rotation" @@ -180,3 +177,6 @@ maintenance-windows-initial-installation: maintenance-windows-skip: go test -timeout 20m -ginkgo.v -ginkgo.focus "Maintenance Windows - No Wait for Maintenance Widnow on Skip" + +watcher-zero-downtime: + go test -timeout 20m -ginkgo.v -ginkgo.focus "Watcher Zero Downtime" diff --git a/tests/e2e/ca_certificate_rotation_test.go b/tests/e2e/ca_certificate_rotation_test.go deleted file mode 100644 index 9b18d93eaa..0000000000 --- a/tests/e2e/ca_certificate_rotation_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package e2e_test - -import ( - "time" - - certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - "k8s.io/apimachinery/pkg/types" - - "github.com/kyma-project/lifecycle-manager/api/v1beta2" - "github.com/kyma-project/lifecycle-manager/pkg/watcher" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - . "github.com/kyma-project/lifecycle-manager/pkg/testutils" - . "github.com/kyma-project/lifecycle-manager/tests/e2e/commontestutils" -) - -var _ = Describe("CA Certificate Rotation", Ordered, func() { - kyma := NewKymaWithSyncLabel("kyma-sample", ControlPlaneNamespace, v1beta2.DefaultChannel) - InitEmptyKymaBeforeAll(kyma) - CleanupKymaAfterAll(kyma) - - var caCertificate *certmanagerv1.Certificate - caCertName := "klm-watcher-serving" - - Context("Given KCP Cluster and rotated CA certificate", func() { - kcpSecretName := types.NamespacedName{ - Name: kyma.Name + "-webhook-tls", - Namespace: IstioNamespace, - } - skrSecretName := types.NamespacedName{ - Name: watcher.SkrTLSName, - Namespace: RemoteNamespace, - } - It("Then KCP TLS Certificate is removed", func() { - var err error - namespacedSecretName := types.NamespacedName{ - Name: watcher.ResolveTLSCertName(kyma.Name), - Namespace: IstioNamespace, - } - tlsSecret, err := GetTLSSecret(ctx, namespacedSecretName, kcpClient) - Expect(err).NotTo(HaveOccurred()) - - // The timeout used is 4 minutes bec the certificate gets rotated every 1 minute - Eventually(TLSSecretRotated, 4*time.Minute). - WithContext(ctx). - WithArguments(tlsSecret.CreationTimestamp.Time, namespacedSecretName, kcpClient). - Should(Succeed()) - - By("And new TLS Certificate is created") - namespacedCertName := types.NamespacedName{ - Name: caCertName, - Namespace: IstioNamespace, - } - caCertificate, err = GetCACertificate(ctx, namespacedCertName, kcpClient) - Expect(err).NotTo(HaveOccurred()) - Eventually(CertificateSecretIsCreatedAfter). - WithContext(ctx). - WithArguments(kcpSecretName, kcpClient, caCertificate.Status.NotBefore). - Should(Succeed()) - - By("And new TLS Certificate is synced to SKR Cluster") - Eventually(CertificateSecretIsSyncedToSkrCluster). - WithContext(ctx). - WithArguments(kcpSecretName, kcpClient, skrSecretName, skrClient). - Should(Succeed()) - }) - }) -}) diff --git a/tests/e2e/commontestutils/metrics.go b/tests/e2e/commontestutils/metrics.go index bab02dd0d9..879be3e05e 100644 --- a/tests/e2e/commontestutils/metrics.go +++ b/tests/e2e/commontestutils/metrics.go @@ -13,10 +13,25 @@ import ( "github.com/kyma-project/lifecycle-manager/internal/pkg/metrics" ) +const ( + kcpMetricsPort = 9081 + skrMetricsPort = 2112 +) + var ErrMetricNotFound = errors.New("metric was not found") +func GetMaintenanceWindowGauge(ctx context.Context) (int, error) { + bodyString, err := getKCPMetricsBody(ctx) + if err != nil { + return 0, err + } + + re := regexp.MustCompile(metrics.MetricMaintenanceWindowConfigReadSuccess + ` (\d+)`) + return parseCount(re, bodyString) +} + func GetKymaStateMetricCount(ctx context.Context, kymaName string, state shared.State) (int, error) { - bodyString, err := getMetricsBody(ctx) + bodyString, err := getKCPMetricsBody(ctx) if err != nil { return 0, err } @@ -32,7 +47,7 @@ func getKymaStateMetricRegex(kymaName string, state shared.State) *regexp.Regexp } func AssertKymaStateMetricNotFound(ctx context.Context, kymaName string, state shared.State) error { - bodyString, err := getMetricsBody(ctx) + bodyString, err := getKCPMetricsBody(ctx) if err != nil { return err } @@ -49,7 +64,7 @@ func AssertKymaStateMetricNotFound(ctx context.Context, kymaName string, state s func GetRequeueReasonCount(ctx context.Context, requeueReason, requeueType string, ) (int, error) { - bodyString, err := getMetricsBody(ctx) + bodyString, err := getKCPMetricsBody(ctx) if err != nil { return 0, err } @@ -63,7 +78,7 @@ func GetRequeueReasonCount(ctx context.Context, func IsManifestRequeueReasonCountIncreased(ctx context.Context, requeueReason, requeueType string) (bool, error, ) { - bodyString, err := getMetricsBody(ctx) + bodyString, err := getKCPMetricsBody(ctx) if err != nil { return false, err } @@ -76,7 +91,7 @@ func IsManifestRequeueReasonCountIncreased(ctx context.Context, requeueReason, r } func GetModuleStateMetricCount(ctx context.Context, kymaName, moduleName string, state shared.State) (int, error) { - bodyString, err := getMetricsBody(ctx) + bodyString, err := getKCPMetricsBody(ctx) if err != nil { return 0, err } @@ -93,7 +108,7 @@ func PurgeMetricsAreAsExpected(ctx context.Context, ) bool { correctCount := false correctTime := false - bodyString, err := getMetricsBody(ctx) + bodyString, err := getKCPMetricsBody(ctx) if err != nil { return false } @@ -121,7 +136,7 @@ func PurgeMetricsAreAsExpected(ctx context.Context, } func GetSelfSignedCertNotRenewMetricsGauge(ctx context.Context, kymaName string) (int, error) { - bodyString, err := getMetricsBody(ctx) + bodyString, err := getKCPMetricsBody(ctx) if err != nil { return 0, err } @@ -133,7 +148,7 @@ func GetSelfSignedCertNotRenewMetricsGauge(ctx context.Context, kymaName string) } func GetMandatoryModuleTemplateCountMetric(ctx context.Context) (int, error) { - bodyString, err := getMetricsBody(ctx) + bodyString, err := getKCPMetricsBody(ctx) if err != nil { return 0, err } @@ -143,7 +158,7 @@ func GetMandatoryModuleTemplateCountMetric(ctx context.Context) (int, error) { } func GetMandatoryModuleStateMetric(ctx context.Context, kymaName, moduleName, state string) (int, error) { - bodyString, err := getMetricsBody(ctx) + bodyString, err := getKCPMetricsBody(ctx) if err != nil { return 0, err } @@ -153,9 +168,27 @@ func GetMandatoryModuleStateMetric(ctx context.Context, kymaName, moduleName, st return parseCount(re, bodyString) } -func getMetricsBody(ctx context.Context) (string, error) { +func GetWatcherFailedKcpTotalMetric(ctx context.Context) (int, error) { + metricsBody, err := getSKRMetricsBody(ctx) + if err != nil { + return 0, err + } + regex := regexp.MustCompile(`watcher_failed_kcp_total{error_reason="failed-request"} (\d+)`) + return parseCount(regex, metricsBody) +} + +func getKCPMetricsBody(ctx context.Context) (string, error) { + return getMetricsBody(ctx, kcpMetricsPort) +} + +func getSKRMetricsBody(ctx context.Context) (string, error) { + return getMetricsBody(ctx, skrMetricsPort) +} + +func getMetricsBody(ctx context.Context, port int) (string, error) { clnt := &http.Client{} - request, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:9081/metrics", nil) + url := fmt.Sprintf("http://localhost:%d/metrics", port) + request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return "", fmt.Errorf("request to metrics endpoint :%w", err) } diff --git a/tests/e2e/commontestutils/rbac.go b/tests/e2e/commontestutils/rbac.go index 2cec1f78d4..5eb39dfd0a 100644 --- a/tests/e2e/commontestutils/rbac.go +++ b/tests/e2e/commontestutils/rbac.go @@ -55,7 +55,7 @@ func ListKlmRoleBindings(clnt client.Client, ctx context.Context, return klmRoleBindings, nil } -func GetClusterRoleBindingPolicyRules(ctx context.Context, clnt client.Client, roleName string, +func GetClusterRolePolicyRules(ctx context.Context, clnt client.Client, roleName string, clusterRoleBindings apirbacv1.ClusterRoleBindingList, ) ([]apirbacv1.PolicyRule, error) { var policyRules []apirbacv1.PolicyRule @@ -71,22 +71,6 @@ func GetClusterRoleBindingPolicyRules(ctx context.Context, clnt client.Client, r return policyRules, nil } -func GetRoleBindingwithClusterRolePolicyRules(ctx context.Context, clnt client.Client, roleName string, - roleBindings apirbacv1.RoleBindingList, -) ([]apirbacv1.PolicyRule, error) { - var policyRules []apirbacv1.PolicyRule - for _, rb := range roleBindings.Items { - if rb.RoleRef.Name == roleName { - var err error - policyRules, err = getClusterRolePolicyRules(ctx, clnt, roleName) - if err != nil { - return nil, errFailedToFetchClusterRole - } - } - } - return policyRules, nil -} - func GetRoleBindingRolePolicyRules(ctx context.Context, clnt client.Client, roleName, namespace string, roleBindings apirbacv1.RoleBindingList, ) ([]apirbacv1.PolicyRule, error) { @@ -104,6 +88,15 @@ func GetRoleBindingRolePolicyRules(ctx context.Context, clnt client.Client, role return policyRules, nil } +func GetClusterRole(ctx context.Context, clnt client.Client, roleName string) (apirbacv1.ClusterRole, error) { + clusterRole := apirbacv1.ClusterRole{} + err := clnt.Get(ctx, client.ObjectKey{Name: roleName}, &clusterRole) + if err != nil { + return clusterRole, errFailedToFetchClusterRole + } + return clusterRole, nil +} + func getClusterRolePolicyRules(ctx context.Context, clnt client.Client, roleName string) ([]apirbacv1.PolicyRule, error, ) { diff --git a/tests/e2e/kyma_metrics_test.go b/tests/e2e/kyma_metrics_test.go index 524823a683..7055583ce9 100644 --- a/tests/e2e/kyma_metrics_test.go +++ b/tests/e2e/kyma_metrics_test.go @@ -15,7 +15,7 @@ import ( . "github.com/kyma-project/lifecycle-manager/tests/e2e/commontestutils" ) -var _ = Describe("Manage Module metrics", Ordered, func() { +var _ = Describe("Manage Module Metrics", Ordered, func() { kyma := NewKymaWithSyncLabel("kyma-sample", ControlPlaneNamespace, v1beta2.DefaultChannel) module := NewTemplateOperator(v1beta2.DefaultChannel) moduleCR := NewTestModuleCR(RemoteNamespace) @@ -56,7 +56,7 @@ var _ = Describe("Manage Module metrics", Ordered, func() { Should(Equal(1)) }) - It("Then Related Manifest Requeue metrics Get Increased", func() { + It("Then Related Manifest Requeue Metrics Get Increased", func() { Eventually(IsManifestRequeueReasonCountIncreased). WithContext(ctx). WithArguments(string(metrics.ManifestAddFinalizer), string(queue.IntendedRequeue)). @@ -102,7 +102,7 @@ var _ = Describe("Manage Module metrics", Ordered, func() { Should(Equal(0)) }) - It("Then Related Manifest Requeue metrics Get Increased", func() { + It("Then Related Manifest Requeue Metrics Get Increased", func() { Eventually(IsManifestRequeueReasonCountIncreased). WithContext(ctx). WithArguments(string(metrics.ManifestPreDeleteEnqueueRequired), string(queue.IntendedRequeue)). @@ -130,7 +130,7 @@ var _ = Describe("Manage Module metrics", Ordered, func() { WithArguments(string(metrics.KymaDeletion), string(queue.IntendedRequeue)). Should(Equal(1)) - By("And Kyma metrics are removed") + By("And Kyma Metrics are removed") for _, state := range shared.AllStates() { Eventually(AssertKymaStateMetricNotFound). WithContext(ctx). diff --git a/tests/e2e/istio_gateway_secret_rotation_test.go b/tests/e2e/legacy_istio_gateway_secret_rotation_test.go similarity index 95% rename from tests/e2e/istio_gateway_secret_rotation_test.go rename to tests/e2e/legacy_istio_gateway_secret_rotation_test.go index b979553003..945a8e02fe 100644 --- a/tests/e2e/istio_gateway_secret_rotation_test.go +++ b/tests/e2e/legacy_istio_gateway_secret_rotation_test.go @@ -12,7 +12,7 @@ import ( . "github.com/onsi/gomega" ) -var _ = Describe("Istio Gateway Secret Rotation", Ordered, func() { +var _ = Describe("Legacy Istio Gateway Secret Rotation", Ordered, func() { kyma := NewKymaWithSyncLabel("kyma-sample", ControlPlaneNamespace, v1beta2.DefaultChannel) InitEmptyKymaBeforeAll(kyma) CleanupKymaAfterAll(kyma) diff --git a/tests/e2e/maintenance_windows_initial_installation_test.go b/tests/e2e/maintenance_windows_initial_installation_test.go index 60d78721db..c4002b196e 100644 --- a/tests/e2e/maintenance_windows_initial_installation_test.go +++ b/tests/e2e/maintenance_windows_initial_installation_test.go @@ -17,7 +17,6 @@ Maintenance Windows are defined as such: */ var _ = Describe("Maintenance Windows - No Wait for Maintenance Window on Initial Installation", Ordered, func() { - const fastChannel = "fast" const europe = "europe" kyma := NewKymaWithSyncLabel("kyma-sample", ControlPlaneNamespace, v1beta2.DefaultChannel) @@ -30,9 +29,18 @@ var _ = Describe("Maintenance Windows - No Wait for Maintenance Window on Initia InitEmptyKymaBeforeAll(kyma) CleanupKymaAfterAll(kyma) + Context("Given KCP Cluster", func() { + It("When KLM is initialized", func() { + By("Then maintenance window metrics are initialized") + Eventually(GetMaintenanceWindowGauge). + WithContext(ctx). + Should(Equal(1)) + }) + }) + Context("Given SKR Cluster; Kyma CR .spec.skipMaintenanceWindows=false; NO active maintenance window", func() { It("When module in fast channel is enabled (requiresDowntime=true)", func() { - module.Channel = fastChannel + module.Channel = FastChannel Eventually(EnableModule). WithContext(ctx). WithArguments(skrClient, defaultRemoteKymaName, RemoteNamespace, module). @@ -53,7 +61,8 @@ var _ = Describe("Maintenance Windows - No Wait for Maintenance Window on Initia By("And SKR Kyma CR is in \"Ready\" State") Eventually(KymaIsInState). WithContext(ctx). - WithArguments(shared.DefaultRemoteKymaName, shared.DefaultRemoteNamespace, skrClient, shared.StateReady). + WithArguments(shared.DefaultRemoteKymaName, shared.DefaultRemoteNamespace, skrClient, + shared.StateReady). Should(Succeed()) By("And KCP Kyma CR is in \"Ready\" State") @@ -78,7 +87,8 @@ var _ = Describe("Maintenance Windows - No Wait for Maintenance Window on Initia By("And SKR Kyma CR is in \"Ready\" State") Eventually(KymaIsInState). WithContext(ctx). - WithArguments(shared.DefaultRemoteKymaName, shared.DefaultRemoteNamespace, skrClient, shared.StateReady). + WithArguments(shared.DefaultRemoteKymaName, shared.DefaultRemoteNamespace, skrClient, + shared.StateReady). Should(Succeed()) By("And KCP Kyma CR is in \"Ready\" State") diff --git a/tests/e2e/maintenance_windows_skip_test.go b/tests/e2e/maintenance_windows_skip_test.go index f776e351aa..a3bd8007b6 100644 --- a/tests/e2e/maintenance_windows_skip_test.go +++ b/tests/e2e/maintenance_windows_skip_test.go @@ -17,7 +17,6 @@ Maintenance Windows are defined as such: */ var _ = Describe("Maintenance Windows - No Wait for Maintenance Widnow on Skip", Ordered, func() { - const fastChannel = "fast" const europe = "europe" kyma := NewKymaWithSyncLabel("kyma-sample", ControlPlaneNamespace, v1beta2.DefaultChannel) @@ -64,7 +63,7 @@ var _ = Describe("Maintenance Windows - No Wait for Maintenance Widnow on Skip", }) It("When module channel is changed to fast (requiresDowntime=true)", func() { - module.Channel = fastChannel + module.Channel = FastChannel Eventually(UpdateKymaModuleChannel). WithContext(ctx). WithArguments(skrClient, shared.DefaultRemoteKymaName, shared.DefaultRemoteNamespace, module.Channel). diff --git a/tests/e2e/maintenance_windows_wait_test.go b/tests/e2e/maintenance_windows_wait_test.go index 5c580bd320..0897ff135f 100644 --- a/tests/e2e/maintenance_windows_wait_test.go +++ b/tests/e2e/maintenance_windows_wait_test.go @@ -17,7 +17,6 @@ Maintenance Windows are defined as such: */ var _ = Describe("Maintenance Windows - Wait for Maintenance Window", Ordered, func() { - const fastChannel = "fast" const europe = "europe" const asia = "asia" @@ -65,7 +64,7 @@ var _ = Describe("Maintenance Windows - Wait for Maintenance Window", Ordered, f }) It("When module channel is changed to fast (requiresDowntime=true)", func() { - module.Channel = fastChannel + module.Channel = FastChannel Eventually(UpdateKymaModuleChannel). WithContext(ctx). WithArguments(skrClient, shared.DefaultRemoteKymaName, shared.DefaultRemoteNamespace, module.Channel). diff --git a/tests/e2e/mandatory_modules_metrics_test.go b/tests/e2e/mandatory_modules_metrics_test.go index e0826455bf..9402b82162 100644 --- a/tests/e2e/mandatory_modules_metrics_test.go +++ b/tests/e2e/mandatory_modules_metrics_test.go @@ -14,7 +14,7 @@ import ( . "github.com/kyma-project/lifecycle-manager/tests/e2e/commontestutils" ) -var _ = Describe("Mandatory Module metrics", Ordered, func() { +var _ = Describe("Mandatory Module Metrics", Ordered, func() { kyma := NewKymaWithSyncLabel("kyma-sample", "kcp-system", v1beta2.DefaultChannel) InitEmptyKymaBeforeAll(kyma) diff --git a/tests/e2e/mandatory_modules_with_old_naming_pattern_metrics_test.go b/tests/e2e/mandatory_modules_with_old_naming_pattern_metrics_test.go index d13fbf2c06..7f9f202e79 100644 --- a/tests/e2e/mandatory_modules_with_old_naming_pattern_metrics_test.go +++ b/tests/e2e/mandatory_modules_with_old_naming_pattern_metrics_test.go @@ -14,7 +14,7 @@ import ( . "github.com/kyma-project/lifecycle-manager/tests/e2e/commontestutils" ) -var _ = Describe("Mandatory Module With Old Naming Pattern metrics", Ordered, func() { +var _ = Describe("Mandatory Module With Old Naming Pattern Metrics", Ordered, func() { kyma := NewKymaWithSyncLabel("kyma-sample", "kcp-system", v1beta2.DefaultChannel) InitEmptyKymaBeforeAll(kyma) diff --git a/tests/e2e/module_deletion_test.go b/tests/e2e/module_deletion_test.go index 8387af78c6..8bbd524fe4 100644 --- a/tests/e2e/module_deletion_test.go +++ b/tests/e2e/module_deletion_test.go @@ -97,7 +97,7 @@ var _ = Describe("Non Blocking Kyma Module Deletion", Ordered, func() { }) It("When Kyma Module is re-enabled in different Module Distribution Channel", func() { - module.Channel = "fast" + module.Channel = FastChannel Eventually(EnableModule). WithContext(ctx). WithArguments(skrClient, defaultRemoteKymaName, RemoteNamespace, module). diff --git a/tests/e2e/module_unmanage_test.go b/tests/e2e/module_unmanage_test.go index 406b59b010..9f8e0477c1 100644 --- a/tests/e2e/module_unmanage_test.go +++ b/tests/e2e/module_unmanage_test.go @@ -180,7 +180,9 @@ var _ = Describe("Unmanaging Kyma Module", Ordered, func() { Should(Succeed()) }) - It("When Module is enabled again", func() { + It("When Module is enabled again with CustomResourcePolicy:Ignore", func() { + module.CustomResourcePolicy = v1beta2.CustomResourcePolicyIgnore + Eventually(EnableModule). WithContext(ctx). WithArguments(skrClient, defaultRemoteKymaName, RemoteNamespace, module). @@ -203,5 +205,45 @@ var _ = Describe("Unmanaging Kyma Module", Ordered, func() { WithArguments(kyma.GetName(), kyma.GetNamespace(), kcpClient, shared.StateReady). Should(Succeed()) }) + + It("When Module is unmanaged", func() { + Eventually(SetModuleManaged). + WithContext(ctx). + WithArguments(skrClient, defaultRemoteKymaName, RemoteNamespace, module.Name, false). + Should(Succeed()) + + By("And Manifest CR is removed") + Eventually(NoManifestExist). + WithContext(ctx). + WithArguments(kcpClient). + Should(Succeed()) + + By("And Module Operator Deployment is not removed on SKR cluster") + Consistently(CheckIfExists). + WithContext(ctx). + WithArguments(ModuleResourceName, TestModuleResourceNamespace, + "apps", "v1", "Deployment", skrClient). + Should(Succeed()) + + By("And all manifest resources no longer have managed-by labels") + for _, resource := range manifestResources { + objectKey := client.ObjectKey{Name: resource.Name, Namespace: resource.Namespace} + gvk := schema.GroupVersionKind{ + Group: resource.Group, + Version: resource.Version, + Kind: resource.Kind, + } + Eventually(HasExpectedLabel). + WithContext(ctx). + WithArguments(skrClient, objectKey, gvk, + shared.ManagedBy, shared.ManagedByLabelValue).Should(Equal(ErrLabelNotFound)) + } + + By("And KCP Kyma CR is in \"Ready\" State") + Eventually(KymaIsInState). + WithContext(ctx). + WithArguments(kyma.GetName(), kyma.GetNamespace(), kcpClient, shared.StateReady). + Should(Succeed()) + }) }) }) diff --git a/tests/e2e/module_upgrade_channel_switch_test.go b/tests/e2e/module_upgrade_channel_switch_test.go index eeaec78526..6c96db811a 100644 --- a/tests/e2e/module_upgrade_channel_switch_test.go +++ b/tests/e2e/module_upgrade_channel_switch_test.go @@ -53,7 +53,7 @@ var _ = Describe("Module Upgrade By Channel Switch", Ordered, func() { It("When upgrade version by switch Channel", func() { Eventually(UpdateKymaModuleChannel). WithContext(ctx). - WithArguments(skrClient, defaultRemoteKymaName, RemoteNamespace, "fast"). + WithArguments(skrClient, defaultRemoteKymaName, RemoteNamespace, FastChannel). Should(Succeed()) }) diff --git a/tests/e2e/purge_metrics_test.go b/tests/e2e/purge_metrics_test.go index 993a9708fe..d2a3fcba87 100644 --- a/tests/e2e/purge_metrics_test.go +++ b/tests/e2e/purge_metrics_test.go @@ -12,7 +12,7 @@ import ( . "github.com/kyma-project/lifecycle-manager/tests/e2e/commontestutils" ) -var _ = Describe("Purge metrics", Ordered, func() { +var _ = Describe("Purge Metrics", Ordered, func() { kyma := NewKymaWithSyncLabel("kyma-sample", ControlPlaneNamespace, v1beta2.DefaultChannel) module := NewTemplateOperator(v1beta2.DefaultChannel) moduleCR := NewTestModuleCR(RemoteNamespace) @@ -45,7 +45,7 @@ var _ = Describe("Purge metrics", Ordered, func() { Should(BeTrue()) }) - It("Then Purge metrics are updated", func() { + It("Then Purge Metrics are updated", func() { time.Sleep(5 * time.Second) Eventually(PurgeMetricsAreAsExpected). WithContext(ctx). diff --git a/tests/e2e/rbac_privileges_test.go b/tests/e2e/rbac_privileges_test.go index 588d2d1a34..3357558e2d 100644 --- a/tests/e2e/rbac_privileges_test.go +++ b/tests/e2e/rbac_privileges_test.go @@ -11,11 +11,12 @@ import ( var _ = Describe("RBAC Privileges", func() { Context("Given KCP Cluster with KLM Service Account", func() { - It("Then KLM Service Account has the correct ClusterRoleBindings", func() { + It("Then KLM Service Account has the correct number of ClusterRoleBindings", func() { klmClusterRoleBindings, err := ListKlmClusterRoleBindings(kcpClient, ctx, "klm-controller-manager") Expect(err).ToNot(HaveOccurred()) Expect(klmClusterRoleBindings.Items).To(HaveLen(1)) + By("And CRD ClusterRole has the correct PolicyRules") crdRoleRules := []apirbacv1.PolicyRule{ { APIGroups: []string{"apiextensions.k8s.io"}, @@ -28,15 +29,17 @@ var _ = Describe("RBAC Privileges", func() { Verbs: []string{"update"}, }, } - Expect(GetClusterRoleBindingPolicyRules(ctx, kcpClient, "klm-controller-manager-crds", + Expect(GetClusterRolePolicyRules(ctx, kcpClient, "klm-controller-manager-crds", klmClusterRoleBindings)).To(Equal(crdRoleRules)) - By("And KLM Service Account has the correct RoleBindings in kcp-system namespace") + By("And KLM Service Account has the correct number of RoleBindings in kcp-system namespace") + expectedNumberOfRoleBindings := 2 kcpSystemKlmRoleBindings, err := ListKlmRoleBindings(kcpClient, ctx, "klm-controller-manager", "kcp-system") Expect(err).ToNot(HaveOccurred()) - Expect(kcpSystemKlmRoleBindings.Items).To(HaveLen(2)) + Expect(kcpSystemKlmRoleBindings.Items).To(HaveLen(expectedNumberOfRoleBindings)) + By("And leader-election Role has the correct PolicyRules") leaderElectionRoleRules := []apirbacv1.PolicyRule{ { APIGroups: []string{""}, @@ -54,15 +57,18 @@ var _ = Describe("RBAC Privileges", func() { Verbs: []string{"create", "patch"}, }, } - Expect(GetRoleBindingRolePolicyRules(ctx, kcpClient, "klm-controller-manager-leader-election", + Expect(GetRoleBindingRolePolicyRules(ctx, + kcpClient, + "klm-controller-manager-leader-election", "kcp-system", kcpSystemKlmRoleBindings)).To(Equal(leaderElectionRoleRules)) + By("And controller-manager Role has the correct PolicyRules") klmManagerRoleRules := []apirbacv1.PolicyRule{ { APIGroups: []string{""}, Resources: []string{"configmaps"}, - Verbs: []string{"create", "delete", "get", "list", "patch", "update", "watch"}, + Verbs: []string{"get", "list", "watch"}, }, { APIGroups: []string{""}, @@ -79,16 +85,6 @@ var _ = Describe("RBAC Privileges", func() { Resources: []string{"services"}, Verbs: []string{"get", "list", "watch"}, }, - { - APIGroups: []string{"apiextensions.k8s.io"}, - Resources: []string{"customresourcedefinitions"}, - Verbs: []string{"get", "list", "watch"}, - }, - { - APIGroups: []string{"apiextensions.k8s.io"}, - Resources: []string{"customresourcedefinitions/status"}, - Verbs: []string{"update"}, - }, { APIGroups: []string{"cert-manager.io"}, Resources: []string{"certificates"}, @@ -112,7 +108,7 @@ var _ = Describe("RBAC Privileges", func() { { APIGroups: []string{"operator.kyma-project.io"}, Resources: []string{"kymas"}, - Verbs: []string{"create", "delete", "get", "list", "patch", "update", "watch"}, + Verbs: []string{"get", "list", "patch", "update", "watch"}, }, { APIGroups: []string{"operator.kyma-project.io"}, @@ -147,7 +143,7 @@ var _ = Describe("RBAC Privileges", func() { { APIGroups: []string{"operator.kyma-project.io"}, Resources: []string{"moduletemplates"}, - Verbs: []string{"create", "delete", "get", "list", "patch", "update", "watch"}, + Verbs: []string{"get", "list", "patch", "update", "watch"}, }, { APIGroups: []string{"operator.kyma-project.io"}, @@ -157,7 +153,7 @@ var _ = Describe("RBAC Privileges", func() { { APIGroups: []string{"operator.kyma-project.io"}, Resources: []string{"watchers"}, - Verbs: []string{"create", "delete", "get", "list", "patch", "update", "watch"}, + Verbs: []string{"get", "list", "patch", "update", "watch"}, }, { APIGroups: []string{"operator.kyma-project.io"}, @@ -170,10 +166,22 @@ var _ = Describe("RBAC Privileges", func() { Verbs: []string{"get", "patch", "update"}, }, } - Expect(GetRoleBindingwithClusterRolePolicyRules(ctx, kcpClient, "klm-controller-manager", + _, err = GetClusterRole(ctx, kcpClient, "klm-controller-manager") + Expect(err).To(HaveOccurred()) + + Expect(GetRoleBindingRolePolicyRules(ctx, + kcpClient, + "klm-controller-manager", + "kcp-system", kcpSystemKlmRoleBindings)).To(Equal(klmManagerRoleRules)) - By("And KLM Service Account has the correct RoleBindings in istio-system namespace") + By("And KLM Service Account has the correct number of RoleBindings in istio-system namespace") + istioSystemKlmRoleBindings, err := ListKlmRoleBindings(kcpClient, ctx, "klm-controller-manager", + "istio-system") + Expect(err).ToNot(HaveOccurred()) + Expect(istioSystemKlmRoleBindings.Items).To(HaveLen(1)) + + By("And certmanager Role has the correct PolicyRules") istioNamespaceRoleRules := []apirbacv1.PolicyRule{ { APIGroups: []string{""}, @@ -191,14 +199,12 @@ var _ = Describe("RBAC Privileges", func() { Verbs: []string{"list", "watch"}, }, } - istioSystemKlmRoleBindings, err := ListKlmRoleBindings(kcpClient, ctx, "klm-controller-manager", - "istio-system") - Expect(err).ToNot(HaveOccurred()) - Expect(istioSystemKlmRoleBindings.Items).To(HaveLen(1)) - - Expect(GetRoleBindingRolePolicyRules(ctx, kcpClient, "klm-controller-manager-watcher-certmanager", + Expect(GetRoleBindingRolePolicyRules(ctx, + kcpClient, + "klm-controller-manager-certmanager", "istio-system", - istioSystemKlmRoleBindings)).To(Equal(istioNamespaceRoleRules)) + istioSystemKlmRoleBindings)). + To(Equal(istioNamespaceRoleRules)) }) }) }) diff --git a/tests/e2e/watcher_test.go b/tests/e2e/watcher_test.go index c00cf7cf5a..35d15435e6 100644 --- a/tests/e2e/watcher_test.go +++ b/tests/e2e/watcher_test.go @@ -83,7 +83,7 @@ var _ = Describe("Enqueue Event from Watcher", Ordered, func() { timeNow := &apimetav1.Time{Time: time.Now()} It("When spec of SKR Kyma CR is changed", func() { GinkgoWriter.Println(fmt.Sprintf("Spec watching logs since %s: ", timeNow)) - switchedChannel := "fast" + switchedChannel := FastChannel Eventually(changeRemoteKymaChannel). WithContext(ctx). WithArguments(RemoteNamespace, switchedChannel, skrClient). diff --git a/tests/e2e/watcher_zero_downtime_test.go b/tests/e2e/watcher_zero_downtime_test.go new file mode 100644 index 0000000000..3f4f899727 --- /dev/null +++ b/tests/e2e/watcher_zero_downtime_test.go @@ -0,0 +1,72 @@ +package e2e_test + +import ( + "context" + "errors" + "strings" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/kyma-project/lifecycle-manager/api/v1beta2" + . "github.com/kyma-project/lifecycle-manager/pkg/testutils" + . "github.com/kyma-project/lifecycle-manager/tests/e2e/commontestutils" +) + +var _ = Describe("Watcher Zero Downtime", Ordered, func() { + kyma := NewKymaWithSyncLabel("kyma-sample", ControlPlaneNamespace, v1beta2.DefaultChannel) + + InitEmptyKymaBeforeAll(kyma) + CleanupKymaAfterAll(kyma) + + Context("Given SKR Cluster", func() { + It("When SKR metrics service is exposed", func() { + Expect(PatchServiceToTypeLoadBalancer(ctx, skrClient, + "skr-webhook-metrics", "kyma-system")). + To(Succeed()) + time.Sleep(1 * time.Second) + }) + + It("Then no downtime errors can be observed", func() { + Consistently(triggerWatcherAndCheckDowntime). + WithContext(ctx). + WithArguments(skrClient, defaultRemoteKymaName, RemoteNamespace). + WithTimeout(4 * time.Minute). + WithPolling(10 * time.Second). + Should(Succeed()) + }) + }) +}) + +func triggerWatcherAndCheckDowntime(ctx context.Context, skrClient client.Client, + kymaName, kymaNamespace string, +) error { + // Triggering watcher request + kyma, err := GetKyma(ctx, skrClient, kymaName, kymaNamespace) + if err != nil { + return err + } + if kyma.Spec.Channel == v1beta2.DefaultChannel { + kyma.Spec.Channel = FastChannel + } else { + kyma.Spec.Channel = v1beta2.DefaultChannel + } + if err := skrClient.Update(ctx, kyma); err != nil && !strings.Contains(err.Error(), + "the object has been modified") { + return err + } + + time.Sleep(1 * time.Second) + + // Checking that failed KCP error metrics is not increasing + count, err := GetWatcherFailedKcpTotalMetric(ctx) + if err != nil && !strings.Contains(err.Error(), "EOF") { + return err + } + if count > 0 { + return errors.New("watcher is experiencing downtime") + } + return nil +} diff --git a/tests/integration/controller/kyma/kyma_module_channel_test.go b/tests/integration/controller/kyma/kyma_module_channel_test.go index 3208e96a7c..9e93a5a518 100644 --- a/tests/integration/controller/kyma/kyma_module_channel_test.go +++ b/tests/integration/controller/kyma/kyma_module_channel_test.go @@ -20,9 +20,7 @@ import ( ) const ( - FastChannel = "fast" ValidChannel = "valid" - InvalidNoneChannel = string(shared.NoneChannel) InValidChannel = "Invalid01" // lower case characters from a to z InValidMinLengthChannel = "ch" // minlength = 3 InValidMaxLengthChannel = "averylongchannelwhichlargerthanallowedmaxlength" // maxlength = 32 diff --git a/unit-test-coverage.yaml b/unit-test-coverage.yaml index 4bfc67663c..dff703d78b 100644 --- a/unit-test-coverage.yaml +++ b/unit-test-coverage.yaml @@ -1,23 +1,24 @@ packages: - internal/controller/istiogatewaysecret: 31 + internal/controller/istiogatewaysecret: 28.9 internal/crd: 92.1 internal/descriptor/cache: 92.3 internal/descriptor/provider: 66.7 internal/event: 100 - internal/gatewaysecret: 100 + internal/gatewaysecret/legacy: 100 + internal/gatewaysecret/cabundle: 97.6 internal/manifest: 15.8 internal/manifest/statecheck: 71 internal/manifest/filemutex: 100 internal/manifest/finalizer: 17.5 internal/manifest/skrresources: 20.2 - internal/manifest/labelsremoval: 93 + internal/manifest/labelsremoval: 100 internal/manifest/img: 65.5 internal/manifest/manifestclient: 5.0 - internal/manifest/modulecr: 50.0 + internal/manifest/modulecr: 47.0 internal/maintenancewindows: 87.5 internal/istio: 63.3 internal/pkg/resources: 91.7 - internal/remote: 20.2 - internal/util/collections: 86 + internal/remote: 29 + internal/util/collections: 87 pkg/templatelookup: 88 - pkg/templatelookup/moduletemplateinfolookup: 72 + pkg/templatelookup/moduletemplateinfolookup: 98.4 diff --git a/versions.yaml b/versions.yaml index 95c1d6f366..24de30c1a4 100644 --- a/versions.yaml +++ b/versions.yaml @@ -1,8 +1,8 @@ # defines the versions of the tools used in the project -certManager: "1.15.0" +certManager: "1.17.1" controllerTools: "0.14.0" -docker: "27.4.0" -go: "1.23.5" +docker: "27.5.1" +go: "1.23.6" golangciLint: "1.60.3" istio: "1.24.1" k3d: "5.7.4"