From 6243e491807f37f0a3103ed8806e198a6ba44bef Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 15 Aug 2023 10:13:30 +0200 Subject: [PATCH 01/40] Add workflow to split helm charts into their own repo This will push any change done to a chart folder out into the separate repo corresponding to the chart that has been changed. This workflow needs a secret called CHARTS_REPOS_TOKEN that is a Personal Access Token with fine grained repo and workflow write access on the following repos: - acm-chart - hashicorp-vault-chart - golang-external-secrets-chart - clustergroup-chart - letsencrypt-chart --- .github/workflows/chart-branches.yml | 117 +++++++++++++++++++++++++++ .github/workflows/chart-split.yml | 61 ++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 .github/workflows/chart-branches.yml create mode 100644 .github/workflows/chart-split.yml diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml new file mode 100644 index 00000000..0eb7d978 --- /dev/null +++ b/.github/workflows/chart-branches.yml @@ -0,0 +1,117 @@ +--- +name: Create per-chart branches + +# We only run this job on the charts that will be later moved to full blown charts +# We also want to run the subtree comand only for the charts that have been actually changed +# because git subtree split is a bit of an expensive operation +# github actions do not support yaml anchors so there is more duplication than usual +on: + push: + branches: + - main + paths: + - 'acm/**' + - 'golang-external-secrets/**' + - 'hashicorp-vault/**' + - 'letsencrypt/**' + - 'clustergroup/**' + +jobs: + changes: + name: Figure out per-chart changes + runs-on: ubuntu-latest + permissions: read-all + outputs: + acm: ${{ steps.filter.outputs.acm }} + golang-external-secrets: ${{ steps.filter.outputs.golang-external-secrets }} + hashicorp-vault: ${{ steps.filter.outputs.hashicorp-vault }} + letsencrypt: ${{ steps.filter.outputs.letsencrypt }} + clustergroup: ${{ steps.filter.outputs.clustergroup }} + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + acm: + - 'acm/**' + golang-external-secrets: + - 'golang-external-secrets/**' + hashicorp-vault: + - 'hashicorp-vault/**' + letsencrypt: + - 'letsencrypt/**' + clustergroup: + - 'clustergroup/**' + + acm: + needs: changes + if: ${{ needs.changes.outputs.acm == 'true' }} + uses: validatedpatterns/common/.github/workflows/chart-split.yml@main + permissions: + actions: write + contents: write + with: + chart_name: acm + upstream_repository: validatedpatterns/common + target_repository: validatedpatterns/acm-chart + force: true + secrets: inherit + + golang-external-secrets: + needs: changes + if: ${{ needs.changes.outputs.golang-external-secrets == 'true' }} + uses: validatedpatterns/common/.github/workflows/chart-split.yml@main + permissions: + actions: write + contents: write + with: + chart_name: golang-external-secrets + upstream_repository: validatedpatterns/common + target_repository: validatedpatterns/golang-external-secrets-chart + force: true + secrets: inherit + + hashicorp-vault: + needs: changes + if: ${{ needs.changes.outputs.hashicorp-vault == 'true' }} + uses: validatedpatterns/common/.github/workflows/chart-split.yml@main + permissions: + actions: write + contents: write + with: + chart_name: hashicorp-vault + upstream_repository: validatedpatterns/common + target_repository: validatedpatterns/hashicorp-vault-chart + force: true + secrets: inherit + + letsencrypt: + needs: changes + if: ${{ needs.changes.outputs.letsencrypt == 'true' }} + uses: validatedpatterns/common/.github/workflows/chart-split.yml@main + permissions: + actions: write + contents: write + with: + chart_name: letsencrypt + upstream_repository: validatedpatterns/common + target_repository: validatedpatterns/letsencrypt-chart + force: true + secrets: inherit + + clustergroup: + needs: changes + if: ${{ needs.changes.outputs.clustergroup == 'true' }} + uses: validatedpatterns/common/.github/workflows/chart-split.yml@main + permissions: + actions: write + contents: write + with: + chart_name: clustergroup + upstream_repository: validatedpatterns/common + target_repository: validatedpatterns/clustergroup-chart + force: true + secrets: inherit diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml new file mode 100644 index 00000000..df1bd548 --- /dev/null +++ b/.github/workflows/chart-split.yml @@ -0,0 +1,61 @@ +--- +name: Split into chart repo branches + +on: + workflow_call: + inputs: + chart_name: + required: true + type: string + upstream_repository: + required: true + type: string + target_repository: + required: true + type: string + target_branch: + required: false + type: string + default: main + force: + required: false + type: boolean + default: false + tags: + required: false + type: boolean + default: false + +jobs: + split_chart: + runs-on: ubuntu-latest + permissions: + actions: write + contents: write + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: ${{ secrets.CHARTS_REPOS_TOKEN }} + + - name: Run git subtree split + env: + GITHUB_TOKEN: ${{ secrets.CHARTS_REPOS_TOKEN }} + run: | + set -e + N=${{ inputs.chart_name }} + B="${N}-main-single-chart" + git push origin -d "${B}" || /bin/true + git subtree split -P "${N}" -b "${B}" + git push -f -u origin "${B}" + + - uses: TobKed/github-forks-sync-action@master + with: + github_token: ${{ secrets.CHARTS_REPOS_TOKEN }} + upstream_repository: ${{ inputs.upstream_repository }} + upstream_branch: "${{ inputs.chart_name }}-main-single-chart" + target_repository: ${{ inputs.target_repository }} + target_branch: ${{ inputs.target_branch }} + force: ${{ inputs.force }} + tags: ${{ inputs.tags }} From f6ead1e2704aa8c7e22bdd91bc8f2145f9063398 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 15 Aug 2023 16:06:10 +0200 Subject: [PATCH 02/40] Small test for the workflow towards single chart repos --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 1c3db911..3bae9da5 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -description: A Helm chart to configure Advanced Cluster Manager for OpenShift +description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm From 23c9753fc728a3f338182908507db28880a07c85 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 15 Aug 2023 16:22:48 +0200 Subject: [PATCH 03/40] Small test for the workflow towards single chart repos (part 2) --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 3bae9da5..1c3db911 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -description: A Helm chart to configure Advanced Cluster Manager for OpenShift. +description: A Helm chart to configure Advanced Cluster Manager for OpenShift keywords: - pattern name: acm From 09bfa2c1a5ef89e6281b083342511b7790bcf923 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 15 Aug 2023 16:57:21 +0200 Subject: [PATCH 04/40] Simplify split workflow --- .github/workflows/chart-branches.yml | 10 ---------- .github/workflows/chart-split.yml | 29 +++------------------------- 2 files changed, 3 insertions(+), 36 deletions(-) diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml index 0eb7d978..66acda13 100644 --- a/.github/workflows/chart-branches.yml +++ b/.github/workflows/chart-branches.yml @@ -55,9 +55,7 @@ jobs: contents: write with: chart_name: acm - upstream_repository: validatedpatterns/common target_repository: validatedpatterns/acm-chart - force: true secrets: inherit golang-external-secrets: @@ -69,9 +67,7 @@ jobs: contents: write with: chart_name: golang-external-secrets - upstream_repository: validatedpatterns/common target_repository: validatedpatterns/golang-external-secrets-chart - force: true secrets: inherit hashicorp-vault: @@ -83,9 +79,7 @@ jobs: contents: write with: chart_name: hashicorp-vault - upstream_repository: validatedpatterns/common target_repository: validatedpatterns/hashicorp-vault-chart - force: true secrets: inherit letsencrypt: @@ -97,9 +91,7 @@ jobs: contents: write with: chart_name: letsencrypt - upstream_repository: validatedpatterns/common target_repository: validatedpatterns/letsencrypt-chart - force: true secrets: inherit clustergroup: @@ -111,7 +103,5 @@ jobs: contents: write with: chart_name: clustergroup - upstream_repository: validatedpatterns/common target_repository: validatedpatterns/clustergroup-chart - force: true secrets: inherit diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml index df1bd548..fbc4075f 100644 --- a/.github/workflows/chart-split.yml +++ b/.github/workflows/chart-split.yml @@ -7,24 +7,9 @@ on: chart_name: required: true type: string - upstream_repository: - required: true - type: string target_repository: required: true type: string - target_branch: - required: false - type: string - default: main - force: - required: false - type: boolean - default: false - tags: - required: false - type: boolean - default: false jobs: split_chart: @@ -39,7 +24,7 @@ jobs: fetch-depth: 0 token: ${{ secrets.CHARTS_REPOS_TOKEN }} - - name: Run git subtree split + - name: Run git subtree split and push env: GITHUB_TOKEN: ${{ secrets.CHARTS_REPOS_TOKEN }} run: | @@ -49,13 +34,5 @@ jobs: git push origin -d "${B}" || /bin/true git subtree split -P "${N}" -b "${B}" git push -f -u origin "${B}" - - - uses: TobKed/github-forks-sync-action@master - with: - github_token: ${{ secrets.CHARTS_REPOS_TOKEN }} - upstream_repository: ${{ inputs.upstream_repository }} - upstream_branch: "${{ inputs.chart_name }}-main-single-chart" - target_repository: ${{ inputs.target_repository }} - target_branch: ${{ inputs.target_branch }} - force: ${{ inputs.force }} - tags: ${{ inputs.tags }} + #git clone https://validatedpatterns:${GITHUB_TOKEN}@github.com/validatedpatterns/common.git -b "acm-main-single-chart" --single-branch + git push --force https://validatedpatterns:${GITHUB_TOKEN}@github.com/${{ inputs.target_repository }}.git "${B}:main" From f24578972cb1fb4ab83ce46cb513177d828a3c2a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 15 Aug 2023 16:57:46 +0200 Subject: [PATCH 05/40] Small test for the workflow towards single chart repos (part 3) --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 1c3db911..3bae9da5 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -description: A Helm chart to configure Advanced Cluster Manager for OpenShift +description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm From bf91925391f64986396c6bc6bc6b00014d0ffa95 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 15 Aug 2023 17:01:01 +0200 Subject: [PATCH 06/40] Tiny change to trigger split workflow --- clustergroup/Chart.yaml | 2 +- golang-external-secrets/Chart.yaml | 2 +- hashicorp-vault/Chart.yaml | 2 +- letsencrypt/Chart.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 38ece255..d4dfdc63 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -description: A Helm chart to create per-clustergroup ArgoCD applications and any required namespaces or subscriptions +description: A Helm chart to create per-clustergroup ArgoCD applications and any required namespaces or subscriptions. keywords: - pattern name: clustergroup diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index ab900162..e7b779b6 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -description: A Helm chart to configure the golang-based external-secrets +description: A Helm chart to configure the golang-based external-secrets. keywords: - pattern name: golang-external-secrets diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index 649bd4e2..84e7edc7 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -description: A Helm chart to configure Hashicorp's vault +description: A Helm chart to configure Hashicorp's vault. keywords: - pattern name: hashicorp-vault diff --git a/letsencrypt/Chart.yaml b/letsencrypt/Chart.yaml index b5b1c31b..899c790e 100644 --- a/letsencrypt/Chart.yaml +++ b/letsencrypt/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: letsencrypt -description: A Helm chart to add letsencrypt support to Validated Patterns +description: A Helm chart to add letsencrypt support to Validated Patterns. type: application From 698aeb31744d089c6ce8da693776f9ba0754f7bd Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 15 Aug 2023 17:30:15 +0200 Subject: [PATCH 07/40] Add initial helm releasing workflow for acm chart --- acm/.github/workflows/update-helm-repo.yml | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 acm/.github/workflows/update-helm-repo.yml diff --git a/acm/.github/workflows/update-helm-repo.yml b/acm/.github/workflows/update-helm-repo.yml new file mode 100644 index 00000000..d781397d --- /dev/null +++ b/acm/.github/workflows/update-helm-repo.yml @@ -0,0 +1,34 @@ +# Note this workflow is only maintained in this repo +# It should be invoked from each chart's repo +# +# This invokes the workflow named 'publish-charts' in the umbrella repo +# It expects to have a secret called UMBRELLA_REPO_PAT which contains +# the GitHub token that has permissions to invoke workflows and commit code +# inside the umbrella-repo. +# The following fine-grained permissions were used in testing and were limited +# to the umbrella repo only: +# - Actions: r/w +# - Commit statuses: r/w +# - Contents: r/w +# - Deployments: r/w +# - Pages: r/w + +name: vp-patterns/update-helm-repo +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +jobs: + helmlint: + uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@main + permissions: + contents: read + + update-helm-repo: + needs: [helmlint] + runs-on: ubuntu-latest + uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@main + permissions: + id-token: write + contents: read From 3e1b0ac165a5399b84464e524cb302dee4277f59 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 15 Aug 2023 18:19:35 +0200 Subject: [PATCH 08/40] Add helm repo updating workflow in the per-chart workflows folder --- acm/.github/workflows/update-helm-repo.yml | 11 ++----- .../.github/workflows/update-helm-repo.yml | 29 +++++++++++++++++++ .../.github/workflows/update-helm-repo.yml | 29 +++++++++++++++++++ .../.github/workflows/update-helm-repo.yml | 29 +++++++++++++++++++ .../.github/workflows/update-helm-repo.yml | 29 +++++++++++++++++++ 5 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 clustergroup/.github/workflows/update-helm-repo.yml create mode 100644 golang-external-secrets/.github/workflows/update-helm-repo.yml create mode 100644 hashicorp-vault/.github/workflows/update-helm-repo.yml create mode 100644 letsencrypt/.github/workflows/update-helm-repo.yml diff --git a/acm/.github/workflows/update-helm-repo.yml b/acm/.github/workflows/update-helm-repo.yml index d781397d..8c658a18 100644 --- a/acm/.github/workflows/update-helm-repo.yml +++ b/acm/.github/workflows/update-helm-repo.yml @@ -1,8 +1,5 @@ -# Note this workflow is only maintained in this repo -# It should be invoked from each chart's repo -# # This invokes the workflow named 'publish-charts' in the umbrella repo -# It expects to have a secret called UMBRELLA_REPO_PAT which contains +# It expects to have a secret called CHARTS_REPOS_TOKEN which contains # the GitHub token that has permissions to invoke workflows and commit code # inside the umbrella-repo. # The following fine-grained permissions were used in testing and were limited @@ -27,8 +24,6 @@ jobs: update-helm-repo: needs: [helmlint] - runs-on: ubuntu-latest uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@main - permissions: - id-token: write - contents: read + permissions: read-all + secrets: inherit diff --git a/clustergroup/.github/workflows/update-helm-repo.yml b/clustergroup/.github/workflows/update-helm-repo.yml new file mode 100644 index 00000000..8c658a18 --- /dev/null +++ b/clustergroup/.github/workflows/update-helm-repo.yml @@ -0,0 +1,29 @@ +# This invokes the workflow named 'publish-charts' in the umbrella repo +# It expects to have a secret called CHARTS_REPOS_TOKEN which contains +# the GitHub token that has permissions to invoke workflows and commit code +# inside the umbrella-repo. +# The following fine-grained permissions were used in testing and were limited +# to the umbrella repo only: +# - Actions: r/w +# - Commit statuses: r/w +# - Contents: r/w +# - Deployments: r/w +# - Pages: r/w + +name: vp-patterns/update-helm-repo +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +jobs: + helmlint: + uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@main + permissions: + contents: read + + update-helm-repo: + needs: [helmlint] + uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@main + permissions: read-all + secrets: inherit diff --git a/golang-external-secrets/.github/workflows/update-helm-repo.yml b/golang-external-secrets/.github/workflows/update-helm-repo.yml new file mode 100644 index 00000000..8c658a18 --- /dev/null +++ b/golang-external-secrets/.github/workflows/update-helm-repo.yml @@ -0,0 +1,29 @@ +# This invokes the workflow named 'publish-charts' in the umbrella repo +# It expects to have a secret called CHARTS_REPOS_TOKEN which contains +# the GitHub token that has permissions to invoke workflows and commit code +# inside the umbrella-repo. +# The following fine-grained permissions were used in testing and were limited +# to the umbrella repo only: +# - Actions: r/w +# - Commit statuses: r/w +# - Contents: r/w +# - Deployments: r/w +# - Pages: r/w + +name: vp-patterns/update-helm-repo +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +jobs: + helmlint: + uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@main + permissions: + contents: read + + update-helm-repo: + needs: [helmlint] + uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@main + permissions: read-all + secrets: inherit diff --git a/hashicorp-vault/.github/workflows/update-helm-repo.yml b/hashicorp-vault/.github/workflows/update-helm-repo.yml new file mode 100644 index 00000000..8c658a18 --- /dev/null +++ b/hashicorp-vault/.github/workflows/update-helm-repo.yml @@ -0,0 +1,29 @@ +# This invokes the workflow named 'publish-charts' in the umbrella repo +# It expects to have a secret called CHARTS_REPOS_TOKEN which contains +# the GitHub token that has permissions to invoke workflows and commit code +# inside the umbrella-repo. +# The following fine-grained permissions were used in testing and were limited +# to the umbrella repo only: +# - Actions: r/w +# - Commit statuses: r/w +# - Contents: r/w +# - Deployments: r/w +# - Pages: r/w + +name: vp-patterns/update-helm-repo +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +jobs: + helmlint: + uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@main + permissions: + contents: read + + update-helm-repo: + needs: [helmlint] + uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@main + permissions: read-all + secrets: inherit diff --git a/letsencrypt/.github/workflows/update-helm-repo.yml b/letsencrypt/.github/workflows/update-helm-repo.yml new file mode 100644 index 00000000..8c658a18 --- /dev/null +++ b/letsencrypt/.github/workflows/update-helm-repo.yml @@ -0,0 +1,29 @@ +# This invokes the workflow named 'publish-charts' in the umbrella repo +# It expects to have a secret called CHARTS_REPOS_TOKEN which contains +# the GitHub token that has permissions to invoke workflows and commit code +# inside the umbrella-repo. +# The following fine-grained permissions were used in testing and were limited +# to the umbrella repo only: +# - Actions: r/w +# - Commit statuses: r/w +# - Contents: r/w +# - Deployments: r/w +# - Pages: r/w + +name: vp-patterns/update-helm-repo +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +jobs: + helmlint: + uses: validatedpatterns/helm-charts/.github/workflows/helmlint.yml@main + permissions: + contents: read + + update-helm-repo: + needs: [helmlint] + uses: validatedpatterns/helm-charts/.github/workflows/update-helm-repo.yml@main + permissions: read-all + secrets: inherit From 7d442bb38798f8892bbc19d20793d11f73609917 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 16 Aug 2023 16:22:54 +0200 Subject: [PATCH 09/40] Fix up CI superlinter on github actions --- .github/workflows/chart-split.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml index fbc4075f..84f027f6 100644 --- a/.github/workflows/chart-split.yml +++ b/.github/workflows/chart-split.yml @@ -29,10 +29,10 @@ jobs: GITHUB_TOKEN: ${{ secrets.CHARTS_REPOS_TOKEN }} run: | set -e - N=${{ inputs.chart_name }} + N="${{ inputs.chart_name }}" B="${N}-main-single-chart" git push origin -d "${B}" || /bin/true git subtree split -P "${N}" -b "${B}" git push -f -u origin "${B}" #git clone https://validatedpatterns:${GITHUB_TOKEN}@github.com/validatedpatterns/common.git -b "acm-main-single-chart" --single-branch - git push --force https://validatedpatterns:${GITHUB_TOKEN}@github.com/${{ inputs.target_repository }}.git "${B}:main" + git push --force https://validatedpatterns:"${GITHUB_TOKEN}"@github.com/${{ inputs.target_repository }}.git "${B}:main" From a86f25fe6869ca7c9bbb94e305c8fd64e3d75056 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Wed, 16 Aug 2023 09:42:19 -0500 Subject: [PATCH 10/40] Fix tests and make .disabled explicit --- acm/values.yaml | 1 + clustergroup/templates/plumbing/applications.yaml | 3 ++- clustergroup/values.yaml | 1 + tests/clustergroup-industrial-edge-factory.expected.yaml | 1 + tests/clustergroup-industrial-edge-hub.expected.yaml | 1 + tests/clustergroup-medical-diagnosis-hub.expected.yaml | 1 + tests/clustergroup-naked.expected.yaml | 1 + tests/clustergroup-normal.expected.yaml | 1 + 8 files changed, 9 insertions(+), 1 deletion(-) diff --git a/acm/values.yaml b/acm/values.yaml index 7c4a19c0..1100bafd 100644 --- a/acm/values.yaml +++ b/acm/values.yaml @@ -3,6 +3,7 @@ main: channel: "gitops-1.8" global: + extraValueFiles: [] pattern: none repoURL: none targetRevision: main diff --git a/clustergroup/templates/plumbing/applications.yaml b/clustergroup/templates/plumbing/applications.yaml index 075e1bdb..16f5c11a 100644 --- a/clustergroup/templates/plumbing/applications.yaml +++ b/clustergroup/templates/plumbing/applications.yaml @@ -4,7 +4,8 @@ {{- $namespace = "openshift-gitops" }} {{- end }} {{- range .Values.clusterGroup.applications }} -{{- if or (.generators) (.generatorFile) (.useGeneratorValues) (.destinationServer) (.destinationNamespace) }} +{{- if .disabled }} {{- /* This allows us to null out an Application entry by specifying disabled: true in an override file */}} +{{- else if or (.generators) (.generatorFile) (.useGeneratorValues) (.destinationServer) (.destinationNamespace) }} apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index 117e009e..b63e8cc2 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -1,4 +1,5 @@ global: + extraValueFiles: [] pattern: common targetRevision: main options: diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index be93aa88..1875637b 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -136,6 +136,7 @@ data: enabled: all global: clusterDomain: region.example.com + extraValueFiles: [] git: account: hybrid-cloud-patterns dev_revision: main diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index a759bdde..79c1ca76 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -297,6 +297,7 @@ data: enabled: all global: clusterDomain: region.example.com + extraValueFiles: [] git: account: hybrid-cloud-patterns dev_revision: main diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 175f134b..5553e916 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -284,6 +284,7 @@ data: enabled: all global: clusterDomain: region.example.com + extraValueFiles: [] git: account: hybrid-cloud-patterns dev_revision: main diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index e15566b0..9499eb5d 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -65,6 +65,7 @@ data: targetCluster: in-cluster enabled: all global: + extraValueFiles: [] options: applicationRetryLimit: 20 installPlanApproval: Automatic diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index ab4d4d08..e77c84d8 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -193,6 +193,7 @@ data: enabled: all global: clusterDomain: region.example.com + extraValueFiles: [] git: account: hybrid-cloud-patterns dev_revision: main From 28dd3afff7a08723fef75281f4ceacfdea9ca2af Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 16 Aug 2023 16:52:20 +0200 Subject: [PATCH 11/40] Make sure we run the split workflow only when the changes land in validatedpatterns/common Otherwise a push to a private for to main would still invoke the split workflow, if a member of the vp org would do so. Since we do not want that let's make sure we limit this workflow to when the repository name is 'validatedpatterns/common' --- .github/workflows/chart-branches.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml index 66acda13..a1b36cf6 100644 --- a/.github/workflows/chart-branches.yml +++ b/.github/workflows/chart-branches.yml @@ -19,6 +19,7 @@ on: jobs: changes: name: Figure out per-chart changes + if: github.repository == 'validatedpatterns/common' runs-on: ubuntu-latest permissions: read-all outputs: @@ -48,7 +49,9 @@ jobs: acm: needs: changes - if: ${{ needs.changes.outputs.acm == 'true' }} + if: | + ${{ needs.changes.outputs.acm == 'true' }} && + github.repository == 'validatedpatterns/common' uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -60,7 +63,9 @@ jobs: golang-external-secrets: needs: changes - if: ${{ needs.changes.outputs.golang-external-secrets == 'true' }} + if: | + ${{ needs.changes.outputs.golang-external-secrets == 'true' }} && + github.repository == 'validatedpatterns/common' uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -72,7 +77,9 @@ jobs: hashicorp-vault: needs: changes - if: ${{ needs.changes.outputs.hashicorp-vault == 'true' }} + if: | + ${{ needs.changes.outputs.hashicorp-vault == 'true' }} && + github.repository == 'validatedpatterns/common' uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -84,7 +91,9 @@ jobs: letsencrypt: needs: changes - if: ${{ needs.changes.outputs.letsencrypt == 'true' }} + if: | + ${{ needs.changes.outputs.letsencrypt == 'true' }} && + github.repository == 'validatedpatterns/common' uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -96,7 +105,9 @@ jobs: clustergroup: needs: changes - if: ${{ needs.changes.outputs.clustergroup == 'true' }} + if: | + ${{ needs.changes.outputs.clustergroup == 'true' }} && + github.repository == 'validatedpatterns/common' uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write From 765eb017fb0d4c2fc349eb7389d8c02fded2e87e Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Wed, 16 Aug 2023 09:55:14 -0500 Subject: [PATCH 12/40] Update tests. We get an extra (non-impacting whitespace) with the new code --- clustergroup/templates/_helpers.tpl | 5 ++++ ...roup-industrial-edge-factory.expected.yaml | 2 +- ...tergroup-industrial-edge-hub.expected.yaml | 14 +++++----- ...rgroup-medical-diagnosis-hub.expected.yaml | 26 +++++++++---------- tests/clustergroup-normal.expected.yaml | 4 +-- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index c3a730fb..b9feb738 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -39,4 +39,9 @@ Default always defined valueFiles to be included in Applications {{- if $.Values.global.clusterVersion }} - "/values-{{ $.Values.global.clusterVersion }}-{{ $.Values.clusterGroup.name }}.yaml" {{- end }} +{{- if $.Values.global.extraValueFiles }} +{{- range $.Values.global.extraValueFiles }} +- {{ . | quote }} +{{- end }} {{/* range $.Values.global.extraValueFiles */}} +{{- end }} {{/* if $.Values.global.extraValueFiles */}} {{- end }} {{/* clustergroup.app.globalvalues.valuefiles */}} diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 1875637b..3c6d6286 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -408,7 +408,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-factory.yaml" + - "/values-factory.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 79c1ca76..8a5220b2 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -683,7 +683,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -738,7 +738,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -784,7 +784,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -830,7 +830,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -906,7 +906,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -952,7 +952,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1023,7 +1023,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 5553e916..dbecaa84 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -628,7 +628,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -674,7 +674,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -720,7 +720,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -766,7 +766,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -812,7 +812,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -858,7 +858,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -904,7 +904,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -950,7 +950,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1014,7 +1014,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1060,7 +1060,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1106,7 +1106,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1161,7 +1161,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1216,7 +1216,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index e77c84d8..901a7d62 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -538,7 +538,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-example.yaml" + - "/values-example.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -593,7 +593,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-example.yaml" + - "/values-example.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL From 2bc3c61ce3bd070086678d128269dabc31c17805 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Wed, 16 Aug 2023 10:23:01 -0500 Subject: [PATCH 13/40] re-add logic for extravaluefiles --- acm/templates/_helpers.tpl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/acm/templates/_helpers.tpl b/acm/templates/_helpers.tpl index fdd91273..48ff486b 100644 --- a/acm/templates/_helpers.tpl +++ b/acm/templates/_helpers.tpl @@ -10,4 +10,9 @@ Default always defined valueFiles to be included when pushing the cluster wide a # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - '/values-{{ `{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}` }}-{{ .name }}.yaml' +{{- if $.Values.global.extraValueFiles }} +{{- range $.Values.global.extraValueFiles }} +- {{ . | quote }} +{{- end }} {{/* if $.Values.global.extraValueFiles */}} +{{- end }} {{/* range $.Values.global.extraValueFiles */}} {{- end }} {{- /*acm.app.policies.valuefiles */}} From e0f956a42f07db09090586af52eb1ac1ecffd21c Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Wed, 16 Aug 2023 10:32:26 -0500 Subject: [PATCH 14/40] Add more tests for variable definedness/truth --- acm/templates/_helpers.tpl | 2 +- tests/acm-industrial-edge-hub.expected.yaml | 2 +- tests/acm-medical-diagnosis-hub.expected.yaml | 2 +- tests/acm-normal.expected.yaml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/acm/templates/_helpers.tpl b/acm/templates/_helpers.tpl index 48ff486b..80b0cf69 100644 --- a/acm/templates/_helpers.tpl +++ b/acm/templates/_helpers.tpl @@ -10,7 +10,7 @@ Default always defined valueFiles to be included when pushing the cluster wide a # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - '/values-{{ `{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}` }}-{{ .name }}.yaml' -{{- if $.Values.global.extraValueFiles }} +{{- if and $.Values $.Values.global $.Values.global.extraValueFiles }} {{- range $.Values.global.extraValueFiles }} - {{ . | quote }} {{- end }} {{/* if $.Values.global.extraValueFiles */}} diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 444b833c..428d90d2 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -213,7 +213,7 @@ spec: - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-factory.yaml' # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-factory.yaml' + - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-factory.yaml' parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index f79e013b..0a12c2dc 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -204,7 +204,7 @@ spec: - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-region-one.yaml' # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-region-one.yaml' + - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-region-one.yaml' parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 900cc291..42d306b6 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -607,7 +607,7 @@ spec: - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-edge.yaml' # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-edge.yaml' + - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-edge.yaml' parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -701,7 +701,7 @@ spec: - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-edge.yaml' # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-provision-edge.yaml' + - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-provision-edge.yaml' parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL From 8096369923fb406272ae770eb6c274cd5e37f507 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 16 Aug 2023 17:52:29 +0200 Subject: [PATCH 15/40] Switch helm to v3.12.3 in CI --- .github/workflows/linter.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 28c3944d..1bf7e5e4 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -35,9 +35,9 @@ jobs: fetch-depth: 0 - name: Setup helm uses: azure/setup-helm@v3 - # with: - # version: '' # default is latest stable - id: install + with: + version: 'v3.12.3' + ################################ # Run Linter against code base # From b76d830d2d015f8b76734f794b6e6cc22328c089 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Wed, 16 Aug 2023 11:25:10 -0500 Subject: [PATCH 16/40] Unroll global.extraValueFiles in application-policies directly due to namespacing in the _helper.tpl --- acm/templates/_helpers.tpl | 5 ----- acm/templates/policies/application-policies.yaml | 3 +++ tests/acm-industrial-edge-hub.expected.yaml | 2 +- tests/acm-medical-diagnosis-hub.expected.yaml | 2 +- tests/acm-normal.expected.yaml | 4 ++-- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/acm/templates/_helpers.tpl b/acm/templates/_helpers.tpl index 80b0cf69..fdd91273 100644 --- a/acm/templates/_helpers.tpl +++ b/acm/templates/_helpers.tpl @@ -10,9 +10,4 @@ Default always defined valueFiles to be included when pushing the cluster wide a # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - '/values-{{ `{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}` }}-{{ .name }}.yaml' -{{- if and $.Values $.Values.global $.Values.global.extraValueFiles }} -{{- range $.Values.global.extraValueFiles }} -- {{ . | quote }} -{{- end }} {{/* if $.Values.global.extraValueFiles */}} -{{- end }} {{/* range $.Values.global.extraValueFiles */}} {{- end }} {{- /*acm.app.policies.valuefiles */}} diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 5bc5de6a..d854ae72 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -44,6 +44,9 @@ spec: ignoreMissingValueFiles: true valueFiles: {{- include "acm.app.policies.valuefiles" . | nindent 24 }} + {{- range $valueFile := $.Values.global.extraValueFiles }} + - {{ $valueFile | quote }} + {{- end }} {{- range $valueFile := .extraValueFiles }} - {{ $valueFile | quote }} {{- end }} diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 428d90d2..444b833c 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -213,7 +213,7 @@ spec: - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-factory.yaml' # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-factory.yaml' + - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-factory.yaml' parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 0a12c2dc..f79e013b 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -204,7 +204,7 @@ spec: - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-region-one.yaml' # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-region-one.yaml' + - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-region-one.yaml' parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 42d306b6..900cc291 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -607,7 +607,7 @@ spec: - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-edge.yaml' # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-edge.yaml' + - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-edge.yaml' parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -701,7 +701,7 @@ spec: - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-edge.yaml' # We cannot use $.Values.global.clusterVersion because that gets resolved to the # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-provision-edge.yaml' + - '/values-{{ printf "%d.%d" ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Major) ((semver (lookup "operator.openshift.io/v1" "OpenShiftControllerManager" "" "cluster").status.version).Minor) }}-acm-provision-edge.yaml' parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL From 69837ae26f5687007e8fda31dc15143d4d2ba247 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Wed, 16 Aug 2023 13:57:18 -0500 Subject: [PATCH 17/40] Re-add code to operator-install to understand global.extraValueFiles --- operator-install/templates/pattern.yaml | 6 ++++++ operator-install/values.yaml | 3 +++ 2 files changed, 9 insertions(+) diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index d8b3df81..205389dc 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -17,4 +17,10 @@ spec: - name: {{ .name }} value: {{ .value }} {{- end }} +{{- if .Values.global.extraValueFiles }} + extraValueFiles: +{{- range .Values.global.extraValueFiles }} + - {{ . | quote }} +{{- end }} +{{- end }} {{- end }} diff --git a/operator-install/values.yaml b/operator-install/values.yaml index d5b0b13f..4ef3fe4a 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -1,3 +1,6 @@ +global: + extraValueFiles: [] + main: git: repoURL: https://github.com/pattern-clone/mypattern From 751e37395e53274ddaf916ff5351b7a1eab3fb9b Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Wed, 16 Aug 2023 13:59:26 -0500 Subject: [PATCH 18/40] Make sure to add dollar sign --- operator-install/templates/pattern.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index 205389dc..b640bb56 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -17,9 +17,9 @@ spec: - name: {{ .name }} value: {{ .value }} {{- end }} -{{- if .Values.global.extraValueFiles }} +{{- if $.Values.global.extraValueFiles }} extraValueFiles: -{{- range .Values.global.extraValueFiles }} +{{- range $.Values.global.extraValueFiles }} - {{ . | quote }} {{- end }} {{- end }} From e450c492ee2a04bdaef1df8c8c376fa437517d7b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 17 Aug 2023 12:36:38 +0200 Subject: [PATCH 19/40] Add initial multi-source support This change adds initial multiSource support to patterns' applications. The way this works is that nothing changes for applications defined in values-*.yaml by default. So all patterns will work as usual. What can change with this patch is that applications can slowly migrate towards using multi source by changing an app definition from: acm: name: acm path: common/acm To: acm: name: acm chart: acm chartVersion: 0.0.* So any time we have a `chart` field with a `chartVersion` and no `repoURL` defined, the clustergroup chart will create a multisource application with the values files taken from the patterns git repo and the helm chart from https://charts.validatedpatterns.io/ using the `chartVersion` defined in the application. For example the above acm app would prodice the following: project: hub sources: - ref: patternref repoURL: https://github.com/mbaldessari/multicloud-gitops targetRevision: multisource-test2 - chart: acm helm: ignoreMissingValueFiles: true parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL - name: global.targetRevision value: $ARGOCD_APP_SOURCE_TARGET_REVISION - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern value: pattern-sample - name: global.clusterDomain value: mcg-hub.blueprints.rhecoeng.com - name: global.clusterVersion value: "4.13" - name: global.clusterPlatform value: AWS - name: global.hubClusterDomain value: apps.mcg-hub.blueprints.rhecoeng.com - name: global.localClusterDomain value: apps.mcg-hub.blueprints.rhecoeng.com valueFiles: - $patternref/values-global.yaml - $patternref/values-hub.yaml - $patternref/values-AWS.yaml - $patternref/values-AWS-4.13.yaml - $patternref/values-AWS-hub.yaml - $patternref/values-4.13-hub.yaml repoURL: https://charts.validatedpatterns.io/ targetRevision: 0.0.* Note that this depends on the operator supporting multiSource applications (version > 0.0.17). --- clustergroup/templates/_helpers.tpl | 23 +++++++ .../templates/plumbing/applications.yaml | 67 +++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index b9feb738..e7736a6c 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -45,3 +45,26 @@ Default always defined valueFiles to be included in Applications {{- end }} {{/* range $.Values.global.extraValueFiles */}} {{- end }} {{/* if $.Values.global.extraValueFiles */}} {{- end }} {{/* clustergroup.app.globalvalues.valuefiles */}} + +{{/* +Default always defined valueFiles to be included in Applications but with a prefix called $patternref +*/}} +{{- define "clustergroup.app.globalvalues.prefixedvaluefiles" -}} +- "$patternref/values-global.yaml" +- "$patternref/values-{{ $.Values.clusterGroup.name }}.yaml" +{{- if $.Values.global.clusterPlatform }} +- "$patternref/values-{{ $.Values.global.clusterPlatform }}.yaml" + {{- if $.Values.global.clusterVersion }} +- "$patternref/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.global.clusterVersion }}.yaml" + {{- end }} +- "$patternref/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.clusterGroup.name }}.yaml" +{{- end }} +{{- if $.Values.global.clusterVersion }} +- "$patternref/values-{{ $.Values.global.clusterVersion }}-{{ $.Values.clusterGroup.name }}.yaml" +{{- end }} +{{- if $.Values.global.extraValueFiles }} +{{- range $.Values.global.extraValueFiles }} +- "$patternref/{{ . }}" +{{- end }} {{/* range $.Values.global.extraValueFiles */}} +{{- end }} {{/* if $.Values.global.extraValueFiles */}} +{{- end }} {{/* clustergroup.app.globalvalues.prefixedvaluefiles */}} diff --git a/clustergroup/templates/plumbing/applications.yaml b/clustergroup/templates/plumbing/applications.yaml index 16f5c11a..536ff0d3 100644 --- a/clustergroup/templates/plumbing/applications.yaml +++ b/clustergroup/templates/plumbing/applications.yaml @@ -128,6 +128,72 @@ spec: name: {{ $.Values.clusterGroup.targetCluster }} namespace: {{ default $namespace .namespace }} project: {{ .project }} + {{- if and .chart .chartVersion }} {{- /* if .chartVersion is set *and* .repoURL is undefined we assume this is a multisource app */}} + sources: + - repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} + {{- /* We do not allow overriding the values with .targetRevision because when we use .targetRevision in a chart to specify the helm + chart, that revision (e.g. 0.0.1) won't exist in the git tree. So here we simply always take the pattern's git branch/commit */}} + targetRevision: {{ $.Values.global.targetRevision }} + ref: patternref + - repoURL: {{ coalesce .repoURL $.Values.global.multiSourceRepoUrl }} + chart: {{ .chart }} + targetRevision: {{ .chartVersion }} + {{- if .plugin }} + plugin: {{ .plugin | toPrettyJson }} + {{- else }} + helm: + ignoreMissingValueFiles: true + valueFiles: + {{- include "clustergroup.app.globalvalues.prefixedvaluefiles" $ | nindent 8 }} + {{- range $valueFile := .extraValueFiles }} + - {{ $valueFile | quote }} + {{- end }} + parameters: + {{- include "clustergroup.app.globalvalues.helmparameters" $ | nindent 8 }} + {{- range .extraHubClusterDomainFields }} + - name: {{ . }} + value: {{ $.Values.global.hubClusterDomain }} + {{- end }} + {{- range .extraLocalClusterDomainFields }} + - name: {{ . }} + value: {{ $.Values.global.localClusterDomain }} + {{- end }} + {{- range .extraRepoURLFields }} + - name: {{ . }} + value: $ARGOCD_APP_SOURCE_REPO_URL + {{- end }} + {{- range .extraTargetRevisionFields }} + - name: {{ . }} + value: $ARGOCD_APP_SOURCE_TARGET_REVISION + {{- end }} + {{- range .extraNamespaceFields }} + - name: {{ . }} + value: $ARGOCD_APP_NAMESPACE + {{- end }} + {{- range .extraPatternNameFields }} + - name: {{ . }} + value: {{ $.Values.global.pattern }} + {{- end }} + {{- range $k, $v := $.Values.extraParametersNested }} + - name: {{ $k }} + value: {{ $v }} + {{- end }} + {{- range .overrides }} + - name: {{ .name }} + value: {{ .value | quote }} + {{- if .forceString }} + forceString: true + {{- end }} + {{- end }}{{- /* range .overrides */}} + {{- if .fileParameters }} + fileParameters: + {{- range .fileParameters }} + - name: {{ .name }} + path: {{ .path }} + {{- end }} + {{- end }}{{- /* if .fileParameters */}} + {{- end }}{{- /* if .plugin */}} + {{- else }} {{- /* if .chartVersion */}} source: repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} targetRevision: {{ coalesce .targetRevision $.Values.global.targetRevision }} @@ -191,6 +257,7 @@ spec: {{- end }}{{- /* range .fileParameters */}} {{- end }}{{- /* if .fileParameters */}} {{- end }}{{- /* if .plugin */}} + {{- end }}{{- /* if .chartVersion */}} {{- if .ignoreDifferences }} ignoreDifferences: {{ .ignoreDifferences | toPrettyJson }} {{- end }} From adb9aec875bf8531ada962557a638540b1c0da6e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 17 Aug 2023 16:31:52 +0200 Subject: [PATCH 20/40] Add changelog entry and add an explicit property entry to the schema --- Changes.md | 4 ++++ clustergroup/values.schema.json | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Changes.md b/Changes.md index 0e1e8c47..ab6027d0 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,9 @@ # Changes +## Aug 17, 2023 + +* Introduced support for multisource applications via .chart + .chartVersion + ## Jul 8, 2023 * Introduced a default of 20 for sync failures retries in argo applications (global override via global.options.applicationRetryLimit diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index e64a8125..74f8e4b5 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -388,6 +388,10 @@ "type": "string", "description": "Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo." }, + "chartVersion": { + "type": "string", + "description": "The version of the helm chart to be used. Can be a regex like '0.0.*'." + }, "kustomize": { "type": "boolean", "description": "If set to true it will tell ArgoCD to use kustomize to deploy the application." From 9e45344c96c983580f2ea63ea736c5f34de35ff4 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Thu, 17 Aug 2023 09:52:48 -0500 Subject: [PATCH 21/40] Correct ifs and ranges in pattern, add comments --- operator-install/templates/pattern.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index b640bb56..fbf12308 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -16,11 +16,11 @@ spec: {{- range .Values.main.extraParameters }} - name: {{ .name }} value: {{ .value }} -{{- end }} -{{- if $.Values.global.extraValueFiles }} +{{- end }} {{/* range .Values.main.extraParameters */}} +{{- end }} {{/* if .Values.main.extraParameters */}} +{{- if .Values.global.extraValueFiles }} extraValueFiles: -{{- range $.Values.global.extraValueFiles }} +{{- range .Values.global.extraValueFiles }} - {{ . | quote }} -{{- end }} -{{- end }} -{{- end }} +{{- end }} {{/* range .Values.global.extraValueFiles */}} +{{- end }} {{/* if .Values.global.extraValueFiles */}} From 1a209e22bb36a4004199269a223cc5ef2c00084f Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Thu, 17 Aug 2023 09:57:21 -0500 Subject: [PATCH 22/40] Also quote name and value values --- operator-install/templates/pattern.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index fbf12308..eaa94807 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -14,8 +14,8 @@ spec: {{- if .Values.main.extraParameters }} extraParameters: {{- range .Values.main.extraParameters }} - - name: {{ .name }} - value: {{ .value }} + - name: {{ .name | quote }} + value: {{ .value | quote }} {{- end }} {{/* range .Values.main.extraParameters */}} {{- end }} {{/* if .Values.main.extraParameters */}} {{- if .Values.global.extraValueFiles }} From b0e828b97165f77f865117489511cbfa452db5f7 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 23 Aug 2023 18:07:52 +0200 Subject: [PATCH 23/40] Drop vault.ui.serviceType: "LoadBalancer" It is not needed and it adds a requirement to the cluster to have a proper LadBalancer which is not always the case. The default in the helm chart is "ClusterIP", so let's leave that default. Tested this on an OCP 4.13 SNO cluster (without LB) and the UI is correctly accessible. --- hashicorp-vault/values.yaml | 1 - tests/hashicorp-vault-industrial-edge-factory.expected.yaml | 3 +-- tests/hashicorp-vault-industrial-edge-hub.expected.yaml | 3 +-- tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml | 3 +-- tests/hashicorp-vault-naked.expected.yaml | 3 +-- tests/hashicorp-vault-normal.expected.yaml | 3 +-- 6 files changed, 5 insertions(+), 11 deletions(-) diff --git a/hashicorp-vault/values.yaml b/hashicorp-vault/values.yaml index 2ab5f920..780f574a 100644 --- a/hashicorp-vault/values.yaml +++ b/hashicorp-vault/values.yaml @@ -8,7 +8,6 @@ vault: enabled: false ui: enabled: true - serviceType: "LoadBalancer" server: extraEnvironmentVars: VAULT_CACERT: /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt diff --git a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml index 3d1ed2db..ccb5e5bb 100644 --- a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. diff --git a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml index 3d1ed2db..ccb5e5bb 100644 --- a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. diff --git a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml index 3d1ed2db..ccb5e5bb 100644 --- a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. diff --git a/tests/hashicorp-vault-naked.expected.yaml b/tests/hashicorp-vault-naked.expected.yaml index 85d00b14..aa4f5b87 100644 --- a/tests/hashicorp-vault-naked.expected.yaml +++ b/tests/hashicorp-vault-naked.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. diff --git a/tests/hashicorp-vault-normal.expected.yaml b/tests/hashicorp-vault-normal.expected.yaml index 3d1ed2db..ccb5e5bb 100644 --- a/tests/hashicorp-vault-normal.expected.yaml +++ b/tests/hashicorp-vault-normal.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. From af839b4907c8f4c402a561fbfac43f3d4a913941 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 25 Aug 2023 07:56:03 +0200 Subject: [PATCH 24/40] Release clustergroup chart version 0.0.2 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index d4dfdc63..031b6ff0 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.0.1 +version: 0.0.2 From f1f98f27610d6ab9d3bfeb9788ffec234bfd6d87 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 26 Aug 2023 16:29:58 +0200 Subject: [PATCH 25/40] Update crd in common This is needed if we want to support multisource installations from the CLI --- ...ops.hybrid-cloud-patterns.io_patterns.yaml | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml b/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml index c4563288..d0464ef6 100644 --- a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml +++ b/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 + controller-gen.kubebuilder.io/version: v0.11.4 creationTimestamp: null name: patterns.gitops.hybrid-cloud-patterns.io spec: @@ -49,7 +49,7 @@ spec: type: string extraParameters: description: '.Name is dot separated per the helm --set syntax, such - as: global.something.field' + as: global.something.field' items: properties: name: @@ -108,6 +108,7 @@ spec: Does not support short-sha's. Default to HEAD type: string pollInterval: + default: 180 description: 'Interval in seconds to poll for drifts between origin and target repositories. Default: 180 seconds' type: integer @@ -122,6 +123,35 @@ spec: required: - targetRepo type: object + multiSourceConfig: + properties: + clusterGroupChartGitRevision: + default: main + description: The git reference when deploying the clustergroup + helm chart directly from a git repo Defaults to 'main'. (Only + used when developing the clustergroup helm chart) + type: string + clusterGroupChartVersion: + default: 0.0.* + description: Which chart version for the clustergroup helm chart + Defaults to "0.0.*" + type: string + clusterGroupGitRepoUrl: + description: The url when deploying the clustergroup helm chart + directly from a git repo Defaults to '' which means not used + (Only used when developing the clustergroup helm chart) + type: string + enabled: + default: false + description: (EXPERIMENTAL) Enable multi-source support when deploying + the clustergroup argo application + type: boolean + helmRepoUrl: + default: https://charts.validatedpatterns.io/ + description: The helm chart url to fetch the helm charts from + in order to deploy the pattern Defaults to https://charts.validatedpatterns.io/ + type: string + type: object required: - clusterGroupName - gitSpec @@ -188,5 +218,5 @@ status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null From d65f7e4f3a9ef04bb3e6a8711ba469afd278292e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 26 Aug 2023 16:50:42 +0200 Subject: [PATCH 26/40] Add support for passing EXTRA_HELM_OPTS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently a user can set additional helm params via the EXTRA_HELM_OPTS environment variable in order to tweak a value at `make install` time. This does not work correctly when we run things from our utility container, that is because that variable is never passed from the host to the container. According to `man podman run` if we simply pass `-e EXTRA_HELM_OPTS` to the podman invocation: "If an environment variable is spec‐ ified without a value, Podman checks the host environment for a value and set the variable only if it is set on the host" * Without setting EXTRA_HELM_OPTS: unset EXTRA_HELM_OPTS; ./pattern.sh make install make -f common/Makefile operator-deploy make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Checking prerequisites: Check for 'git helm oc ansible': OK Check for python-kubernetes: OK Check for kubernetes.core collection: OK Checking repository: https://github.com/mbaldessari/multicloud-gitops.git - branch main: Running inside a container: Skipping git ssh checks + oc get crds patterns.gitops.hybrid-cloud-patterns.io + echo 'Running helm:' Running helm: + helm upgrade --install multicloud-gitops common/operator-install/ -f values-global.yaml --set main.git.repoURL=https://github.com/mbaldessari/multicloud-gitops.git --set main.git.revision=main * With EXTRA_HELM_OPTS set: export EXTRA_HELM_OPTS="--set main.multiSourceConfig.enabled=true"; ./pattern.sh make install make -f common/Makefile operator-deploy make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Checking prerequisites: Check for 'git helm oc ansible': OK Check for python-kubernetes: OK Check for kubernetes.core collection: OK Checking repository: https://github.com/mbaldessari/multicloud-gitops.git - branch main: Running inside a container: Skipping git ssh checks + oc get crds patterns.gitops.hybrid-cloud-patterns.io + echo 'Running helm:' Running helm: + helm upgrade --install multicloud-gitops common/operator-install/ -f values-global.yaml --set main.git.repoURL=https://github.com/mbaldessari/multicloud-gitops.git --set main.git.revision=main --set main.multiSourceConfig.enabled=true (Briefly added set -x to see the exact commands during testing) --- scripts/pattern-util.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index f55bbdee..baa0e9de 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -36,6 +36,7 @@ fi # which will be confused podman run -it --rm \ --security-opt label=disable \ + -e EXTRA_HELM_OPTS \ ${KUBECONF_ENV} \ -v "${HOME}":"${HOME}" \ -v "${HOME}":/pattern-home \ From 449b9a8a17e580f091ef923c93cd3c3a832721ae Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 28 Aug 2023 10:43:48 +0200 Subject: [PATCH 27/40] Disable kubeconform for the time being --- .github/workflows/linter.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 1bf7e5e4..59e64541 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -56,9 +56,10 @@ jobs: run: | make helmlint - - name: Run make helm kubeconform - run: | - curl -L -O https://github.com/yannh/kubeconform/releases/download/v0.4.13/kubeconform-linux-amd64.tar.gz - tar xf kubeconform-linux-amd64.tar.gz - sudo mv -v kubeconform /usr/local/bin - make kubeconform + # For now disable this until we have a nice and simple process to update the schemas in our repo + # - name: Run make helm kubeconform + # run: | + # curl -L -O https://github.com/yannh/kubeconform/releases/download/v0.4.13/kubeconform-linux-amd64.tar.gz + # tar xf kubeconform-linux-amd64.tar.gz + # sudo mv -v kubeconform /usr/local/bin + # make kubeconform From 36366454eff92ed1e58810843b37cb25c739083f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 28 Aug 2023 08:37:31 +0200 Subject: [PATCH 28/40] Add support for deploying multi source via CLI Via: ``` export EXTRA_HELM_OPTS="--set main.multiSourceConfig.enabled=true" ./pattern.sh make install ``` one can now deploy a pattern with the experimental multisource support enabled. Tested with the above command and correctly deployed a multi-source based pattern. --- clustergroup/values.schema.json | 10 ++++++++++ operator-install/templates/pattern.yaml | 2 ++ operator-install/values.yaml | 3 +++ ...rator-install-industrial-edge-factory.expected.yaml | 2 ++ .../operator-install-industrial-edge-hub.expected.yaml | 2 ++ ...perator-install-medical-diagnosis-hub.expected.yaml | 2 ++ tests/operator-install-naked.expected.yaml | 2 ++ tests/operator-install-normal.expected.yaml | 2 ++ 8 files changed, 25 insertions(+) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 74f8e4b5..a33432b2 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -92,6 +92,16 @@ "description": "The channel from which to install the gitops operator" } } + }, + "multiSourceConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable the experimental support for multi source" + } + } } } }, diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index eaa94807..a340598b 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -11,6 +11,8 @@ spec: gitOpsSpec: operatorChannel: {{ default "gitops-1.8" .Values.main.gitops.channel }} operatorSource: {{ default "redhat-operators" .Values.main.gitops.operatorSource }} + multiSourceConfig: + enabled: {{ .Values.main.multiSourceConfig.enabled }} {{- if .Values.main.extraParameters }} extraParameters: {{- range .Values.main.extraParameters }} diff --git a/operator-install/values.yaml b/operator-install/values.yaml index 4ef3fe4a..01605b21 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -10,6 +10,9 @@ main: channel: "gitops-1.8" operatorSource: redhat-operators + multiSourceConfig: + enabled: false + patternsOperator: channel: fast source: community-operators diff --git a/tests/operator-install-industrial-edge-factory.expected.yaml b/tests/operator-install-industrial-edge-factory.expected.yaml index 5fc96bf3..8e9adf88 100644 --- a/tests/operator-install-industrial-edge-factory.expected.yaml +++ b/tests/operator-install-industrial-edge-factory.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 diff --git a/tests/operator-install-industrial-edge-hub.expected.yaml b/tests/operator-install-industrial-edge-hub.expected.yaml index 5fc96bf3..8e9adf88 100644 --- a/tests/operator-install-industrial-edge-hub.expected.yaml +++ b/tests/operator-install-industrial-edge-hub.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 diff --git a/tests/operator-install-medical-diagnosis-hub.expected.yaml b/tests/operator-install-medical-diagnosis-hub.expected.yaml index 5fc96bf3..8e9adf88 100644 --- a/tests/operator-install-medical-diagnosis-hub.expected.yaml +++ b/tests/operator-install-medical-diagnosis-hub.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 diff --git a/tests/operator-install-naked.expected.yaml b/tests/operator-install-naked.expected.yaml index 4c7837fe..b32c2577 100644 --- a/tests/operator-install-naked.expected.yaml +++ b/tests/operator-install-naked.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 diff --git a/tests/operator-install-normal.expected.yaml b/tests/operator-install-normal.expected.yaml index 5fc96bf3..8e9adf88 100644 --- a/tests/operator-install-normal.expected.yaml +++ b/tests/operator-install-normal.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 From 3e7654f71e6e7f61784344e042547ec5a1996d70 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 31 Aug 2023 12:26:06 +0200 Subject: [PATCH 29/40] Upgrade ESO to v0.9.4 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.8.5.tgz | Bin 78631 -> 0 bytes .../charts/external-secrets-0.9.4.tgz | Bin 0 -> 82899 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 452 ++++++++++++++++-- ...-secrets-industrial-edge-hub.expected.yaml | 452 ++++++++++++++++-- ...ecrets-medical-diagnosis-hub.expected.yaml | 452 ++++++++++++++++-- ...olang-external-secrets-naked.expected.yaml | 452 ++++++++++++++++-- ...lang-external-secrets-normal.expected.yaml | 452 ++++++++++++++++-- 9 files changed, 1999 insertions(+), 269 deletions(-) delete mode 100644 golang-external-secrets/charts/external-secrets-0.8.5.tgz create mode 100644 golang-external-secrets/charts/external-secrets-0.9.4.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index e7b779b6..c618b677 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.0.1 dependencies: - name: external-secrets - version: "0.8.5" + version: "0.9.4" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.8.5.tgz b/golang-external-secrets/charts/external-secrets-0.8.5.tgz deleted file mode 100644 index af7525bf38dd4b6bea620632fd055a0e412e4f81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78631 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 P`~qK}8u$WXLIC+c2~34q diff --git a/golang-external-secrets/charts/external-secrets-0.9.4.tgz b/golang-external-secrets/charts/external-secrets-0.9.4.tgz new file mode 100644 index 0000000000000000000000000000000000000000..313a13018ce45950fb408eb3c3871bcf63d2409d GIT binary patch literal 82899 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 literal 0 HcmV?d00001 diff --git a/golang-external-secrets/values.yaml b/golang-external-secrets/values.yaml index 0030eda3..dc26b4c1 100644 --- a/golang-external-secrets/values.yaml +++ b/golang-external-secrets/values.yaml @@ -11,10 +11,10 @@ clusterGroup: external-secrets: image: - tag: v0.8.5-ubi + tag: v0.9.4-ubi webhook: image: - tag: v0.8.5-ubi + tag: v0.9.4-ubi certController: image: - tag: v0.8.5-ubi + tag: v0.9.4-ubi diff --git a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml index 1452df28..867d9ef3 100644 --- a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml b/tests/golang-external-secrets-industrial-edge-hub.expected.yaml index f0314907..5f6831b7 100644 --- a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml b/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml index f0314907..5f6831b7 100644 --- a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml +++ b/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-naked.expected.yaml b/tests/golang-external-secrets-naked.expected.yaml index 063464e7..127be81d 100644 --- a/tests/golang-external-secrets-naked.expected.yaml +++ b/tests/golang-external-secrets-naked.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-normal.expected.yaml b/tests/golang-external-secrets-normal.expected.yaml index f0314907..5f6831b7 100644 --- a/tests/golang-external-secrets-normal.expected.yaml +++ b/tests/golang-external-secrets-normal.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook From 71f5639671f848d67abfb035a9f9d6f8f07cb810 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 31 Aug 2023 23:10:33 +0200 Subject: [PATCH 30/40] Release 0.0.2 golang-external-secrets --- golang-external-secrets/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index c618b677..8b58c7e5 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure the golang-based external-secrets. keywords: - pattern name: golang-external-secrets -version: 0.0.1 +version: 0.0.2 dependencies: - name: external-secrets version: "0.9.4" From dcd9b8184eb27cf5401a19c1bef171da6de0d989 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 4 Sep 2023 09:05:14 +0200 Subject: [PATCH 31/40] Simplify the passing of KUBECONFIG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to `man podman run` if we simply pass `-e KUBECONFIG` to the podman invocation: "If an environment variable is spec‐ ified without a value, Podman checks the host environment for a value and set the variable only if it is set on the host" So let's just do that and drop the current more complex fragile logic. Tested with: * No KUBECONFIG set unset KUBECONFIG; ./pattern.sh make install make -f common/Makefile operator-deploy make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Checking prerequisites: Check for 'git helm oc ansible': OK Check for python-kubernetes: OK Check for kubernetes.core collection: OK Checking repository: https://github.com/mbaldessari/multicloud-gitops.git - branch script-fix: Running inside a container: Skipping git ssh checks Running helm: Error: Kubernetes cluster unreachable: Get "https://localhos:6443/version" * With KUBECONFIG set export KUBECONFIG=~/sno1-kubeconfig ./pattern.sh make install make -f common/Makefile operator-deploy make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' Checking prerequisites: Check for 'git helm oc ansible': OK Check for python-kubernetes: OK Check for kubernetes.core collection: OK Checking repository: https://github.com/mbaldessari/multicloud-gitops.git - branch script-fix: Running inside a container: Skipping git ssh checks Running helm: WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/michele/sno1-kubeconfig Release "multicloud-gitops" does not exist. Installing it now. NAME: multicloud-gitops LAST DEPLOYED: Mon Sep 4 07:04:16 2023 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None make[1]: Leaving directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make load-secrets make[1]: Entering directory '/home/michele/Engineering/cloud-patterns/multicloud-gitops' make -f common/Makefile load-secrets ... --- scripts/pattern-util.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/scripts/pattern-util.sh b/scripts/pattern-util.sh index baa0e9de..e02776df 100755 --- a/scripts/pattern-util.sh +++ b/scripts/pattern-util.sh @@ -25,19 +25,12 @@ fi # $HOME is mounted as itself for any files that are referenced with absolute paths # $HOME is mounted to /root because the UID in the container is 0 and that's where SSH looks for credentials -# We must pass -e KUBECONFIG *only* if it is set, otherwise we end up passing -# KUBECONFIG="" which then will confuse ansible -KUBECONF_ENV="" -if [ -n "$KUBECONFIG" ]; then - KUBECONF_ENV="-e KUBECONFIG=${KUBECONFIG}" -fi - # Do not quote the ${KUBECONF_ENV} below, otherwise we will pass '' to podman # which will be confused podman run -it --rm \ --security-opt label=disable \ -e EXTRA_HELM_OPTS \ - ${KUBECONF_ENV} \ + -e KUBECONFIG \ -v "${HOME}":"${HOME}" \ -v "${HOME}":/pattern-home \ -v "${HOME}":/root \ From 7207fbd29cba586e547fa49895cf3d5f33c489e9 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 4 Sep 2023 14:59:42 +0200 Subject: [PATCH 32/40] Update CRD for the operator --- .../crds/gitops.hybrid-cloud-patterns.io_patterns.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml b/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml index d0464ef6..330e0222 100644 --- a/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml +++ b/operator-install/crds/gitops.hybrid-cloud-patterns.io_patterns.yaml @@ -45,6 +45,10 @@ spec: spec: description: PatternSpec defines the desired state of Pattern properties: + analyticsUUID: + description: Analytics UUID. Leave empty to autogenerate a random + one. Not PII information + type: string clusterGroupName: type: string extraParameters: From 4d0fafd6048a54434236c19915385475f5a707a1 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 4 Sep 2023 15:49:01 +0200 Subject: [PATCH 33/40] Expose UUID Tested as: $ helm template . > /tmp/a; helm template . --set 'main.analyticsUUID=foo' > /tmp/b; diff -u /tmp/a /tmp/b --- /tmp/a 2023-09-04 15:49:51.160607725 +0200 +++ /tmp/b 2023-09-04 15:49:51.177607813 +0200 @@ -15,6 +15,7 @@ operatorSource: redhat-operators multiSourceConfig: enabled: false + analyticsUUID: foo --- clustergroup/values.schema.json | 4 ++++ operator-install/templates/pattern.yaml | 3 +++ 2 files changed, 7 insertions(+) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index a33432b2..07f8e717 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -102,6 +102,10 @@ "description": "Enable the experimental support for multi source" } } + }, + "analyticsUUID": { + "type": "string", + "description": "UUID used to generate analytics" } } }, diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index a340598b..d0227e58 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -13,6 +13,9 @@ spec: operatorSource: {{ default "redhat-operators" .Values.main.gitops.operatorSource }} multiSourceConfig: enabled: {{ .Values.main.multiSourceConfig.enabled }} +{{- if .Values.main.analyticsUUID }} + analyticsUUID: {{ .Values.main.analyticsUUID }} +{{- end }} {{/* if .Values.main.analyticsUUID */}} {{- if .Values.main.extraParameters }} extraParameters: {{- range .Values.main.extraParameters }} From 39833a3dfb72efee9b27cc53ee4f8432a20ecf90 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 4 Sep 2023 16:07:10 +0200 Subject: [PATCH 34/40] Move to newly released checkout action version --- .github/workflows/ansible-lint.yml | 2 +- .github/workflows/ansible-unittest.yml | 2 +- .github/workflows/chart-branches.yml | 2 +- .github/workflows/chart-split.yml | 2 +- .github/workflows/jsonschema.yaml | 2 +- .github/workflows/linter.yml | 2 +- .github/workflows/superlinter.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ansible-lint.yml b/.github/workflows/ansible-lint.yml index 1bf2f7dd..c2b2981b 100644 --- a/.github/workflows/ansible-lint.yml +++ b/.github/workflows/ansible-lint.yml @@ -8,7 +8,7 @@ jobs: steps: # Important: This sets up your GITHUB_WORKSPACE environment variable - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Lint Ansible Playbook uses: ansible/ansible-lint-action@v6 diff --git a/.github/workflows/ansible-unittest.yml b/.github/workflows/ansible-unittest.yml index af326b66..90d4507f 100644 --- a/.github/workflows/ansible-unittest.yml +++ b/.github/workflows/ansible-unittest.yml @@ -32,7 +32,7 @@ jobs: # Checkout the code base # ########################## - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml index a1b36cf6..d93b1dbb 100644 --- a/.github/workflows/chart-branches.yml +++ b/.github/workflows/chart-branches.yml @@ -30,7 +30,7 @@ jobs: clustergroup: ${{ steps.filter.outputs.clustergroup }} steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: dorny/paths-filter@v2 id: filter diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml index 84f027f6..2792d6ad 100644 --- a/.github/workflows/chart-split.yml +++ b/.github/workflows/chart-split.yml @@ -19,7 +19,7 @@ jobs: contents: write steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 token: ${{ secrets.CHARTS_REPOS_TOKEN }} diff --git a/.github/workflows/jsonschema.yaml b/.github/workflows/jsonschema.yaml index a0c60c11..ad83173a 100644 --- a/.github/workflows/jsonschema.yaml +++ b/.github/workflows/jsonschema.yaml @@ -32,7 +32,7 @@ jobs: # Checkout the code base # ########################## - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 59e64541..947cc127 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -29,7 +29,7 @@ jobs: # Checkout the code base # ########################## - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 30cb00a8..7430db09 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 From c328c1ec3d39faac747424ff022fb0458d24928b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 5 Sep 2023 08:09:12 +0200 Subject: [PATCH 35/40] Update URLs to new github org --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bb60d248..568a2396 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,17 @@ This repository is never used as standalone. It is usually imported in each pattern as a subtree. In order to import the common/ the very first time you can use -`https://github.com/hybrid-cloud-patterns/multicloud-gitops/blob/main/common/scripts/make_common_subtree.sh` +`https://github.com/validatedpatterns/multicloud-gitops/blob/main/common/scripts/make_common_subtree.sh` In order to update your common subtree inside your pattern repository you can either use -`https://github.com/hybrid-cloud-patterns/utilities/blob/main/scripts/update-common-everywhere.sh` or +`https://github.com/validatedpatterns/utilities/blob/main/scripts/update-common-everywhere.sh` or do it manually by doing the following: ```sh -git remote add -f upstream-common https://github.com/hybrid-cloud-patterns/common.git +git remote add -f upstream-common https://github.com/validatedpatterns/common.git git merge -s subtree -Xtheirs -Xsubtree=common upstream-common/ha-vault ``` ## Secrets -There are two different secret formats parsed by the ansible bits. Both are documented [here](https://github.com/hybrid-cloud-patterns/common/tree/main/ansible/roles/vault_utils/README.md) +There are two different secret formats parsed by the ansible bits. Both are documented [here](https://github.com/validatedpatterns/common/tree/main/ansible/roles/vault_utils/README.md) From 5585af0508e2a9680ac996efbe9db24b50c2e010 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 5 Sep 2023 08:10:30 +0200 Subject: [PATCH 36/40] Add ~/.config/validated-patterns in the secret search path --- ansible/roles/vault_utils/README.md | 14 ++++++++++---- ansible/roles/vault_utils/tasks/push_secrets.yaml | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ansible/roles/vault_utils/README.md b/ansible/roles/vault_utils/README.md index 55babb03..7198752c 100644 --- a/ansible/roles/vault_utils/README.md +++ b/ansible/roles/vault_utils/README.md @@ -42,10 +42,16 @@ This relies on [kubernetes.core](https://docs.ansible.com/ansible/latest/collect ## Values secret file format -Currently this role supports two formats: version 1.0 (which is the assumed default when not specified) and version 2.0. -The latter is more fatureful and supports generating secrets directly into the vault and also prompting the user for a secret. -By default, the first file that will looked up is `~/.config/hybrid-cloud-patterns/values-secret-.yaml`, then -`~/values-secret-.yaml` and should that not exist it will look for `~/values-secret.yaml`. +Currently this role supports two formats: version 1.0 (which is the assumed +default when not specified) and version 2.0. The latter is more fatureful and +supports generating secrets directly into the vault and also prompting the user +for a secret. + +By default, the first file that will looked up is +`~/.config/hybrid-cloud-patterns/values-secret-.yaml`, then +`~/.config/validated-patterns/values-secret-.yaml`, +`~/values-secret-.yaml` and should that not exist it will look for +`~/values-secret.yaml`. The paths can be overridden by setting the environment variable `VALUES_SECRET` to the path of the secret file. diff --git a/ansible/roles/vault_utils/tasks/push_secrets.yaml b/ansible/roles/vault_utils/tasks/push_secrets.yaml index a820f40a..9255a0ca 100644 --- a/ansible/roles/vault_utils/tasks/push_secrets.yaml +++ b/ansible/roles/vault_utils/tasks/push_secrets.yaml @@ -66,6 +66,7 @@ vars: findme: - "~/.config/hybrid-cloud-patterns/values-secret-{{ pattern_name }}.yaml" + - "~/.config/validated-patterns/values-secret-{{ pattern_name }}.yaml" - "~/values-secret-{{ pattern_name }}.yaml" - "~/values-secret.yaml" - "{{ pattern_dir }}/values-secret.yaml.template" From 92e83bf0b184eaffad82a99e58038423b480d85f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 5 Sep 2023 08:18:14 +0200 Subject: [PATCH 37/40] Add support for ~/.config/validated-patterns/pattern-uuid * Pristine environment: $ make show helm template common/operator-install/ --name-template common -f values-global.yaml --set main.git.repoURL="https://github.com/hybrid-cloud-patterns/common.git" --set main.git.revision=vp-paths --- apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 kind: Pattern metadata: name: common namespace: openshift-operators spec: clusterGroupName: example gitSpec: targetRepo: https://github.com/hybrid-cloud-patterns/common.git targetRevision: vp-paths gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators multiSourceConfig: enabled: false ... * Add UUID to the environment $ echo "vp-team-bandini" >> ~/.config/validated-patterns/pattern-uuid $ make show helm template common/operator-install/ --name-template common -f values-global.yaml --set main.git.repoURL="https://github.com/hybrid-cloud-patterns/common.git" --set main.git.revision=vp-paths --set main.analyticsUUID=vp-team-bandini --- apiVersion: gitops.hybrid-cloud-patterns.io/v1alpha1 kind: Pattern metadata: name: common namespace: openshift-operators spec: clusterGroupName: example gitSpec: targetRepo: https://github.com/hybrid-cloud-patterns/common.git targetRevision: vp-paths gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators multiSourceConfig: enabled: false analyticsUUID: vp-team-bandini ... --- Makefile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d8182da6..23d43f7c 100644 --- a/Makefile +++ b/Makefile @@ -19,8 +19,16 @@ TARGET_REPO=$(shell git ls-remote --get-url --symref $(TARGET_ORIGIN) | sed -e ' # git branch --show-current is also available as of git 2.22, but we will use this for compatibility TARGET_BRANCH=$(shell git rev-parse --abbrev-ref HEAD) +UUID_FILE ?= ~/.config/validated-patterns/pattern-uuid + # --set values always take precedence over the contents of -f -HELM_OPTS=-f values-global.yaml --set main.git.repoURL="$(TARGET_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(EXTRA_HELM_OPTS) +ifneq ("$(wildcard $(UUID_FILE))","") + UUID := $(shell cat $(UUID_FILE)) + HELM_OPTS=-f values-global.yaml --set main.git.repoURL="$(TARGET_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) --set main.analyticsUUID=$(UUID) $(EXTRA_HELM_OPTS) +else + HELM_OPTS=-f values-global.yaml --set main.git.repoURL="$(TARGET_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(EXTRA_HELM_OPTS) +endif + ##@ Pattern Common Tasks From 34a22f01f496517d6e00a5b73b67c5ac6f2f5589 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 5 Sep 2023 09:07:52 +0200 Subject: [PATCH 38/40] Simplify the code around UUID variable definition --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 23d43f7c..682e53ba 100644 --- a/Makefile +++ b/Makefile @@ -20,15 +20,16 @@ TARGET_REPO=$(shell git ls-remote --get-url --symref $(TARGET_ORIGIN) | sed -e ' TARGET_BRANCH=$(shell git rev-parse --abbrev-ref HEAD) UUID_FILE ?= ~/.config/validated-patterns/pattern-uuid +UUID_HELM_OPTS ?= # --set values always take precedence over the contents of -f ifneq ("$(wildcard $(UUID_FILE))","") UUID := $(shell cat $(UUID_FILE)) - HELM_OPTS=-f values-global.yaml --set main.git.repoURL="$(TARGET_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) --set main.analyticsUUID=$(UUID) $(EXTRA_HELM_OPTS) -else - HELM_OPTS=-f values-global.yaml --set main.git.repoURL="$(TARGET_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(EXTRA_HELM_OPTS) + UUID_HELM_OPTS := --set main.analyticsUUID=$(UUID) endif +HELM_OPTS=-f values-global.yaml --set main.git.repoURL="$(TARGET_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(UUID_HELM_OPTS) $(EXTRA_HELM_OPTS) + ##@ Pattern Common Tasks From afcef70eeb7843b0414ee715798106f97f0ada8a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 6 Sep 2023 09:14:02 +0200 Subject: [PATCH 39/40] Fix up common/ tests --- ...roup-industrial-edge-factory.expected.yaml | 3 +- ...tergroup-industrial-edge-hub.expected.yaml | 15 +- ...rgroup-medical-diagnosis-hub.expected.yaml | 27 +- tests/common-clustergroup-naked.expected.yaml | 1 + .../common-clustergroup-normal.expected.yaml | 5 +- ...rets-industrial-edge-factory.expected.yaml | 452 ++++++++++++++++-- ...-secrets-industrial-edge-hub.expected.yaml | 452 ++++++++++++++++-- ...ecrets-medical-diagnosis-hub.expected.yaml | 452 ++++++++++++++++-- ...olang-external-secrets-naked.expected.yaml | 452 ++++++++++++++++-- ...lang-external-secrets-normal.expected.yaml | 452 ++++++++++++++++-- ...ault-industrial-edge-factory.expected.yaml | 3 +- ...rp-vault-industrial-edge-hub.expected.yaml | 3 +- ...-vault-medical-diagnosis-hub.expected.yaml | 3 +- ...common-hashicorp-vault-naked.expected.yaml | 3 +- ...ommon-hashicorp-vault-normal.expected.yaml | 3 +- ...tall-industrial-edge-factory.expected.yaml | 2 + ...-install-industrial-edge-hub.expected.yaml | 2 + ...nstall-medical-diagnosis-hub.expected.yaml | 2 + ...ommon-operator-install-naked.expected.yaml | 2 + ...mmon-operator-install-normal.expected.yaml | 2 + 20 files changed, 2038 insertions(+), 298 deletions(-) diff --git a/tests/common-clustergroup-industrial-edge-factory.expected.yaml b/tests/common-clustergroup-industrial-edge-factory.expected.yaml index 3531cf9b..86e8d51d 100644 --- a/tests/common-clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/common-clustergroup-industrial-edge-factory.expected.yaml @@ -138,6 +138,7 @@ data: cicd: namespace: devsecops-ci clusterDomain: region.example.com + extraValueFiles: [] git: account: PLAINTEXT dev_revision: main @@ -422,7 +423,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-factory.yaml" + - "/values-factory.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/common-clustergroup-industrial-edge-hub.expected.yaml b/tests/common-clustergroup-industrial-edge-hub.expected.yaml index 8cac1f75..7787a1a6 100644 --- a/tests/common-clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/common-clustergroup-industrial-edge-hub.expected.yaml @@ -299,6 +299,7 @@ data: cicd: namespace: devsecops-ci clusterDomain: region.example.com + extraValueFiles: [] git: account: PLAINTEXT dev_revision: main @@ -697,7 +698,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -752,7 +753,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -798,7 +799,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -844,7 +845,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -920,7 +921,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -966,7 +967,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1037,7 +1038,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-datacenter.yaml" + - "/values-datacenter.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml b/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml index f06758fa..035b7149 100644 --- a/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml @@ -286,6 +286,7 @@ data: cicd: namespace: devsecops-ci clusterDomain: region.example.com + extraValueFiles: [] git: account: PLAINTEXT dev_revision: main @@ -642,7 +643,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -688,7 +689,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -734,7 +735,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -780,7 +781,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -826,7 +827,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -872,7 +873,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -918,7 +919,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -964,7 +965,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1028,7 +1029,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1074,7 +1075,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1120,7 +1121,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1175,7 +1176,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -1230,7 +1231,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-hub.yaml" + - "/values-hub.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/common-clustergroup-naked.expected.yaml b/tests/common-clustergroup-naked.expected.yaml index e15566b0..9499eb5d 100644 --- a/tests/common-clustergroup-naked.expected.yaml +++ b/tests/common-clustergroup-naked.expected.yaml @@ -65,6 +65,7 @@ data: targetCluster: in-cluster enabled: all global: + extraValueFiles: [] options: applicationRetryLimit: 20 installPlanApproval: Automatic diff --git a/tests/common-clustergroup-normal.expected.yaml b/tests/common-clustergroup-normal.expected.yaml index 769f7b0a..7770d9ca 100644 --- a/tests/common-clustergroup-normal.expected.yaml +++ b/tests/common-clustergroup-normal.expected.yaml @@ -195,6 +195,7 @@ data: cicd: namespace: devsecops-ci clusterDomain: region.example.com + extraValueFiles: [] git: account: PLAINTEXT dev_revision: main @@ -552,7 +553,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-example.yaml" + - "/values-example.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL @@ -607,7 +608,7 @@ spec: ignoreMissingValueFiles: true valueFiles: - "/values-global.yaml" - - "/values-example.yaml" + - "/values-example.yaml" parameters: - name: global.repoURL value: $ARGOCD_APP_SOURCE_REPO_URL diff --git a/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml index 1ef6cf66..ce2f17c3 100644 --- a/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml +++ b/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=common-golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml b/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml index b516e345..c106cd42 100644 --- a/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml +++ b/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=common-golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml b/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml index b516e345..c106cd42 100644 --- a/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml +++ b/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=common-golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/common-golang-external-secrets-naked.expected.yaml b/tests/common-golang-external-secrets-naked.expected.yaml index ac3c1ad1..01cb5e98 100644 --- a/tests/common-golang-external-secrets-naked.expected.yaml +++ b/tests/common-golang-external-secrets-naked.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=common-golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/common-golang-external-secrets-normal.expected.yaml b/tests/common-golang-external-secrets-normal.expected.yaml index b516e345..c106cd42 100644 --- a/tests/common-golang-external-secrets-normal.expected.yaml +++ b/tests/common-golang-external-secrets-normal.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -208,7 +208,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -224,15 +224,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.secretStoreRef.name + - jsonPath: .spec.externalSecretSpec.secretStoreRef.name name: Store type: string - - jsonPath: .spec.refreshInterval + - jsonPath: .spec.refreshTime name: Refresh Interval type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].reason - name: Status - type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string @@ -252,6 +249,18 @@ spec: spec: description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. properties: + externalSecretMetadata: + description: The metadata of the external secrets to be created + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object externalSecretName: description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret type: string @@ -665,7 +674,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2155,6 +2164,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -2238,6 +2265,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -2285,6 +2420,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -3103,6 +3239,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -3387,7 +3550,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -3515,7 +3678,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -4152,7 +4315,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4213,7 +4376,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4321,7 +4484,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -4399,7 +4562,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -4619,7 +4782,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -6109,6 +6272,24 @@ spec: - SecretsManager - ParameterStore type: string + sessionTags: + description: AWS STS assume role session tags + items: + properties: + key: + type: string + value: + type: string + required: + - key + - value + type: object + type: array + transitiveTagKeys: + description: AWS STS assume role transitive session tags. Required when multiple rules are used with SecretStore + items: + type: string + type: array required: - region - service @@ -6192,6 +6373,114 @@ spec: required: - vaultUrl type: object + conjur: + description: Conjur configures this store to sync secrets using conjur provider + properties: + auth: + properties: + apikey: + properties: + account: + type: string + apiKeyRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + userRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - account + - apiKeyRef + - userRef + type: object + required: + - apikey + type: object + caBundle: + type: string + url: + type: string + required: + - auth + - url + type: object + delinea: + description: Delinea DevOps Secrets Vault https://docs.delinea.com/online-help/products/devops-secrets-vault/current + properties: + clientId: + description: ClientID is the non-secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + clientSecret: + description: ClientSecret is the secret part of the credential. + properties: + secretRef: + description: SecretRef references a key in a secret that will be used as value. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + value: + description: Value can be specified directly to set a value without using a secret. + type: string + type: object + tenant: + description: Tenant is the chosen hostname / site name. + type: string + tld: + description: TLD is based on the server location that was chosen during provisioning. If unset, defaults to "com". + type: string + urlTemplate: + description: URLTemplate If unset, defaults to "https://%s.secretsvaultcloud.%s/v1/%s%s". + type: string + required: + - clientId + - clientSecret + - tenant + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -6239,6 +6528,7 @@ spec: - lower-snake - tf-var - dotnet-env + - lower-kebab type: string project: description: Doppler project (required if not using a Service Token) @@ -7057,6 +7347,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7341,7 +7658,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.4 + controller-gen.kubebuilder.io/version: v0.12.1 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -7688,6 +8005,33 @@ spec: description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. type: string type: object + userPass: + description: UserPass authenticates with Vault by passing username/password pair + properties: + path: + default: user + description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a user name used to authenticate using the UserPass Vault authentication method + type: string + required: + - path + - username + type: object type: object caBundle: description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. @@ -7771,10 +8115,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7838,10 +8182,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -7947,10 +8291,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -7987,10 +8331,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -8031,10 +8375,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8052,10 +8396,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8072,10 +8416,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8108,10 +8452,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -8147,10 +8491,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -8168,10 +8512,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -8192,10 +8536,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8222,7 +8566,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - certcontroller @@ -8231,6 +8575,8 @@ spec: - --service-namespace=default - --secret-name=common-golang-external-secrets-webhook - --secret-namespace=default + - --metrics-addr=:8080 + - --healthz-addr=:8081 ports: - containerPort: 8080 @@ -8250,10 +8596,10 @@ metadata: name: common-golang-external-secrets namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8280,7 +8626,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -8296,10 +8642,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: "default" labels: - helm.sh/chart: external-secrets-0.8.5 + helm.sh/chart: external-secrets-0.9.4 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.8.5" + app.kubernetes.io/version: "v0.9.4" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -8326,7 +8672,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "ghcr.io/external-secrets/external-secrets:v0.8.5-ubi" + image: "ghcr.io/external-secrets/external-secrets:v0.9.4-ubi" imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml index b4b36a37..1fc97cf0 100644 --- a/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml +++ b/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. diff --git a/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml index b4b36a37..1fc97cf0 100644 --- a/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml +++ b/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. diff --git a/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml index b4b36a37..1fc97cf0 100644 --- a/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ b/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. diff --git a/tests/common-hashicorp-vault-naked.expected.yaml b/tests/common-hashicorp-vault-naked.expected.yaml index 5982e388..edd614b8 100644 --- a/tests/common-hashicorp-vault-naked.expected.yaml +++ b/tests/common-hashicorp-vault-naked.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. diff --git a/tests/common-hashicorp-vault-normal.expected.yaml b/tests/common-hashicorp-vault-normal.expected.yaml index b4b36a37..1fc97cf0 100644 --- a/tests/common-hashicorp-vault-normal.expected.yaml +++ b/tests/common-hashicorp-vault-normal.expected.yaml @@ -140,8 +140,7 @@ spec: - name: http port: 8200 targetPort: 8200 - type: LoadBalancer - externalTrafficPolicy: Cluster + type: ClusterIP --- # Source: hashicorp-vault/charts/vault/templates/server-statefulset.yaml # StatefulSet to run the actual vault server cluster. diff --git a/tests/common-operator-install-industrial-edge-factory.expected.yaml b/tests/common-operator-install-industrial-edge-factory.expected.yaml index 3a65cc7c..e6502fa4 100644 --- a/tests/common-operator-install-industrial-edge-factory.expected.yaml +++ b/tests/common-operator-install-industrial-edge-factory.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 diff --git a/tests/common-operator-install-industrial-edge-hub.expected.yaml b/tests/common-operator-install-industrial-edge-hub.expected.yaml index 3a65cc7c..e6502fa4 100644 --- a/tests/common-operator-install-industrial-edge-hub.expected.yaml +++ b/tests/common-operator-install-industrial-edge-hub.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 diff --git a/tests/common-operator-install-medical-diagnosis-hub.expected.yaml b/tests/common-operator-install-medical-diagnosis-hub.expected.yaml index 3a65cc7c..e6502fa4 100644 --- a/tests/common-operator-install-medical-diagnosis-hub.expected.yaml +++ b/tests/common-operator-install-medical-diagnosis-hub.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 diff --git a/tests/common-operator-install-naked.expected.yaml b/tests/common-operator-install-naked.expected.yaml index beabcc82..91bb784a 100644 --- a/tests/common-operator-install-naked.expected.yaml +++ b/tests/common-operator-install-naked.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 diff --git a/tests/common-operator-install-normal.expected.yaml b/tests/common-operator-install-normal.expected.yaml index 3a65cc7c..e6502fa4 100644 --- a/tests/common-operator-install-normal.expected.yaml +++ b/tests/common-operator-install-normal.expected.yaml @@ -13,6 +13,8 @@ spec: gitOpsSpec: operatorChannel: gitops-1.8 operatorSource: redhat-operators + multiSourceConfig: + enabled: false --- # Source: pattern-install/templates/subscription.yaml apiVersion: operators.coreos.com/v1alpha1 From f123f0538a389fdb63f22a7b5bda17a33217fc13 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Wed, 6 Sep 2023 09:14:26 +0200 Subject: [PATCH 40/40] Move to new checkout action version --- .github/workflows/linter.yml | 3 ++- .github/workflows/superlinter.yml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index f0bc6af0..e055fda5 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -29,10 +29,11 @@ jobs: # Checkout the code base # ########################## - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 + - name: Setup helm uses: azure/setup-helm@v3 # with: diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 47ca9999..0141aa05 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0