Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a99083843c |
@@ -24,44 +24,6 @@ jobs:
|
||||
name: action on ${{ matrix.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup flux
|
||||
uses: ./action
|
||||
|
||||
plugins:
|
||||
runs-on: ubuntu-latest
|
||||
name: action plugins on ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
- name: Build flux
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p cmd/flux/manifests "$RUNNER_TEMP/flux-bin"
|
||||
printf "apiVersion: v1\nkind: List\nitems: []\n" > cmd/flux/manifests/dummy.yaml
|
||||
CGO_ENABLED=0 go build -ldflags="-s -w -X main.VERSION=0.0.0-pr" -o "$RUNNER_TEMP/flux-bin/flux" ./cmd/flux
|
||||
- name: Setup flux with plugin
|
||||
id: setup
|
||||
uses: ./action
|
||||
with:
|
||||
version: 0.0.0-pr
|
||||
bindir: ${{ runner.temp }}/flux-bin
|
||||
plugins: |
|
||||
mirror@sha256:91a1e04c2015ee66b1633e362cdb6d4550891b91bf3391a83414b9e9912e53f1
|
||||
- name: Assert plugin installation
|
||||
shell: bash
|
||||
env:
|
||||
ACTION_PLUGIN_DIR: ${{ steps.setup.outputs['plugin-dir'] }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
test -n "${FLUXCD_PLUGINS:-}"
|
||||
test "$ACTION_PLUGIN_DIR" = "$FLUXCD_PLUGINS"
|
||||
test -x "$FLUXCD_PLUGINS/flux-mirror"
|
||||
flux plugin list
|
||||
flux mirror --help
|
||||
|
||||
@@ -8,6 +8,6 @@ jobs:
|
||||
permissions:
|
||||
contents: write # for reading and creating branches.
|
||||
pull-requests: write # for creating pull requests against release branches.
|
||||
uses: fluxcd/gha-workflows/.github/workflows/backport.yaml@v0.11.0
|
||||
uses: fluxcd/gha-workflows/.github/workflows/backport.yaml@v0.9.0
|
||||
secrets:
|
||||
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
|
||||
@@ -19,13 +19,13 @@ jobs:
|
||||
matrix:
|
||||
# Keep this list up-to-date with https://endoflife.date/kubernetes
|
||||
# Build images with https://github.com/fluxcd/flux-benchmark/actions/workflows/build-kind.yaml
|
||||
KUBERNETES_VERSION: [1.34.1, 1.35.2, 1.36.1]
|
||||
KUBERNETES_VERSION: [1.33.0, 1.34.1, 1.35.0]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: |
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
|
||||
with:
|
||||
version: v0.32.0
|
||||
version: v0.30.0
|
||||
cluster_name: ${{ steps.prep.outputs.CLUSTER }}
|
||||
node_image: ghcr.io/fluxcd/kindest/node:v${{ matrix.KUBERNETES_VERSION }}-arm64
|
||||
- name: Run e2e tests
|
||||
@@ -76,13 +76,13 @@ jobs:
|
||||
matrix:
|
||||
# Keep this list up-to-date with https://endoflife.date/kubernetes
|
||||
# Available versions can be found with "replicated cluster versions"
|
||||
K3S_VERSION: [ 1.34.8, 1.35.5, 1.36.1 ]
|
||||
K3S_VERSION: [ 1.33.7, 1.34.3, 1.35.0 ]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: |
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
KUBECONFIG_PATH="$(git rev-parse --show-toplevel)/bin/kubeconfig.yaml"
|
||||
echo "kubeconfig-path=${KUBECONFIG_PATH}" >> $GITHUB_OUTPUT
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@5a7f3ce0de742b6c561a50f90940d81cf6fc698d # main
|
||||
uses: fluxcd/pkg/actions/kustomize@9a8c0edd5da84dc51a585738c67e3a3950d7fbf0 # main
|
||||
- name: Build
|
||||
run: make build-dev
|
||||
- name: Create repository
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
|
||||
- name: Create cluster
|
||||
id: create-cluster
|
||||
uses: replicatedhq/replicated-actions/create-cluster@6803131db735f7cc067de88fa14237c7462b247a # v1.27.0
|
||||
uses: replicatedhq/replicated-actions/create-cluster@1abb33f5274580b14f49f2a12d819df7920e4d9b # v1.20.0
|
||||
with:
|
||||
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
|
||||
kubernetes-distribution: "k3s"
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
kubectl delete ns flux-system --wait
|
||||
- name: Delete cluster
|
||||
if: ${{ always() }}
|
||||
uses: replicatedhq/replicated-actions/remove-cluster@6803131db735f7cc067de88fa14237c7462b247a # v1.27.0
|
||||
uses: replicatedhq/replicated-actions/remove-cluster@1abb33f5274580b14f49f2a12d819df7920e4d9b # v1.20.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
|
||||
@@ -168,13 +168,13 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
# Keep this list up-to-date with https://endoflife.date/red-hat-openshift
|
||||
OPENSHIFT_VERSION: [ 4.20.0-okd, 4.21.0-okd ]
|
||||
OPENSHIFT_VERSION: [ 4.20.0-okd ]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: |
|
||||
@@ -189,7 +189,7 @@ jobs:
|
||||
KUBECONFIG_PATH="$(git rev-parse --show-toplevel)/bin/kubeconfig.yaml"
|
||||
echo "kubeconfig-path=${KUBECONFIG_PATH}" >> $GITHUB_OUTPUT
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@5a7f3ce0de742b6c561a50f90940d81cf6fc698d # main
|
||||
uses: fluxcd/pkg/actions/kustomize@9a8c0edd5da84dc51a585738c67e3a3950d7fbf0 # main
|
||||
- name: Build
|
||||
run: make build-dev
|
||||
- name: Create repository
|
||||
@@ -199,7 +199,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
|
||||
- name: Create cluster
|
||||
id: create-cluster
|
||||
uses: replicatedhq/replicated-actions/create-cluster@6803131db735f7cc067de88fa14237c7462b247a # v1.27.0
|
||||
uses: replicatedhq/replicated-actions/create-cluster@1abb33f5274580b14f49f2a12d819df7920e4d9b # v1.20.0
|
||||
with:
|
||||
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
|
||||
kubernetes-distribution: "openshift"
|
||||
@@ -240,7 +240,7 @@ jobs:
|
||||
kubectl delete ns flux-system --wait
|
||||
- name: Delete cluster
|
||||
if: ${{ always() }}
|
||||
uses: replicatedhq/replicated-actions/remove-cluster@6803131db735f7cc067de88fa14237c7462b247a # v1.27.0
|
||||
uses: replicatedhq/replicated-actions/remove-cluster@1abb33f5274580b14f49f2a12d819df7920e4d9b # v1.20.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
|
||||
|
||||
@@ -29,14 +29,14 @@ jobs:
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- name: CheckoutD
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||
with:
|
||||
go-version: 1.26.x
|
||||
cache-dependency-path: tests/integration/go.sum
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
|
||||
uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4.0.0
|
||||
- name: Setup Flux CLI
|
||||
run: make build
|
||||
working-directory: ./
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
env:
|
||||
SOPS_VER: 3.7.1
|
||||
- name: Authenticate to Azure
|
||||
uses: Azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v1.4.6
|
||||
uses: Azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v1.4.6
|
||||
with:
|
||||
creds: '{"clientId":"${{ secrets.ARM_CLIENT_ID }}","clientSecret":"${{ secrets.ARM_CLIENT_SECRET }}","subscriptionId":"${{ secrets.ARM_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.ARM_TENANT_ID }}"}'
|
||||
- name: Set dynamic variables in .env
|
||||
|
||||
@@ -17,9 +17,9 @@ jobs:
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||
with:
|
||||
go-version: 1.26.x
|
||||
cache-dependency-path: |
|
||||
@@ -28,16 +28,16 @@ jobs:
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
|
||||
with:
|
||||
version: v0.32.0
|
||||
version: v0.30.0
|
||||
cluster_name: kind
|
||||
# The versions below should target the newest Kubernetes version
|
||||
# Keep this up-to-date with https://endoflife.date/kubernetes
|
||||
node_image: ghcr.io/fluxcd/kindest/node:v1.36.1-amd64
|
||||
kubectl_version: v1.36.0
|
||||
node_image: ghcr.io/fluxcd/kindest/node:v1.33.0-amd64
|
||||
kubectl_version: v1.33.0
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@5a7f3ce0de742b6c561a50f90940d81cf6fc698d # main
|
||||
uses: fluxcd/pkg/actions/kustomize@9a8c0edd5da84dc51a585738c67e3a3950d7fbf0 # main
|
||||
- name: Setup yq
|
||||
uses: fluxcd/pkg/actions/yq@5a7f3ce0de742b6c561a50f90940d81cf6fc698d # main
|
||||
uses: fluxcd/pkg/actions/yq@9a8c0edd5da84dc51a585738c67e3a3950d7fbf0 # main
|
||||
- name: Build
|
||||
run: make build-dev
|
||||
- name: Set outputs
|
||||
|
||||
@@ -29,14 +29,14 @@ jobs:
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||
with:
|
||||
go-version: 1.26.x
|
||||
cache-dependency-path: tests/integration/go.sum
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
|
||||
uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4.0.0
|
||||
- name: Setup Flux CLI
|
||||
run: make build
|
||||
working-directory: ./
|
||||
@@ -56,11 +56,11 @@ jobs:
|
||||
- name: Setup gcloud
|
||||
uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
|
||||
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
- name: Log into us-central1-docker.pkg.dev
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
registry: us-central1-docker.pkg.dev
|
||||
username: oauth2accesstoken
|
||||
|
||||
@@ -18,14 +18,14 @@ jobs:
|
||||
labels: ubuntu-latest-16-cores
|
||||
services:
|
||||
registry:
|
||||
image: registry:3
|
||||
image: registry:2
|
||||
ports:
|
||||
- 5000:5000
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||
with:
|
||||
go-version: 1.26.x
|
||||
cache-dependency-path: |
|
||||
@@ -34,19 +34,19 @@ jobs:
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
|
||||
with:
|
||||
version: v0.32.0
|
||||
version: v0.30.0
|
||||
cluster_name: kind
|
||||
wait: 5s
|
||||
config: .github/kind/config.yaml # disable KIND-net
|
||||
# The versions below should target the oldest supported Kubernetes version
|
||||
# Keep this up-to-date with https://endoflife.date/kubernetes
|
||||
node_image: ghcr.io/fluxcd/kindest/node:v1.34.1-amd64
|
||||
kubectl_version: v1.34.0
|
||||
node_image: ghcr.io/fluxcd/kindest/node:v1.33.0-amd64
|
||||
kubectl_version: v1.33.0
|
||||
- name: Setup Calico for network policy
|
||||
run: |
|
||||
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.32.0/manifests/calico.yaml
|
||||
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/calico.yaml
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@5a7f3ce0de742b6c561a50f90940d81cf6fc698d # main
|
||||
uses: fluxcd/pkg/actions/kustomize@9a8c0edd5da84dc51a585738c67e3a3950d7fbf0 # main
|
||||
- name: Run tests
|
||||
run: make test
|
||||
- name: Run e2e tests
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
actions: read
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Run analysis
|
||||
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
||||
with:
|
||||
@@ -28,12 +28,12 @@ jobs:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_results: true
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
- name: Upload SARIF results
|
||||
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -22,35 +22,35 @@ jobs:
|
||||
packages: write # needed for ghcr access
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Unshallow
|
||||
run: git fetch --prune --unshallow
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||
with:
|
||||
go-version: 1.26.x
|
||||
cache: false
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
|
||||
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
- name: Setup Syft
|
||||
uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
|
||||
uses: anchore/sbom-action/download-syft@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0.23.1
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
||||
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
|
||||
with:
|
||||
cosign-release: v2.6.1 # TODO: remove after Flux 2.8 with support for cosign v3
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@5a7f3ce0de742b6c561a50f90940d81cf6fc698d # main
|
||||
uses: fluxcd/pkg/actions/kustomize@9a8c0edd5da84dc51a585738c67e3a3950d7fbf0 # main
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
run: |
|
||||
kustomize build manifests/crds > all-crds.yaml
|
||||
- name: Generate OpenAPI JSON schemas from CRDs
|
||||
uses: fluxcd/pkg/actions/crdjsonschema@5a7f3ce0de742b6c561a50f90940d81cf6fc698d # main
|
||||
uses: fluxcd/pkg/actions/crdjsonschema@9a8c0edd5da84dc51a585738c67e3a3950d7fbf0 # main
|
||||
with:
|
||||
crd: all-crds.yaml
|
||||
output: schemas
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
tar -czvf ./output/crd-schemas.tar.gz -C schemas .
|
||||
- name: Run GoReleaser
|
||||
id: run-goreleaser
|
||||
uses: goreleaser/goreleaser-action@5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89 # v7.2.2
|
||||
uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0
|
||||
with:
|
||||
version: latest
|
||||
args: release --skip=validate
|
||||
@@ -103,9 +103,9 @@ jobs:
|
||||
id-token: write
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@5a7f3ce0de742b6c561a50f90940d81cf6fc698d # main
|
||||
uses: fluxcd/pkg/actions/kustomize@9a8c0edd5da84dc51a585738c67e3a3950d7fbf0 # main
|
||||
- name: Setup Flux CLI
|
||||
uses: ./action/
|
||||
with:
|
||||
@@ -116,13 +116,13 @@ jobs:
|
||||
VERSION=$(flux version --client | awk '{ print $NF }')
|
||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
|
||||
with:
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
--path="./flux-system" \
|
||||
--source=${{ github.repositoryUrl }} \
|
||||
--revision="${{ github.ref_name }}@sha1:${{ github.sha }}"
|
||||
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
||||
- uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
|
||||
with:
|
||||
cosign-release: v2.6.1 # TODO: remove after Flux 2.8 with support for cosign v3
|
||||
- name: Sign manifests
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read # for reading the repository code.
|
||||
security-events: write # for uploading the CodeQL analysis results.
|
||||
uses: fluxcd/gha-workflows/.github/workflows/code-scan.yaml@v0.11.0
|
||||
uses: fluxcd/gha-workflows/.github/workflows/code-scan.yaml@v0.9.0
|
||||
secrets:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
fossa-token: ${{ secrets.FOSSA_TOKEN }}
|
||||
|
||||
@@ -12,6 +12,6 @@ jobs:
|
||||
permissions:
|
||||
contents: read # for reading the labels file.
|
||||
issues: write # for creating and updating labels.
|
||||
uses: fluxcd/gha-workflows/.github/workflows/labels-sync.yaml@v0.11.0
|
||||
uses: fluxcd/gha-workflows/.github/workflows/labels-sync.yaml@v0.9.0
|
||||
secrets:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -16,9 +16,9 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
||||
with:
|
||||
go-version: 1.26.x
|
||||
cache-dependency-path: |
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
|
||||
with:
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
commit-message: |
|
||||
|
||||
@@ -8,6 +8,6 @@ permissions:
|
||||
|
||||
jobs:
|
||||
upgrade-fluxcd-pkg:
|
||||
uses: fluxcd/gha-workflows/.github/workflows/upgrade-fluxcd-pkg.yaml@v0.11.0
|
||||
uses: fluxcd/gha-workflows/.github/workflows/upgrade-fluxcd-pkg.yaml@v0.9.0
|
||||
secrets:
|
||||
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ FROM alpine:3.23 AS builder
|
||||
RUN apk add --no-cache ca-certificates curl
|
||||
|
||||
ARG ARCH=linux/amd64
|
||||
ARG KUBECTL_VER=1.36.1
|
||||
ARG KUBECTL_VER=1.35.0
|
||||
|
||||
RUN curl -sL https://dl.k8s.io/release/v${KUBECTL_VER}/bin/${ARCH}/kubectl \
|
||||
-o /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl
|
||||
|
||||
@@ -2,9 +2,8 @@ VERSION?=$(shell grep 'VERSION' cmd/flux/main.go | awk '{ print $$4 }' | head -n
|
||||
DEV_VERSION?=0.0.0-$(shell git rev-parse --abbrev-ref HEAD)-$(shell git rev-parse --short HEAD)-$(shell date +%s)
|
||||
EMBEDDED_MANIFESTS_TARGET=cmd/flux/.manifests.done
|
||||
TEST_KUBECONFIG?=/tmp/flux-e2e-test-kubeconfig
|
||||
# Architecture to use envtest with; defaults to the host architecture.
|
||||
LOCALARCH ?= $(shell go env GOARCH)
|
||||
ENVTEST_ARCH ?= $(LOCALARCH)
|
||||
# Architecture to use envtest with
|
||||
ENVTEST_ARCH ?= amd64
|
||||
|
||||
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
|
||||
ifeq (,$(shell go env GOBIN))
|
||||
|
||||
@@ -12,26 +12,6 @@ steps:
|
||||
run: flux version --client
|
||||
```
|
||||
|
||||
To install Flux plugins alongside the CLI:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
with:
|
||||
plugins: |
|
||||
mirror@0.0.1
|
||||
- name: Run Flux plugin
|
||||
run: flux mirror --help
|
||||
```
|
||||
|
||||
Installing plugins requires a Flux version with plugin support (v2.9.0 or later).
|
||||
The `plugins` input accepts one plugin per line in `<name>`,
|
||||
`<name>@<version>`, or `<name>@<digest>` format. Entries without a version or
|
||||
digest install the latest version from the catalog. The `plugin-dir` input is
|
||||
only used when `plugins` is set; when plugins are installed, the action exports
|
||||
`FLUXCD_PLUGINS` for subsequent steps.
|
||||
|
||||
The Flux GitHub Action can be used to automate various tasks in CI, such as:
|
||||
|
||||
- [Automate Flux upgrades on clusters via Pull Requests](https://fluxcd.io/flux/flux-gh-action/#automate-flux-updates)
|
||||
|
||||
+5
-87
@@ -12,36 +12,17 @@ inputs:
|
||||
description: "arch can be amd64, arm64 or arm"
|
||||
required: false
|
||||
deprecationMessage: "No longer required, action will now detect runner arch."
|
||||
plugins:
|
||||
description: >
|
||||
Plugins to install alongside Flux. One per line: `<name>`, `<name>@<version>` or
|
||||
`<name>@<digest>`. Entries without a version or digest install the latest
|
||||
version from the catalog. Example: `mirror@0.0.1`
|
||||
required: false
|
||||
plugin-dir:
|
||||
description: >
|
||||
Directory where requested plugins are installed. This input is only used when
|
||||
`plugins` is set. When plugins are installed, the action exports
|
||||
`FLUXCD_PLUGINS` for subsequent steps. Defaults to a `plugins` directory
|
||||
alongside the Flux binary in $RUNNER_TOOL_CACHE.
|
||||
required: false
|
||||
bindir:
|
||||
description: "Alternative location for the Flux binary, defaults to path relative to $RUNNER_TOOL_CACHE."
|
||||
required: false
|
||||
token:
|
||||
description: "Token used to authenticate against the GitHub.com API."
|
||||
required: false
|
||||
outputs:
|
||||
plugin-dir:
|
||||
description: >
|
||||
Directory where the plugins were installed by the action.
|
||||
value: ${{ steps.set-outputs.outputs.plugin-dir }}
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: "Download the binary to the runner's cache dir"
|
||||
shell: bash
|
||||
id: setup-flux-bin
|
||||
env:
|
||||
VERSION: "${{ inputs.version }}"
|
||||
FLUX_TOOL_DIR: "${{ inputs.bindir }}"
|
||||
@@ -61,13 +42,11 @@ runs:
|
||||
if [[ $VERSION = v* ]]; then
|
||||
VERSION="${VERSION:1}"
|
||||
fi
|
||||
echo "installed-flux-version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
OS=$(echo "${RUNNER_OS}" | tr '[:upper:]' '[:lower:]')
|
||||
if [[ "$OS" == "macos" ]]; then
|
||||
OS="darwin"
|
||||
fi
|
||||
echo "os=$OS" >> "$GITHUB_OUTPUT"
|
||||
|
||||
ARCH=$(echo "${RUNNER_ARCH}" | tr '[:upper:]' '[:lower:]')
|
||||
if [[ "$ARCH" == "x64" ]]; then
|
||||
@@ -75,7 +54,6 @@ runs:
|
||||
elif [[ "$ARCH" == "x86" ]]; then
|
||||
ARCH="386"
|
||||
fi
|
||||
echo "arch=$ARCH" >> "$GITHUB_OUTPUT"
|
||||
|
||||
FLUX_EXEC_FILE="flux"
|
||||
if [[ "$OS" == "windows" ]]; then
|
||||
@@ -85,7 +63,7 @@ runs:
|
||||
if [[ -z "$FLUX_TOOL_DIR" ]]; then
|
||||
FLUX_TOOL_DIR="${RUNNER_TOOL_CACHE}/flux2/${VERSION}/${OS}/${ARCH}"
|
||||
fi
|
||||
if [[ ! -x "$FLUX_TOOL_DIR/$FLUX_EXEC_FILE" ]]; then
|
||||
if [[ ! -x "$FLUX_TOOL_DIR/FLUX_EXEC_FILE" ]]; then
|
||||
DL_DIR="$(mktemp -dt flux2-XXXXXX)"
|
||||
trap 'rm -rf $DL_DIR' EXIT
|
||||
|
||||
@@ -101,7 +79,7 @@ runs:
|
||||
|
||||
MAX_RETRIES=5
|
||||
RETRY_DELAY=5
|
||||
|
||||
|
||||
for i in $(seq 1 $MAX_RETRIES); do
|
||||
echo "Downloading flux binary (attempt $i/$MAX_RETRIES)"
|
||||
if curl -fsSL -o "$DL_DIR/$FLUX_TARGET_FILE" "$FLUX_DOWNLOAD_URL/$FLUX_TARGET_FILE"; then
|
||||
@@ -115,7 +93,7 @@ runs:
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
for i in $(seq 1 $MAX_RETRIES); do
|
||||
echo "Downloading checksums file (attempt $i/$MAX_RETRIES)"
|
||||
if curl -fsSL -o "$DL_DIR/$FLUX_CHECKSUMS_FILE" "$FLUX_DOWNLOAD_URL/$FLUX_CHECKSUMS_FILE"; then
|
||||
@@ -129,7 +107,7 @@ runs:
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
echo "Verifying checksum"
|
||||
sum=""
|
||||
if command -v openssl > /dev/null; then
|
||||
@@ -151,7 +129,7 @@ runs:
|
||||
|
||||
echo "Installing flux to ${FLUX_TOOL_DIR}"
|
||||
mkdir -p "$FLUX_TOOL_DIR"
|
||||
|
||||
|
||||
if [[ "$OS" == "windows" ]]; then
|
||||
unzip "$DL_DIR/$FLUX_TARGET_FILE" "$FLUX_EXEC_FILE" -d "$FLUX_TOOL_DIR"
|
||||
else
|
||||
@@ -168,63 +146,3 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
flux -v
|
||||
|
||||
- name: "Plugin support gate"
|
||||
id: plugin-support-gate
|
||||
shell: bash
|
||||
if: inputs.plugins != ''
|
||||
run: |
|
||||
flux_version="$(flux -v 2>/dev/null | awk '{print $3}')"
|
||||
if flux plugin --help >/dev/null 2>&1; then
|
||||
echo "plugin-support=yes" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
else
|
||||
echo "plugin-support=no" >> "$GITHUB_OUTPUT"
|
||||
msg="Installed Flux version ${flux_version:-unknown} does not support plugins; need >= 2.9.0. Requested plugins cannot be installed."
|
||||
echo "::error title=Unsupported Flux version::$msg"
|
||||
echo "> [!CAUTION]" >> $GITHUB_STEP_SUMMARY
|
||||
echo "> $msg" >> $GITHUB_STEP_SUMMARY
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: "Setup Plugins Dir"
|
||||
shell: bash
|
||||
if: steps.plugin-support-gate.outputs.plugin-support == 'yes'
|
||||
env:
|
||||
FLUXCD_PLUGINS: ${{ inputs.plugin-dir }}
|
||||
VERSION: ${{ steps.setup-flux-bin.outputs.installed-flux-version }}
|
||||
OS: ${{ steps.setup-flux-bin.outputs.os }}
|
||||
ARCH: ${{ steps.setup-flux-bin.outputs.arch }}
|
||||
run: |
|
||||
# Use a default plugin directory when plugin-dir was not provided.
|
||||
if [[ -z "$FLUXCD_PLUGINS" ]]; then
|
||||
FLUXCD_PLUGINS="${RUNNER_TOOL_CACHE}/flux2/${VERSION}/${OS}/${ARCH}/plugins/"
|
||||
fi
|
||||
|
||||
# Export it so subsequent steps can discover the installed plugins.
|
||||
echo "FLUXCD_PLUGINS=$FLUXCD_PLUGINS" >> "$GITHUB_ENV"
|
||||
|
||||
# Create the directory if it does not exist.
|
||||
mkdir -p "$FLUXCD_PLUGINS"
|
||||
|
||||
- name: "Install Plugins"
|
||||
shell: bash
|
||||
id: install-plugins
|
||||
if: steps.plugin-support-gate.outputs.plugin-support == 'yes'
|
||||
env:
|
||||
PLUGINS: ${{ inputs.plugins }}
|
||||
run: |
|
||||
echo "$PLUGINS" | while read -r PLUGIN; do
|
||||
trimmed="${PLUGIN//[[:space:]]/}"
|
||||
if [[ -n "$trimmed" ]]; then
|
||||
echo Installing: "$PLUGIN"
|
||||
flux plugin install "$PLUGIN"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: "Set Output"
|
||||
id: set-outputs
|
||||
if: steps.plugin-support-gate.outputs.plugin-support == 'yes'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "plugin-dir=$FLUXCD_PLUGINS" >> "$GITHUB_OUTPUT"
|
||||
|
||||
@@ -20,11 +20,9 @@ import (
|
||||
"context"
|
||||
"crypto/elliptic"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/signature"
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -32,7 +30,6 @@ import (
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
"github.com/fluxcd/flux2/v2/internal/utils"
|
||||
"github.com/fluxcd/flux2/v2/pkg/bootstrap"
|
||||
"github.com/fluxcd/flux2/v2/pkg/manifestgen"
|
||||
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret"
|
||||
)
|
||||
@@ -50,7 +47,6 @@ type bootstrapFlags struct {
|
||||
|
||||
branch string
|
||||
recurseSubmodules bool
|
||||
sparseCheckout []string
|
||||
manifestsPath string
|
||||
|
||||
defaultComponents []string
|
||||
@@ -83,11 +79,6 @@ type bootstrapFlags struct {
|
||||
gpgPassphrase string
|
||||
gpgKeyID string
|
||||
|
||||
sshSigningKeyFile string
|
||||
sshSigningPassword string
|
||||
sshSigningPassphrase string
|
||||
sshSigningReusePrivateKey bool
|
||||
|
||||
force bool
|
||||
|
||||
commitMessageAppendix string
|
||||
@@ -118,8 +109,6 @@ func init() {
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.branch, "branch", bootstrapDefaultBranch, "Git branch")
|
||||
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapArgs.recurseSubmodules, "recurse-submodules", false,
|
||||
"when enabled, configures the GitRepository source to initialize and include Git submodules in the artifact it produces")
|
||||
bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.sparseCheckout, "sparse-checkout", nil,
|
||||
"list of directories to be included in the GitRepository sparse checkout, the configured --path must be one of them, accepts comma-separated values")
|
||||
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.manifestsPath, "manifests", "", "path to the manifest directory")
|
||||
|
||||
@@ -150,12 +139,6 @@ func init() {
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.gpgPassphrase, "gpg-passphrase", "", "passphrase for decrypting GPG private key")
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.gpgKeyID, "gpg-key-id", "", "key id for selecting a particular key")
|
||||
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.sshSigningKeyFile, "ssh-signing-key-file", "", "path to an SSH private key file used for signing commits")
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.sshSigningPassword, "ssh-signing-password", "", "passphrase for decrypting SSH signing key")
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.sshSigningPassphrase, "ssh-signing-passphrase", "", "alias for --ssh-signing-password")
|
||||
bootstrapCmd.PersistentFlags().MarkHidden("ssh-signing-passphrase")
|
||||
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapArgs.sshSigningReusePrivateKey, "ssh-signing-reuse-private-key", false, "use the SSH transport key (--private-key-file) to sign commits")
|
||||
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.commitMessageAppendix, "commit-message-appendix", "", "string to add to the commit messages, e.g. '[ci skip]'")
|
||||
|
||||
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapArgs.force, "force", false, "override existing Flux installation if it's managed by a different tool such as Helm")
|
||||
@@ -212,31 +195,6 @@ func bootstrapValidate() error {
|
||||
return fmt.Errorf("invalid --registry-creds format, expected 'user:password'")
|
||||
}
|
||||
|
||||
sshSigningSet := bootstrapArgs.sshSigningKeyFile != "" || bootstrapArgs.sshSigningReusePrivateKey
|
||||
if bootstrapArgs.gpgKeyRingPath != "" && sshSigningSet {
|
||||
return fmt.Errorf("--gpg-* and --ssh-signing-* are mutually exclusive; pick one signing format")
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningKeyFile != "" && bootstrapArgs.sshSigningReusePrivateKey {
|
||||
return fmt.Errorf("--ssh-signing-key-file and --ssh-signing-reuse-private-key are mutually exclusive")
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningReusePrivateKey && bootstrapArgs.privateKeyFile == "" {
|
||||
return fmt.Errorf("--ssh-signing-reuse-private-key requires --private-key-file")
|
||||
}
|
||||
|
||||
sshSigningPwd, err := effectiveSshSigningPassword()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sshSigningPwd != "" && bootstrapArgs.sshSigningKeyFile == "" {
|
||||
return fmt.Errorf("--ssh-signing-password requires --ssh-signing-key-file")
|
||||
}
|
||||
|
||||
if err := preflightSigningKey(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(bootstrapArgs.sshHostKeyAlgorithms) > 0 {
|
||||
git.HostKeyAlgos = bootstrapArgs.sshHostKeyAlgorithms
|
||||
}
|
||||
@@ -256,57 +214,6 @@ func mapTeamSlice(s []string, defaultPermission string) map[string]string {
|
||||
return m
|
||||
}
|
||||
|
||||
// preflightSigningKey reads and parses the configured signing key so
|
||||
// malformed PEM, wrong passphrases, and unsupported SSH algorithms
|
||||
// surface before any clone runs.
|
||||
func preflightSigningKey() error {
|
||||
switch {
|
||||
case bootstrapArgs.gpgKeyRingPath != "":
|
||||
ring, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid GPG signing key: %w", err)
|
||||
}
|
||||
if _, err := bootstrap.SelectOpenPGPSigningEntity(ring, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID); err != nil {
|
||||
return fmt.Errorf("invalid GPG signing key: %w", err)
|
||||
}
|
||||
case bootstrapArgs.sshSigningKeyFile != "":
|
||||
pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read SSH signing key file: %w", err)
|
||||
}
|
||||
pwd, err := effectiveSshSigningPassword()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := signature.NewSSHSigner(pemBytes, []byte(pwd)); err != nil {
|
||||
return fmt.Errorf("invalid SSH signing key: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// effectiveSshSigningPassword resolves the SSH signing-key passphrase
|
||||
// from --ssh-signing-password and its hidden alias
|
||||
// --ssh-signing-passphrase. When both are set with the same value, the
|
||||
// value is returned. When both are set with different non-empty values,
|
||||
// an error is returned. When neither is set, an empty string is
|
||||
// returned with no error.
|
||||
func effectiveSshSigningPassword() (string, error) {
|
||||
pw := bootstrapArgs.sshSigningPassword
|
||||
alias := bootstrapArgs.sshSigningPassphrase
|
||||
switch {
|
||||
case pw != "" && alias != "":
|
||||
if pw != alias {
|
||||
return "", fmt.Errorf("--ssh-signing-password and --ssh-signing-passphrase are aliases; do not pass both")
|
||||
}
|
||||
return pw, nil
|
||||
case pw == "" && alias != "":
|
||||
return alias, nil
|
||||
default:
|
||||
return pw, nil
|
||||
}
|
||||
}
|
||||
|
||||
// confirmBootstrap gets a confirmation for running bootstrap over an existing Flux installation.
|
||||
// It returns a nil error if Flux is not installed or the user confirms overriding an existing installation
|
||||
func confirmBootstrap(ctx context.Context, kubeClient client.Client) error {
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/fluxcd/pkg/git/signature"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
@@ -254,7 +253,6 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
|
||||
TargetPath: bServerArgs.path.ToSlash(),
|
||||
ManifestFile: sync.MakeDefaultOptions().ManifestFile,
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
SparseCheckout: bootstrapArgs.sparseCheckout,
|
||||
}
|
||||
|
||||
entityList, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
@@ -289,31 +287,6 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile())
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningKeyFile != "" {
|
||||
pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read SSH signing key file: %w", err)
|
||||
}
|
||||
pwd, err := effectiveSshSigningPassword()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bootstrapOpts = append(bootstrapOpts,
|
||||
bootstrap.WithSSHCommitSigning(pemBytes, []byte(pwd)))
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningReusePrivateKey {
|
||||
pemBytes, err := os.ReadFile(bootstrapArgs.privateKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read transport private key for signing: %w", err)
|
||||
}
|
||||
if _, err := signature.NewSSHSigner(pemBytes, []byte(gitArgs.password)); err != nil {
|
||||
return fmt.Errorf("invalid signing key (reused from --private-key-file): %w", err)
|
||||
}
|
||||
bootstrapOpts = append(bootstrapOpts,
|
||||
bootstrap.WithSSHCommitSigning(pemBytes, []byte(gitArgs.password)))
|
||||
}
|
||||
|
||||
// Setup bootstrapper with constructed configs
|
||||
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
||||
if err != nil {
|
||||
|
||||
@@ -28,12 +28,8 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/fluxcd/pkg/auth"
|
||||
"github.com/fluxcd/pkg/auth/aws"
|
||||
authutils "github.com/fluxcd/pkg/auth/utils"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/fluxcd/pkg/git/signature"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
"github.com/fluxcd/flux2/v2/internal/utils"
|
||||
@@ -66,12 +62,9 @@ command will perform an upgrade if needed.`,
|
||||
# Run bootstrap for a Git repository with a private key and password
|
||||
flux bootstrap git --url=ssh://git@example.com/repository.git --private-key-file=<path/to/private.key> --password=<password> --path=clusters/my-cluster
|
||||
|
||||
# Run bootstrap for a Git repository on AWS CodeCommit using SSH
|
||||
# Run bootstrap for a Git repository on AWS CodeCommit
|
||||
flux bootstrap git --url=ssh://<SSH-Key-ID>@git-codecommit.<region>.amazonaws.com/v1/repos/<repository> --private-key-file=<path/to/private.key> --password=<SSH-passphrase> --path=clusters/my-cluster
|
||||
|
||||
# Run bootstrap for a Git repository on AWS CodeCommit using HTTPS (requires AWS IAM credentials)
|
||||
flux bootstrap git --url=https://git-codecommit.<region>.amazonaws.com/v1/repos/<repository> --path=clusters/my-cluster
|
||||
|
||||
# Run bootstrap for a Git repository on Azure Devops
|
||||
flux bootstrap git --url=ssh://git@ssh.dev.azure.com/v3/<org>/<project>/<repository> --private-key-file=<path/to/rsa-sha2-private.key> --ssh-hostkey-algos=rsa-sha2-512,rsa-sha2-256 --path=clusters/my-cluster
|
||||
|
||||
@@ -116,7 +109,6 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
bootstrapArgs.tokenAuth = true
|
||||
}
|
||||
|
||||
var gitProvider string
|
||||
gitPassword := os.Getenv(gitPasswordEnvVar)
|
||||
if gitPassword != "" && gitArgs.password == "" {
|
||||
gitArgs.password = gitPassword
|
||||
@@ -139,12 +131,8 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
if strings.Contains(repositoryURL.Hostname(), "git-codecommit") && strings.Contains(repositoryURL.Hostname(), "amazonaws.com") {
|
||||
// https://docs.aws.amazon.com/codecommit/latest/userguide/auth-and-access-control.html
|
||||
if repositoryURL.Scheme == string(git.SSH) { // IAM user + SSH
|
||||
if repositoryURL.Scheme == string(git.SSH) {
|
||||
if repositoryURL.User == nil {
|
||||
return fmt.Errorf("invalid AWS CodeCommit url: ssh username should be specified in the url")
|
||||
}
|
||||
@@ -154,19 +142,15 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.privateKeyFile == "" {
|
||||
return fmt.Errorf("private key file is required for bootstrapping against AWS CodeCommit using ssh")
|
||||
}
|
||||
} else if repositoryURL.Scheme == string(git.HTTPS) && !bootstrapArgs.tokenAuth { // IAM role + HTTPS
|
||||
creds, err := authutils.GetGitCredentials(ctx, "aws", auth.WithGitURL(*repositoryURL))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get AWS CodeCommit IAM git credentials: %w", err)
|
||||
}
|
||||
gitArgs.username = creds.Username
|
||||
gitArgs.password = creds.Password
|
||||
bootstrapArgs.tokenAuth = true
|
||||
gitProvider = aws.ProviderName
|
||||
}
|
||||
|
||||
if repositoryURL.Scheme == string(git.HTTPS) && !bootstrapArgs.tokenAuth {
|
||||
return fmt.Errorf("--token-auth=true must be specified for using an HTTPS AWS CodeCommit url")
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -312,10 +296,6 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
TargetPath: gitArgs.path.ToSlash(),
|
||||
ManifestFile: sync.MakeDefaultOptions().ManifestFile,
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
SparseCheckout: bootstrapArgs.sparseCheckout,
|
||||
}
|
||||
if gitProvider != "" {
|
||||
syncOpts.Provider = gitProvider
|
||||
}
|
||||
|
||||
entityList, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
@@ -335,33 +315,6 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
bootstrap.WithGitCommitSigning(entityList, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningKeyFile != "" {
|
||||
pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read SSH signing key file: %w", err)
|
||||
}
|
||||
pwd, err := effectiveSshSigningPassword()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bootstrapOpts = append(bootstrapOpts,
|
||||
bootstrap.WithSSHCommitSigning(pemBytes, []byte(pwd)))
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningReusePrivateKey {
|
||||
pemBytes, err := os.ReadFile(bootstrapArgs.privateKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read transport private key for signing: %w", err)
|
||||
}
|
||||
// Reuse-path pre-flight: bootstrapValidate cannot run this check
|
||||
// because the SSH transport password is subcommand-local.
|
||||
if _, err := signature.NewSSHSigner(pemBytes, []byte(gitArgs.password)); err != nil {
|
||||
return fmt.Errorf("invalid signing key (reused from --private-key-file): %w", err)
|
||||
}
|
||||
bootstrapOpts = append(bootstrapOpts,
|
||||
bootstrap.WithSSHCommitSigning(pemBytes, []byte(gitArgs.password)))
|
||||
}
|
||||
|
||||
// Setup bootstrapper with constructed configs
|
||||
b, err := bootstrap.NewPlainGitProvider(gitClient, kubeClient, bootstrapOpts...)
|
||||
if err != nil {
|
||||
|
||||
@@ -107,11 +107,6 @@ func init() {
|
||||
}
|
||||
|
||||
func bootstrapGiteaCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.sshSigningReusePrivateKey {
|
||||
return fmt.Errorf("--ssh-signing-reuse-private-key is not supported by 'bootstrap gitea'; " +
|
||||
"that subcommand generates the SSH transport key in-process and has no operator-supplied key to reuse")
|
||||
}
|
||||
|
||||
gtToken := os.Getenv(gtTokenEnvVar)
|
||||
if gtToken == "" {
|
||||
var err error
|
||||
@@ -237,7 +232,6 @@ func bootstrapGiteaCmdRun(cmd *cobra.Command, args []string) error {
|
||||
TargetPath: giteaArgs.path.ToSlash(),
|
||||
ManifestFile: sync.MakeDefaultOptions().ManifestFile,
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
SparseCheckout: bootstrapArgs.sparseCheckout,
|
||||
}
|
||||
|
||||
entityList, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
@@ -258,7 +252,6 @@ func bootstrapGiteaCmdRun(cmd *cobra.Command, args []string) error {
|
||||
bootstrap.WithLogger(logger),
|
||||
bootstrap.WithGitCommitSigning(entityList, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithSSHHostname(bootstrapArgs.sshHostname))
|
||||
}
|
||||
@@ -272,19 +265,6 @@ func bootstrapGiteaCmdRun(cmd *cobra.Command, args []string) error {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile())
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningKeyFile != "" {
|
||||
pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read SSH signing key file: %w", err)
|
||||
}
|
||||
pwd, err := effectiveSshSigningPassword()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bootstrapOpts = append(bootstrapOpts,
|
||||
bootstrap.WithSSHCommitSigning(pemBytes, []byte(pwd)))
|
||||
}
|
||||
|
||||
// Setup bootstrapper with constructed configs
|
||||
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
||||
if err != nil {
|
||||
|
||||
@@ -107,11 +107,6 @@ func init() {
|
||||
}
|
||||
|
||||
func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.sshSigningReusePrivateKey {
|
||||
return fmt.Errorf("--ssh-signing-reuse-private-key is not supported by 'bootstrap github'; " +
|
||||
"that subcommand generates the SSH transport key in-process and has no operator-supplied key to reuse")
|
||||
}
|
||||
|
||||
ghToken := os.Getenv(ghTokenEnvVar)
|
||||
if ghToken == "" {
|
||||
var err error
|
||||
@@ -244,7 +239,6 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
TargetPath: githubArgs.path.ToSlash(),
|
||||
ManifestFile: sync.MakeDefaultOptions().ManifestFile,
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
SparseCheckout: bootstrapArgs.sparseCheckout,
|
||||
}
|
||||
|
||||
entityList, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
@@ -265,7 +259,6 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
bootstrap.WithLogger(logger),
|
||||
bootstrap.WithGitCommitSigning(entityList, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithSSHHostname(bootstrapArgs.sshHostname))
|
||||
}
|
||||
@@ -279,19 +272,6 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile())
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningKeyFile != "" {
|
||||
pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read SSH signing key file: %w", err)
|
||||
}
|
||||
pwd, err := effectiveSshSigningPassword()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bootstrapOpts = append(bootstrapOpts,
|
||||
bootstrap.WithSSHCommitSigning(pemBytes, []byte(pwd)))
|
||||
}
|
||||
|
||||
// Setup bootstrapper with constructed configs
|
||||
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
||||
if err != nil {
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"github.com/fluxcd/go-git-providers/gitprovider"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/fluxcd/pkg/git/signature"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
@@ -288,7 +287,6 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
TargetPath: gitlabArgs.path.ToSlash(),
|
||||
ManifestFile: sync.MakeDefaultOptions().ManifestFile,
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
SparseCheckout: bootstrapArgs.sparseCheckout,
|
||||
}
|
||||
|
||||
entityList, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
@@ -323,31 +321,6 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile())
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningKeyFile != "" {
|
||||
pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read SSH signing key file: %w", err)
|
||||
}
|
||||
pwd, err := effectiveSshSigningPassword()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bootstrapOpts = append(bootstrapOpts,
|
||||
bootstrap.WithSSHCommitSigning(pemBytes, []byte(pwd)))
|
||||
}
|
||||
|
||||
if bootstrapArgs.sshSigningReusePrivateKey {
|
||||
pemBytes, err := os.ReadFile(bootstrapArgs.privateKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read transport private key for signing: %w", err)
|
||||
}
|
||||
if _, err := signature.NewSSHSigner(pemBytes, []byte(gitArgs.password)); err != nil {
|
||||
return fmt.Errorf("invalid signing key (reused from --private-key-file): %w", err)
|
||||
}
|
||||
bootstrapOpts = append(bootstrapOpts,
|
||||
bootstrap.WithSSHCommitSigning(pemBytes, []byte(gitArgs.password)))
|
||||
}
|
||||
|
||||
// Setup bootstrapper with constructed configs
|
||||
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
Copyright 2026 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBootstrapValidate_signingFlags(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
gpgRing string
|
||||
gpgPass string
|
||||
sshKey string
|
||||
sshPass string
|
||||
sshPassp string
|
||||
privateKey string
|
||||
reuse bool
|
||||
wantErr string
|
||||
}{
|
||||
{name: "no signing flags is valid"},
|
||||
{name: "GPG only is valid", gpgRing: "./testdata/bootstrap/gpg.pgp"},
|
||||
{name: "SSH only is valid", sshKey: "./testdata/bootstrap/ed25519.private"},
|
||||
{
|
||||
name: "Reuse-private-key with private-key-file is valid",
|
||||
privateKey: "./testdata/bootstrap/ed25519.private",
|
||||
reuse: true,
|
||||
},
|
||||
{
|
||||
name: "GPG + SSH errors",
|
||||
gpgRing: "./testdata/bootstrap/gpg.pgp",
|
||||
sshKey: "./testdata/bootstrap/ed25519.private",
|
||||
wantErr: "--gpg-* and --ssh-signing-* are mutually exclusive",
|
||||
},
|
||||
{
|
||||
name: "GPG + reuse errors",
|
||||
gpgRing: "./testdata/bootstrap/gpg.pgp",
|
||||
privateKey: "./testdata/bootstrap/ed25519.private",
|
||||
reuse: true,
|
||||
wantErr: "--gpg-* and --ssh-signing-* are mutually exclusive",
|
||||
},
|
||||
{
|
||||
name: "SSH key-file + reuse errors",
|
||||
sshKey: "./testdata/bootstrap/ed25519.private",
|
||||
privateKey: "./testdata/bootstrap/ed25519.private",
|
||||
reuse: true,
|
||||
wantErr: "--ssh-signing-key-file and --ssh-signing-reuse-private-key are mutually exclusive",
|
||||
},
|
||||
{
|
||||
name: "Reuse without private-key-file errors",
|
||||
reuse: true,
|
||||
wantErr: "--ssh-signing-reuse-private-key requires --private-key-file",
|
||||
},
|
||||
{
|
||||
name: "SSH password without key errors",
|
||||
sshPass: "secret",
|
||||
wantErr: "--ssh-signing-password requires --ssh-signing-key-file",
|
||||
},
|
||||
{
|
||||
name: "SSH passphrase alias alone applies",
|
||||
sshKey: "./testdata/bootstrap/ed25519-encrypted.private",
|
||||
sshPassp: "abcde12345",
|
||||
},
|
||||
{
|
||||
name: "SSH password and passphrase with same value passes",
|
||||
sshKey: "./testdata/bootstrap/ed25519-encrypted.private",
|
||||
sshPass: "abcde12345",
|
||||
sshPassp: "abcde12345",
|
||||
},
|
||||
{
|
||||
name: "SSH password and passphrase with different values errors",
|
||||
sshKey: "./testdata/bootstrap/ed25519-encrypted.private",
|
||||
sshPass: "right",
|
||||
sshPassp: "wrong",
|
||||
wantErr: "are aliases; do not pass both",
|
||||
},
|
||||
{
|
||||
name: "SSH malformed key fails pre-flight",
|
||||
sshKey: "./testdata/bootstrap/malformed.private",
|
||||
wantErr: "invalid SSH signing key",
|
||||
},
|
||||
{
|
||||
name: "SSH encrypted key without password fails pre-flight",
|
||||
sshKey: "./testdata/bootstrap/ed25519-encrypted.private",
|
||||
wantErr: "passphrase required",
|
||||
},
|
||||
// The GPG fixture used here is encrypted (passphrase: "right") so that
|
||||
// passing the wrong passphrase exercises the Decrypt error path.
|
||||
// An unencrypted key would make Decrypt a no-op regardless of the
|
||||
// passphrase supplied.
|
||||
{
|
||||
name: "GPG with wrong passphrase fails pre-flight",
|
||||
gpgRing: "./testdata/bootstrap/gpg-encrypted.pgp",
|
||||
gpgPass: "wrong",
|
||||
wantErr: "invalid GPG signing key",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
savedDefaultComponents := bootstrapArgs.defaultComponents
|
||||
savedGpgRing := bootstrapArgs.gpgKeyRingPath
|
||||
savedGpgPass := bootstrapArgs.gpgPassphrase
|
||||
savedSshKey := bootstrapArgs.sshSigningKeyFile
|
||||
savedSshPass := bootstrapArgs.sshSigningPassword
|
||||
savedSshPassp := bootstrapArgs.sshSigningPassphrase
|
||||
savedPrivKey := bootstrapArgs.privateKeyFile
|
||||
savedReuse := bootstrapArgs.sshSigningReusePrivateKey
|
||||
defer func() {
|
||||
bootstrapArgs.defaultComponents = savedDefaultComponents
|
||||
bootstrapArgs.gpgKeyRingPath = savedGpgRing
|
||||
bootstrapArgs.gpgPassphrase = savedGpgPass
|
||||
bootstrapArgs.sshSigningKeyFile = savedSshKey
|
||||
bootstrapArgs.sshSigningPassword = savedSshPass
|
||||
bootstrapArgs.sshSigningPassphrase = savedSshPassp
|
||||
bootstrapArgs.privateKeyFile = savedPrivKey
|
||||
bootstrapArgs.sshSigningReusePrivateKey = savedReuse
|
||||
}()
|
||||
|
||||
// The e2e TestMain calls resetCmdArgs which clears the
|
||||
// cobra-populated default components, so seed them here to
|
||||
// satisfy the requiredComponents pre-check in bootstrapValidate.
|
||||
bootstrapArgs.defaultComponents = bootstrapArgs.requiredComponents
|
||||
bootstrapArgs.gpgKeyRingPath = tt.gpgRing
|
||||
bootstrapArgs.gpgPassphrase = tt.gpgPass
|
||||
bootstrapArgs.sshSigningKeyFile = tt.sshKey
|
||||
bootstrapArgs.sshSigningPassword = tt.sshPass
|
||||
bootstrapArgs.sshSigningPassphrase = tt.sshPassp
|
||||
bootstrapArgs.privateKeyFile = tt.privateKey
|
||||
bootstrapArgs.sshSigningReusePrivateKey = tt.reuse
|
||||
|
||||
err := bootstrapValidate()
|
||||
if tt.wantErr == "" {
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatalf("expected error containing %q, got nil", tt.wantErr)
|
||||
}
|
||||
if !strings.Contains(err.Error(), tt.wantErr) {
|
||||
t.Fatalf("expected error containing %q, got: %v", tt.wantErr, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Providers that generate the SSH transport key in-process (github, gitea)
|
||||
// must reject --ssh-signing-reuse-private-key with their own, provider-
|
||||
// specific error before bootstrapValidate runs — otherwise the generic
|
||||
// "--ssh-signing-reuse-private-key requires --private-key-file" error
|
||||
// shadows the fact that the flag is fundamentally unsupported there.
|
||||
func TestBootstrapProviderRejectsReuseBeforeValidate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
runE func() error
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "github rejects reuse with provider-specific error",
|
||||
runE: func() error { return bootstrapGitHubCmdRun(nil, nil) },
|
||||
wantErr: "not supported by 'bootstrap github'",
|
||||
},
|
||||
{
|
||||
name: "gitea rejects reuse with provider-specific error",
|
||||
runE: func() error { return bootstrapGiteaCmdRun(nil, nil) },
|
||||
wantErr: "not supported by 'bootstrap gitea'",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
savedReuse := bootstrapArgs.sshSigningReusePrivateKey
|
||||
savedPrivKey := bootstrapArgs.privateKeyFile
|
||||
defer func() {
|
||||
bootstrapArgs.sshSigningReusePrivateKey = savedReuse
|
||||
bootstrapArgs.privateKeyFile = savedPrivKey
|
||||
}()
|
||||
|
||||
// Reuse flag set, no --private-key-file: bootstrapValidate
|
||||
// would otherwise return "requires --private-key-file".
|
||||
bootstrapArgs.sshSigningReusePrivateKey = true
|
||||
bootstrapArgs.privateKeyFile = ""
|
||||
|
||||
err := tt.runE()
|
||||
if err == nil {
|
||||
t.Fatalf("expected error containing %q, got nil", tt.wantErr)
|
||||
}
|
||||
if !strings.Contains(err.Error(), tt.wantErr) {
|
||||
t.Fatalf("expected error containing %q, got: %v", tt.wantErr, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -218,7 +218,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
if len(helmReleaseArgs.dependsOn) > 0 {
|
||||
ls := meta.MakeDependsOn(helmReleaseArgs.dependsOn)
|
||||
ls := utils.MakeDependsOn(helmReleaseArgs.dependsOn)
|
||||
hrDependsOn := make([]helmv2.DependencyReference, 0, len(ls))
|
||||
for _, d := range ls {
|
||||
hrDependsOn = append(hrDependsOn, helmv2.DependencyReference{
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
@@ -76,8 +75,6 @@ type imageUpdateFlags struct {
|
||||
commitTemplate string
|
||||
authorName string
|
||||
authorEmail string
|
||||
signingKeySecret string
|
||||
signingKeyType string
|
||||
}
|
||||
|
||||
var imageUpdateArgs = imageUpdateFlags{}
|
||||
@@ -92,8 +89,6 @@ func init() {
|
||||
flags.StringVar(&imageUpdateArgs.commitTemplate, "commit-template", "", "a template for commit messages")
|
||||
flags.StringVar(&imageUpdateArgs.authorName, "author-name", "", "the name to use for commit author")
|
||||
flags.StringVar(&imageUpdateArgs.authorEmail, "author-email", "", "the email to use for commit author")
|
||||
flags.StringVar(&imageUpdateArgs.signingKeySecret, "signing-key-secret", "", "name of the Secret containing the signing key referenced in spec.git.commit.signingKey")
|
||||
flags.StringVar(&imageUpdateArgs.signingKeyType, "signing-key-type", "", "signing-key format: gpg or ssh (defaults to gpg when --signing-key-secret is set)")
|
||||
|
||||
createImageCmd.AddCommand(createImageUpdateCmd)
|
||||
}
|
||||
@@ -117,15 +112,6 @@ func createImageUpdateRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("the author email is required (--author-email)")
|
||||
}
|
||||
|
||||
if imageUpdateArgs.signingKeyType != "" && imageUpdateArgs.signingKeySecret == "" {
|
||||
return fmt.Errorf("--signing-key-type requires --signing-key-secret")
|
||||
}
|
||||
if imageUpdateArgs.signingKeyType != "" &&
|
||||
imageUpdateArgs.signingKeyType != string(autov1.SigningKeyTypeGPG) &&
|
||||
imageUpdateArgs.signingKeyType != string(autov1.SigningKeyTypeSSH) {
|
||||
return fmt.Errorf("--signing-key-type must be one of: gpg, ssh")
|
||||
}
|
||||
|
||||
labels, err := parseLabels()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -177,13 +163,6 @@ func createImageUpdateRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if imageUpdateArgs.signingKeySecret != "" {
|
||||
update.Spec.GitSpec.Commit.SigningKey = &autov1.SigningKey{
|
||||
SecretRef: meta.LocalObjectReference{Name: imageUpdateArgs.signingKeySecret},
|
||||
Type: autov1.SigningKeyType(imageUpdateArgs.signingKeyType),
|
||||
}
|
||||
}
|
||||
|
||||
if createArgs.export {
|
||||
return printExport(exportImageUpdate(&update))
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
Copyright 2026 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCreateImageUpdate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args string
|
||||
assert assertFunc
|
||||
}{
|
||||
{
|
||||
name: "no signing key",
|
||||
args: "create image update flux-system --git-repo-ref=flux-system --checkout-branch=main --author-name=flux --author-email=flux@example.com --interval=1m0s --namespace=flux-system --export",
|
||||
assert: assertGoldenFile("./testdata/create_image_update/no-signing.yaml"),
|
||||
},
|
||||
{
|
||||
name: "signing secret without explicit type defaults to gpg",
|
||||
args: "create image update flux-system --git-repo-ref=flux-system --checkout-branch=main --author-name=flux --author-email=flux@example.com --signing-key-secret=my-key --interval=1m0s --namespace=flux-system --export",
|
||||
assert: assertGoldenFile("./testdata/create_image_update/signing-default-gpg.yaml"),
|
||||
},
|
||||
{
|
||||
name: "ssh signing key",
|
||||
args: "create image update flux-system --git-repo-ref=flux-system --checkout-branch=main --author-name=flux --author-email=flux@example.com --signing-key-secret=my-deploy-key --signing-key-type=ssh --interval=1m0s --namespace=flux-system --export",
|
||||
assert: assertGoldenFile("./testdata/create_image_update/signing-ssh.yaml"),
|
||||
},
|
||||
{
|
||||
name: "signing-key-type without secret errors",
|
||||
args: "create image update flux-system --git-repo-ref=flux-system --checkout-branch=main --author-name=flux --author-email=flux@example.com --signing-key-type=ssh --namespace=flux-system --export",
|
||||
assert: assertError("--signing-key-type requires --signing-key-secret"),
|
||||
},
|
||||
{
|
||||
name: "invalid signing-key-type errors",
|
||||
args: "create image update flux-system --git-repo-ref=flux-system --checkout-branch=main --author-name=flux --author-email=flux@example.com --signing-key-secret=k --signing-key-type=pgp --namespace=flux-system --export",
|
||||
assert: assertError("--signing-key-type must be one of: gpg, ssh"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: tt.args,
|
||||
assert: tt.assert,
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
if len(kustomizationArgs.dependsOn) > 0 {
|
||||
ls := meta.MakeDependsOn(kustomizationArgs.dependsOn)
|
||||
ls := utils.MakeDependsOn(kustomizationArgs.dependsOn)
|
||||
ksDependsOn := make([]kustomizev1.DependencyReference, 0, len(ls))
|
||||
for _, d := range ls {
|
||||
ksDependsOn = append(ksDependsOn, kustomizev1.DependencyReference{
|
||||
|
||||
@@ -77,18 +77,16 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("secret ref is required")
|
||||
}
|
||||
|
||||
resources := []notificationv1.ReceiverResource{}
|
||||
resources := []notificationv1.CrossNamespaceObjectReference{}
|
||||
for _, resource := range receiverArgs.resources {
|
||||
kind, name := utils.ParseObjectKindName(resource)
|
||||
if kind == "" {
|
||||
return fmt.Errorf("invalid event source '%s', must be in format <kind>/<name>", resource)
|
||||
}
|
||||
|
||||
resources = append(resources, notificationv1.ReceiverResource{
|
||||
CrossNamespaceObjectReference: notificationv1.CrossNamespaceObjectReference{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
},
|
||||
resources = append(resources, notificationv1.CrossNamespaceObjectReference{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -115,7 +113,7 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
|
||||
Type: receiverArgs.receiverType.String(),
|
||||
Events: receiverArgs.events,
|
||||
Resources: resources,
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
SecretRef: meta.LocalObjectReference{
|
||||
Name: receiverArgs.secretRef,
|
||||
},
|
||||
Suspend: false,
|
||||
|
||||
@@ -130,7 +130,7 @@ func createSourceChartCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
if provider := sourceChartArgs.verifyProvider.String(); provider != "" {
|
||||
helmChart.Spec.Verify = &sourcev1.HelmChartVerification{
|
||||
helmChart.Spec.Verify = &sourcev1.OCIRepositoryVerification{
|
||||
Provider: provider,
|
||||
}
|
||||
if secretName := sourceChartArgs.verifySecretRef; secretName != "" {
|
||||
|
||||
@@ -124,12 +124,6 @@ For private Git repositories, the basic authentication credentials are stored in
|
||||
--username=username \
|
||||
--password=password
|
||||
|
||||
# Create a source for a Git repository using AWS CodeCommit with IAM credentials
|
||||
flux create source git podinfo \
|
||||
--url=https://git-codecommit.<region>.amazonaws.com/v1/repos/podinfo \
|
||||
--branch=master \
|
||||
--provider=aws
|
||||
|
||||
# Create a source for a Git repository using azure provider
|
||||
flux create source git podinfo \
|
||||
--url=https://dev.azure.com/foo/bar/_git/podinfo \
|
||||
|
||||
@@ -152,7 +152,7 @@ func TestCreateSourceGitExport(t *testing.T) {
|
||||
{
|
||||
name: "source with invalid provider",
|
||||
args: "create source git podinfo --namespace=flux-system --url=https://dev.azure.com/foo/bar/_git/podinfo --provider dummy --branch=test --interval=1m0s --export",
|
||||
assert: assertError("invalid argument \"dummy\" for \"--provider\" flag: source Git provider 'dummy' is not supported, must be one of: generic|github|aws|azure"),
|
||||
assert: assertError("invalid argument \"dummy\" for \"--provider\" flag: source Git provider 'dummy' is not supported, must be one of: generic|azure|github"),
|
||||
},
|
||||
{
|
||||
name: "source with empty provider",
|
||||
|
||||
@@ -114,16 +114,9 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
helmURL, err := url.Parse(sourceHelmArgs.url)
|
||||
if err != nil {
|
||||
if _, err := url.Parse(sourceHelmArgs.url); err != nil {
|
||||
return fmt.Errorf("url parse failed: %w", err)
|
||||
}
|
||||
if helmURL.Scheme != "http" && helmURL.Scheme != "https" && helmURL.Scheme != sourcev1.HelmRepositoryTypeOCI {
|
||||
return fmt.Errorf("url scheme '%s' not supported, can be: http, https and oci", helmURL.Scheme)
|
||||
}
|
||||
if helmURL.Host == "" {
|
||||
return fmt.Errorf("url host is required")
|
||||
}
|
||||
|
||||
helmRepository := &sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -139,7 +132,11 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
},
|
||||
}
|
||||
|
||||
if helmURL.Scheme == sourcev1.HelmRepositoryTypeOCI {
|
||||
url, err := url.Parse(sourceHelmArgs.url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse URL: %w", err)
|
||||
}
|
||||
if url.Scheme == sourcev1.HelmRepositoryTypeOCI {
|
||||
helmRepository.Spec.Type = sourcev1.HelmRepositoryTypeOCI
|
||||
helmRepository.Spec.Provider = sourceHelmArgs.ociProvider
|
||||
}
|
||||
|
||||
@@ -36,12 +36,6 @@ func TestCreateSourceHelm(t *testing.T) {
|
||||
resultFile: "name is required",
|
||||
assertFunc: "assertError",
|
||||
},
|
||||
{
|
||||
name: "unsupported URL scheme",
|
||||
args: "create source helm podinfo --url=git://example.com/charts --export",
|
||||
resultFile: "url scheme 'git' not supported, can be: http, https and oci",
|
||||
assertFunc: "assertError",
|
||||
},
|
||||
{
|
||||
name: "OCI repo",
|
||||
args: "create source helm podinfo --url=oci://ghcr.io/stefanprodan/charts/podinfo --interval 5m --export",
|
||||
|
||||
@@ -53,12 +53,6 @@ var createSourceOCIRepositoryCmd = &cobra.Command{
|
||||
--verify-provider=cosign \
|
||||
--verify-subject="^https://github.com/stefanprodan/podinfo/.github/workflows/release.yml@refs/tags/6.6.2$" \
|
||||
--verify-issuer="^https://token.actions.githubusercontent.com$"
|
||||
|
||||
# Create an OCIRepository for a Helm chart layer
|
||||
flux create source oci valkey-cluster \
|
||||
--url=oci://example.com/charts/valkey \
|
||||
--tag=0.11.6 \
|
||||
--layer-selector=application/vnd.cncf.helm.chart.content.v1.tar+gzip:copy
|
||||
`,
|
||||
RunE: createSourceOCIRepositoryCmdRun,
|
||||
}
|
||||
@@ -79,7 +73,6 @@ type sourceOCIRepositoryFlags struct {
|
||||
ignorePaths []string
|
||||
provider flags.SourceOCIProvider
|
||||
insecure bool
|
||||
layerSelector string
|
||||
}
|
||||
|
||||
var sourceOCIRepositoryArgs = newSourceOCIFlags()
|
||||
@@ -106,7 +99,6 @@ func init() {
|
||||
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.verifyOIDCIssuer, "verify-issuer", "", "regular expression to use for the OIDC issuer during signature verification")
|
||||
createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)")
|
||||
createSourceOCIRepositoryCmd.Flags().BoolVar(&sourceOCIRepositoryArgs.insecure, "insecure", false, "for when connecting to a non-TLS registries over plain HTTP")
|
||||
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.layerSelector, "layer-selector", "", "the OCI artifact layer selector in the format '<media-type>:<operation>'")
|
||||
|
||||
createSourceCmd.AddCommand(createSourceOCIRepositoryCmd)
|
||||
}
|
||||
@@ -122,11 +114,6 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("--tag, --tag-semver or --digest is required")
|
||||
}
|
||||
|
||||
layerSelector, err := parseLayerSelector(sourceOCIRepositoryArgs.layerSelector)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sourceLabels, err := parseLabels()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -165,7 +152,6 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if tag := sourceOCIRepositoryArgs.tag; tag != "" {
|
||||
repository.Spec.Reference.Tag = tag
|
||||
}
|
||||
repository.Spec.LayerSelector = layerSelector
|
||||
|
||||
if createSourceArgs.fetchTimeout > 0 {
|
||||
repository.Spec.Timeout = &metav1.Duration{Duration: createSourceArgs.fetchTimeout}
|
||||
@@ -248,28 +234,6 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseLayerSelector(selector string) (*sourcev1.OCILayerSelector, error) {
|
||||
if selector == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
mediaType, operation, found := strings.Cut(selector, ":")
|
||||
if !found || mediaType == "" || operation == "" {
|
||||
return nil, fmt.Errorf("invalid --layer-selector %q: must be in the format '<media-type>:<operation>'", selector)
|
||||
}
|
||||
|
||||
switch operation {
|
||||
case sourcev1.OCILayerExtract, sourcev1.OCILayerCopy:
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid --layer-selector %q: operation must be %q or %q", selector, sourcev1.OCILayerExtract, sourcev1.OCILayerCopy)
|
||||
}
|
||||
|
||||
return &sourcev1.OCILayerSelector{
|
||||
MediaType: mediaType,
|
||||
Operation: operation,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func upsertOCIRepository(ctx context.Context, kubeClient client.Client,
|
||||
ociRepository *sourcev1.OCIRepository) (types.NamespacedName, error) {
|
||||
namespacedName := types.NamespacedName{
|
||||
|
||||
@@ -81,21 +81,6 @@ func TestCreateSourceOCI(t *testing.T) {
|
||||
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --verify-provider=cosign --verify-secret-ref=cosign-pub --export",
|
||||
assertFunc: assertGoldenFile("./testdata/oci/export_with_verify_secret.golden"),
|
||||
},
|
||||
{
|
||||
name: "export manifest with layer selector",
|
||||
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --layer-selector=application/vnd.cncf.helm.chart.content.v1.tar+gzip:copy --export",
|
||||
assertFunc: assertGoldenFile("./testdata/oci/export_with_layer_selector.golden"),
|
||||
},
|
||||
{
|
||||
name: "invalid layer selector operation",
|
||||
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --layer-selector=application/vnd.cncf.helm.chart.content.v1.tar+gzip:move --export",
|
||||
assertFunc: assertError("invalid --layer-selector \"application/vnd.cncf.helm.chart.content.v1.tar+gzip:move\": operation must be \"extract\" or \"copy\""),
|
||||
},
|
||||
{
|
||||
name: "invalid layer selector format",
|
||||
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --layer-selector=application/vnd.cncf.helm.chart.content.v1.tar+gzip --export",
|
||||
assertFunc: assertError("invalid --layer-selector \"application/vnd.cncf.helm.chart.content.v1.tar+gzip\": must be in the format '<media-type>:<operation>'"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -270,36 +270,3 @@ func createObjectFromFile(objectFile string, templateValues map[string]string, t
|
||||
|
||||
return clientObjects
|
||||
}
|
||||
|
||||
// TestDiffKustomizationDriftIgnoreRules tests `flux diff ks` with drift ignore
|
||||
// rules. A service with a drifted port is pre-applied to the cluster, and the
|
||||
// kustomization specifies driftIgnoreRules that ignore /spec/ports on Services.
|
||||
// The diff should not show the service as drifted.
|
||||
func TestDiffKustomizationDriftIgnoreRules(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
setupTestNamespace(tmpl["fluxns"], t)
|
||||
|
||||
b, _ := build.NewBuilder("podinfo", "", build.WithClientConfig(kubeconfigArgs, kubeclientOptions))
|
||||
resourceManager, err := b.Manager()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Pre-apply the drifted service (port 9899 instead of 9898) without Flux labels.
|
||||
if _, err := resourceManager.ApplyAll(context.Background(), createObjectFromFile("./testdata/diff-kustomization/drifted-service-no-labels.yaml", tmpl, t), ssa.DefaultApplyOptions()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := cmdTestCase{
|
||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo --progress-bar=false " +
|
||||
"--kustomization-file ./testdata/diff-kustomization/flux-kustomization-drift-ignore.yaml " +
|
||||
"--ignore-not-found" +
|
||||
" -n " + tmpl["fluxns"],
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-drift-ignore.golden"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
|
||||
testEnv.DeleteObjectFile("./testdata/diff-kustomization/drifted-service-no-labels.yaml", tmpl, t)
|
||||
}
|
||||
|
||||
+6
-25
@@ -78,7 +78,7 @@ func init() {
|
||||
getCmd.PersistentFlags().BoolVarP(&getArgs.noHeader, "no-header", "", false, "skip the header when printing the results")
|
||||
getCmd.PersistentFlags().BoolVarP(&getArgs.watch, "watch", "w", false, "After listing/getting the requested object, watch for changes.")
|
||||
getCmd.PersistentFlags().StringVar(&getArgs.statusSelector, "status-selector", "",
|
||||
"specify the status condition name and the desired state to filter the get result, e.g. ready=false or ready!=true")
|
||||
"specify the status condition name and the desired state to filter the get result, e.g. ready=false")
|
||||
getCmd.PersistentFlags().StringVarP(&getArgs.labelSelector, "label-selector", "l", "",
|
||||
"filter objects by label selector")
|
||||
rootCmd.AddCommand(getCmd)
|
||||
@@ -114,11 +114,6 @@ func statusMatches(conditionType, conditionStatus string, conditions []metav1.Co
|
||||
return false
|
||||
}
|
||||
|
||||
func readyStatusMatches(conditionType, conditionStatus string) bool {
|
||||
return strings.EqualFold(conditionType, meta.ReadyCondition) &&
|
||||
strings.EqualFold(conditionStatus, string(metav1.ConditionTrue))
|
||||
}
|
||||
|
||||
func nameColumns(item named, includeNamespace bool, includeKind bool) []string {
|
||||
name := item.GetName()
|
||||
if includeKind {
|
||||
@@ -212,9 +207,6 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if getAll && len(rows) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = printers.TablePrinter(header).Print(cmd.OutOrStdout(), rows)
|
||||
if err != nil {
|
||||
@@ -236,31 +228,20 @@ func namespaceNameOrAny(allNamespaces bool, namespaceName string) string {
|
||||
}
|
||||
|
||||
func getRowsToPrint(getAll bool, list summarisable) ([][]string, error) {
|
||||
filter := func(i int) bool { return true }
|
||||
noFilter := true
|
||||
var conditionType, conditionStatus string
|
||||
if getArgs.statusSelector != "" {
|
||||
// Support both type=status (match) and type!=status (negated match).
|
||||
// "!=" must be checked first since it also contains "=".
|
||||
separator := "="
|
||||
filter = func(i int) bool {
|
||||
return list.statusSelectorMatches(i, conditionType, conditionStatus)
|
||||
}
|
||||
if strings.Contains(getArgs.statusSelector, "!=") {
|
||||
separator = "!="
|
||||
filter = func(i int) bool {
|
||||
return !list.statusSelectorMatches(i, conditionType, conditionStatus)
|
||||
}
|
||||
}
|
||||
parts := strings.SplitN(getArgs.statusSelector, separator, 2)
|
||||
parts := strings.SplitN(getArgs.statusSelector, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("expected status selector in type=status or type!=status format, but found: %s", getArgs.statusSelector)
|
||||
return nil, fmt.Errorf("expected status selector in type=status format, but found: %s", getArgs.statusSelector)
|
||||
}
|
||||
conditionType = parts[0]
|
||||
conditionStatus = parts[1]
|
||||
noFilter = false
|
||||
}
|
||||
var rows [][]string
|
||||
for i := 0; i < list.len(); i++ {
|
||||
if filter(i) {
|
||||
if noFilter || list.statusSelectorMatches(i, conditionType, conditionStatus) {
|
||||
row := list.summariseItem(i, getArgs.allNamespaces, getAll)
|
||||
rows = append(rows, row)
|
||||
}
|
||||
|
||||
@@ -92,5 +92,5 @@ func (s alertListAdapter) headers(includeNamespace bool) []string {
|
||||
}
|
||||
|
||||
func (s alertListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
|
||||
return readyStatusMatches(conditionType, conditionStatus)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -88,5 +88,5 @@ func (s alertProviderListAdapter) headers(includeNamespace bool) []string {
|
||||
}
|
||||
|
||||
func (s alertProviderListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
|
||||
return readyStatusMatches(conditionType, conditionStatus)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ var getArtifactGeneratorCmd = &cobra.Command{
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(swapi.GroupVersion.WithKind(swapi.ArtifactGeneratorKind)),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
get := getCommand{
|
||||
apiType: artifactGeneratorType,
|
||||
apiType: receiverType,
|
||||
list: artifactGeneratorListAdapter{&swapi.ArtifactGeneratorList{}},
|
||||
funcMap: make(typeMap),
|
||||
}
|
||||
|
||||
@@ -63,141 +63,6 @@ func Test_GetCmd(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetCmdStatusSelector(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
testEnv.CreateObjectFile("./testdata/get/status_objects.yaml", tmpl, t)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "equal status selector matches one",
|
||||
args: "--status-selector Ready=True",
|
||||
expected: "testdata/get/get_status_ready_true.golden",
|
||||
},
|
||||
{
|
||||
name: "equal status selector matches false",
|
||||
args: "--status-selector Ready=False",
|
||||
expected: "testdata/get/get_status_ready_false.golden",
|
||||
},
|
||||
{
|
||||
name: "not-equal status selector matches all not-true",
|
||||
args: "--status-selector Ready!=True",
|
||||
expected: "testdata/get/get_status_ready_not_true.golden",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "get sources git " + tt.args + " -n " + tmpl["fluxns"],
|
||||
assert: assertGoldenTemplateFile(tt.expected, nil),
|
||||
}
|
||||
|
||||
cmd.runTestCmd(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetCmdStatusSelectorSyntheticReady(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
testEnv.CreateObjectFile("./testdata/get/notification_objects.yaml", tmpl, t)
|
||||
|
||||
commands := []string{
|
||||
"get alerts",
|
||||
"get alert-providers",
|
||||
"get all",
|
||||
}
|
||||
for _, command := range commands {
|
||||
t.Run(command, func(t *testing.T) {
|
||||
unfilteredOutput, err := executeCommand(command + " -n " + tmpl["fluxns"])
|
||||
if err != nil {
|
||||
t.Fatalf("%s failed: %v", command, err)
|
||||
}
|
||||
if unfilteredOutput == "" {
|
||||
t.Fatalf("expected %s output for namespace with notification objects", command)
|
||||
}
|
||||
|
||||
filteredOutput, err := executeCommand(command + " --status-selector Ready=True -n " + tmpl["fluxns"])
|
||||
if err != nil {
|
||||
t.Fatalf("%s with Ready=True status selector failed: %v", command, err)
|
||||
}
|
||||
|
||||
if filteredOutput != unfilteredOutput {
|
||||
t.Fatalf("expected Ready=True filtered output to match unfiltered output:\nfiltered:\n%s\nunfiltered:\n%s", filteredOutput, unfilteredOutput)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetAllCmdStatusSelectorNoMatches(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
testEnv.CreateObjectFile("./testdata/get/status_objects.yaml", tmpl, t)
|
||||
|
||||
cmd := cmdTestCase{
|
||||
args: "get all --status-selector foo=bar -n " + tmpl["fluxns"],
|
||||
assert: assertGoldenValue(""),
|
||||
}
|
||||
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func Test_GetAllCmdStatusSelectorKustomizationOnlyMatches(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
testEnv.CreateObjectFile("./testdata/get/kustomization_only.yaml", tmpl, t)
|
||||
|
||||
unfilteredOutput, err := executeCommand("get all -n " + tmpl["fluxns"])
|
||||
if err != nil {
|
||||
t.Fatalf("get all failed: %v", err)
|
||||
}
|
||||
if unfilteredOutput == "" {
|
||||
t.Fatal("expected get all output for namespace with one Kustomization")
|
||||
}
|
||||
|
||||
filteredOutput, err := executeCommand("get all --status-selector Ready=True -n " + tmpl["fluxns"])
|
||||
if err != nil {
|
||||
t.Fatalf("get all with matching status selector failed: %v", err)
|
||||
}
|
||||
|
||||
if filteredOutput != unfilteredOutput {
|
||||
t.Fatalf("expected filtered output to match unfiltered output:\nfiltered:\n%s\nunfiltered:\n%s", filteredOutput, unfilteredOutput)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetAllCmdStatusSelectorKustomizationOnlyNoMatch(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
testEnv.CreateObjectFile("./testdata/get/kustomization_only.yaml", tmpl, t)
|
||||
|
||||
emptyNamespace := allocateNamespace("empty")
|
||||
setupTestNamespace(emptyNamespace, t)
|
||||
|
||||
emptyOutput, err := executeCommand("get all -n " + emptyNamespace)
|
||||
if err != nil {
|
||||
t.Fatalf("get all in empty namespace failed: %v", err)
|
||||
}
|
||||
|
||||
filteredOutput, err := executeCommand("get all --status-selector Ready=False -n " + tmpl["fluxns"])
|
||||
if err != nil {
|
||||
t.Fatalf("get all with non-matching status selector failed: %v", err)
|
||||
}
|
||||
|
||||
if filteredOutput != emptyOutput {
|
||||
t.Fatalf("expected filtered output to match empty namespace output:\nfiltered:\n%s\nempty namespace:\n%s", filteredOutput, emptyOutput)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetCmdErrors(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
@@ -219,16 +84,6 @@ func Test_GetCmdErrors(t *testing.T) {
|
||||
args: "get helmrelease -n " + tmpl["fluxns"],
|
||||
assert: assertError(fmt.Sprintf("no HelmRelease objects found in \"%s\" namespace", tmpl["fluxns"])),
|
||||
},
|
||||
{
|
||||
name: "no artifact generators found in namespace",
|
||||
args: "get artifact generators -n " + tmpl["fluxns"],
|
||||
assert: assertError(fmt.Sprintf("no ArtifactGenerator objects found in \"%s\" namespace", tmpl["fluxns"])),
|
||||
},
|
||||
{
|
||||
name: "malformed status selector",
|
||||
args: "get sources git --status-selector Ready -n " + tmpl["fluxns"],
|
||||
assert: assertError("expected status selector in type=status or type!=status format, but found: Ready"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDuUiEMA0
|
||||
eUvKlmOsur2w9FAAAAGAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDF/w86ZQb5qmZtv
|
||||
m1GvyLojiJdhmPtI9hJ9XPcP7HBoAAAAkG2cIOuSVdWInSC0P81ExiorUpiAGOjxxpgvKW
|
||||
VYERfU1zU72Z/c9n1+z/IH5cJOhZ1vlqBO0rubl4s0KQFvY/LKcsc4N0x0uzpqrvcJP4tO
|
||||
9VW8LrMnrPp7b6KVJPsbeSW1SBcUM24aCMzF4/wV03mN/Uqz30s+YgS9SU4Lz8AOkX58xX
|
||||
yAV0gkmndIzZl+Og==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACAWDldtCFdSMXIV1vLwXvRwk4eEmSoDCpxNkcbNph3dCAAAAIjjSDmx40g5
|
||||
sQAAAAtzc2gtZWQyNTUxOQAAACAWDldtCFdSMXIV1vLwXvRwk4eEmSoDCpxNkcbNph3dCA
|
||||
AAAEAGpzSFuLkCNDD49+tysxSFFwdOsRnDj67vDT9bfwoSDhYOV20IV1IxchXW8vBe9HCT
|
||||
h4SZKgMKnE2Rxs2mHd0IAAAABHRlc3QB
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -1 +0,0 @@
|
||||
not a real ssh key
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
apiVersion: image.toolkit.fluxcd.io/v1
|
||||
kind: ImageUpdateAutomation
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
spec:
|
||||
git:
|
||||
checkout:
|
||||
ref:
|
||||
branch: main
|
||||
commit:
|
||||
author:
|
||||
email: flux@example.com
|
||||
name: flux
|
||||
interval: 1m0s
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
apiVersion: image.toolkit.fluxcd.io/v1
|
||||
kind: ImageUpdateAutomation
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
spec:
|
||||
git:
|
||||
checkout:
|
||||
ref:
|
||||
branch: main
|
||||
commit:
|
||||
author:
|
||||
email: flux@example.com
|
||||
name: flux
|
||||
signingKey:
|
||||
secretRef:
|
||||
name: my-key
|
||||
interval: 1m0s
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
apiVersion: image.toolkit.fluxcd.io/v1
|
||||
kind: ImageUpdateAutomation
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
spec:
|
||||
git:
|
||||
checkout:
|
||||
ref:
|
||||
branch: main
|
||||
commit:
|
||||
author:
|
||||
email: flux@example.com
|
||||
name: flux
|
||||
signingKey:
|
||||
secretRef:
|
||||
name: my-deploy-key
|
||||
type: ssh
|
||||
interval: 1m0s
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
@@ -1,14 +0,0 @@
|
||||
► Deployment/default/podinfo created
|
||||
► HorizontalPodAutoscaler/default/podinfo created
|
||||
► Service/default/podinfo drifted
|
||||
|
||||
metadata
|
||||
+ one map entry added:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: podinfo
|
||||
kustomize.toolkit.fluxcd.io/namespace:
|
||||
|
||||
► Secret/default/docker-secret created
|
||||
► Secret/default/secret-basic-auth-stringdata created
|
||||
► Secret/default/podinfo-token-77t89m9b67 created
|
||||
► Secret/default/db-user-pass-bkbd782d2c created
|
||||
@@ -1,18 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: default
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: podinfo
|
||||
ports:
|
||||
- name: http
|
||||
port: 9899
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
- port: 9999
|
||||
targetPort: grpc
|
||||
protocol: TCP
|
||||
name: grpc
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: podinfo
|
||||
spec:
|
||||
interval: 5m0s
|
||||
path: ./kustomize
|
||||
force: true
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: podinfo
|
||||
targetNamespace: default
|
||||
ignore:
|
||||
- paths:
|
||||
- "/spec/ports"
|
||||
target:
|
||||
kind: Service
|
||||
-4
@@ -10,10 +10,6 @@ spec:
|
||||
author:
|
||||
email: fluxcdbot@users.noreply.github.com
|
||||
name: fluxcdbot
|
||||
signingKey:
|
||||
secretRef:
|
||||
name: my-signing-key
|
||||
type: ssh
|
||||
interval: 1m0s
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
|
||||
-4
@@ -67,10 +67,6 @@ spec:
|
||||
email: fluxcdbot@users.noreply.github.com
|
||||
name: fluxcdbot
|
||||
messageTemplate: '{{range .Updated.Images}}{{println .}}{{end}}'
|
||||
signingKey:
|
||||
secretRef:
|
||||
name: my-signing-key
|
||||
type: ssh
|
||||
update:
|
||||
path: ./clusters/my-cluster
|
||||
strategy: Setters
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
NAME REVISION SUSPENDED READY MESSAGE
|
||||
gr-failed False False failed to checkout and determine revision
|
||||
@@ -1,3 +0,0 @@
|
||||
NAME REVISION SUSPENDED READY MESSAGE
|
||||
gr-failed False False failed to checkout and determine revision
|
||||
gr-unknown False Unknown reconciliation in progress
|
||||
@@ -1,2 +0,0 @@
|
||||
NAME REVISION SUSPENDED READY MESSAGE
|
||||
gr-ready main@sha1:696f056d False True Fetched revision: main@sha1:696f056d
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ .fluxns }}
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
interval: 5m
|
||||
path: ./clusters/production
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: podinfo
|
||||
status:
|
||||
lastAppliedRevision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f
|
||||
conditions:
|
||||
- lastTransitionTime: "2021-08-01T04:52:56Z"
|
||||
message: 'Applied revision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f'
|
||||
reason: ReconciliationSucceeded
|
||||
status: "True"
|
||||
type: Ready
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ .fluxns }}
|
||||
---
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta3
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: slack
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
address: https://hooks.slack.com/services/mock
|
||||
channel: alerts
|
||||
type: slack
|
||||
---
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta3
|
||||
kind: Alert
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
eventSeverity: info
|
||||
eventSources:
|
||||
- kind: GitRepository
|
||||
name: '*'
|
||||
- kind: Kustomization
|
||||
name: '*'
|
||||
providerRef:
|
||||
name: slack
|
||||
summary: Slack notification
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ .fluxns }}
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: gr-failed
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
ref:
|
||||
branch: main
|
||||
secretRef:
|
||||
name: flux-system
|
||||
url: ssh://git@github.com/example/repo
|
||||
interval: 5m
|
||||
status:
|
||||
conditions:
|
||||
- lastTransitionTime: "2021-07-20T00:48:16Z"
|
||||
message: 'failed to checkout and determine revision'
|
||||
reason: GitOperationFailed
|
||||
status: "False"
|
||||
type: Ready
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: gr-ready
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
ref:
|
||||
branch: main
|
||||
secretRef:
|
||||
name: flux-system
|
||||
url: ssh://git@github.com/example/repo
|
||||
interval: 5m
|
||||
status:
|
||||
artifact:
|
||||
lastUpdateTime: "2021-08-01T04:28:42Z"
|
||||
revision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f
|
||||
path: "example"
|
||||
url: "example"
|
||||
digest: sha1:696f056df216eea4f9401adbee0ff744d4df390f
|
||||
conditions:
|
||||
- lastTransitionTime: "2021-07-20T00:48:16Z"
|
||||
message: 'Fetched revision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f'
|
||||
reason: GitOperationSucceed
|
||||
status: "True"
|
||||
type: Ready
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: gr-unknown
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
ref:
|
||||
branch: main
|
||||
secretRef:
|
||||
name: flux-system
|
||||
url: ssh://git@github.com/example/repo
|
||||
interval: 5m
|
||||
status:
|
||||
conditions:
|
||||
- lastTransitionTime: "2021-07-20T00:48:16Z"
|
||||
message: 'reconciliation in progress'
|
||||
reason: Progressing
|
||||
status: "Unknown"
|
||||
type: Ready
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: OCIRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m0s
|
||||
layerSelector:
|
||||
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
|
||||
operation: copy
|
||||
ref:
|
||||
tag: 6.3.5
|
||||
url: oci://ghcr.io/stefanprodan/manifests/podinfo
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
Copyright 2026 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var triggerCmd = &cobra.Command{
|
||||
Use: "trigger",
|
||||
Short: "Trigger Flux resources from outside the cluster",
|
||||
Long: `The trigger sub-commands invoke Flux resources from outside the cluster, such as a Receiver's incoming webhook.`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(triggerCmd)
|
||||
}
|
||||
@@ -1,368 +0,0 @@
|
||||
/*
|
||||
Copyright 2026 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/fluxcd/pkg/auth/actionsoidc"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
// genericOIDCReceiver mirrors notificationv1.GenericOIDCReceiver from the
|
||||
// upcoming notification-controller release.
|
||||
// TODO: Replace it with the constant from the api module once the dependency
|
||||
// is bumped.
|
||||
genericOIDCReceiver = "generic-oidc"
|
||||
|
||||
// defaultOIDCAudience mirrors notificationv1.DefaultOIDCAudience.
|
||||
// TODO: Replace it with the constant from the api module once the dependency
|
||||
// is bumped.
|
||||
defaultOIDCAudience = "notification-controller"
|
||||
|
||||
// defaultOIDCTokenEnvVar is the environment variable the OIDC token is read
|
||||
// from when neither --oidc-provider nor --oidc-token is set.
|
||||
defaultOIDCTokenEnvVar = "FLUX_TRIGGER_RECEIVER_OIDC_TOKEN"
|
||||
)
|
||||
|
||||
const (
|
||||
oidcProviderGitHub = "github"
|
||||
oidcProviderForgejo = "forgejo"
|
||||
)
|
||||
|
||||
var triggerReceiverCmd = &cobra.Command{
|
||||
Use: "receiver [name]",
|
||||
Short: "Trigger the webhook of a Receiver",
|
||||
Long: `The trigger receiver command sends a request to the incoming webhook of a Receiver.
|
||||
|
||||
The command computes the webhook path from the Receiver name, namespace and token,
|
||||
appends it to the base URL and sends an HTTP POST request with the given payload.
|
||||
It does not require access to the Kubernetes cluster.`,
|
||||
Example: ` # Trigger a generic Receiver
|
||||
flux trigger receiver my-receiver \
|
||||
--token=my-token \
|
||||
--url=https://flux-webhook.example.com
|
||||
|
||||
# Trigger a generic Receiver with a custom JSON payload
|
||||
flux trigger receiver my-receiver \
|
||||
--token=my-token \
|
||||
--url=https://flux-webhook.example.com \
|
||||
--payload='{"image":"ghcr.io/org/app:v1.0.0"}'
|
||||
|
||||
# Trigger a generic-hmac Receiver
|
||||
flux trigger receiver my-receiver \
|
||||
--type=generic-hmac \
|
||||
--token=my-token \
|
||||
--url=https://flux-webhook.example.com \
|
||||
--payload='{"image":"ghcr.io/org/app:v1.0.0"}'
|
||||
|
||||
# Trigger a generic-oidc Receiver from a GitHub Actions workflow.
|
||||
# The job needs 'permissions: id-token: write'. The OIDC token is fetched
|
||||
# automatically and the receiver token is not used by this type.
|
||||
flux trigger receiver my-receiver \
|
||||
--type=generic-oidc \
|
||||
--oidc-provider=github \
|
||||
--url=https://flux-webhook.example.com
|
||||
|
||||
# Trigger a generic-oidc Receiver from a GitHub Actions workflow with a custom OIDC audience
|
||||
flux trigger receiver my-receiver \
|
||||
--type=generic-oidc \
|
||||
--oidc-provider=github \
|
||||
--oidc-audience=my-flux-instance \
|
||||
--url=https://flux-webhook.example.com
|
||||
|
||||
# Trigger a generic-oidc Receiver from a Forgejo Actions workflow
|
||||
flux trigger receiver my-receiver \
|
||||
--type=generic-oidc \
|
||||
--oidc-provider=forgejo \
|
||||
--url=https://flux-webhook.example.com
|
||||
|
||||
# Trigger a generic-oidc Receiver from a GitLab CI/CD job, reading the OIDC
|
||||
# token from an id_token environment variable defined in the job spec.
|
||||
flux trigger receiver my-receiver \
|
||||
--type=generic-oidc \
|
||||
--oidc-token="${MY_ID_TOKEN}" \
|
||||
--url=https://flux-webhook.example.com
|
||||
|
||||
# Trigger a generic-oidc Receiver from a GitLab CI/CD job, reading the OIDC
|
||||
# token from the default FLUX_TRIGGER_RECEIVER_OIDC_TOKEN environment variable,
|
||||
# e.g. defined as:
|
||||
# job:
|
||||
# id_tokens:
|
||||
# FLUX_TRIGGER_RECEIVER_OIDC_TOKEN:
|
||||
# aud: notification-controller
|
||||
flux trigger receiver my-receiver \
|
||||
--type=generic-oidc \
|
||||
--url=https://flux-webhook.example.com
|
||||
|
||||
# Trigger a Receiver in a specific namespace
|
||||
flux trigger receiver my-receiver -n apps \
|
||||
--token=my-token \
|
||||
--url=https://flux-webhook.example.com
|
||||
|
||||
# Trigger a Receiver in the namespace of the current kubeconfig context
|
||||
flux trigger receiver my-receiver \
|
||||
--ns-follows-kube-context \
|
||||
--token=my-token \
|
||||
--url=https://flux-webhook.example.com`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: triggerReceiverCmdRun,
|
||||
}
|
||||
|
||||
type triggerReceiverFlags struct {
|
||||
token string
|
||||
url string
|
||||
receiverType string
|
||||
oidcProvider string
|
||||
oidcToken string
|
||||
oidcAudience string
|
||||
payload string
|
||||
retries int
|
||||
retryDelay time.Duration
|
||||
}
|
||||
|
||||
var triggerReceiverArgs triggerReceiverFlags
|
||||
|
||||
func init() {
|
||||
triggerReceiverCmd.Flags().StringVar(&triggerReceiverArgs.token, "token", "",
|
||||
"the Receiver token, required for all types except generic-oidc where it must not be set")
|
||||
triggerReceiverCmd.Flags().StringVar(&triggerReceiverArgs.url, "url", "",
|
||||
"the base URL of the notification-controller webhook receiver, may contain a base path")
|
||||
triggerReceiverCmd.Flags().StringVar(&triggerReceiverArgs.receiverType, "type", notificationv1.GenericReceiver,
|
||||
fmt.Sprintf("the Receiver type, one of: %s, %s, %s",
|
||||
notificationv1.GenericReceiver, notificationv1.GenericHMACReceiver, genericOIDCReceiver))
|
||||
triggerReceiverCmd.Flags().StringVar(&triggerReceiverArgs.oidcProvider, "oidc-provider", "",
|
||||
fmt.Sprintf("the OIDC provider to fetch the token from, one of: %s, %s (generic-oidc only, mutually exclusive with --oidc-token)",
|
||||
oidcProviderGitHub, oidcProviderForgejo))
|
||||
triggerReceiverCmd.Flags().StringVar(&triggerReceiverArgs.oidcToken, "oidc-token", "",
|
||||
fmt.Sprintf("the OIDC token to authenticate the request (generic-oidc only, mutually exclusive with --oidc-provider); defaults to the %s environment variable", defaultOIDCTokenEnvVar))
|
||||
triggerReceiverCmd.Flags().StringVar(&triggerReceiverArgs.oidcAudience, "oidc-audience", "",
|
||||
fmt.Sprintf("the audience of the OIDC token to fetch (requires --oidc-provider); defaults to %q", defaultOIDCAudience))
|
||||
triggerReceiverCmd.Flags().StringVar(&triggerReceiverArgs.payload, "payload", "{}",
|
||||
"the JSON payload to send in the request body")
|
||||
triggerReceiverCmd.Flags().IntVar(&triggerReceiverArgs.retries, "retries", 10,
|
||||
"the number of times to retry on connection errors or retryable HTTP status codes (404, 408, 429, 5xx); set to 0 to disable")
|
||||
triggerReceiverCmd.Flags().DurationVar(&triggerReceiverArgs.retryDelay, "retry-delay", 10*time.Second,
|
||||
"the delay between retries")
|
||||
|
||||
triggerCmd.AddCommand(triggerReceiverCmd)
|
||||
}
|
||||
|
||||
func triggerReceiverCmdRun(cmd *cobra.Command, args []string) error {
|
||||
name := args[0]
|
||||
|
||||
if triggerReceiverArgs.url == "" {
|
||||
return fmt.Errorf("--url is required")
|
||||
}
|
||||
|
||||
if err := validateTriggerReceiverArgs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
// For generic-oidc the Receiver has no secretRef, so the webhook path is
|
||||
// salted with an empty token. For all other types the token is required.
|
||||
pathToken := triggerReceiverArgs.token
|
||||
if triggerReceiverArgs.receiverType == genericOIDCReceiver {
|
||||
pathToken = ""
|
||||
}
|
||||
|
||||
receiver := ¬ificationv1.Receiver{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
},
|
||||
}
|
||||
webhookURL := strings.TrimRight(triggerReceiverArgs.url, "/") + receiver.GetWebhookPath(pathToken)
|
||||
|
||||
payload := []byte(triggerReceiverArgs.payload)
|
||||
|
||||
// Compute the request headers once; the auth material does not change between
|
||||
// attempts, so they are applied to a fresh request on each retry.
|
||||
headers := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": fmt.Sprintf("flux/v%s", VERSION),
|
||||
}
|
||||
switch triggerReceiverArgs.receiverType {
|
||||
case notificationv1.GenericReceiver:
|
||||
// No authentication, the payload is sent as-is.
|
||||
case notificationv1.GenericHMACReceiver:
|
||||
mac := hmac.New(sha256.New, []byte(triggerReceiverArgs.token))
|
||||
mac.Write(payload)
|
||||
headers["X-Signature"] = "sha256=" + hex.EncodeToString(mac.Sum(nil))
|
||||
case genericOIDCReceiver:
|
||||
oidcToken, err := resolveOIDCToken(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headers["Authorization"] = "Bearer " + oidcToken
|
||||
}
|
||||
|
||||
// send performs a single attempt. It reports retryable=true for transient
|
||||
// failures (connection errors and retryable HTTP status codes) so the caller
|
||||
// can retry; permanent failures (e.g. authentication or validation errors)
|
||||
// report retryable=false and fail immediately.
|
||||
send := func() (retryable bool, err error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, webhookURL, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to create request: %w", err)
|
||||
}
|
||||
for k, v := range headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("request to %s failed: %w", webhookURL, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
|
||||
statusErr := fmt.Errorf("request to %s failed with status %s", webhookURL, resp.Status)
|
||||
if msg := strings.TrimSpace(string(body)); msg != "" {
|
||||
statusErr = fmt.Errorf("request to %s failed with status %s: %s", webhookURL, resp.Status, msg)
|
||||
}
|
||||
return isRetryableStatus(resp.StatusCode), statusErr
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
logger.Actionf("triggering Receiver %s/%s", *kubeconfigArgs.Namespace, name)
|
||||
for attempt := 0; ; attempt++ {
|
||||
retryable, err := send()
|
||||
if err == nil {
|
||||
logger.Successf("Receiver %s/%s triggered", *kubeconfigArgs.Namespace, name)
|
||||
return nil
|
||||
}
|
||||
if !retryable || attempt >= triggerReceiverArgs.retries {
|
||||
return err
|
||||
}
|
||||
logger.Waitingf("%s; retrying in %s (%d/%d)",
|
||||
err, triggerReceiverArgs.retryDelay, attempt+1, triggerReceiverArgs.retries)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(triggerReceiverArgs.retryDelay):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isRetryableStatus reports whether an HTTP status returned by the webhook
|
||||
// receiver is worth retrying. 404 is included because the Receiver's webhook
|
||||
// path may not be registered yet right after the notification-controller starts
|
||||
// or while the Receiver reconciles.
|
||||
func isRetryableStatus(code int) bool {
|
||||
switch code {
|
||||
case http.StatusNotFound, // 404
|
||||
http.StatusRequestTimeout, // 408
|
||||
http.StatusTooManyRequests, // 429
|
||||
http.StatusInternalServerError, // 500
|
||||
http.StatusBadGateway, // 502
|
||||
http.StatusServiceUnavailable, // 503
|
||||
http.StatusGatewayTimeout: // 504
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// validateTriggerReceiverArgs validates the receiver type and the combination of
|
||||
// token and OIDC flags.
|
||||
func validateTriggerReceiverArgs() error {
|
||||
isOIDC := triggerReceiverArgs.receiverType == genericOIDCReceiver
|
||||
|
||||
switch triggerReceiverArgs.receiverType {
|
||||
case notificationv1.GenericReceiver, notificationv1.GenericHMACReceiver, genericOIDCReceiver:
|
||||
default:
|
||||
return fmt.Errorf("invalid --type %q, must be one of: %s, %s, %s",
|
||||
triggerReceiverArgs.receiverType,
|
||||
notificationv1.GenericReceiver, notificationv1.GenericHMACReceiver, genericOIDCReceiver)
|
||||
}
|
||||
|
||||
if !isOIDC {
|
||||
if triggerReceiverArgs.token == "" {
|
||||
return fmt.Errorf("--token is required for --type=%s", triggerReceiverArgs.receiverType)
|
||||
}
|
||||
if triggerReceiverArgs.oidcProvider != "" || triggerReceiverArgs.oidcToken != "" || triggerReceiverArgs.oidcAudience != "" {
|
||||
return fmt.Errorf("--oidc-provider, --oidc-token and --oidc-audience can only be set for --type=%s", genericOIDCReceiver)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// generic-oidc.
|
||||
if triggerReceiverArgs.token != "" {
|
||||
return fmt.Errorf("--token must not be set for --type=%s, the Receiver of this type has no secret", genericOIDCReceiver)
|
||||
}
|
||||
if triggerReceiverArgs.oidcProvider != "" && triggerReceiverArgs.oidcToken != "" {
|
||||
return fmt.Errorf("--oidc-provider and --oidc-token are mutually exclusive")
|
||||
}
|
||||
if triggerReceiverArgs.oidcProvider != "" {
|
||||
switch triggerReceiverArgs.oidcProvider {
|
||||
case oidcProviderGitHub, oidcProviderForgejo:
|
||||
default:
|
||||
return fmt.Errorf("invalid --oidc-provider %q, must be one of: %s, %s",
|
||||
triggerReceiverArgs.oidcProvider, oidcProviderGitHub, oidcProviderForgejo)
|
||||
}
|
||||
}
|
||||
if triggerReceiverArgs.oidcAudience != "" && triggerReceiverArgs.oidcProvider == "" {
|
||||
return fmt.Errorf("--oidc-audience can only be set together with --oidc-provider")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// resolveOIDCToken returns the OIDC token used to authenticate the request,
|
||||
// either by fetching it from the configured provider or by reading it from the
|
||||
// --oidc-token flag or the default environment variable.
|
||||
func resolveOIDCToken(ctx context.Context) (string, error) {
|
||||
switch {
|
||||
case triggerReceiverArgs.oidcProvider != "":
|
||||
audience := triggerReceiverArgs.oidcAudience
|
||||
if audience == "" {
|
||||
audience = defaultOIDCAudience
|
||||
}
|
||||
// GitHub and Forgejo Actions expose the same token request endpoint.
|
||||
token, err := actionsoidc.FetchToken(ctx, audience)
|
||||
return token, err
|
||||
case triggerReceiverArgs.oidcToken != "":
|
||||
return triggerReceiverArgs.oidcToken, nil
|
||||
default:
|
||||
token := os.Getenv(defaultOIDCTokenEnvVar)
|
||||
if token == "" {
|
||||
return "", fmt.Errorf("no OIDC token provided: set --oidc-provider, --oidc-token or the %s environment variable", defaultOIDCTokenEnvVar)
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
}
|
||||
@@ -1,353 +0,0 @@
|
||||
//go:build unit
|
||||
// +build unit
|
||||
|
||||
/*
|
||||
Copyright 2026 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1"
|
||||
)
|
||||
|
||||
// resetTriggerReceiverArgs restores the package-global flags to their defaults
|
||||
// so tests do not leak state into each other.
|
||||
func resetTriggerReceiverArgs(t *testing.T) {
|
||||
t.Helper()
|
||||
prev := triggerReceiverArgs
|
||||
prevNS := kubeconfigArgs.Namespace
|
||||
prevTimeout := rootArgs.timeout
|
||||
|
||||
triggerReceiverArgs = triggerReceiverFlags{
|
||||
receiverType: notificationv1.GenericReceiver,
|
||||
payload: "{}",
|
||||
}
|
||||
ns := "default"
|
||||
kubeconfigArgs.Namespace = &ns
|
||||
rootArgs.timeout = time.Minute
|
||||
|
||||
t.Cleanup(func() {
|
||||
triggerReceiverArgs = prev
|
||||
kubeconfigArgs.Namespace = prevNS
|
||||
rootArgs.timeout = prevTimeout
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidateTriggerReceiverArgs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args triggerReceiverFlags
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "generic requires token",
|
||||
args: triggerReceiverFlags{receiverType: notificationv1.GenericReceiver},
|
||||
wantErr: "--token is required",
|
||||
},
|
||||
{
|
||||
name: "generic with token is valid",
|
||||
args: triggerReceiverFlags{receiverType: notificationv1.GenericReceiver, token: "t"},
|
||||
},
|
||||
{
|
||||
name: "generic rejects oidc flags",
|
||||
args: triggerReceiverFlags{receiverType: notificationv1.GenericReceiver, token: "t", oidcProvider: "github"},
|
||||
wantErr: "can only be set for --type=generic-oidc",
|
||||
},
|
||||
{
|
||||
name: "hmac with token is valid",
|
||||
args: triggerReceiverFlags{receiverType: notificationv1.GenericHMACReceiver, token: "t"},
|
||||
},
|
||||
{
|
||||
name: "unknown type",
|
||||
args: triggerReceiverFlags{receiverType: "bogus", token: "t"},
|
||||
wantErr: "invalid --type",
|
||||
},
|
||||
{
|
||||
name: "oidc rejects token",
|
||||
args: triggerReceiverFlags{receiverType: genericOIDCReceiver, token: "t"},
|
||||
wantErr: "--token must not be set",
|
||||
},
|
||||
{
|
||||
name: "oidc provider and token mutually exclusive",
|
||||
args: triggerReceiverFlags{receiverType: genericOIDCReceiver, oidcProvider: "github", oidcToken: "x"},
|
||||
wantErr: "mutually exclusive",
|
||||
},
|
||||
{
|
||||
name: "oidc invalid provider",
|
||||
args: triggerReceiverFlags{receiverType: genericOIDCReceiver, oidcProvider: "gitlab"},
|
||||
wantErr: "invalid --oidc-provider",
|
||||
},
|
||||
{
|
||||
name: "oidc audience requires provider",
|
||||
args: triggerReceiverFlags{receiverType: genericOIDCReceiver, oidcToken: "x", oidcAudience: "aud"},
|
||||
wantErr: "--oidc-audience can only be set together with --oidc-provider",
|
||||
},
|
||||
{
|
||||
name: "oidc with provider is valid",
|
||||
args: triggerReceiverFlags{receiverType: genericOIDCReceiver, oidcProvider: "forgejo", oidcAudience: "aud"},
|
||||
},
|
||||
{
|
||||
name: "oidc with token is valid",
|
||||
args: triggerReceiverFlags{receiverType: genericOIDCReceiver, oidcToken: "x"},
|
||||
},
|
||||
{
|
||||
name: "oidc without provider or token is valid (env fallback)",
|
||||
args: triggerReceiverFlags{receiverType: genericOIDCReceiver},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
resetTriggerReceiverArgs(t)
|
||||
triggerReceiverArgs = tt.args
|
||||
|
||||
err := validateTriggerReceiverArgs()
|
||||
if tt.wantErr == "" {
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatalf("expected error containing %q, got nil", tt.wantErr)
|
||||
}
|
||||
if !strings.Contains(err.Error(), tt.wantErr) {
|
||||
t.Fatalf("expected error containing %q, got: %v", tt.wantErr, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTriggerReceiverRun(t *testing.T) {
|
||||
const name = "my-receiver"
|
||||
const ns = "default"
|
||||
const token = "my-token"
|
||||
|
||||
expectedPath := (¬ificationv1.Receiver{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns},
|
||||
}).GetWebhookPath(token)
|
||||
expectedOIDCPath := (¬ificationv1.Receiver{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns},
|
||||
}).GetWebhookPath("")
|
||||
|
||||
t.Run("generic sends payload with default headers", func(t *testing.T) {
|
||||
resetTriggerReceiverArgs(t)
|
||||
var got *http.Request
|
||||
var gotBody string
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
got = r
|
||||
b, _ := io.ReadAll(r.Body)
|
||||
gotBody = string(b)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
triggerReceiverArgs.url = srv.URL
|
||||
triggerReceiverArgs.token = token
|
||||
triggerReceiverArgs.payload = `{"hello":"world"}`
|
||||
|
||||
if err := triggerReceiverCmdRun(nil, []string{name}); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if got.URL.Path != expectedPath {
|
||||
t.Errorf("path = %q, want %q", got.URL.Path, expectedPath)
|
||||
}
|
||||
if got.Method != http.MethodPost {
|
||||
t.Errorf("method = %q, want POST", got.Method)
|
||||
}
|
||||
if ct := got.Header.Get("Content-Type"); ct != "application/json" {
|
||||
t.Errorf("Content-Type = %q, want application/json", ct)
|
||||
}
|
||||
if ua := got.Header.Get("User-Agent"); !strings.HasPrefix(ua, "flux/v") {
|
||||
t.Errorf("User-Agent = %q, want prefix flux/v", ua)
|
||||
}
|
||||
if gotBody != `{"hello":"world"}` {
|
||||
t.Errorf("body = %q", gotBody)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("generic-hmac sets X-Signature", func(t *testing.T) {
|
||||
resetTriggerReceiverArgs(t)
|
||||
var sig string
|
||||
payload := `{"a":1}`
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
sig = r.Header.Get("X-Signature")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
triggerReceiverArgs.url = srv.URL
|
||||
triggerReceiverArgs.token = token
|
||||
triggerReceiverArgs.receiverType = notificationv1.GenericHMACReceiver
|
||||
triggerReceiverArgs.payload = payload
|
||||
|
||||
if err := triggerReceiverCmdRun(nil, []string{name}); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
mac := hmac.New(sha256.New, []byte(token))
|
||||
mac.Write([]byte(payload))
|
||||
want := "sha256=" + hex.EncodeToString(mac.Sum(nil))
|
||||
if sig != want {
|
||||
t.Errorf("X-Signature = %q, want %q", sig, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("generic-oidc with --oidc-token sets bearer and empty-token path", func(t *testing.T) {
|
||||
resetTriggerReceiverArgs(t)
|
||||
var auth, path string
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
auth = r.Header.Get("Authorization")
|
||||
path = r.URL.Path
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
triggerReceiverArgs.url = srv.URL
|
||||
triggerReceiverArgs.receiverType = genericOIDCReceiver
|
||||
triggerReceiverArgs.oidcToken = "the-oidc-token"
|
||||
|
||||
if err := triggerReceiverCmdRun(nil, []string{name}); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if auth != "Bearer the-oidc-token" {
|
||||
t.Errorf("Authorization = %q, want Bearer the-oidc-token", auth)
|
||||
}
|
||||
if path != expectedOIDCPath {
|
||||
t.Errorf("path = %q, want %q (empty token salt)", path, expectedOIDCPath)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("generic-oidc reads default env var", func(t *testing.T) {
|
||||
resetTriggerReceiverArgs(t)
|
||||
t.Setenv(defaultOIDCTokenEnvVar, "env-oidc-token")
|
||||
var auth string
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
auth = r.Header.Get("Authorization")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
triggerReceiverArgs.url = srv.URL
|
||||
triggerReceiverArgs.receiverType = genericOIDCReceiver
|
||||
|
||||
if err := triggerReceiverCmdRun(nil, []string{name}); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if auth != "Bearer env-oidc-token" {
|
||||
t.Errorf("Authorization = %q, want Bearer env-oidc-token", auth)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("non-2xx response is an error", func(t *testing.T) {
|
||||
resetTriggerReceiverArgs(t)
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = w.Write([]byte("nope"))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
triggerReceiverArgs.url = srv.URL
|
||||
triggerReceiverArgs.token = token
|
||||
|
||||
err := triggerReceiverCmdRun(nil, []string{name})
|
||||
if err == nil || !strings.Contains(err.Error(), "nope") {
|
||||
t.Fatalf("expected error containing response body, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("retries on retryable status then succeeds", func(t *testing.T) {
|
||||
resetTriggerReceiverArgs(t)
|
||||
var attempts int32
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if atomic.AddInt32(&attempts, 1) < 3 {
|
||||
w.WriteHeader(http.StatusNotFound) // transient: path not registered yet
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
triggerReceiverArgs.url = srv.URL
|
||||
triggerReceiverArgs.token = token
|
||||
triggerReceiverArgs.retries = 5
|
||||
triggerReceiverArgs.retryDelay = time.Millisecond
|
||||
|
||||
if err := triggerReceiverCmdRun(nil, []string{name}); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if got := atomic.LoadInt32(&attempts); got != 3 {
|
||||
t.Errorf("attempts = %d, want 3", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("does not retry non-retryable status", func(t *testing.T) {
|
||||
resetTriggerReceiverArgs(t)
|
||||
var attempts int32
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
atomic.AddInt32(&attempts, 1)
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
triggerReceiverArgs.url = srv.URL
|
||||
triggerReceiverArgs.token = token
|
||||
triggerReceiverArgs.retries = 5
|
||||
triggerReceiverArgs.retryDelay = time.Millisecond
|
||||
|
||||
if err := triggerReceiverCmdRun(nil, []string{name}); err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
if got := atomic.LoadInt32(&attempts); got != 1 {
|
||||
t.Errorf("attempts = %d, want 1 (no retry on 403)", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("returns error after exhausting retries", func(t *testing.T) {
|
||||
resetTriggerReceiverArgs(t)
|
||||
var attempts int32
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
atomic.AddInt32(&attempts, 1)
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
triggerReceiverArgs.url = srv.URL
|
||||
triggerReceiverArgs.token = token
|
||||
triggerReceiverArgs.retries = 2
|
||||
triggerReceiverArgs.retryDelay = time.Millisecond
|
||||
|
||||
if err := triggerReceiverCmdRun(nil, []string{name}); err == nil {
|
||||
t.Fatal("expected error after exhausting retries")
|
||||
}
|
||||
if got := atomic.LoadInt32(&attempts); got != 3 {
|
||||
t.Errorf("attempts = %d, want 3 (1 initial + 2 retries)", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -6,61 +6,61 @@ go 1.26.0
|
||||
replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver/v3 v3.5.0
|
||||
github.com/Masterminds/semver/v3 v3.4.0
|
||||
github.com/ProtonMail/go-crypto v1.4.1
|
||||
github.com/briandowns/spinner v1.23.2
|
||||
github.com/cyphar/filepath-securejoin v0.6.1
|
||||
github.com/distribution/distribution/v3 v3.1.1
|
||||
github.com/fluxcd/cli-utils v1.2.2
|
||||
github.com/fluxcd/go-git-providers v0.27.0
|
||||
github.com/fluxcd/helm-controller/api v1.6.1
|
||||
github.com/fluxcd/image-automation-controller/api v1.2.1
|
||||
github.com/fluxcd/image-reflector-controller/api v1.2.1
|
||||
github.com/fluxcd/kustomize-controller/api v1.9.1
|
||||
github.com/fluxcd/notification-controller/api v1.9.1
|
||||
github.com/fluxcd/pkg/apis/event v0.27.1
|
||||
github.com/fluxcd/pkg/apis/meta v1.30.1
|
||||
github.com/fluxcd/pkg/auth v0.54.1
|
||||
github.com/fluxcd/pkg/chartutil v1.27.1
|
||||
github.com/fluxcd/cli-utils v1.2.0
|
||||
github.com/fluxcd/go-git-providers v0.26.0
|
||||
github.com/fluxcd/helm-controller/api v1.5.5
|
||||
github.com/fluxcd/image-automation-controller/api v1.1.4
|
||||
github.com/fluxcd/image-reflector-controller/api v1.1.2
|
||||
github.com/fluxcd/kustomize-controller/api v1.8.5
|
||||
github.com/fluxcd/notification-controller/api v1.8.4
|
||||
github.com/fluxcd/pkg/apis/event v0.26.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.27.0
|
||||
github.com/fluxcd/pkg/auth v0.45.0
|
||||
github.com/fluxcd/pkg/chartutil v1.24.0
|
||||
github.com/fluxcd/pkg/envsubst v1.7.0
|
||||
github.com/fluxcd/pkg/git v0.52.0
|
||||
github.com/fluxcd/pkg/kustomize v1.35.1
|
||||
github.com/fluxcd/pkg/oci v0.68.0
|
||||
github.com/fluxcd/pkg/runtime v0.110.1
|
||||
github.com/fluxcd/pkg/git v0.49.0
|
||||
github.com/fluxcd/pkg/kustomize v1.32.0
|
||||
github.com/fluxcd/pkg/oci v0.66.0
|
||||
github.com/fluxcd/pkg/runtime v0.106.0
|
||||
github.com/fluxcd/pkg/sourceignore v0.18.0
|
||||
github.com/fluxcd/pkg/ssa v0.76.1
|
||||
github.com/fluxcd/pkg/ssa v0.74.0
|
||||
github.com/fluxcd/pkg/ssh v0.25.0
|
||||
github.com/fluxcd/pkg/tar v1.2.0
|
||||
github.com/fluxcd/pkg/version v0.16.0
|
||||
github.com/fluxcd/source-controller/api v1.9.1
|
||||
github.com/fluxcd/source-watcher/api/v2 v2.2.1
|
||||
github.com/fluxcd/pkg/version v0.15.0
|
||||
github.com/fluxcd/source-controller/api v1.8.5
|
||||
github.com/fluxcd/source-watcher/api/v2 v2.1.1
|
||||
github.com/go-git/go-git/v5 v5.19.1
|
||||
github.com/go-logr/logr v1.4.3
|
||||
github.com/gonvenience/bunt v1.4.2
|
||||
github.com/gonvenience/ytbx v1.4.7
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/go-containerregistry v0.21.6
|
||||
github.com/google/go-containerregistry v0.21.5
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8
|
||||
github.com/homeport/dyff v1.10.2
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||
github.com/manifoldco/promptui v0.9.0
|
||||
github.com/mattn/go-shellwords v1.0.13
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
github.com/notaryproject/notation-go v1.3.2
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/onsi/gomega v1.42.1
|
||||
github.com/onsi/gomega v1.40.0
|
||||
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
|
||||
github.com/spf13/cobra v1.10.2
|
||||
golang.org/x/crypto v0.53.0
|
||||
golang.org/x/term v0.44.0
|
||||
golang.org/x/text v0.38.0
|
||||
k8s.io/api v0.36.2
|
||||
k8s.io/apiextensions-apiserver v0.36.2
|
||||
k8s.io/apimachinery v0.36.2
|
||||
k8s.io/cli-runtime v0.36.2
|
||||
k8s.io/client-go v0.36.2
|
||||
k8s.io/kubectl v0.36.2
|
||||
sigs.k8s.io/controller-runtime v0.24.1
|
||||
golang.org/x/crypto v0.50.0
|
||||
golang.org/x/term v0.42.0
|
||||
golang.org/x/text v0.36.0
|
||||
k8s.io/api v0.36.0
|
||||
k8s.io/apiextensions-apiserver v0.36.0
|
||||
k8s.io/apimachinery v0.36.0
|
||||
k8s.io/cli-runtime v0.36.0
|
||||
k8s.io/client-go v0.36.0
|
||||
k8s.io/kubectl v0.36.0
|
||||
sigs.k8s.io/controller-runtime v0.24.0
|
||||
sigs.k8s.io/kustomize/api v0.21.1
|
||||
sigs.k8s.io/kustomize/kyaml v0.21.1
|
||||
sigs.k8s.io/yaml v1.6.0
|
||||
@@ -70,16 +70,16 @@ require (
|
||||
cloud.google.com/go/auth v0.20.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
code.gitea.io/sdk/gitea v0.25.1 // indirect
|
||||
code.gitea.io/sdk/gitea v0.23.2 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/42wim/httpsig v1.2.4 // indirect
|
||||
github.com/42wim/httpsig v1.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.1.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect
|
||||
github.com/BurntSushi/toml v1.6.0 // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
@@ -110,13 +110,14 @@ require (
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.7.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/cli v29.4.3+incompatible // indirect
|
||||
github.com/docker/cli v29.4.0+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.5 // indirect
|
||||
github.com/docker/go-events v0.0.0-20250808211157-605354379745 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
@@ -125,13 +126,13 @@ require (
|
||||
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.10.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.19.1 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.18.0 // indirect
|
||||
github.com/fluxcd/pkg/cache v0.14.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.2 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
||||
github.com/go-errors/errors v1.5.1 // indirect
|
||||
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||
@@ -141,18 +142,7 @@ require (
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/cmdutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/conv v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/jsonname v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/loading v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/mangling v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/netutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/gonvenience/idem v0.0.2 // indirect
|
||||
@@ -173,22 +163,24 @@ require (
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-version v1.9.0 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
|
||||
github.com/hiddeco/sshsig v0.2.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v1.4.0 // indirect
|
||||
github.com/klauspost/compress v1.18.6 // indirect
|
||||
github.com/klauspost/compress v1.18.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/hashstructure v1.1.0 // indirect
|
||||
@@ -224,12 +216,13 @@ require (
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
github.com/vbatts/tar-split v0.12.2 // indirect
|
||||
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 // indirect
|
||||
github.com/wI2L/jsondiff v0.6.1 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
gitlab.com/gitlab-org/api/client-go v1.46.0 // indirect
|
||||
gitlab.com/gitlab-org/api/client-go v1.29.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 // indirect
|
||||
go.opentelemetry.io/contrib/exporters/autoexport v0.67.0 // indirect
|
||||
@@ -255,10 +248,10 @@ require (
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/net v0.56.0 // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/sync v0.21.0 // indirect
|
||||
golang.org/x/sys v0.46.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/api v0.278.0 // indirect
|
||||
@@ -271,12 +264,12 @@ require (
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
helm.sh/helm/v4 v4.2.2 // indirect
|
||||
k8s.io/component-base v0.36.2 // indirect
|
||||
helm.sh/helm/v4 v4.1.4 // indirect
|
||||
k8s.io/component-base v0.36.0 // indirect
|
||||
k8s.io/klog/v2 v2.140.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20260603220949-865597e52e25 // indirect
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect
|
||||
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect
|
||||
)
|
||||
|
||||
@@ -4,12 +4,12 @@ cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIi
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
||||
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
|
||||
code.gitea.io/sdk/gitea v0.25.1 h1:yywxWwoV+SdjHtbC6unBiXojWdZOtoHuGhEazEXeWuE=
|
||||
code.gitea.io/sdk/gitea v0.25.1/go.mod h1:uDFWYBU8dgZsgOHwe6C/6olxvf8FHguNB3wW1i83fgg=
|
||||
code.gitea.io/sdk/gitea v0.23.2 h1:iJB1FDmLegwfwjX8gotBDHdPSbk/ZR8V9VmEJaVsJYg=
|
||||
code.gitea.io/sdk/gitea v0.23.2/go.mod h1:yyF5+GhljqvA30sRDreoyHILruNiy4ASufugzYg0VHM=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/42wim/httpsig v1.2.4 h1:mI5bH0nm4xn7K18fo1K3okNDRq8CCJ0KbBYWyA6r8lU=
|
||||
github.com/42wim/httpsig v1.2.4/go.mod h1:yKsYfSyTBEohkPik224QPFylmzEBtda/kjyIAJjh3ps=
|
||||
github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs=
|
||||
github.com/42wim/httpsig v1.2.3/go.mod h1:nZq9OlYKDrUBhptd77IHx4/sZZD+IxTBADvAPI9G/EM=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1 h1:jHb/wfvRikGdxMXYV3QG/SzUOPYN9KEUUuC0Yd0/vC0=
|
||||
@@ -26,8 +26,9 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontai
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0/go.mod h1:TmlMW4W5OvXOmOyKNnor8nlMMiO1ctIyzmHme/VHsrA=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/Azure/go-ntlmssp v0.1.1 h1:l+FM/EEMb0U9QZE7mKNEDw5Mu3mFiaa2GKOoTSsNDPw=
|
||||
github.com/Azure/go-ntlmssp v0.1.1/go.mod h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
|
||||
@@ -36,8 +37,8 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk
|
||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE=
|
||||
github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
@@ -123,6 +124,8 @@ github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY=
|
||||
github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
|
||||
github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
|
||||
github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA=
|
||||
@@ -146,8 +149,8 @@ github.com/distribution/distribution/v3 v3.1.1 h1:KUbk7C8CfaLXy8kbf/hGq9cad/wCoL
|
||||
github.com/distribution/distribution/v3 v3.1.1/go.mod h1:d7lXwZpph0bVcOj4Aqn0nMrWHIwRQGdiV5TLeI+/w6Y=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v29.4.3+incompatible h1:u+UliYm2J/rYrIh2FqHQg32neRG8GjbvNuwQRTzGspU=
|
||||
github.com/docker/cli v29.4.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM=
|
||||
github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY=
|
||||
github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
|
||||
github.com/docker/go-events v0.0.0-20250808211157-605354379745 h1:yOn6Ze6IbYI/KAw2lw/83ELYvZh6hvsygTVkD0dzMC4=
|
||||
@@ -166,70 +169,70 @@ github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjT
|
||||
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
|
||||
github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
|
||||
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fluxcd/cli-utils v1.2.2 h1:adDOmwE+LSwTzmYUaoEFPblruOuaQEKAg1ZNTmPJObE=
|
||||
github.com/fluxcd/cli-utils v1.2.2/go.mod h1:FsghNGY+3Sr70c0FOB7I5So0kzoYVdvQ8GTid3XXVWM=
|
||||
github.com/fluxcd/cli-utils v1.2.0 h1:1o07pXTMxJ/XJ1GpAbLtjdXwfCUMq4Ku1OcnvJHLohI=
|
||||
github.com/fluxcd/cli-utils v1.2.0/go.mod h1:d5HdTDdR5sCbsIbgtOQ7x7srKYwYeZORU6CD2yn4j/M=
|
||||
github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg=
|
||||
github.com/fluxcd/gitkit v0.6.0/go.mod h1:svOHuKi0fO9HoawdK4HfHAJJseZDHHjk7I3ihnCIqNo=
|
||||
github.com/fluxcd/go-git-providers v0.27.0 h1:ll7qL4xYW6JtlcdRCpLYKQPqqXNs3je+J7xyEAF+fgw=
|
||||
github.com/fluxcd/go-git-providers v0.27.0/go.mod h1:l1ODx/sh0/pJ0LM8K3HJHhiMBR9dxaJcNUazT+I7VRM=
|
||||
github.com/fluxcd/helm-controller/api v1.6.1 h1:h48BXjp/hvN8pIst5KfU++3oyLlO2OpigXfclSj7NW4=
|
||||
github.com/fluxcd/helm-controller/api v1.6.1/go.mod h1:CaI5bHedusLcXYj1+pkd4RkSE8TtiEHI3ReHNsUySbg=
|
||||
github.com/fluxcd/image-automation-controller/api v1.2.1 h1:RgJzncZf/aZpGlySOkqztOoDaQjm0afyFzMC4gTJbjw=
|
||||
github.com/fluxcd/image-automation-controller/api v1.2.1/go.mod h1:LmGIeIsxdrmzJbXpexrRUaBLjJCPrNY3XhaDu6osKQY=
|
||||
github.com/fluxcd/image-reflector-controller/api v1.2.1 h1:MfaLweSrJjR7YTahHKB8xPhx0Iq2KvcNPsboSjYLRGM=
|
||||
github.com/fluxcd/image-reflector-controller/api v1.2.1/go.mod h1:1dZKQPfQdjdCYWOUA2UUYlF9+xhfosfsGgWaNI875Ts=
|
||||
github.com/fluxcd/kustomize-controller/api v1.9.1 h1:QiGAlrjJh8RzderBavB6Z8MoJgzU0SWi0pK3+uYhZSw=
|
||||
github.com/fluxcd/kustomize-controller/api v1.9.1/go.mod h1:utxc483AZDArFeBW5XeD/wiD0+E1oQbPi3b/TZc+v10=
|
||||
github.com/fluxcd/notification-controller/api v1.9.1 h1:XGg9Muj0x/t5wmeqZh/8ZAgTpz4NIylP0wIhNI3cN+M=
|
||||
github.com/fluxcd/notification-controller/api v1.9.1/go.mod h1:TpGuKZjeo2yXXKZ/X3oPIxMm/YGFQkccO31CDeXzrv4=
|
||||
github.com/fluxcd/go-git-providers v0.26.0 h1:0DUsXc1nS9Fe4n8tXSEUCGemWzHShd66gmotayDPekw=
|
||||
github.com/fluxcd/go-git-providers v0.26.0/go.mod h1:VJDKUOhZwNAIqDF5iPtIpTr/annsDbKMkPpWiDMBdpo=
|
||||
github.com/fluxcd/helm-controller/api v1.5.5 h1:xQA/9gbifMvZPGhSNKHsrkq829dI/yTBASVdYp9/s4Y=
|
||||
github.com/fluxcd/helm-controller/api v1.5.5/go.mod h1:lTgeUmtVYExMKp7mRDncsr4JwHTz3LFtLjRJZeR98lI=
|
||||
github.com/fluxcd/image-automation-controller/api v1.1.4 h1:i78AwbcICXSX+a1MQwjNA1Uxxs1e3kfi3EJ21fWzb7w=
|
||||
github.com/fluxcd/image-automation-controller/api v1.1.4/go.mod h1:lkD/drkD6Wc+2SDjVj5KqfozEucTLFexWgby/5ft660=
|
||||
github.com/fluxcd/image-reflector-controller/api v1.1.2 h1:VPwUgA8WyPVVs16uSkwvjOAY6pvTYgAb0fL90t0RKLE=
|
||||
github.com/fluxcd/image-reflector-controller/api v1.1.2/go.mod h1:j4JSIocL42HQ77Veg1t60sApOy+lng8/cbXHXGSnfi0=
|
||||
github.com/fluxcd/kustomize-controller/api v1.8.5 h1:4fGPh6foGVKUUbt5OjVzbC5iTyX+Q+NS50atPboDC4w=
|
||||
github.com/fluxcd/kustomize-controller/api v1.8.5/go.mod h1:c/mUPIffDDLg1EicXCJtX4N/rc+z5Zh0e/CXjhd7Dyc=
|
||||
github.com/fluxcd/notification-controller/api v1.8.4 h1:KhHHVhQNtQsY+cVm/Y/8vhhFfrEOxM2AL/8JF8LAjMg=
|
||||
github.com/fluxcd/notification-controller/api v1.8.4/go.mod h1:ozgJGQPy0dG5eOsLZlwAr6n0q/y6+TWd1fGOtavlXJA=
|
||||
github.com/fluxcd/pkg/apis/acl v0.10.0 h1:KPfAmELNvtvaz8wixnm/MYXqa+MJf7ntVVMUU93Aenk=
|
||||
github.com/fluxcd/pkg/apis/acl v0.10.0/go.mod h1:a87i2A7AlFO5N2J8CxtzaUCCDmuLLWOHwkKu3eJF5fY=
|
||||
github.com/fluxcd/pkg/apis/event v0.27.1 h1:bFnP6gcZzCVm/Dxf/ByFz6BW+FzSn4RoWUkf7ri2bOs=
|
||||
github.com/fluxcd/pkg/apis/event v0.27.1/go.mod h1:ThqUZxG48o5PDN9Qh0tVTdpb+6PlVa6J2beEeMZoKMk=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.19.1 h1:rmN3hTceBVABGbrqRXEDYoAJDBUIPFRO9zbDJ98Xt/o=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.19.1/go.mod h1:9FUs77fd/Rh5/mDgZbGBUCL0UqmXiGj8rYywG3T3x+s=
|
||||
github.com/fluxcd/pkg/apis/meta v1.30.1 h1:TRqdvb/zo9h9Ig10xHxV7jMilG+e1jOv3djI00GFr9g=
|
||||
github.com/fluxcd/pkg/apis/meta v1.30.1/go.mod h1:Gx+YRq26a+mTbCjotSXC7/6kSSyo0zXQ8JnsEXf2vVk=
|
||||
github.com/fluxcd/pkg/auth v0.54.1 h1:UomwXboodolc5MWcyfXMw4aviqICKfcwlIDXCUOnNiQ=
|
||||
github.com/fluxcd/pkg/auth v0.54.1/go.mod h1:LV+XsZNll2CJ879UZs17PJdVAidPJ3bFpo85MSTvkyY=
|
||||
github.com/fluxcd/pkg/apis/event v0.26.0 h1:QzBRz9Qy91jzJmLlOhd4ecp6OWDpMVFvm311AwxCXzY=
|
||||
github.com/fluxcd/pkg/apis/event v0.26.0/go.mod h1:0yy7FMJABzq8PP5/VEi1Gro6ssPaPlH9xuPIoF+Rm6M=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.18.0 h1:FCNjViCLyKYj6lddpnjXybKBTC2eK6eXK9YOaNwLVTM=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.18.0/go.mod h1:mvtMtM4NNLipdCna6DYPC6Bd42xeaF15N+tNO+F6kxY=
|
||||
github.com/fluxcd/pkg/apis/meta v1.27.0 h1:EspByEk5j8w3rs1cGbEh9AjSmpDwQIz7DFG/zzqf6uI=
|
||||
github.com/fluxcd/pkg/apis/meta v1.27.0/go.mod h1:2t6JyrRfvIBhx6EBnXfFh/6sCCJ1db9WGaqko0JmNOE=
|
||||
github.com/fluxcd/pkg/auth v0.45.0 h1:3p/CMdFJ1c8LevdLd2cikackaTW1Tw8JB2xg4YqpP8A=
|
||||
github.com/fluxcd/pkg/auth v0.45.0/go.mod h1:/ijjR9G/l6URmEo/zWzpJ3XIMIXWP1Ad7AXTCqmWioY=
|
||||
github.com/fluxcd/pkg/cache v0.14.0 h1:wEwJA8NhYj+nH9P6ifcsglDZARWlcbxbmwngGOzfU4c=
|
||||
github.com/fluxcd/pkg/cache v0.14.0/go.mod h1:KwzU2gyVQ83YOHJsbBeveJ0HsXmLrH0I668zX19d/+s=
|
||||
github.com/fluxcd/pkg/chartutil v1.27.1 h1:Px0z/7c8VpOVmVRr76rVpHyXoBwaqj69vGJoAfKvUIM=
|
||||
github.com/fluxcd/pkg/chartutil v1.27.1/go.mod h1:Ws7JTAtiWitogxvbwaritE2mh2MxE1eRMSj+ZOP4M6k=
|
||||
github.com/fluxcd/pkg/chartutil v1.24.0 h1:Rh9o50eJUnAioL5q2JVPxO4DjFjwHwPE5K9LcBy7lqA=
|
||||
github.com/fluxcd/pkg/chartutil v1.24.0/go.mod h1:oycULCP00m46dxiskme1Yawe74UFLZzX0jqHb6xzdmQ=
|
||||
github.com/fluxcd/pkg/envsubst v1.7.0 h1:PL9Nj/V2fgaMR9KYZR7mEEw+vlYgP80nFZjOQQKAfJs=
|
||||
github.com/fluxcd/pkg/envsubst v1.7.0/go.mod h1:aoWeSIOamhqBZ3bHVj1GDwpdA10DXrI8yYbyjPiFly0=
|
||||
github.com/fluxcd/pkg/git v0.52.0 h1:dgsliHdaLADUcDO4pI0pc11N4dZ21NfDdhNcgRNuAkM=
|
||||
github.com/fluxcd/pkg/git v0.52.0/go.mod h1:mOvFDxoiuz+Mm4Ux1wKeTTckvBgZFvbTK8lNxmVHzKs=
|
||||
github.com/fluxcd/pkg/git v0.49.0 h1:OtI0TjMVC/GV/yPos4waA5fAs5u3/2YEYBFuZuJA3Rc=
|
||||
github.com/fluxcd/pkg/git v0.49.0/go.mod h1:Xnrqtz60/0jqfcy5UsY9sxlvPmlvzelPsej2v3L7wW8=
|
||||
github.com/fluxcd/pkg/gittestserver v0.29.0 h1:2j03zKVL6iVn6oiUuecG/O/3Q1pULWM9JrF/HSjkpnc=
|
||||
github.com/fluxcd/pkg/gittestserver v0.29.0/go.mod h1:O8151jV0ppBZTb9IUXMjxh6hZpkiuLq8JQHDBPOkZFw=
|
||||
github.com/fluxcd/pkg/kustomize v1.35.1 h1:qAGikUZE9eDtY2EXSXl56ueWy8420Sdg8s8s0IwEa1E=
|
||||
github.com/fluxcd/pkg/kustomize v1.35.1/go.mod h1:LKjh2x9MjoJ8Ry0WTgB84WWgF999VwA4jWDix2x+QmE=
|
||||
github.com/fluxcd/pkg/oci v0.68.0 h1:eykB9HrMGOmCTT6MSKRIBMxTiieBigah1wFedMMyhYM=
|
||||
github.com/fluxcd/pkg/oci v0.68.0/go.mod h1:lNxvxqjGSGfEKI4Lnpj8mHTVDMy4Fdiico6Oml0tafU=
|
||||
github.com/fluxcd/pkg/runtime v0.110.1 h1:O7eVI/R40MQMQpi6cAlWsNka2hZ0YfMXzETmui9D06c=
|
||||
github.com/fluxcd/pkg/runtime v0.110.1/go.mod h1:h5HDYgi4RXHGZD/5TCdy/47Vdlplf3/KM6U8aEDcagA=
|
||||
github.com/fluxcd/pkg/kustomize v1.32.0 h1:5lLT2dgR+JrcoJHB7/K50o0AcJikKvXcRd3r7jIYZC8=
|
||||
github.com/fluxcd/pkg/kustomize v1.32.0/go.mod h1:Xz1QIUIKexXuSolRQY63843wSycPVuIsVhE9C+aJWl8=
|
||||
github.com/fluxcd/pkg/oci v0.66.0 h1:nlBA3/MvJShjA+VFPKDRoXLUpH+e8THVvCMST+qUTlI=
|
||||
github.com/fluxcd/pkg/oci v0.66.0/go.mod h1:9Z4Juu/BhLLKHKOkOalfwIkZYsjTViD0YDHzW9w5R9c=
|
||||
github.com/fluxcd/pkg/runtime v0.106.0 h1:SGzUaO/G6bUBLkZIxLGnCVEEURSPuldSG2exYjlrsQk=
|
||||
github.com/fluxcd/pkg/runtime v0.106.0/go.mod h1:7lCogUwTGKoG3bfBvCn6eQgPYF7cvVp5R+gL3bB1HX8=
|
||||
github.com/fluxcd/pkg/sourceignore v0.18.0 h1:WU2tPKasG9AM7/H/LlqdjULyaSknnZBTrpHsDDtOuns=
|
||||
github.com/fluxcd/pkg/sourceignore v0.18.0/go.mod h1:mnH7rFFlEbMTclhz7JZP7tiHssKdXRNpCqnly2JGvaI=
|
||||
github.com/fluxcd/pkg/ssa v0.76.1 h1:IckNphuK3LuTRNkdRZlXEri7ZFXPc1Qj39TUHwOspv0=
|
||||
github.com/fluxcd/pkg/ssa v0.76.1/go.mod h1:bNImnO/GHtjjgp7BtGXVk181CoZbH9rEVEJfOwg1Xo8=
|
||||
github.com/fluxcd/pkg/ssa v0.74.0 h1:a5VqQXBQ5TQlzucwZ9l37bshzR3IPK5awzfMEBF3pdM=
|
||||
github.com/fluxcd/pkg/ssa v0.74.0/go.mod h1:6mdhG+O1db8oXsP7Ex3buJTexM5r9F7+LzSybBgT1f0=
|
||||
github.com/fluxcd/pkg/ssh v0.25.0 h1:4Y9WmuNqyKvH759UznU5DGHRcOuoJ/dQM6sbsaDZYYM=
|
||||
github.com/fluxcd/pkg/ssh v0.25.0/go.mod h1:Fli2Ogu4uaIVGbCy+r0vvZlMO0RfuInyNY1q2FVIx0o=
|
||||
github.com/fluxcd/pkg/tar v1.2.0 h1:T6WFB5M0YRHktlrgdKNskqpdp76TVDdWTOeuWz33CFs=
|
||||
github.com/fluxcd/pkg/tar v1.2.0/go.mod h1:Wlalp5vIVe+BbckkKkqExKcoHAeeWJPAzwK7ONeFcS0=
|
||||
github.com/fluxcd/pkg/version v0.16.0 h1:VR9+143LAwbyUSAaMhiJHbfsiU+fTjA9L/3dr1ucfrI=
|
||||
github.com/fluxcd/pkg/version v0.16.0/go.mod h1:2M/l90CmbDaD21JTh77hjwaUbd/YM96+Fo8x4fMdxLI=
|
||||
github.com/fluxcd/source-controller/api v1.9.1 h1:04Elx6/iFwgNOmrymfetaDfFFBqw5/LfoiTgyeLlrqQ=
|
||||
github.com/fluxcd/source-controller/api v1.9.1/go.mod h1:qO98L20gw0MvLpSPapJKypyxHP7PejmJN5KxWXxDjCA=
|
||||
github.com/fluxcd/source-watcher/api/v2 v2.2.1 h1:eRQnrksg/CylJSBFTHXMUpADRB0B2YC11YaUjSW9ZWE=
|
||||
github.com/fluxcd/source-watcher/api/v2 v2.2.1/go.mod h1:v84ckEC92IRw9HZVHzUamwkgIv1Vh38NQn/jCwo8Sro=
|
||||
github.com/fluxcd/pkg/version v0.15.0 h1:E2Ju4i0vj8ZXLHKz/F4a8JTmDh7Jcg8okB0hK5rEoTM=
|
||||
github.com/fluxcd/pkg/version v0.15.0/go.mod h1:LEHnvLMgbTk4kelF+JHHzaG77kY9uTWodMtadPRMEW8=
|
||||
github.com/fluxcd/source-controller/api v1.8.5 h1:mLKc9YVMk46JCt1BQbkG6irkrpBZp95kiXh2+GYB6KQ=
|
||||
github.com/fluxcd/source-controller/api v1.8.5/go.mod h1:sio4t49RDx+S1etHRFAEEw8qfVuw0KKlOg8bRVlEYPM=
|
||||
github.com/fluxcd/source-watcher/api/v2 v2.1.1 h1:1LfT50ty+78MKKbschAZl28QbVqIyjaNq17KmW5wPJI=
|
||||
github.com/fluxcd/source-watcher/api/v2 v2.1.1/go.mod h1:6M1BzBGQRoIuSenSQlfJHwMVVobFPiNPxXqfN0IILc4=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.9.2 h1:X4Ksno9+x3cz0TZv69ec1hxP/+tymuR8PXQJyDwfh78=
|
||||
github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk=
|
||||
@@ -264,36 +267,8 @@ github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMK
|
||||
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU=
|
||||
github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ=
|
||||
github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4=
|
||||
github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
|
||||
github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4=
|
||||
github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU=
|
||||
github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y=
|
||||
github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk=
|
||||
github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI=
|
||||
github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM=
|
||||
github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s=
|
||||
github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE=
|
||||
github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48=
|
||||
github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg=
|
||||
github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0=
|
||||
github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg=
|
||||
github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8=
|
||||
github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0=
|
||||
github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw=
|
||||
github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg=
|
||||
github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls=
|
||||
github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
|
||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
@@ -329,8 +304,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-containerregistry v0.21.6 h1:T+yqQIlJXKrM98Om4DlW3GoWQAmhZuLMwoDOvVrtiUM=
|
||||
github.com/google/go-containerregistry v0.21.6/go.mod h1:U7MMSBIJynke2MVQrQk19NP9k/uQsGz/h0amIFSHMbo=
|
||||
github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM=
|
||||
github.com/google/go-containerregistry v0.21.5/go.mod h1:ySvMuiWg+dOsRW0Hw8GYwfMwBlNRTmpYBFJPlkco5zU=
|
||||
github.com/google/go-github/v82 v82.0.0 h1:OH09ESON2QwKCUVMYmMcVu1IFKFoaZHwqYaUtr/MVfk=
|
||||
github.com/google/go-github/v82 v82.0.0/go.mod h1:hQ6Xo0VKfL8RZ7z1hSfB4fvISg0QqHOqe9BP0qo+WvM=
|
||||
github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0=
|
||||
@@ -354,8 +329,6 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/graph-gophers/graphql-go v1.9.0 h1:yu0ucKHLc5qGpRwLYKIWtr9bOoxovkWasuBrPQwlHls=
|
||||
github.com/graph-gophers/graphql-go v1.9.0/go.mod h1:23olKZ7duEvHlF/2ELEoSZaY1aNPfShjP782SOoNTyM=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
|
||||
@@ -374,14 +347,12 @@ github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA=
|
||||
github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw=
|
||||
github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hiddeco/sshsig v0.2.0 h1:gMWllgKCITXdydVkDL+Zro0PU96QI55LwUwebSwNTSw=
|
||||
github.com/hiddeco/sshsig v0.2.0/go.mod h1:nJc98aGgiH6Yql2doqH4CTBVHexQA40Q+hMMLHP4EqE=
|
||||
github.com/homeport/dyff v1.10.2 h1:XyB+D0KVwjbUFTZYIkvPtsImwkfh+ObH2CEdEHTqdr4=
|
||||
github.com/homeport/dyff v1.10.2/go.mod h1:0kIjL/JOGaXigzrLY6kcl5esSStbAa99r6GzEvr7lrs=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
@@ -400,6 +371,8 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
@@ -409,8 +382,8 @@ github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PW
|
||||
github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
|
||||
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
|
||||
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
|
||||
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
|
||||
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
|
||||
github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -428,20 +401,25 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhn
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
||||
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 h1:BXxTozrOU8zgC5dkpn3J6NTRdoP+hjok/e+ACr4Hibk=
|
||||
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3/go.mod h1:x1uk6vxTiVuNt6S5R2UYgdhpj3oKojXvOXauHZ7dEnI=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-shellwords v1.0.13 h1:DC0OMEpGjm6LfNFU4ckYcvbQKyp2vE8atyFGXNtDcf4=
|
||||
github.com/mattn/go-shellwords v1.0.13/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
||||
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
@@ -475,8 +453,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI=
|
||||
github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
|
||||
github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I=
|
||||
github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg=
|
||||
github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc=
|
||||
github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
@@ -574,6 +552,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4=
|
||||
github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo=
|
||||
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c=
|
||||
github.com/wI2L/jsondiff v0.6.1 h1:ISZb9oNWbP64LHnu4AUhsMF5W0FIj5Ok3Krip9Shqpw=
|
||||
@@ -587,8 +567,8 @@ github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
|
||||
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||
gitlab.com/gitlab-org/api/client-go v1.46.0 h1:YxBWFZIFYKcGESCb9fpkwzouo+apyB9pr/XTWzNoL24=
|
||||
gitlab.com/gitlab-org/api/client-go v1.46.0/go.mod h1:FtgyU6g2HS5+fMhw6nLK96GBEEBx5MzntOiJWfIaiN8=
|
||||
gitlab.com/gitlab-org/api/client-go v1.29.0 h1:3KnF6vENry/9v9eVrnLi2OfBV0m/WSrwh3RcxgH/hkA=
|
||||
gitlab.com/gitlab-org/api/client-go v1.29.0/go.mod h1:6i3EZtC6gKiTTmDwp+f6r/Yi9OY4AaYubl5B3yXEdHE=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 h1:dkBzNEAIKADEaFnuESzcXvpd09vxvDZsOjx11gjUqLk=
|
||||
@@ -641,8 +621,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo=
|
||||
go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q=
|
||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
||||
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
@@ -658,15 +638,15 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
|
||||
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
|
||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
|
||||
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
|
||||
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
|
||||
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -682,8 +662,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -695,8 +675,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -713,6 +693,7 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -721,8 +702,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -732,8 +713,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
||||
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
||||
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
||||
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -744,8 +725,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
|
||||
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -754,8 +735,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
|
||||
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
|
||||
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
|
||||
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
|
||||
@@ -794,30 +775,30 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||
helm.sh/helm/v4 v4.2.2 h1:E2zSCA2uUm9PNiZsSC/BioDVGsYk7nF2jNJFg/i+Dng=
|
||||
helm.sh/helm/v4 v4.2.2/go.mod h1:dp3ihfy1AhCLKANDaPETmVWhqPkOmwvJtpK/biHfopE=
|
||||
k8s.io/api v0.36.2 h1:TF6YDLIzKfccK7cq9YpTcGX8TJmEkHVRv78DM51fRYY=
|
||||
k8s.io/api v0.36.2/go.mod h1:F4LbMO4brjZYh7yFkXWhynSvtB7YauxV4c+HHkNRGNg=
|
||||
k8s.io/apiextensions-apiserver v0.36.2 h1:3O5gqOj/dt2XWWbpMe+TXWpE9yU6pjM/tXxtHHJT/K4=
|
||||
k8s.io/apiextensions-apiserver v0.36.2/go.mod h1:cL1tBWe8XSaP1H30iWKGo7hf6iAUUUJPEU70dskmAnA=
|
||||
k8s.io/apimachinery v0.36.2 h1:0PE/W/WNy1UX61NLbXY5TMbJ6UwLL6E6lAPkYrKFxbQ=
|
||||
k8s.io/apimachinery v0.36.2/go.mod h1:fvf/HOLXq9RId0rnDIbN1OEBvHXdQbLMM8nu0LcBUf4=
|
||||
k8s.io/cli-runtime v0.36.2 h1:CconTvEeV4DJs4ZX3HQKCFbFRGsm6OtuBM9yjmMP2VM=
|
||||
k8s.io/cli-runtime v0.36.2/go.mod h1:LddcjiMf4YlnHO7c1Y7rEtDqL84FyiYVLco7V679GUU=
|
||||
k8s.io/client-go v0.36.2 h1:bfgxmFKc9CgqsgX4xKLAAdmTQlWee7Ob/HlDOrJ5TBI=
|
||||
k8s.io/client-go v0.36.2/go.mod h1:1vgO4OAlfPnoLcb+Rze2GF5rAr14w8qjrYMoyXJzQj0=
|
||||
k8s.io/component-base v0.36.2 h1:Z0VH80O7Ng0HDZnZj3WRR3urEGa0kTwmO8CwEwjVK1w=
|
||||
k8s.io/component-base v0.36.2/go.mod h1:mGfFOA7Gwpdm1VW2cwSQYbiDIlz8GD2WGwH88QSeCyA=
|
||||
helm.sh/helm/v4 v4.1.4 h1:zwTrNkalG4f7SYigRSdQnYrTj0QEz1qzetzAlYoDVSo=
|
||||
helm.sh/helm/v4 v4.1.4/go.mod h1:5dSo8rRgn3OTkDAc/k0Ipw5/Q+BlqKIKZwa0XwSiINI=
|
||||
k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80=
|
||||
k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34=
|
||||
k8s.io/apiextensions-apiserver v0.36.0 h1:Wt7E8J+VBCbj4FjiBfDTK/neXDDjyJVJc7xfuOHImZ0=
|
||||
k8s.io/apiextensions-apiserver v0.36.0/go.mod h1:kGDjH0msuiIB3tgsYRV0kS9GqpMYMUsQ3GHv7TApyug=
|
||||
k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ=
|
||||
k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc=
|
||||
k8s.io/cli-runtime v0.36.0 h1:HNxciQpQMMOKS0/GiUXcKDyA6J2FDILJj9NmP2BZrTg=
|
||||
k8s.io/cli-runtime v0.36.0/go.mod h1:KObkknK9Ro5LYX+1RdiKc7C8CvGg4aX+V/Zv+E8WPHA=
|
||||
k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c=
|
||||
k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y=
|
||||
k8s.io/component-base v0.36.0 h1:hFjEktssxiJhrK1zfybkH4kJOi8iZuF+mIDCqS5+jRo=
|
||||
k8s.io/component-base v0.36.0/go.mod h1:JZvIfcNHk+uck+8LhJzhSBtydWXaZNQwX2OdL+Mnwsk=
|
||||
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
|
||||
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
|
||||
k8s.io/kube-openapi v0.0.0-20260603220949-865597e52e25 h1:mPMaPMpBij2V1Wv/fR+HW124vVGXXvOSS9ver/9yjWs=
|
||||
k8s.io/kube-openapi v0.0.0-20260603220949-865597e52e25/go.mod h1:V/QaCUYDa+0QpcHhVVc5l99Uz56wEMEXBSj9oCDkNDY=
|
||||
k8s.io/kubectl v0.36.2 h1:rpUGGpeL09XVOLep2yle5jrtk//JA1L6ZHfkQQtVEwk=
|
||||
k8s.io/kubectl v0.36.2/go.mod h1:gVbQ3B/yb4bSR2ggQ7rd0W6icUSWs7sduH4e16Vii+0=
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 h1:wU4tMEhLGgIbLvXQb1cfN+EcM0wf7zC6CPF+C79jroc=
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4=
|
||||
sigs.k8s.io/controller-runtime v0.24.1/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw=
|
||||
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hkbPJgdATINPMAxaynU2Ovg=
|
||||
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0=
|
||||
k8s.io/kubectl v0.36.0 h1:hEGr8NvIm2Wjqs2Xy48Uzmvo6lpHdGKlLyMvau2gTms=
|
||||
k8s.io/kubectl v0.36.0/go.mod h1:iDe8aV5BEi45W8k+5n71I2pJ/nwE0PHDu+/2cejzYoo=
|
||||
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU=
|
||||
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
sigs.k8s.io/controller-runtime v0.24.0 h1:Ck6N2LdS8Lovy1o25BB4r1xjvLEKUl1s2o9kU+KWDE4=
|
||||
sigs.k8s.io/controller-runtime v0.24.0/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/kustomize/api v0.21.1 h1:lzqbzvz2CSvsjIUZUBNFKtIMsEw7hVLJp0JeSIVmuJs=
|
||||
@@ -826,7 +807,7 @@ sigs.k8s.io/kustomize/kyaml v0.21.1 h1:IVlbmhC076nf6foyL6Taw4BkrLuEsXUXNpsE+ScX7
|
||||
sigs.k8s.io/kustomize/kyaml v0.21.1/go.mod h1:hmxADesM3yUN2vbA5z1/YTBnzLJ1dajdqpQonwBL1FQ=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.0 h1:qmp2e3ZfFi1/jJbDGpD4mt3wyp6PE1NfKHCYLqgNQJo=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||
|
||||
@@ -620,7 +620,6 @@ func (b *Builder) do(ctx context.Context, kustomization kustomizev1.Kustomizatio
|
||||
res,
|
||||
kustomize.SubstituteWithDryRun(b.dryRun),
|
||||
kustomize.SubstituteWithStrict(b.strictSubst),
|
||||
kustomize.SubstituteWithAlways(kustomization.GetSubstituteStrategy() == kustomizev1.SubstituteStrategyAlways),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("var substitution failed for '%s': %w", res.GetName(), err)
|
||||
@@ -660,10 +659,17 @@ func kustomizationsEqual(k1 *kustomizev1.Kustomization, k2 *kustomizev1.Kustomiz
|
||||
}
|
||||
|
||||
func (b *Builder) setOwnerLabels(res *resource.Resource) error {
|
||||
if err := res.PipeE(yaml.SetLabel(controllerGroup+"/name", b.kustomization.GetName())); err != nil {
|
||||
labels := res.GetLabels()
|
||||
|
||||
labels[controllerGroup+"/name"] = b.kustomization.GetName()
|
||||
labels[controllerGroup+"/namespace"] = b.kustomization.GetNamespace()
|
||||
|
||||
err := res.SetLabels(labels)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return res.PipeE(yaml.SetLabel(controllerGroup+"/namespace", b.kustomization.GetNamespace()))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func maskSopsData(res *resource.Resource) error {
|
||||
|
||||
@@ -840,93 +840,3 @@ resources:
|
||||
t.Fatal("expected error when referencing resource outside cwd, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Build_preserveAllLabels(t *testing.T) {
|
||||
b, err := NewBuilder("test-ks", "testdata/invalid-labels/resources",
|
||||
WithDryRun(true),
|
||||
WithNamespace("flux-system"),
|
||||
WithKustomizationFile("testdata/invalid-labels/kustomization.yaml"),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create builder: %v", err)
|
||||
}
|
||||
|
||||
objects, err := b.Build()
|
||||
if err != nil {
|
||||
t.Fatalf("build failed: %v", err)
|
||||
}
|
||||
|
||||
if len(objects) == 0 {
|
||||
t.Fatal("expected at least one object, got none")
|
||||
}
|
||||
|
||||
rawLabels, _, _ := unstructured.NestedMap(objects[0].Object, "metadata", "labels")
|
||||
|
||||
if got, ok := rawLabels["invalid"]; !ok || got != int64(0) {
|
||||
t.Errorf("expected label invalid=0, got %#v", got)
|
||||
}
|
||||
if got, ok := rawLabels["valid"]; !ok || got != "yes" {
|
||||
t.Errorf("expected label valid=\"yes\", got %v", got)
|
||||
}
|
||||
if got := rawLabels[controllerGroup+"/name"]; got != "test-ks" {
|
||||
t.Errorf("expected owner name label \"test-ks\", got %v", got)
|
||||
}
|
||||
if got := rawLabels[controllerGroup+"/namespace"]; got != "flux-system" {
|
||||
t.Errorf("expected owner namespace label \"flux-system\", got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Build_substituteStrategy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ksFile string
|
||||
wantColor string
|
||||
wantShape string
|
||||
}{
|
||||
{
|
||||
// The default WithVariables strategy skips substitution when no
|
||||
// variables are defined, leaving the defaulted expressions untouched.
|
||||
name: "WithVariables skips substitution without variables",
|
||||
ksFile: "testdata/substitute-strategy/with-variables.yaml",
|
||||
wantColor: "${color:=blue}",
|
||||
wantShape: "${shape:=square}",
|
||||
},
|
||||
{
|
||||
// The Always strategy performs substitution even without variables,
|
||||
// resolving the expressions to their defaults.
|
||||
name: "Always substitutes defaults without variables",
|
||||
ksFile: "testdata/substitute-strategy/always.yaml",
|
||||
wantColor: "blue",
|
||||
wantShape: "square",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b, err := NewBuilder("test-ks", "testdata/substitute-strategy/resources",
|
||||
WithDryRun(true),
|
||||
WithNamespace("flux-system"),
|
||||
WithKustomizationFile(tt.ksFile),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create builder: %v", err)
|
||||
}
|
||||
|
||||
objects, err := b.Build()
|
||||
if err != nil {
|
||||
t.Fatalf("build failed: %v", err)
|
||||
}
|
||||
if len(objects) == 0 {
|
||||
t.Fatal("expected at least one object, got none")
|
||||
}
|
||||
|
||||
data, _, _ := unstructured.NestedStringMap(objects[0].Object, "data")
|
||||
if got := data["color"]; got != tt.wantColor {
|
||||
t.Errorf("expected color=%q, got %q", tt.wantColor, got)
|
||||
}
|
||||
if got := data["shape"]; got != tt.wantShape {
|
||||
t.Errorf("expected shape=%q, got %q", tt.wantShape, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ import (
|
||||
"github.com/fluxcd/cli-utils/pkg/object"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
"github.com/fluxcd/pkg/ssa/jsondiff"
|
||||
"github.com/fluxcd/pkg/ssa/normalize"
|
||||
ssautil "github.com/fluxcd/pkg/ssa/utils"
|
||||
|
||||
@@ -95,28 +94,6 @@ func (b *Builder) diff() (string, bool, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
|
||||
defer cancel()
|
||||
|
||||
// Convert drift ignore rules from the Kustomization spec to jsondiff.IgnoreRule.
|
||||
var driftIgnoreRules []jsondiff.IgnoreRule
|
||||
if rules := b.kustomization.Spec.Ignore; len(rules) > 0 {
|
||||
driftIgnoreRules = make([]jsondiff.IgnoreRule, len(rules))
|
||||
for i, rule := range rules {
|
||||
driftIgnoreRules[i] = jsondiff.IgnoreRule{
|
||||
Paths: rule.Paths,
|
||||
}
|
||||
if rule.Target != nil {
|
||||
driftIgnoreRules[i].Selector = &jsondiff.Selector{
|
||||
Group: rule.Target.Group,
|
||||
Version: rule.Target.Version,
|
||||
Kind: rule.Target.Kind,
|
||||
Name: rule.Target.Name,
|
||||
Namespace: rule.Target.Namespace,
|
||||
AnnotationSelector: rule.Target.AnnotationSelector,
|
||||
LabelSelector: rule.Target.LabelSelector,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var diffErrs []error
|
||||
// create an inventory of objects to be reconciled
|
||||
newInventory := newInventory()
|
||||
@@ -132,7 +109,6 @@ func (b *Builder) diff() (string, bool, error) {
|
||||
ForceSelector: map[string]string{
|
||||
"kustomize.toolkit.fluxcd.io/force": "enabled",
|
||||
},
|
||||
DriftIgnoreRules: driftIgnoreRules,
|
||||
}
|
||||
change, liveObject, mergedObject, err := resourceManager.Diff(ctx, obj, diffOptions)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: test-ks
|
||||
namespace: flux-system
|
||||
spec:
|
||||
path: "./resources"
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: invalid-resource
|
||||
labels:
|
||||
invalid: 0
|
||||
valid: yes
|
||||
@@ -1,4 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- invalid-resource.yaml
|
||||
@@ -1,9 +0,0 @@
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: test-ks
|
||||
namespace: flux-system
|
||||
spec:
|
||||
path: "./resources"
|
||||
postBuild:
|
||||
substituteStrategy: Always
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-config
|
||||
data:
|
||||
color: "${color:=blue}"
|
||||
shape: "${shape:=square}"
|
||||
@@ -1,4 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- configmap.yaml
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: test-ks
|
||||
namespace: flux-system
|
||||
spec:
|
||||
path: "./resources"
|
||||
postBuild: {}
|
||||
@@ -21,16 +21,13 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/utils"
|
||||
"github.com/fluxcd/pkg/auth/aws"
|
||||
"github.com/fluxcd/pkg/auth/azure"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
var supportedSourceGitProviders = []string{
|
||||
sourcev1.GitProviderGeneric,
|
||||
sourcev1.GitProviderAzure,
|
||||
sourcev1.GitProviderGitHub,
|
||||
aws.ProviderName,
|
||||
azure.ProviderName,
|
||||
}
|
||||
|
||||
type SourceGitProvider string
|
||||
|
||||
@@ -20,8 +20,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
@@ -85,16 +83,6 @@ func (c *CatalogClient) FetchManifest(name string) (*plugintypes.Manifest, error
|
||||
return nil, fmt.Errorf("plugin %q has unexpected kind %q (expected %q)", name, manifest.Kind, plugintypes.PluginKind)
|
||||
}
|
||||
|
||||
// Bin becomes the on-disk binary path during install. Require a plain
|
||||
// flux-prefixed filename: no separators or traversal, matching what the
|
||||
// discovery layer surfaces.
|
||||
if manifest.Bin == "" ||
|
||||
manifest.Bin != filepath.Base(manifest.Bin) ||
|
||||
!filepath.IsLocal(manifest.Bin) ||
|
||||
!strings.HasPrefix(manifest.Bin, pluginPrefix) {
|
||||
return nil, fmt.Errorf("plugin %q has invalid bin %q (must be a plain filename prefixed with %q)", name, manifest.Bin, pluginPrefix)
|
||||
}
|
||||
|
||||
return &manifest, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,8 @@ limitations under the License.
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
plugintypes "github.com/fluxcd/flux2/v2/pkg/plugin"
|
||||
@@ -92,61 +90,6 @@ func TestFetchManifestNotFound(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchManifestRejectsInvalidBin(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
bin string
|
||||
}{
|
||||
{"parent traversal", "../evil"},
|
||||
{"nested traversal", "../../bin/evil"},
|
||||
{"absolute path", "/tmp/evil"},
|
||||
{"subdirectory", "sub/flux-evil"},
|
||||
{"missing prefix", "evil"},
|
||||
{"empty", ""},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
manifest := fmt.Sprintf(`
|
||||
apiVersion: cli.fluxcd.io/v1beta1
|
||||
kind: Plugin
|
||||
name: operator
|
||||
description: Flux Operator CLI
|
||||
bin: %q
|
||||
versions:
|
||||
- version: 0.45.0
|
||||
platforms:
|
||||
- os: linux
|
||||
arch: amd64
|
||||
url: https://example.com/archive.tar.gz
|
||||
checksum: sha256:abc123
|
||||
`, tc.bin)
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/operator.yaml" {
|
||||
w.Write([]byte(manifest))
|
||||
return
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := &CatalogClient{
|
||||
BaseURL: server.URL + "/",
|
||||
HTTPClient: server.Client(),
|
||||
GetEnv: func(key string) string { return "" },
|
||||
}
|
||||
|
||||
_, err := client.FetchManifest("operator")
|
||||
if err == nil {
|
||||
t.Fatal("expected error for invalid bin, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "invalid bin") {
|
||||
t.Errorf("expected 'invalid bin' error, got: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchCatalog(t *testing.T) {
|
||||
catalog := `
|
||||
apiVersion: cli.fluxcd.io/v1beta1
|
||||
|
||||
@@ -84,13 +84,7 @@ func (inst *Installer) Install(pluginDir string, manifest *plugintypes.Manifest,
|
||||
// name (e.g. "flux-validate"). On Windows we always append ".exe".
|
||||
// For archives it's also the entry name we look up; for raw binaries
|
||||
// it's the rename target regardless of the URL's filename.
|
||||
//
|
||||
// Bin is remote-controlled and joined to pluginDir below, so it must be a
|
||||
// plain filename: reject separators and traversal so the write can't escape.
|
||||
binName := manifest.Bin
|
||||
if binName == "" || binName != filepath.Base(binName) || !filepath.IsLocal(binName) {
|
||||
return fmt.Errorf("invalid plugin binary name %q: must be a plain filename", manifest.Bin)
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
binName += ".exe"
|
||||
}
|
||||
|
||||
@@ -239,147 +239,6 @@ func TestInstallChecksumMismatch(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstallRejectsUnsafeBinName(t *testing.T) {
|
||||
// A malicious manifest must not be able to write the binary outside the
|
||||
// plugin directory via path traversal or an absolute path in Bin.
|
||||
cases := []struct {
|
||||
name string
|
||||
bin string
|
||||
}{
|
||||
{"parent traversal", "../evil"},
|
||||
{"nested traversal", "../../bin/evil"},
|
||||
{"absolute path", "/tmp/evil"},
|
||||
{"subdirectory", "sub/evil"},
|
||||
{"empty", ""},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
binaryContent := []byte("#!/bin/sh\necho pwned")
|
||||
archive, err := createTestTarGz("flux-operator", binaryContent)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create test archive: %v", err)
|
||||
}
|
||||
checksum := fmt.Sprintf("sha256:%x", sha256.Sum256(archive))
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(archive)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
pluginDir := t.TempDir()
|
||||
|
||||
manifest := &plugintypes.Manifest{Name: "operator", Bin: tc.bin}
|
||||
pv := &plugintypes.Version{Version: "0.45.0"}
|
||||
plat := &plugintypes.Platform{
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
URL: server.URL + "/archive.tar.gz",
|
||||
Checksum: checksum,
|
||||
}
|
||||
|
||||
installer := &Installer{HTTPClient: server.Client()}
|
||||
err = installer.Install(pluginDir, manifest, pv, plat)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for unsafe binary name, got nil")
|
||||
}
|
||||
if !bytes.Contains([]byte(err.Error()), []byte("invalid plugin binary name")) {
|
||||
t.Errorf("expected 'invalid plugin binary name' error, got: %v", err)
|
||||
}
|
||||
|
||||
// Nothing must have been written outside the plugin directory.
|
||||
if _, statErr := os.Stat(filepath.Join(filepath.Dir(pluginDir), "evil")); statErr == nil {
|
||||
t.Fatal("binary was written outside the plugin directory")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Raw-binary write path (copyPluginBinary): a traversing Bin must be rejected.
|
||||
func TestInstallRejectsUnsafeBinNameRawBinary(t *testing.T) {
|
||||
// Bytes that don't match zip/gzip/tar magic — treated as a raw binary.
|
||||
binaryContent := []byte("#!/bin/sh\necho pwned")
|
||||
checksum := fmt.Sprintf("sha256:%x", sha256.Sum256(binaryContent))
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(binaryContent)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
pluginDir := t.TempDir()
|
||||
|
||||
manifest := &plugintypes.Manifest{Name: "validate", Bin: "../../evil"}
|
||||
pv := &plugintypes.Version{Version: "1.2.3"}
|
||||
plat := &plugintypes.Platform{
|
||||
OS: runtime.GOOS,
|
||||
Arch: runtime.GOARCH,
|
||||
URL: server.URL + "/download/flux-validate",
|
||||
Checksum: checksum,
|
||||
}
|
||||
|
||||
installer := &Installer{HTTPClient: server.Client()}
|
||||
err := installer.Install(pluginDir, manifest, pv, plat)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for unsafe binary name, got nil")
|
||||
}
|
||||
if !bytes.Contains([]byte(err.Error()), []byte("invalid plugin binary name")) {
|
||||
t.Errorf("expected 'invalid plugin binary name' error, got: %v", err)
|
||||
}
|
||||
if _, statErr := os.Stat(filepath.Join(filepath.Dir(pluginDir), "evil")); statErr == nil {
|
||||
t.Fatal("binary was written outside the plugin directory")
|
||||
}
|
||||
}
|
||||
|
||||
// Archive write path with ExtractPath set: the entry is a legitimate local
|
||||
// path, but the destination derives from Bin, so a traversing Bin is rejected.
|
||||
func TestInstallRejectsUnsafeBinNameWithExtractPath(t *testing.T) {
|
||||
binaryContent := []byte("#!/bin/sh\necho pwned")
|
||||
entries := []tarEntry{
|
||||
{
|
||||
header: tar.Header{
|
||||
Name: "subdir/flux-operator",
|
||||
Typeflag: tar.TypeReg,
|
||||
Mode: 0o755,
|
||||
},
|
||||
content: binaryContent,
|
||||
},
|
||||
}
|
||||
archive, err := createTestTarGzMulti(entries)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create archive: %v", err)
|
||||
}
|
||||
checksum := fmt.Sprintf("sha256:%x", sha256.Sum256(archive))
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(archive)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
pluginDir := t.TempDir()
|
||||
|
||||
manifest := &plugintypes.Manifest{Name: "operator", Bin: "../../evil"}
|
||||
pv := &plugintypes.Version{Version: "0.45.0"}
|
||||
plat := &plugintypes.Platform{
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
URL: server.URL + "/archive.tar.gz",
|
||||
Checksum: checksum,
|
||||
ExtractPath: "subdir/flux-operator",
|
||||
}
|
||||
|
||||
installer := &Installer{HTTPClient: server.Client()}
|
||||
err = installer.Install(pluginDir, manifest, pv, plat)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for unsafe binary name, got nil")
|
||||
}
|
||||
if !bytes.Contains([]byte(err.Error()), []byte("invalid plugin binary name")) {
|
||||
t.Errorf("expected 'invalid plugin binary name' error, got: %v", err)
|
||||
}
|
||||
if _, statErr := os.Stat(filepath.Join(filepath.Dir(pluginDir), "evil")); statErr == nil {
|
||||
t.Fatal("binary was written outside the plugin directory")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstallBinaryNotInArchive(t *testing.T) {
|
||||
// Archive contains "wrong-name" instead of "flux-operator".
|
||||
archive, err := createTestTarGz("wrong-name", []byte("content"))
|
||||
|
||||
@@ -47,6 +47,7 @@ import (
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1"
|
||||
notificationv1b3 "github.com/fluxcd/notification-controller/api/v1beta3"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
runclient "github.com/fluxcd/pkg/runtime/client"
|
||||
"github.com/fluxcd/pkg/version"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
@@ -230,6 +231,26 @@ func ParseObjectKindNameNamespace(input string) (kind, name, namespace string) {
|
||||
return kind, name, namespace
|
||||
}
|
||||
|
||||
func MakeDependsOn(deps []string) []meta.NamespacedObjectReference {
|
||||
refs := []meta.NamespacedObjectReference{}
|
||||
for _, dep := range deps {
|
||||
parts := strings.Split(dep, "/")
|
||||
depNamespace := ""
|
||||
depName := ""
|
||||
if len(parts) > 1 {
|
||||
depNamespace = parts[0]
|
||||
depName = parts[1]
|
||||
} else {
|
||||
depName = parts[0]
|
||||
}
|
||||
refs = append(refs, meta.NamespacedObjectReference{
|
||||
Namespace: depNamespace,
|
||||
Name: depName,
|
||||
})
|
||||
}
|
||||
return refs
|
||||
}
|
||||
|
||||
func ValidateComponents(components []string) error {
|
||||
defaults := install.MakeDefaultOptions()
|
||||
bootstrapAllComponents := append(defaults.Components, defaults.ComponentsExtra...)
|
||||
|
||||
@@ -21,7 +21,10 @@ package utils
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
)
|
||||
|
||||
func TestCompatibleVersion(t *testing.T) {
|
||||
@@ -76,6 +79,28 @@ func TestParseObjectKindNameNamespace(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeDependsOn(t *testing.T) {
|
||||
input := []string{
|
||||
"someNSA/someNameA",
|
||||
"someNSB/someNameB",
|
||||
"someNameC",
|
||||
"someNSD/",
|
||||
"",
|
||||
}
|
||||
want := []meta.NamespacedObjectReference{
|
||||
{Namespace: "someNSA", Name: "someNameA"},
|
||||
{Namespace: "someNSB", Name: "someNameB"},
|
||||
{Namespace: "", Name: "someNameC"},
|
||||
{Namespace: "someNSD", Name: ""},
|
||||
{Namespace: "", Name: ""},
|
||||
}
|
||||
|
||||
got := MakeDependsOn(input)
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("MakeDependsOn() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateComponents(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v1.6.1/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v1.6.1/helm-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.5/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.5/helm-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.2.1/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.2.1/image-automation-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.4/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.4/image-automation-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v1.2.1/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v1.2.1/image-reflector-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v1.1.2/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v1.1.2/image-reflector-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.9.1/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.9.1/kustomize-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.5/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.5/kustomize-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v1.9.1/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v1.9.1/notification-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.4/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.4/notification-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v1.9.1/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v1.9.1/source-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v1.8.5/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v1.8.5/source-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-watcher/releases/download/v2.2.1/source-watcher.crds.yaml
|
||||
- https://github.com/fluxcd/source-watcher/releases/download/v2.2.1/source-watcher.deployment.yaml
|
||||
- https://github.com/fluxcd/source-watcher/releases/download/v2.1.1/source-watcher.crds.yaml
|
||||
- https://github.com/fluxcd/source-watcher/releases/download/v2.1.1/source-watcher.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v1.9.1/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.9.1/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v1.6.1/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v1.9.1/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v1.2.1/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.2.1/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-watcher/releases/download/v2.2.1/source-watcher.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v1.8.5/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.5/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.5/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.4/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v1.1.2/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.4/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-watcher/releases/download/v2.1.1/source-watcher.crds.yaml
|
||||
|
||||
@@ -43,7 +43,6 @@ import (
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/repository"
|
||||
"github.com/fluxcd/pkg/git/signature"
|
||||
"github.com/fluxcd/pkg/kustomize/filesys"
|
||||
runclient "github.com/fluxcd/pkg/runtime/client"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
@@ -68,9 +67,6 @@ type PlainGitBootstrapper struct {
|
||||
gpgPassphrase string
|
||||
gpgKeyID string
|
||||
|
||||
sshSigningKey []byte
|
||||
sshSigningPassword []byte
|
||||
|
||||
restClientGetter genericclioptions.RESTClientGetter
|
||||
restClientOptions *runclient.Options
|
||||
|
||||
@@ -159,27 +155,24 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
||||
b.logger.Successf("generated component manifests")
|
||||
|
||||
// Write generated files and make a commit
|
||||
signer, err := b.resolveSigner()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to construct commit signer: %w", err)
|
||||
var signer *openpgp.Entity
|
||||
if b.gpgKeyRing != nil {
|
||||
signer, err = getOpenPgpEntity(b.gpgKeyRing, b.gpgPassphrase, b.gpgKeyID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate OpenPGP entity: %w", err)
|
||||
}
|
||||
}
|
||||
commitMsg := fmt.Sprintf("Add Flux %s component manifests", options.Version)
|
||||
if b.commitMessageAppendix != "" {
|
||||
commitMsg = commitMsg + "\n\n" + b.commitMessageAppendix
|
||||
}
|
||||
|
||||
commitOpts := []repository.CommitOption{
|
||||
repository.WithFiles(map[string]io.Reader{
|
||||
manifests.Path: strings.NewReader(manifests.Content),
|
||||
}),
|
||||
}
|
||||
if signer != nil {
|
||||
commitOpts = append(commitOpts, repository.WithSigner(signer))
|
||||
}
|
||||
commit, err := b.gitClient.Commit(git.Commit{
|
||||
Author: b.signature,
|
||||
Message: commitMsg,
|
||||
}, commitOpts...)
|
||||
}, repository.WithFiles(map[string]io.Reader{
|
||||
manifests.Path: strings.NewReader(manifests.Content),
|
||||
}), repository.WithSigner(signer))
|
||||
if err != nil && err != git.ErrNoStagedFiles {
|
||||
return fmt.Errorf("failed to commit component manifests: %w", err)
|
||||
}
|
||||
@@ -337,27 +330,24 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
||||
b.logger.Successf("generated sync manifests")
|
||||
|
||||
// Write generated files and make a commit
|
||||
signer, err := b.resolveSigner()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to construct commit signer: %w", err)
|
||||
var signer *openpgp.Entity
|
||||
if b.gpgKeyRing != nil {
|
||||
signer, err = getOpenPgpEntity(b.gpgKeyRing, b.gpgPassphrase, b.gpgKeyID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate OpenPGP entity: %w", err)
|
||||
}
|
||||
}
|
||||
commitMsg := "Add Flux sync manifests"
|
||||
if b.commitMessageAppendix != "" {
|
||||
commitMsg = commitMsg + "\n\n" + b.commitMessageAppendix
|
||||
}
|
||||
|
||||
commitOpts := []repository.CommitOption{
|
||||
repository.WithFiles(map[string]io.Reader{
|
||||
kusManifests.Path: strings.NewReader(kusManifests.Content),
|
||||
}),
|
||||
}
|
||||
if signer != nil {
|
||||
commitOpts = append(commitOpts, repository.WithSigner(signer))
|
||||
}
|
||||
commit, err := b.gitClient.Commit(git.Commit{
|
||||
Author: b.signature,
|
||||
Message: commitMsg,
|
||||
}, commitOpts...)
|
||||
}, repository.WithFiles(map[string]io.Reader{
|
||||
kusManifests.Path: strings.NewReader(kusManifests.Content),
|
||||
}), repository.WithSigner(signer))
|
||||
if err != nil && err != git.ErrNoStagedFiles {
|
||||
return fmt.Errorf("failed to commit sync manifests: %w", err)
|
||||
}
|
||||
@@ -521,33 +511,7 @@ func (b *PlainGitBootstrapper) cleanGitRepoDir() error {
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
// resolveSigner returns a signature.Signer derived from the configured
|
||||
// commit-signing options, or (nil, nil) when no signing has been
|
||||
// configured. GPG and SSH signing are mutually exclusive; if both have
|
||||
// been configured the GPG path wins (the caller is responsible for
|
||||
// rejecting the combination at flag-validation time).
|
||||
func (b *PlainGitBootstrapper) resolveSigner() (signature.Signer, error) {
|
||||
switch {
|
||||
case b.gpgKeyRing != nil:
|
||||
entity, err := SelectOpenPGPSigningEntity(b.gpgKeyRing, b.gpgPassphrase, b.gpgKeyID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load OpenPGP signing entity: %w", err)
|
||||
}
|
||||
return signature.NewOpenPGPSigner(entity)
|
||||
case len(b.sshSigningKey) > 0:
|
||||
return signature.NewSSHSigner(b.sshSigningKey, b.sshSigningPassword)
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// SelectOpenPGPSigningEntity selects a single OpenPGP entity from the
|
||||
// given keyring and decrypts its private key with the provided
|
||||
// passphrase. When keyID is empty the keyring must contain exactly one
|
||||
// entity; otherwise the entity with the matching 16-character key ID
|
||||
// is selected. Returns an error if no matching entity is found, the
|
||||
// matching entity has no private key, or decryption fails.
|
||||
func SelectOpenPGPSigningEntity(keyRing openpgp.EntityList, passphrase, keyID string) (*openpgp.Entity, error) {
|
||||
func getOpenPgpEntity(keyRing openpgp.EntityList, passphrase, keyID string) (*openpgp.Entity, error) {
|
||||
if len(keyRing) == 0 {
|
||||
return nil, fmt.Errorf("empty GPG key ring")
|
||||
}
|
||||
@@ -574,10 +538,6 @@ func SelectOpenPGPSigningEntity(keyRing openpgp.EntityList, passphrase, keyID st
|
||||
}
|
||||
} else {
|
||||
entity = keyRing[0]
|
||||
if entity.PrivateKey == nil {
|
||||
return nil, fmt.Errorf("keyring does not contain a private key; " +
|
||||
"export the secret key with 'gpg --export-secret-keys' or specify --gpg-key-id")
|
||||
}
|
||||
}
|
||||
|
||||
err := entity.PrivateKey.Decrypt([]byte(passphrase))
|
||||
|
||||
@@ -18,23 +18,10 @@ package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"encoding/pem"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
gogit "github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/fluxcd/pkg/git/repository"
|
||||
"github.com/fluxcd/pkg/git/signature"
|
||||
extgogit "github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
. "github.com/onsi/gomega"
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -481,164 +468,3 @@ func Test_objectReconciled(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlainGitBootstrapper_resolveSigner(t *testing.T) {
|
||||
t.Run("no signing configured returns nil signer", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
b := &PlainGitBootstrapper{}
|
||||
signer, err := b.resolveSigner()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(signer).To(BeNil())
|
||||
})
|
||||
|
||||
t.Run("GPG key ring returns an OpenPGP signer", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
entity, err := openpgp.NewEntity("Alice", "test", "alice@example.com", nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
b := &PlainGitBootstrapper{gpgKeyRing: openpgp.EntityList{entity}}
|
||||
signer, err := b.resolveSigner()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(signer).ToNot(BeNil())
|
||||
})
|
||||
|
||||
t.Run("SSH key returns an SSH signer", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
_, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
block, err := gossh.MarshalPrivateKey(priv, "test ed25519 key")
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
pemBytes := pem.EncodeToMemory(block)
|
||||
|
||||
b := &PlainGitBootstrapper{sshSigningKey: pemBytes}
|
||||
signer, err := b.resolveSigner()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(signer).ToNot(BeNil())
|
||||
})
|
||||
|
||||
t.Run("encrypted SSH key without password errors", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
_, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
block, err := gossh.MarshalPrivateKeyWithPassphrase(priv, "test ed25519 key", []byte("pw"))
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
pemBytes := pem.EncodeToMemory(block)
|
||||
|
||||
b := &PlainGitBootstrapper{sshSigningKey: pemBytes}
|
||||
_, err = b.resolveSigner()
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
t.Run("GPG path takes precedence over SSH path", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
entity, err := openpgp.NewEntity("Alice", "test", "alice@example.com", nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
b := &PlainGitBootstrapper{
|
||||
gpgKeyRing: openpgp.EntityList{entity},
|
||||
sshSigningKey: []byte("ignored"),
|
||||
}
|
||||
signer, err := b.resolveSigner()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(signer).ToNot(BeNil())
|
||||
})
|
||||
}
|
||||
|
||||
func TestSelectOpenPGPSigningEntity(t *testing.T) {
|
||||
t.Run("empty key ring errors", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
_, err := SelectOpenPGPSigningEntity(openpgp.EntityList{}, "", "")
|
||||
g.Expect(err).To(MatchError(ContainSubstring("empty GPG key ring")))
|
||||
})
|
||||
|
||||
t.Run("public-only key ring without key id errors instead of panicking", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
entity, err := openpgp.NewEntity("Alice", "test", "alice@example.com", nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
entity.PrivateKey = nil
|
||||
|
||||
_, err = SelectOpenPGPSigningEntity(openpgp.EntityList{entity}, "", "")
|
||||
g.Expect(err).To(MatchError(ContainSubstring("keyring does not contain a private key")))
|
||||
})
|
||||
|
||||
t.Run("public-only key ring with matching key id errors with key id context", func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
entity, err := openpgp.NewEntity("Alice", "test", "alice@example.com", nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
keyID := entity.PrimaryKey.KeyIdString()
|
||||
entity.PrivateKey = nil
|
||||
|
||||
_, err = SelectOpenPGPSigningEntity(openpgp.EntityList{entity}, "", keyID)
|
||||
g.Expect(err).To(MatchError(ContainSubstring("keyring does not contain private key for key id")))
|
||||
})
|
||||
}
|
||||
|
||||
// TestPlainGitBootstrapper_sshSignerProducesVerifiableCommit is an
|
||||
// end-to-end wiring test. resolveSigner already has unit tests for
|
||||
// dispatch behaviour, but nothing in pkg/bootstrap exercises the full
|
||||
// path from sshSigningKey → resolveSigner → repository.WithSigner →
|
||||
// gogit.Client.Commit → gpgsig header on the resulting commit object.
|
||||
// This test drives that path and then verifies the signature via
|
||||
// signature.VerifySSHSignature, catching regressions that the existing
|
||||
// dispatcher unit tests would miss.
|
||||
func TestPlainGitBootstrapper_sshSignerProducesVerifiableCommit(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
// Generate an ed25519 keypair and marshal the private key to PEM.
|
||||
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
pemBlock, err := gossh.MarshalPrivateKey(priv, "test ed25519 key")
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
pemBytes := pem.EncodeToMemory(pemBlock)
|
||||
|
||||
// Resolve a Signer via the same path the bootstrap commit code uses.
|
||||
b := &PlainGitBootstrapper{sshSigningKey: pemBytes}
|
||||
signer, err := b.resolveSigner()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(signer).ToNot(BeNil())
|
||||
|
||||
// Initialise a gogit.Client against a fresh on-disk repo. Init sets
|
||||
// the internal repository pointer so that Commit can operate.
|
||||
tmp := t.TempDir()
|
||||
gogitClient, err := gogit.NewClient(tmp, nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
// Use a file:// URL; Init only records the remote URL, it does not
|
||||
// actually connect, so any syntactically valid URL works here.
|
||||
g.Expect(gogitClient.Init(context.Background(), "file:///dev/null", git.DefaultBranch)).To(Succeed())
|
||||
|
||||
// Drive a commit through the same gogit pipeline bootstrap uses.
|
||||
hash, err := gogitClient.Commit(
|
||||
git.Commit{
|
||||
Author: git.Signature{Name: "Test", Email: "test@example.com"},
|
||||
Message: "ssh-signed test commit",
|
||||
},
|
||||
repository.WithFiles(map[string]io.Reader{
|
||||
"signed-file": strings.NewReader("hello sshsig"),
|
||||
}),
|
||||
repository.WithSigner(signer),
|
||||
)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Read the commit object back via a plain go-git open of the same path.
|
||||
repo, err := extgogit.PlainOpen(tmp)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
commit, err := repo.CommitObject(plumbing.NewHash(hash))
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// The commit must carry an SSH signature header.
|
||||
g.Expect(commit.PGPSignature).To(HavePrefix("-----BEGIN SSH SIGNATURE-----"))
|
||||
|
||||
// Reconstruct the canonical payload (commit without signature) and
|
||||
// run the full cryptographic verification against the known public key.
|
||||
encoded := &plumbing.MemoryObject{}
|
||||
g.Expect(commit.EncodeWithoutSignature(encoded)).To(Succeed())
|
||||
payloadReader, err := encoded.Reader()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
payload, err := io.ReadAll(payloadReader)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
gosshPub, err := gossh.NewPublicKey(pub)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
authorizedKey := gossh.MarshalAuthorizedKey(gosshPub)
|
||||
|
||||
_, err = signature.VerifySSHSignature(commit.PGPSignature, payload, string(authorizedKey))
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
@@ -145,34 +145,6 @@ func (o gitCommitSigningOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
o.applyGit(b.PlainGitBootstrapper)
|
||||
}
|
||||
|
||||
// WithSSHCommitSigning configures the bootstrapper to sign commits with
|
||||
// an SSH private key. pem is the PEM-encoded private key (typically the
|
||||
// OpenSSH "-----BEGIN OPENSSH PRIVATE KEY-----" format produced by
|
||||
// ssh-keygen). password is the optional passphrase for the key; pass
|
||||
// nil for an unencrypted key.
|
||||
//
|
||||
// WithSSHCommitSigning and WithGitCommitSigning are mutually exclusive;
|
||||
// calling both is undefined behavior. The caller is responsible for
|
||||
// rejecting that combination before constructing the bootstrapper (the
|
||||
// flux CLI does this in bootstrapValidate).
|
||||
func WithSSHCommitSigning(pem, password []byte) Option {
|
||||
return sshCommitSigningOption{pem: pem, password: password}
|
||||
}
|
||||
|
||||
type sshCommitSigningOption struct {
|
||||
pem []byte
|
||||
password []byte
|
||||
}
|
||||
|
||||
func (o sshCommitSigningOption) applyGit(b *PlainGitBootstrapper) {
|
||||
b.sshSigningKey = o.pem
|
||||
b.sshSigningPassword = o.password
|
||||
}
|
||||
|
||||
func (o sshCommitSigningOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
o.applyGit(b.PlainGitBootstrapper)
|
||||
}
|
||||
|
||||
func LoadEntityListFromPath(path string) (openpgp.EntityList, error) {
|
||||
if path == "" {
|
||||
return nil, nil
|
||||
|
||||
@@ -33,8 +33,6 @@ type Options struct {
|
||||
TargetPath string
|
||||
ManifestFile string
|
||||
RecurseSubmodules bool
|
||||
Provider string
|
||||
SparseCheckout []string
|
||||
}
|
||||
|
||||
func MakeDefaultOptions() Options {
|
||||
|
||||
@@ -68,8 +68,6 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
Name: options.Secret,
|
||||
},
|
||||
RecurseSubmodules: options.RecurseSubmodules,
|
||||
Provider: options.Provider,
|
||||
SparseCheckout: options.SparseCheckout,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+52
-48
@@ -3,61 +3,63 @@ module github.com/fluxcd/flux2/tests/integration
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
cloud.google.com/go/pubsub/v2 v2.6.0
|
||||
cloud.google.com/go/pubsub/v2 v2.0.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/v2 v2.0.2
|
||||
github.com/chainguard-dev/git-urls v1.0.2
|
||||
github.com/fluxcd/helm-controller/api v1.5.5
|
||||
github.com/fluxcd/image-automation-controller/api v1.1.4
|
||||
github.com/fluxcd/image-reflector-controller/api v1.1.2
|
||||
github.com/fluxcd/kustomize-controller/api v1.8.5
|
||||
github.com/fluxcd/notification-controller/api v1.8.4
|
||||
github.com/fluxcd/pkg/apis/event v0.27.1
|
||||
github.com/fluxcd/pkg/apis/meta v1.30.1
|
||||
github.com/fluxcd/pkg/git v0.52.0
|
||||
github.com/fluxcd/pkg/runtime v0.110.1
|
||||
github.com/fluxcd/source-controller/api v1.8.5
|
||||
github.com/fluxcd/test-infra/tftestenv v0.0.0-20260419142339-c6535d1fff77
|
||||
github.com/fluxcd/helm-controller/api v1.4.5
|
||||
github.com/fluxcd/image-automation-controller/api v1.0.4
|
||||
github.com/fluxcd/image-reflector-controller/api v1.0.4
|
||||
github.com/fluxcd/kustomize-controller/api v1.7.3
|
||||
github.com/fluxcd/notification-controller/api v1.7.5
|
||||
github.com/fluxcd/pkg/apis/event v0.26.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.27.0
|
||||
github.com/fluxcd/pkg/git v0.49.0
|
||||
github.com/fluxcd/pkg/runtime v0.106.0
|
||||
github.com/fluxcd/source-controller/api v1.7.4
|
||||
github.com/fluxcd/test-infra/tftestenv v0.0.0-20250626232827-e0ca9c3f8d7b
|
||||
github.com/go-git/go-git/v5 v5.19.1
|
||||
github.com/google/go-containerregistry v0.21.6
|
||||
github.com/hashicorp/terraform-exec v0.25.2
|
||||
github.com/google/go-containerregistry v0.20.7
|
||||
github.com/hashicorp/terraform-exec v0.24.0
|
||||
github.com/hashicorp/terraform-json v0.27.2
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
|
||||
github.com/onsi/gomega v1.42.1
|
||||
google.golang.org/grpc v1.81.1
|
||||
k8s.io/api v0.36.2
|
||||
k8s.io/apimachinery v0.36.2
|
||||
k8s.io/client-go v0.36.2
|
||||
sigs.k8s.io/controller-runtime v0.24.1
|
||||
github.com/onsi/gomega v1.40.0
|
||||
google.golang.org/grpc v1.79.3
|
||||
k8s.io/api v0.36.0
|
||||
k8s.io/apimachinery v0.36.0
|
||||
k8s.io/client-go v0.36.0
|
||||
sigs.k8s.io/controller-runtime v0.24.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.123.0 // indirect
|
||||
cloud.google.com/go/auth v0.18.2 // indirect
|
||||
cloud.google.com/go v0.121.6 // indirect
|
||||
cloud.google.com/go/auth v0.16.4 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
cloud.google.com/go/iam v1.7.0 // indirect
|
||||
cloud.google.com/go/iam v1.5.2 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
|
||||
github.com/Azure/go-amqp v1.5.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.5.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.4.1 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.18.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v29.4.3+incompatible // indirect
|
||||
github.com/docker/cli v29.2.0+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.3 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.10.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.19.1 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.18.0 // indirect
|
||||
github.com/fluxcd/pkg/ssh v0.25.0 // indirect
|
||||
github.com/fluxcd/pkg/version v0.16.0 // indirect
|
||||
github.com/fluxcd/pkg/version v0.15.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.9.0 // indirect
|
||||
@@ -72,22 +74,22 @@ require (
|
||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.21.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
|
||||
github.com/hashicorp/go-version v1.9.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.9.5 // indirect
|
||||
github.com/hiddeco/sshsig v0.2.0 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.9.2 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.18.6 // indirect
|
||||
github.com/klauspost/compress v1.18.1 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
@@ -96,12 +98,14 @@ require (
|
||||
github.com/pjbgf/sha1cd v0.6.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/vbatts/tar-split v0.12.2 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/zclconf/go-cty v1.18.1 // indirect
|
||||
github.com/zclconf/go-cty v1.16.4 // indirect
|
||||
go.einride.tech/aip v0.73.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 // indirect
|
||||
@@ -111,29 +115,29 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.43.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.53.0 // indirect
|
||||
golang.org/x/mod v0.36.0 // indirect
|
||||
golang.org/x/net v0.56.0 // indirect
|
||||
golang.org/x/crypto v0.50.0 // indirect
|
||||
golang.org/x/mod v0.34.0 // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/sync v0.21.0 // indirect
|
||||
golang.org/x/sys v0.46.0 // indirect
|
||||
golang.org/x/term v0.44.0 // indirect
|
||||
golang.org/x/text v0.38.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/term v0.42.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
google.golang.org/api v0.274.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f // indirect
|
||||
google.golang.org/api v0.247.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gotest.tools/v3 v3.5.2 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.36.2 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.36.0 // indirect
|
||||
k8s.io/klog/v2 v2.140.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 // indirect
|
||||
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect
|
||||
|
||||
+119
-112
@@ -1,16 +1,16 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
|
||||
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
|
||||
cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=
|
||||
cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M=
|
||||
cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c=
|
||||
cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI=
|
||||
cloud.google.com/go/auth v0.16.4 h1:fXOAIQmkApVvcIn7Pc2+5J8QTMVbUGLscnSVNl11su8=
|
||||
cloud.google.com/go/auth v0.16.4/go.mod h1:j10ncYwjX/g3cdX7GpEzsdM+d+ZNsXAbb6qXA7p1Y5M=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
||||
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
|
||||
cloud.google.com/go/iam v1.7.0 h1:JD3zh0C6LHl16aCn5Akff0+GELdp1+4hmh6ndoFLl8U=
|
||||
cloud.google.com/go/iam v1.7.0/go.mod h1:tetWZW1PD/m6vcuY2Zj/aU0eCHNPuxedbnbRTyKXvdY=
|
||||
cloud.google.com/go/pubsub/v2 v2.6.0 h1:8pjR0id+GTB+krKx5G6AGJoYrHog58w2Q89PCOrfM64=
|
||||
cloud.google.com/go/pubsub/v2 v2.6.0/go.mod h1:4anqvV/w8Pcgu2tO0qr2XgsF3GXHowzryfQ5gOnVmWY=
|
||||
cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8=
|
||||
cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE=
|
||||
cloud.google.com/go/pubsub/v2 v2.0.0 h1:0qS6mRJ41gD1lNmM/vdm6bR7DQu6coQcVwD+VPf0Bz0=
|
||||
cloud.google.com/go/pubsub/v2 v2.0.0/go.mod h1:0aztFxNzVQIRSZ8vUr79uH2bS3jwLebwK6q1sgEub+E=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||
@@ -32,8 +32,8 @@ github.com/Azure/go-amqp v1.5.0/go.mod h1:vZAogwdrkbyK3Mla8m/CxSc/aKdnTZ4IbPxl51
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE=
|
||||
github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
@@ -56,18 +56,22 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik=
|
||||
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4=
|
||||
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w=
|
||||
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI=
|
||||
github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
|
||||
github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.18.1 h1:cy2/lpgBXDA3cDKSyEfNOFMA/c10O1axL69EU7iirO8=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.18.1/go.mod h1:ALIEqa7B6oVDsrF37GkGN20SuvG/pIMm7FwP7ZmRb0Q=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/cli v29.4.3+incompatible h1:u+UliYm2J/rYrIh2FqHQg32neRG8GjbvNuwQRTzGspU=
|
||||
github.com/docker/cli v29.4.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v29.2.0+incompatible h1:9oBd9+YM7rxjZLfyMGxjraKBKE4/nVyvVfN4qNl9XRM=
|
||||
github.com/docker/cli v29.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
||||
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||
github.com/elazarl/goproxy v1.8.0 h1:dt561rX7UAYMeFRLtzFx6uQGl2TpL1dr6uCG23nFQSY=
|
||||
@@ -80,11 +84,11 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA=
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
|
||||
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
@@ -93,38 +97,38 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg=
|
||||
github.com/fluxcd/gitkit v0.6.0/go.mod h1:svOHuKi0fO9HoawdK4HfHAJJseZDHHjk7I3ihnCIqNo=
|
||||
github.com/fluxcd/helm-controller/api v1.5.5 h1:xQA/9gbifMvZPGhSNKHsrkq829dI/yTBASVdYp9/s4Y=
|
||||
github.com/fluxcd/helm-controller/api v1.5.5/go.mod h1:lTgeUmtVYExMKp7mRDncsr4JwHTz3LFtLjRJZeR98lI=
|
||||
github.com/fluxcd/image-automation-controller/api v1.1.4 h1:i78AwbcICXSX+a1MQwjNA1Uxxs1e3kfi3EJ21fWzb7w=
|
||||
github.com/fluxcd/image-automation-controller/api v1.1.4/go.mod h1:lkD/drkD6Wc+2SDjVj5KqfozEucTLFexWgby/5ft660=
|
||||
github.com/fluxcd/image-reflector-controller/api v1.1.2 h1:VPwUgA8WyPVVs16uSkwvjOAY6pvTYgAb0fL90t0RKLE=
|
||||
github.com/fluxcd/image-reflector-controller/api v1.1.2/go.mod h1:j4JSIocL42HQ77Veg1t60sApOy+lng8/cbXHXGSnfi0=
|
||||
github.com/fluxcd/kustomize-controller/api v1.8.5 h1:4fGPh6foGVKUUbt5OjVzbC5iTyX+Q+NS50atPboDC4w=
|
||||
github.com/fluxcd/kustomize-controller/api v1.8.5/go.mod h1:c/mUPIffDDLg1EicXCJtX4N/rc+z5Zh0e/CXjhd7Dyc=
|
||||
github.com/fluxcd/notification-controller/api v1.8.4 h1:KhHHVhQNtQsY+cVm/Y/8vhhFfrEOxM2AL/8JF8LAjMg=
|
||||
github.com/fluxcd/notification-controller/api v1.8.4/go.mod h1:ozgJGQPy0dG5eOsLZlwAr6n0q/y6+TWd1fGOtavlXJA=
|
||||
github.com/fluxcd/helm-controller/api v1.4.5 h1:hMEBtgXUbJjp+ah0jPI3OOQNVngoToOQvTgFgVpAjNg=
|
||||
github.com/fluxcd/helm-controller/api v1.4.5/go.mod h1:rCgx3qhjjtoIH+1EbzFC2vN71/pp0PgMDrZnGCZX5XY=
|
||||
github.com/fluxcd/image-automation-controller/api v1.0.4 h1:Fgdy97hXkyh/JFjxLIyq4ZDHsKsa49aumtrvIyjVd08=
|
||||
github.com/fluxcd/image-automation-controller/api v1.0.4/go.mod h1:LLBf4XQJAgnpIMlZUwfpVIkCdUtBOi31B6fDbPwBCq4=
|
||||
github.com/fluxcd/image-reflector-controller/api v1.0.4 h1:/JGpTZf4eMcKG2FpWfP5H7SneSrD5P8EvwGnHiH/WLY=
|
||||
github.com/fluxcd/image-reflector-controller/api v1.0.4/go.mod h1:5GS4ojHaz+W6hK80WakGIOYk8sn93AyV5X+YOne1XMw=
|
||||
github.com/fluxcd/kustomize-controller/api v1.7.3 h1:g+C9Il+H33DQi/ZiQ8KpTvL9KXebXnS4oM/0uJ/C8Gw=
|
||||
github.com/fluxcd/kustomize-controller/api v1.7.3/go.mod h1:Yj80JyfQpBUgLhsUZ/c86qcvPGO2+P1VCKsb8fL+L/k=
|
||||
github.com/fluxcd/notification-controller/api v1.7.5 h1:6CO5bKyjodiK9exQFOdBcz0XLeo17rrrWQBTJL9NNa8=
|
||||
github.com/fluxcd/notification-controller/api v1.7.5/go.mod h1:IciwSg8Q0pVtdbsyDyEXx/MxBKWeagxAazpm64C8oCE=
|
||||
github.com/fluxcd/pkg/apis/acl v0.10.0 h1:KPfAmELNvtvaz8wixnm/MYXqa+MJf7ntVVMUU93Aenk=
|
||||
github.com/fluxcd/pkg/apis/acl v0.10.0/go.mod h1:a87i2A7AlFO5N2J8CxtzaUCCDmuLLWOHwkKu3eJF5fY=
|
||||
github.com/fluxcd/pkg/apis/event v0.27.1 h1:bFnP6gcZzCVm/Dxf/ByFz6BW+FzSn4RoWUkf7ri2bOs=
|
||||
github.com/fluxcd/pkg/apis/event v0.27.1/go.mod h1:ThqUZxG48o5PDN9Qh0tVTdpb+6PlVa6J2beEeMZoKMk=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.19.1 h1:rmN3hTceBVABGbrqRXEDYoAJDBUIPFRO9zbDJ98Xt/o=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.19.1/go.mod h1:9FUs77fd/Rh5/mDgZbGBUCL0UqmXiGj8rYywG3T3x+s=
|
||||
github.com/fluxcd/pkg/apis/meta v1.30.1 h1:TRqdvb/zo9h9Ig10xHxV7jMilG+e1jOv3djI00GFr9g=
|
||||
github.com/fluxcd/pkg/apis/meta v1.30.1/go.mod h1:Gx+YRq26a+mTbCjotSXC7/6kSSyo0zXQ8JnsEXf2vVk=
|
||||
github.com/fluxcd/pkg/git v0.52.0 h1:dgsliHdaLADUcDO4pI0pc11N4dZ21NfDdhNcgRNuAkM=
|
||||
github.com/fluxcd/pkg/git v0.52.0/go.mod h1:mOvFDxoiuz+Mm4Ux1wKeTTckvBgZFvbTK8lNxmVHzKs=
|
||||
github.com/fluxcd/pkg/apis/event v0.26.0 h1:QzBRz9Qy91jzJmLlOhd4ecp6OWDpMVFvm311AwxCXzY=
|
||||
github.com/fluxcd/pkg/apis/event v0.26.0/go.mod h1:0yy7FMJABzq8PP5/VEi1Gro6ssPaPlH9xuPIoF+Rm6M=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.18.0 h1:FCNjViCLyKYj6lddpnjXybKBTC2eK6eXK9YOaNwLVTM=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.18.0/go.mod h1:mvtMtM4NNLipdCna6DYPC6Bd42xeaF15N+tNO+F6kxY=
|
||||
github.com/fluxcd/pkg/apis/meta v1.27.0 h1:EspByEk5j8w3rs1cGbEh9AjSmpDwQIz7DFG/zzqf6uI=
|
||||
github.com/fluxcd/pkg/apis/meta v1.27.0/go.mod h1:2t6JyrRfvIBhx6EBnXfFh/6sCCJ1db9WGaqko0JmNOE=
|
||||
github.com/fluxcd/pkg/git v0.49.0 h1:OtI0TjMVC/GV/yPos4waA5fAs5u3/2YEYBFuZuJA3Rc=
|
||||
github.com/fluxcd/pkg/git v0.49.0/go.mod h1:Xnrqtz60/0jqfcy5UsY9sxlvPmlvzelPsej2v3L7wW8=
|
||||
github.com/fluxcd/pkg/gittestserver v0.29.0 h1:2j03zKVL6iVn6oiUuecG/O/3Q1pULWM9JrF/HSjkpnc=
|
||||
github.com/fluxcd/pkg/gittestserver v0.29.0/go.mod h1:O8151jV0ppBZTb9IUXMjxh6hZpkiuLq8JQHDBPOkZFw=
|
||||
github.com/fluxcd/pkg/runtime v0.110.1 h1:O7eVI/R40MQMQpi6cAlWsNka2hZ0YfMXzETmui9D06c=
|
||||
github.com/fluxcd/pkg/runtime v0.110.1/go.mod h1:h5HDYgi4RXHGZD/5TCdy/47Vdlplf3/KM6U8aEDcagA=
|
||||
github.com/fluxcd/pkg/runtime v0.106.0 h1:SGzUaO/G6bUBLkZIxLGnCVEEURSPuldSG2exYjlrsQk=
|
||||
github.com/fluxcd/pkg/runtime v0.106.0/go.mod h1:7lCogUwTGKoG3bfBvCn6eQgPYF7cvVp5R+gL3bB1HX8=
|
||||
github.com/fluxcd/pkg/ssh v0.25.0 h1:4Y9WmuNqyKvH759UznU5DGHRcOuoJ/dQM6sbsaDZYYM=
|
||||
github.com/fluxcd/pkg/ssh v0.25.0/go.mod h1:Fli2Ogu4uaIVGbCy+r0vvZlMO0RfuInyNY1q2FVIx0o=
|
||||
github.com/fluxcd/pkg/version v0.16.0 h1:VR9+143LAwbyUSAaMhiJHbfsiU+fTjA9L/3dr1ucfrI=
|
||||
github.com/fluxcd/pkg/version v0.16.0/go.mod h1:2M/l90CmbDaD21JTh77hjwaUbd/YM96+Fo8x4fMdxLI=
|
||||
github.com/fluxcd/source-controller/api v1.8.5 h1:mLKc9YVMk46JCt1BQbkG6irkrpBZp95kiXh2+GYB6KQ=
|
||||
github.com/fluxcd/source-controller/api v1.8.5/go.mod h1:sio4t49RDx+S1etHRFAEEw8qfVuw0KKlOg8bRVlEYPM=
|
||||
github.com/fluxcd/test-infra/tftestenv v0.0.0-20260419142339-c6535d1fff77 h1:LyvFHL0C7FooVAt1IgW2vJcKN1FAhk94Gf94hPqCaz4=
|
||||
github.com/fluxcd/test-infra/tftestenv v0.0.0-20260419142339-c6535d1fff77/go.mod h1:liFlLEXgambGVdWSJ4JzbIHf1Vjpp1HwUyPazPIVZug=
|
||||
github.com/fluxcd/pkg/version v0.15.0 h1:E2Ju4i0vj8ZXLHKz/F4a8JTmDh7Jcg8okB0hK5rEoTM=
|
||||
github.com/fluxcd/pkg/version v0.15.0/go.mod h1:LEHnvLMgbTk4kelF+JHHzaG77kY9uTWodMtadPRMEW8=
|
||||
github.com/fluxcd/source-controller/api v1.7.4 h1:+EOVnRA9LmLxOx7J273l7IOEU39m+Slt/nQGBy69ygs=
|
||||
github.com/fluxcd/source-controller/api v1.7.4/go.mod h1:ruf49LEgZRBfcP+eshl2n9SX1MfHayCcViAIGnZcaDY=
|
||||
github.com/fluxcd/test-infra/tftestenv v0.0.0-20250626232827-e0ca9c3f8d7b h1:FSPtvaVgL8azcyweqLmD71elAw4vozuXH/QvsJQ7tg0=
|
||||
github.com/fluxcd/test-infra/tftestenv v0.0.0-20250626232827-e0ca9c3f8d7b/go.mod h1:liFlLEXgambGVdWSJ4JzbIHf1Vjpp1HwUyPazPIVZug=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||
@@ -186,8 +190,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-containerregistry v0.21.6 h1:T+yqQIlJXKrM98Om4DlW3GoWQAmhZuLMwoDOvVrtiUM=
|
||||
github.com/google/go-containerregistry v0.21.6/go.mod h1:U7MMSBIJynke2MVQrQk19NP9k/uQsGz/h0amIFSHMbo=
|
||||
github.com/google/go-containerregistry v0.20.7 h1:24VGNpS0IwrOZ2ms2P1QE3Xa5X9p4phx0aUgzYzHW6I=
|
||||
github.com/google/go-containerregistry v0.20.7/go.mod h1:Lx5LCZQjLH1QBaMPeGwsME9biPeo1lPx6lbGj/UmzgM=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 h1:xhMrHhTJ6zxu3gA4enFM9MLn9AY7613teCdFnlUVbSQ=
|
||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
||||
@@ -197,10 +201,10 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
|
||||
github.com/googleapis/gax-go/v2 v2.21.0 h1:h45NjjzEO3faG9Lg/cFrBh2PgegVVgzqKzuZl/wMbiI=
|
||||
github.com/googleapis/gax-go/v2 v2.21.0/go.mod h1:But/NJU6TnZsrLai/xBAQLLz+Hc7fHZJt/hsCz3Fih4=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
|
||||
github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
|
||||
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -212,16 +216,14 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
|
||||
github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA=
|
||||
github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/hc-install v0.9.5 h1:XHCjcMn2563ysuaQ9v9ec2FNc7c2PJOIEEGobAFeIx4=
|
||||
github.com/hashicorp/hc-install v0.9.5/go.mod h1:ihEW4LshrNkxq2bU/MpVbKyn+yt1is2hYqUTHDGhG84=
|
||||
github.com/hashicorp/terraform-exec v0.25.2 h1:fFLAVEtAjKdGfawGUXDnKooCnqJi+TuohT3W99AGbhk=
|
||||
github.com/hashicorp/terraform-exec v0.25.2/go.mod h1:uaQV2oqVLqM4cixJryk6qIWS1qji3GtuwPG5pjGXYfc=
|
||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/hc-install v0.9.2 h1:v80EtNX4fCVHqzL9Lg/2xkp62bbvQMnvPQ0G+OmtO24=
|
||||
github.com/hashicorp/hc-install v0.9.2/go.mod h1:XUqBQNnuT4RsxoxiM9ZaUk0NX8hi2h+Lb6/c0OZnC/I=
|
||||
github.com/hashicorp/terraform-exec v0.24.0 h1:mL0xlk9H5g2bn0pPF6JQZk5YlByqSqrO5VoaNtAf8OE=
|
||||
github.com/hashicorp/terraform-exec v0.24.0/go.mod h1:lluc/rDYfAhYdslLJQg3J0oDqo88oGQAdHR+wDqFvo4=
|
||||
github.com/hashicorp/terraform-json v0.27.2 h1:BwGuzM6iUPqf9JYM/Z4AF1OJ5VVJEEzoKST/tRDBJKU=
|
||||
github.com/hashicorp/terraform-json v0.27.2/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE=
|
||||
github.com/hiddeco/sshsig v0.2.0 h1:gMWllgKCITXdydVkDL+Zro0PU96QI55LwUwebSwNTSw=
|
||||
github.com/hiddeco/sshsig v0.2.0/go.mod h1:nJc98aGgiH6Yql2doqH4CTBVHexQA40Q+hMMLHP4EqE=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
@@ -232,8 +234,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
|
||||
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
||||
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
@@ -253,6 +255,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 h1:YH424zrwLTlyHSH/GzLMJeu5zhYVZSx5RQxGKm1h96s=
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5/go.mod h1:PoGiBqKSQK1vIfQ+yVaFcGjDySHvym6FM1cNYnwzbrY=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -263,8 +267,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/onsi/ginkgo/v2 v2.27.4 h1:fcEcQW/A++6aZAZQNUmNjvA9PSOzefMJBerHJ4t8v8Y=
|
||||
github.com/onsi/ginkgo/v2 v2.27.4/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
|
||||
github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I=
|
||||
github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg=
|
||||
github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc=
|
||||
github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
@@ -294,8 +298,8 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
@@ -308,19 +312,22 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4=
|
||||
github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/zclconf/go-cty v1.18.1 h1:yEGE8M4iIZlyKQURZNb2SnEyZlZHUcBCnx6KF81KuwM=
|
||||
github.com/zclconf/go-cty v1.18.1/go.mod h1:qpnV6EDNgC1sns/AleL1fvatHw72j+S+nS+MJ+T2CSg=
|
||||
go.einride.tech/aip v0.83.0 h1:TI21IdeOnLTwZEJ3BxtImIZk6bsN2Q+sd0x99SLiQ+M=
|
||||
go.einride.tech/aip v0.83.0/go.mod h1:E8+wdTApA70odnpFzJgsGogHozC2JCIhFJBKPr8bVig=
|
||||
github.com/zclconf/go-cty v1.16.4 h1:QGXaag7/7dCzb+odlGrgr+YmYZFaOCMW6DEpS+UD1eE=
|
||||
github.com/zclconf/go-cty v1.16.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||
go.einride.tech/aip v0.73.0 h1:bPo4oqBo2ZQeBKo4ZzLb1kxYXTY1ysJhpvQyfuGzvps=
|
||||
go.einride.tech/aip v0.73.0/go.mod h1:Mj7rFbmXEgw0dq1dqJ7JGMvYCZZVxmGOR3S4ZcV5LvQ=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
@@ -333,10 +340,10 @@ go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
@@ -350,14 +357,14 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
|
||||
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
|
||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4=
|
||||
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
|
||||
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -365,16 +372,16 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -385,16 +392,16 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
|
||||
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
|
||||
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
||||
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
|
||||
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -402,31 +409,31 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
|
||||
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
|
||||
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
|
||||
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.274.0 h1:aYhycS5QQCwxHLwfEHRRLf9yNsfvp1JadKKWBE54RFA=
|
||||
google.golang.org/api v0.274.0/go.mod h1:JbAt7mF+XVmWu6xNP8/+CTiGH30ofmCmk9nM8d8fHew=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/api v0.247.0 h1:tSd/e0QrUlLsrwMKmkbQhYVa109qIintOls2Wh6bngc=
|
||||
google.golang.org/api v0.247.0/go.mod h1:r1qZOPmxXffXg6xS5uhx16Fa/UFY8QU/K4bfKrnvovM=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0=
|
||||
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f h1:Rka45QInERYknkHYfJEPBQaoobXl+YpxTMjAKgWUq2A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401001100-f93e5f3e9f0f/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
|
||||
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -457,22 +464,22 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.36.2 h1:TF6YDLIzKfccK7cq9YpTcGX8TJmEkHVRv78DM51fRYY=
|
||||
k8s.io/api v0.36.2/go.mod h1:F4LbMO4brjZYh7yFkXWhynSvtB7YauxV4c+HHkNRGNg=
|
||||
k8s.io/apiextensions-apiserver v0.36.2 h1:3O5gqOj/dt2XWWbpMe+TXWpE9yU6pjM/tXxtHHJT/K4=
|
||||
k8s.io/apiextensions-apiserver v0.36.2/go.mod h1:cL1tBWe8XSaP1H30iWKGo7hf6iAUUUJPEU70dskmAnA=
|
||||
k8s.io/apimachinery v0.36.2 h1:0PE/W/WNy1UX61NLbXY5TMbJ6UwLL6E6lAPkYrKFxbQ=
|
||||
k8s.io/apimachinery v0.36.2/go.mod h1:fvf/HOLXq9RId0rnDIbN1OEBvHXdQbLMM8nu0LcBUf4=
|
||||
k8s.io/client-go v0.36.2 h1:bfgxmFKc9CgqsgX4xKLAAdmTQlWee7Ob/HlDOrJ5TBI=
|
||||
k8s.io/client-go v0.36.2/go.mod h1:1vgO4OAlfPnoLcb+Rze2GF5rAr14w8qjrYMoyXJzQj0=
|
||||
k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80=
|
||||
k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34=
|
||||
k8s.io/apiextensions-apiserver v0.36.0 h1:Wt7E8J+VBCbj4FjiBfDTK/neXDDjyJVJc7xfuOHImZ0=
|
||||
k8s.io/apiextensions-apiserver v0.36.0/go.mod h1:kGDjH0msuiIB3tgsYRV0kS9GqpMYMUsQ3GHv7TApyug=
|
||||
k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ=
|
||||
k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc=
|
||||
k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c=
|
||||
k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y=
|
||||
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
|
||||
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
|
||||
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hkbPJgdATINPMAxaynU2Ovg=
|
||||
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0=
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 h1:wU4tMEhLGgIbLvXQb1cfN+EcM0wf7zC6CPF+C79jroc=
|
||||
k8s.io/utils v0.0.0-20260507154919-ff6756f316d2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4=
|
||||
sigs.k8s.io/controller-runtime v0.24.1/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw=
|
||||
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU=
|
||||
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
sigs.k8s.io/controller-runtime v0.24.0 h1:Ck6N2LdS8Lovy1o25BB4r1xjvLEKUl1s2o9kU+KWDE4=
|
||||
sigs.k8s.io/controller-runtime v0.24.0/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
|
||||
Reference in New Issue
Block a user