Compare commits
164 Commits
release/v2
...
conform-k8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d04b74fd8d | ||
|
|
975132714b | ||
|
|
09af0becc5 | ||
|
|
d84bff7d1b | ||
|
|
a4c513487e | ||
|
|
2046003714 | ||
|
|
f07ee355ea | ||
|
|
5e02724e49 | ||
|
|
e5926bcaad | ||
|
|
355f2bc5f3 | ||
|
|
7e8e0ab772 | ||
|
|
f0fecf7399 | ||
|
|
54db4ffc8b | ||
|
|
73fff7404f | ||
|
|
24057743bb | ||
|
|
04d87be082 | ||
|
|
e7c6ebccc3 | ||
|
|
48382f885b | ||
|
|
511d8346f2 | ||
|
|
f0e8e84ee0 | ||
|
|
c277fbf14e | ||
|
|
28570296a9 | ||
|
|
39ec0cb594 | ||
|
|
af67405ee4 | ||
|
|
6f65c92fe7 | ||
|
|
c84d312289 | ||
|
|
d37473ff44 | ||
|
|
712b03727a | ||
|
|
14da7d58be | ||
|
|
45da6a86f8 | ||
|
|
3053a0b840 | ||
|
|
96f95b6b4c | ||
|
|
cf92e02f53 | ||
|
|
ce50286a92 | ||
|
|
c15eb30b0d | ||
|
|
8bedcc46d4 | ||
|
|
5d64a9fc76 | ||
|
|
035afd9533 | ||
|
|
c859688b37 | ||
|
|
13b1d199ee | ||
|
|
5f9108c53f | ||
|
|
abf52ff866 | ||
|
|
b319ee1ddf | ||
|
|
b564d2fb3b | ||
|
|
d9e25d86aa | ||
|
|
dcc4251a2a | ||
|
|
960f72fe6a | ||
|
|
6f815a36fe | ||
|
|
1d08cace4f | ||
|
|
cfd369df47 | ||
|
|
9e6f723436 | ||
|
|
e4325961af | ||
|
|
74d748f547 | ||
|
|
6f6d3fb269 | ||
|
|
e51e5df9da | ||
|
|
f604d7f342 | ||
|
|
3346542917 | ||
|
|
f0e7f92ef1 | ||
|
|
e09ba7a8e6 | ||
|
|
f29bcfb108 | ||
|
|
2e9e8e2690 | ||
|
|
3478fe343d | ||
|
|
8b10a32088 | ||
|
|
16ae23a3a6 | ||
|
|
055958d533 | ||
|
|
0cc68e0521 | ||
|
|
fae5d62b07 | ||
|
|
16f55bbf22 | ||
|
|
83c16f9c4a | ||
|
|
b232bbe004 | ||
|
|
5208515604 | ||
|
|
928ea24bcb | ||
|
|
9b1b5e8a51 | ||
|
|
5b740c45d1 | ||
|
|
19568eb94e | ||
|
|
5cf0dcc77d | ||
|
|
b45a8b5c1f | ||
|
|
2b68c8c664 | ||
|
|
939cffa561 | ||
|
|
30ed414938 | ||
|
|
d51a2f8bce | ||
|
|
120ec049f9 | ||
|
|
aa9de2c6bc | ||
|
|
226cb462c2 | ||
|
|
b1bdab4e6a | ||
|
|
8110d2f05d | ||
|
|
13c56f3e4e | ||
|
|
1013e98c0f | ||
|
|
85405928a7 | ||
|
|
570bc81278 | ||
|
|
f42a17de54 | ||
|
|
7697699e65 | ||
|
|
9f854cb7e2 | ||
|
|
995e1dcc32 | ||
|
|
5b83111dc6 | ||
|
|
9abc802f15 | ||
|
|
2a5948fe42 | ||
|
|
af765388d2 | ||
|
|
5350425cdc | ||
|
|
6611a4fba6 | ||
|
|
297b15b82b | ||
|
|
56a3d08bf8 | ||
|
|
cf26cf25f1 | ||
|
|
a3dbf31e87 | ||
|
|
3e4524b987 | ||
|
|
8470f23ad2 | ||
|
|
e17f3f0168 | ||
|
|
e0b8464a6c | ||
|
|
2c7d781ec5 | ||
|
|
c7daf6466f | ||
|
|
0d101e0e36 | ||
|
|
0a5d263f77 | ||
|
|
7d7a8f81f4 | ||
|
|
cbda2be6b8 | ||
|
|
d5427d12cf | ||
|
|
e970a2d6a7 | ||
|
|
a4ef1f6992 | ||
|
|
055d85fc18 | ||
|
|
927f3e50f6 | ||
|
|
d13dec297a | ||
|
|
2d37544b06 | ||
|
|
1b4de026dd | ||
|
|
9af1e85b93 | ||
|
|
cb327a793e | ||
|
|
82671cfd24 | ||
|
|
69964519e7 | ||
|
|
1ac06fd859 | ||
|
|
1563d2b81b | ||
|
|
285495a0e7 | ||
|
|
16e30439b7 | ||
|
|
36dec31fd7 | ||
|
|
bd1ff8f771 | ||
|
|
83402e8834 | ||
|
|
cc87ffd66e | ||
|
|
c39af08b47 | ||
|
|
18e0087439 | ||
|
|
1b0eecd145 | ||
|
|
2694dfd489 | ||
|
|
466d30047a | ||
|
|
2281013050 | ||
|
|
e06e561150 | ||
|
|
41bdb88be2 | ||
|
|
52512a94a8 | ||
|
|
170e4f6f57 | ||
|
|
b8bf44e0ae | ||
|
|
f6a0250712 | ||
|
|
31d160b309 | ||
|
|
fabdbaaf92 | ||
|
|
a9017239b7 | ||
|
|
9f873c0a07 | ||
|
|
0720935fb4 | ||
|
|
298e28b63e | ||
|
|
ec141c63c4 | ||
|
|
b45cd59b7c | ||
|
|
e42aa8e448 | ||
|
|
a5447e4c77 | ||
|
|
638e537b40 | ||
|
|
d95e8b63e0 | ||
|
|
f5f799b5fc | ||
|
|
f42c91448d | ||
|
|
bde7489e45 | ||
|
|
dcca1328a3 | ||
|
|
ffc1f721ac | ||
|
|
6b062fb82f |
15
.github/labels.yaml
vendored
15
.github/labels.yaml
vendored
@@ -44,15 +44,12 @@
|
||||
description: Feature request proposals in the RFC format
|
||||
color: '#D621C3'
|
||||
aliases: ['area/RFC']
|
||||
- name: backport:release/v2.0.x
|
||||
description: To be backported to release/v2.0.x
|
||||
color: '#ffd700'
|
||||
- name: backport:release/v2.1.x
|
||||
description: To be backported to release/v2.1.x
|
||||
color: '#ffd700'
|
||||
- name: backport:release/v2.2.x
|
||||
description: To be backported to release/v2.2.x
|
||||
color: '#ffd700'
|
||||
- name: backport:release/v2.3.x
|
||||
description: To be backported to release/v2.3.x
|
||||
color: '#ffd700'
|
||||
- name: backport:release/v2.4.x
|
||||
description: To be backported to release/v2.4.x
|
||||
color: '#ffd700'
|
||||
- name: backport:release/v2.5.x
|
||||
description: To be backported to release/v2.5.x
|
||||
color: '#ffd700'
|
||||
|
||||
2
.github/workflows/action.yaml
vendored
2
.github/workflows/action.yaml
vendored
@@ -24,6 +24,6 @@ jobs:
|
||||
name: action on ${{ matrix.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup flux
|
||||
uses: ./action
|
||||
|
||||
7
.github/workflows/backport.yaml
vendored
7
.github/workflows/backport.yaml
vendored
@@ -4,6 +4,9 @@ on:
|
||||
pull_request_target:
|
||||
types: [closed, labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
pull-request:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -13,11 +16,11 @@ jobs:
|
||||
if: github.event.pull_request.state == 'closed' && github.event.pull_request.merged && (github.event_name != 'labeled' || startsWith('backport:', github.event.label.name))
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Create backport PRs
|
||||
uses: korthout/backport-action@bd410d37cdcae80be6d969823ff5a225fe5c833f # v3.0.2
|
||||
uses: korthout/backport-action@be567af183754f6a5d831ae90f648954763f17f5 # v3.1.0
|
||||
# xref: https://github.com/korthout/backport-action#inputs
|
||||
with:
|
||||
# Use token to allow workflows to be triggered for the created PR
|
||||
|
||||
36
.github/workflows/conformance.yaml
vendored
36
.github/workflows/conformance.yaml
vendored
@@ -9,7 +9,7 @@ permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.22.x
|
||||
GO_VERSION: 1.23.x
|
||||
|
||||
jobs:
|
||||
conform-kubernetes:
|
||||
@@ -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.28.11, 1.29.6, 1.30.2 ]
|
||||
KUBERNETES_VERSION: [1.30.9, 1.31.5, 1.32.1, 1.33.0]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: |
|
||||
@@ -40,9 +40,9 @@ jobs:
|
||||
run: |
|
||||
make build
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde # v1.10.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
version: v0.22.0
|
||||
version: v0.27.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.28.7, 1.29.2 ]
|
||||
K3S_VERSION: [ 1.30.9, 1.31.5, 1.32.1 ]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.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@main
|
||||
uses: fluxcd/pkg/actions/kustomize@c964ce7b91949ff4b5e3959db4f1d7bb2e029a49 # 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/compatibility-actions/create-cluster@v1
|
||||
uses: replicatedhq/replicated-actions/create-cluster@c98ab3b97925af5db9faf3f9676df7a9c6736985 # v1.17.0
|
||||
with:
|
||||
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
|
||||
kubernetes-distribution: "k3s"
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
kubectl delete ns flux-system --wait
|
||||
- name: Delete cluster
|
||||
if: ${{ always() }}
|
||||
uses: replicatedhq/replicated-actions/remove-cluster@v1
|
||||
uses: replicatedhq/replicated-actions/remove-cluster@c98ab3b97925af5db9faf3f9676df7a9c6736985 # v1.17.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
|
||||
@@ -169,13 +169,13 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
# Keep this list up-to-date with https://endoflife.date/red-hat-openshift
|
||||
OPENSHIFT_VERSION: [ 4.15.0-okd ]
|
||||
OPENSHIFT_VERSION: [ 4.17.0-okd ]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: |
|
||||
@@ -190,7 +190,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@main
|
||||
uses: fluxcd/pkg/actions/kustomize@c964ce7b91949ff4b5e3959db4f1d7bb2e029a49 # main
|
||||
- name: Build
|
||||
run: make build-dev
|
||||
- name: Create repository
|
||||
@@ -200,7 +200,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
|
||||
- name: Create cluster
|
||||
id: create-cluster
|
||||
uses: replicatedhq/compatibility-actions/create-cluster@v1
|
||||
uses: replicatedhq/replicated-actions/create-cluster@c98ab3b97925af5db9faf3f9676df7a9c6736985 # v1.17.0
|
||||
with:
|
||||
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
|
||||
kubernetes-distribution: "openshift"
|
||||
@@ -242,7 +242,7 @@ jobs:
|
||||
kubectl delete ns flux-system --wait
|
||||
- name: Delete cluster
|
||||
if: ${{ always() }}
|
||||
uses: replicatedhq/replicated-actions/remove-cluster@v1
|
||||
uses: replicatedhq/replicated-actions/remove-cluster@c98ab3b97925af5db9faf3f9676df7a9c6736985 # v1.17.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
|
||||
|
||||
10
.github/workflows/e2e-azure.yaml
vendored
10
.github/workflows/e2e-azure.yaml
vendored
@@ -30,12 +30,14 @@ jobs:
|
||||
if: false && (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@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version: 1.22.x
|
||||
go-version: 1.23.x
|
||||
cache-dependency-path: tests/integration/go.sum
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
|
||||
- name: Setup Flux CLI
|
||||
run: make build
|
||||
working-directory: ./
|
||||
@@ -47,7 +49,7 @@ jobs:
|
||||
env:
|
||||
SOPS_VER: 3.7.1
|
||||
- name: Authenticate to Azure
|
||||
uses: Azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v1.4.6
|
||||
uses: Azure/login@a65d910e8af852a8061c627c456678983e180302 # v1.4.6
|
||||
with:
|
||||
creds: '{"clientId":"${{ secrets.AZ_ARM_CLIENT_ID }}","clientSecret":"${{ secrets.AZ_ARM_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZ_ARM_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZ_ARM_TENANT_ID }}"}'
|
||||
- name: Set dynamic variables in .env
|
||||
|
||||
18
.github/workflows/e2e-bootstrap.yaml
vendored
18
.github/workflows/e2e-bootstrap.yaml
vendored
@@ -17,27 +17,27 @@ 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@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version: 1.22.x
|
||||
go-version: 1.23.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde # v1.10.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
version: v0.22.0
|
||||
version: v0.24.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.30.0-amd64
|
||||
kubectl_version: v1.30.0
|
||||
node_image: ghcr.io/fluxcd/kindest/node:v1.31.0-amd64
|
||||
kubectl_version: v1.31.0
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
uses: fluxcd/pkg/actions/kustomize@c964ce7b91949ff4b5e3959db4f1d7bb2e029a49 # main
|
||||
- name: Setup yq
|
||||
uses: fluxcd/pkg/actions/yq@main
|
||||
uses: fluxcd/pkg/actions/yq@c964ce7b91949ff4b5e3959db4f1d7bb2e029a49 # main
|
||||
- name: Build
|
||||
run: make build-dev
|
||||
- name: Set outputs
|
||||
|
||||
18
.github/workflows/e2e-gcp.yaml
vendored
18
.github/workflows/e2e-gcp.yaml
vendored
@@ -29,12 +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@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version: 1.22.x
|
||||
go-version: 1.23.x
|
||||
cache-dependency-path: tests/integration/go.sum
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
|
||||
- name: Setup Flux CLI
|
||||
run: make build
|
||||
working-directory: ./
|
||||
@@ -46,19 +48,19 @@ jobs:
|
||||
env:
|
||||
SOPS_VER: 3.7.1
|
||||
- name: Authenticate to Google Cloud
|
||||
uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
|
||||
uses: google-github-actions/auth@71f986410dfbc7added4569d411d040a91dc6935 # v2.1.8
|
||||
id: 'auth'
|
||||
with:
|
||||
credentials_json: '${{ secrets.FLUX2_E2E_GOOGLE_CREDENTIALS }}'
|
||||
token_format: 'access_token'
|
||||
- name: Setup gcloud
|
||||
uses: google-github-actions/setup-gcloud@98ddc00a17442e89a24bbf282954a3b65ce6d200 # v2.1.0
|
||||
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # v2.1.4
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
|
||||
uses: docker/setup-qemu-action@4574d27a4764455b42196d70a065bc6853246a25 # v3.4.0
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
|
||||
uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3.9.0
|
||||
- name: Log into us-central1-docker.pkg.dev
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
|
||||
with:
|
||||
registry: us-central1-docker.pkg.dev
|
||||
username: oauth2accesstoken
|
||||
|
||||
16
.github/workflows/e2e.yaml
vendored
16
.github/workflows/e2e.yaml
vendored
@@ -23,30 +23,30 @@ jobs:
|
||||
- 5000:5000
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version: 1.22.x
|
||||
go-version: 1.23.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde # v1.10.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
version: v0.22.0
|
||||
version: v0.24.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.28.9-amd64
|
||||
kubectl_version: v1.28.9
|
||||
node_image: ghcr.io/fluxcd/kindest/node:v1.30.9-amd64
|
||||
kubectl_version: v1.30.9
|
||||
- name: Setup Calico for network policy
|
||||
run: |
|
||||
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/calico.yaml
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
uses: fluxcd/pkg/actions/kustomize@c964ce7b91949ff4b5e3959db4f1d7bb2e029a49 # main
|
||||
- name: Run tests
|
||||
run: make test
|
||||
- name: Run e2e tests
|
||||
|
||||
8
.github/workflows/ossf.yaml
vendored
8
.github/workflows/ossf.yaml
vendored
@@ -19,21 +19,21 @@ jobs:
|
||||
actions: read
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Run analysis
|
||||
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_results: true
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
- name: Upload SARIF results
|
||||
uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/upload-sarif@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
65
.github/workflows/release.yaml
vendored
65
.github/workflows/release.yaml
vendored
@@ -2,7 +2,7 @@ name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [ 'v*' ]
|
||||
tags: ["v*"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -20,33 +20,33 @@ jobs:
|
||||
packages: write # needed for ghcr access
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Unshallow
|
||||
run: git fetch --prune --unshallow
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version: 1.22.x
|
||||
go-version: 1.23.x
|
||||
cache: false
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
|
||||
uses: docker/setup-qemu-action@4574d27a4764455b42196d70a065bc6853246a25 # v3.4.0
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
|
||||
uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3.9.0
|
||||
- name: Setup Syft
|
||||
uses: anchore/sbom-action/download-syft@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.16.0
|
||||
uses: anchore/sbom-action/download-syft@f325610c9f50a54015d37c8d16cb3b0e2c8f4de0 # v0.18.0
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
|
||||
uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
uses: fluxcd/pkg/actions/kustomize@c964ce7b91949ff4b5e3959db4f1d7bb2e029a49 # main
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
|
||||
with:
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
@@ -59,30 +59,19 @@ jobs:
|
||||
run: |
|
||||
kustomize build manifests/crds > all-crds.yaml
|
||||
- name: Generate OpenAPI JSON schemas from CRDs
|
||||
uses: fluxcd/pkg/actions/crdjsonschema@main
|
||||
uses: fluxcd/pkg/actions/crdjsonschema@c964ce7b91949ff4b5e3959db4f1d7bb2e029a49 # main
|
||||
with:
|
||||
crd: all-crds.yaml
|
||||
output: schemas
|
||||
- name: Archive the OpenAPI JSON schemas
|
||||
run: |
|
||||
tar -czvf ./output/crd-schemas.tar.gz -C schemas .
|
||||
- name: Download release notes utility
|
||||
env:
|
||||
GH_REL_URL: https://github.com/buchanae/github-release-notes/releases/download/0.2.0/github-release-notes-linux-amd64-0.2.0.tar.gz
|
||||
run: cd /tmp && curl -sSL ${GH_REL_URL} | tar xz && sudo mv github-release-notes /usr/local/bin/
|
||||
- name: Generate release notes
|
||||
run: |
|
||||
NOTES="./output/notes.md"
|
||||
echo '## CLI Changelog' > ${NOTES}
|
||||
github-release-notes -org fluxcd -repo flux2 -since-latest-release -include-author >> ${NOTES}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Run GoReleaser
|
||||
id: run-goreleaser
|
||||
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
|
||||
uses: goreleaser/goreleaser-action@9ed2f89a662bf1735a48bc8557fd212fa902bebf # v6.1.0
|
||||
with:
|
||||
version: latest
|
||||
args: release --release-notes=output/notes.md --skip=validate
|
||||
args: release --skip=validate
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
@@ -93,13 +82,13 @@ jobs:
|
||||
ARTIFACTS: "${{ steps.run-goreleaser.outputs.artifacts }}"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
|
||||
hashes=$(echo -E $ARTIFACTS | jq --raw-output '.[] | {name, "digest": (.extra.Digest // .extra.Checksum)} | select(.digest) | {digest} + {name} | join(" ") | sub("^sha256:";"")' | base64 -w0)
|
||||
echo "hashes=$hashes" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
image_url=fluxcd/flux-cli:$GITHUB_REF_NAME
|
||||
echo "image_url=$image_url" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
image_digest=$(docker buildx imagetools inspect ${image_url} --format '{{json .}}' | jq -r .manifest.digest)
|
||||
echo "image_digest=$image_digest" >> $GITHUB_OUTPUT
|
||||
|
||||
@@ -110,9 +99,9 @@ jobs:
|
||||
id-token: write
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
uses: fluxcd/pkg/actions/kustomize@c964ce7b91949ff4b5e3959db4f1d7bb2e029a49 # main
|
||||
- name: Setup Flux CLI
|
||||
uses: ./action/
|
||||
- name: Prepare
|
||||
@@ -121,13 +110,13 @@ jobs:
|
||||
VERSION=$(flux version --client | awk '{ print $NF }')
|
||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
|
||||
with:
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
@@ -137,7 +126,7 @@ jobs:
|
||||
flux install --registry=ghcr.io/fluxcd \
|
||||
--components-extra=image-reflector-controller,image-automation-controller \
|
||||
--export > ./ghcr.io/flux-system/gotk-components.yaml
|
||||
|
||||
|
||||
cd ./ghcr.io && flux push artifact \
|
||||
oci://ghcr.io/fluxcd/flux-manifests:${{ steps.prep.outputs.version }} \
|
||||
--path="./flux-system" \
|
||||
@@ -149,13 +138,13 @@ jobs:
|
||||
flux install --registry=docker.io/fluxcd \
|
||||
--components-extra=image-reflector-controller,image-automation-controller \
|
||||
--export > ./docker.io/flux-system/gotk-components.yaml
|
||||
|
||||
|
||||
cd ./docker.io && flux push artifact \
|
||||
oci://docker.io/fluxcd/flux-manifests:${{ steps.prep.outputs.version }} \
|
||||
--path="./flux-system" \
|
||||
--source=${{ github.repositoryUrl }} \
|
||||
--revision="${{ github.ref_name }}@sha1:${{ github.sha }}"
|
||||
- uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
|
||||
- uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0
|
||||
- name: Sign manifests
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: 1
|
||||
@@ -208,4 +197,4 @@ jobs:
|
||||
digest: ${{ needs.release-flux-cli.outputs.image_digest }}
|
||||
registry-username: fluxcdbot
|
||||
secrets:
|
||||
registry-password: ${{ secrets.GHCR_TOKEN }}
|
||||
registry-password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
20
.github/workflows/scan.yaml
vendored
20
.github/workflows/scan.yaml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Run FOSSA scan and upload build data
|
||||
uses: fossa-contrib/fossa-action@cdc5065bcdee31a32e47d4585df72d66e8e941c2 # v3.0.0
|
||||
with:
|
||||
@@ -31,11 +31,11 @@ jobs:
|
||||
security-events: write
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
uses: fluxcd/pkg/actions/kustomize@c964ce7b91949ff4b5e3959db4f1d7bb2e029a49 # main
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache-dependency-path: |
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
- name: Upload result to GitHub Code Scanning
|
||||
continue-on-error: true
|
||||
uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/upload-sarif@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
|
||||
with:
|
||||
sarif_file: snyk.sarif
|
||||
|
||||
@@ -65,22 +65,22 @@ jobs:
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/init@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
|
||||
with:
|
||||
languages: go
|
||||
# xref: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# xref: https://codeql.github.com/codeql-query-help/go/
|
||||
queries: security-and-quality
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/autobuild@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
|
||||
uses: github/codeql-action/analyze@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
|
||||
|
||||
2
.github/workflows/sync-labels.yaml
vendored
2
.github/workflows/sync-labels.yaml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2.3.3
|
||||
with:
|
||||
# Configuration file
|
||||
|
||||
8
.github/workflows/update.yaml
vendored
8
.github/workflows/update.yaml
vendored
@@ -18,11 +18,11 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
|
||||
with:
|
||||
go-version: 1.22.x
|
||||
go-version: 1.23.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5
|
||||
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
|
||||
with:
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
commit-message: |
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
project_name: flux
|
||||
changelog:
|
||||
use: github-native
|
||||
builds:
|
||||
- <<: &build_defaults
|
||||
binary: flux
|
||||
|
||||
5
.scorecard.yml
Normal file
5
.scorecard.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
annotations:
|
||||
- checks:
|
||||
- dangerous-workflow
|
||||
reasons:
|
||||
- reason: not-applicable # This workflow does not run untrusted code, the bot will only backport a code if the a PR was approved and merged into main.
|
||||
13
Dockerfile
13
Dockerfile
@@ -1,15 +1,16 @@
|
||||
FROM alpine:3.19 as builder
|
||||
FROM alpine:3.21 AS builder
|
||||
|
||||
RUN apk add --no-cache ca-certificates curl
|
||||
|
||||
ARG ARCH=linux/amd64
|
||||
ARG KUBECTL_VER=1.30.0
|
||||
ARG KUBECTL_VER=1.32.2
|
||||
|
||||
RUN curl -sL https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VER}/bin/${ARCH}/kubectl \
|
||||
-o /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl && \
|
||||
kubectl version --client=true
|
||||
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
|
||||
|
||||
FROM alpine:3.19 as flux-cli
|
||||
RUN kubectl version --client=true
|
||||
|
||||
FROM alpine:3.21 AS flux-cli
|
||||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
|
||||
4
Makefile
4
Makefile
@@ -17,8 +17,8 @@ rwildcard=$(foreach d,$(wildcard $(addsuffix *,$(1))),$(call rwildcard,$(d)/,$(2
|
||||
all: test build
|
||||
|
||||
tidy:
|
||||
go mod tidy -compat=1.22
|
||||
cd tests/integration && go mod tidy -compat=1.22
|
||||
go mod tidy -compat=1.23
|
||||
cd tests/integration && go mod tidy -compat=1.23
|
||||
|
||||
fmt:
|
||||
go fmt ./...
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://github.com/fluxcd/flux2/releases)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/4782)
|
||||
[](https://api.securityscorecards.dev/projects/github.com/fluxcd/flux2)
|
||||
[](https://scorecard.dev/viewer/?uri=github.com/fluxcd/flux2)
|
||||
[](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Ffluxcd%2Fflux2?ref=badge_shield)
|
||||
[](https://artifacthub.io/packages/helm/fluxcd-community/flux2)
|
||||
[](https://fluxcd.io/flux/security/slsa-assessment)
|
||||
|
||||
@@ -226,7 +226,7 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
|
||||
secretOpts.Username = bServerArgs.username
|
||||
}
|
||||
secretOpts.Password = bitbucketToken
|
||||
secretOpts.CAFile = caBundle
|
||||
secretOpts.CACrt = caBundle
|
||||
} else {
|
||||
keypair, err := sourcesecret.LoadKeyPairFromPath(bootstrapArgs.privateKeyFile, gitArgs.password)
|
||||
if err != nil {
|
||||
|
||||
@@ -243,7 +243,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
secretOpts.Password = gitArgs.password
|
||||
}
|
||||
|
||||
secretOpts.CAFile = caBundle
|
||||
secretOpts.CACrt = caBundle
|
||||
|
||||
// Remove port of the given host when not syncing over HTTP/S to not assume port for protocol
|
||||
// This _might_ be overwritten later on by e.g. --ssh-hostname
|
||||
|
||||
@@ -210,7 +210,7 @@ func bootstrapGiteaCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.tokenAuth {
|
||||
secretOpts.Username = "git"
|
||||
secretOpts.Password = gtToken
|
||||
secretOpts.CAFile = caBundle
|
||||
secretOpts.CACrt = caBundle
|
||||
} else {
|
||||
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm)
|
||||
secretOpts.RSAKeyBits = int(bootstrapArgs.keyRSABits)
|
||||
|
||||
@@ -217,7 +217,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.tokenAuth {
|
||||
secretOpts.Username = "git"
|
||||
secretOpts.Password = ghToken
|
||||
secretOpts.CAFile = caBundle
|
||||
secretOpts.CACrt = caBundle
|
||||
} else {
|
||||
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm)
|
||||
secretOpts.RSAKeyBits = int(bootstrapArgs.keyRSABits)
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fluxcd/go-git-providers/gitprovider"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -58,14 +59,14 @@ the bootstrap command will perform an upgrade if needed.`,
|
||||
# Run bootstrap for a repository path
|
||||
flux bootstrap gitlab --owner=<group> --repository=<repository name> --path=dev-cluster
|
||||
|
||||
# Run bootstrap for a public repository on a personal account
|
||||
flux bootstrap gitlab --owner=<user> --repository=<repository name> --private=false --personal --token-auth
|
||||
# Run bootstrap for a public repository
|
||||
flux bootstrap gitlab --owner=<group> --repository=<repository name> --visibility=public --token-auth
|
||||
|
||||
# Run bootstrap for a private repository hosted on a GitLab server
|
||||
flux bootstrap gitlab --owner=<group> --repository=<repository name> --hostname=<domain> --token-auth
|
||||
flux bootstrap gitlab --owner=<group> --repository=<repository name> --hostname=<gitlab_url> --token-auth
|
||||
|
||||
# Run bootstrap for an existing repository with a branch named main
|
||||
flux bootstrap gitlab --owner=<organization> --repository=<repository name> --branch=main --token-auth
|
||||
flux bootstrap gitlab --owner=<group> --repository=<repository name> --branch=main --token-auth
|
||||
|
||||
# Run bootstrap for a private repository using Deploy Token authentication
|
||||
flux bootstrap gitlab --owner=<group> --repository=<repository name> --deploy-token-auth
|
||||
@@ -85,6 +86,7 @@ type gitlabFlags struct {
|
||||
repository string
|
||||
interval time.Duration
|
||||
personal bool
|
||||
visibility flags.GitLabVisibility
|
||||
private bool
|
||||
hostname string
|
||||
path flags.SafeRelativePath
|
||||
@@ -94,7 +96,13 @@ type gitlabFlags struct {
|
||||
deployTokenAuth bool
|
||||
}
|
||||
|
||||
var gitlabArgs gitlabFlags
|
||||
func NewGitlabFlags() gitlabFlags {
|
||||
return gitlabFlags{
|
||||
visibility: flags.GitLabVisibility(gitprovider.RepositoryVisibilityPrivate),
|
||||
}
|
||||
}
|
||||
|
||||
var gitlabArgs = NewGitlabFlags()
|
||||
|
||||
func init() {
|
||||
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.owner, "owner", "", "GitLab user or group name")
|
||||
@@ -102,6 +110,8 @@ func init() {
|
||||
bootstrapGitLabCmd.Flags().StringSliceVar(&gitlabArgs.teams, "team", []string{}, "GitLab teams to be given maintainer access (also accepts comma-separated values)")
|
||||
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.personal, "personal", false, "if true, the owner is assumed to be a GitLab user; otherwise a group")
|
||||
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.private, "private", true, "if true, the repository is setup or configured as private")
|
||||
bootstrapGitLabCmd.Flags().MarkDeprecated("private", "use --visibility instead")
|
||||
bootstrapGitLabCmd.Flags().Var(&gitlabArgs.visibility, "visibility", gitlabArgs.visibility.Description())
|
||||
bootstrapGitLabCmd.Flags().DurationVar(&gitlabArgs.interval, "interval", time.Minute, "sync interval")
|
||||
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.hostname, "hostname", glDefaultDomain, "GitLab hostname")
|
||||
bootstrapGitLabCmd.Flags().Var(&gitlabArgs.path, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path")
|
||||
@@ -133,6 +143,11 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("--token-auth and --deploy-token-auth cannot be set both.")
|
||||
}
|
||||
|
||||
if !gitlabArgs.private {
|
||||
gitlabArgs.visibility.Set(string(gitprovider.RepositoryVisibilityPublic))
|
||||
cmd.Println("Using visibility public as --private=false")
|
||||
}
|
||||
|
||||
if err := bootstrapValidate(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -242,10 +257,10 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.tokenAuth {
|
||||
secretOpts.Username = "git"
|
||||
secretOpts.Password = glToken
|
||||
secretOpts.CAFile = caBundle
|
||||
secretOpts.CACrt = caBundle
|
||||
} else if gitlabArgs.deployTokenAuth {
|
||||
// the actual deploy token will be reconciled later
|
||||
secretOpts.CAFile = caBundle
|
||||
secretOpts.CACrt = caBundle
|
||||
} else {
|
||||
keypair, err := sourcesecret.LoadKeyPairFromPath(bootstrapArgs.privateKeyFile, gitArgs.password)
|
||||
if err != nil {
|
||||
@@ -282,6 +297,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
// Bootstrap config
|
||||
bootstrapOpts := []bootstrap.GitProviderOption{
|
||||
bootstrap.WithProviderRepository(gitlabArgs.owner, gitlabArgs.repository, gitlabArgs.personal),
|
||||
bootstrap.WithProviderVisibility(gitlabArgs.visibility.String()),
|
||||
bootstrap.WithBranch(bootstrapArgs.branch),
|
||||
bootstrap.WithBootstrapTransportType("https"),
|
||||
bootstrap.WithSignature(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
|
||||
@@ -301,9 +317,6 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if gitlabArgs.deployTokenAuth {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithDeployTokenAuth())
|
||||
}
|
||||
if !gitlabArgs.private {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public"))
|
||||
}
|
||||
if gitlabArgs.reconcile {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile())
|
||||
}
|
||||
|
||||
@@ -53,7 +53,12 @@ flux build kustomization my-app --path ./path/to/local/manifests \
|
||||
# Exclude files by providing a comma separated list of entries that follow the .gitignore pattern fromat.
|
||||
flux build kustomization my-app --path ./path/to/local/manifests \
|
||||
--kustomization-file ./path/to/local/my-app.yaml \
|
||||
--ignore-paths "/to_ignore/**/*.yaml,ignore.yaml"`,
|
||||
--ignore-paths "/to_ignore/**/*.yaml,ignore.yaml"
|
||||
|
||||
# Run recursively on all encountered Kustomizations
|
||||
flux build kustomization my-app --path ./path/to/local/manifests \
|
||||
--recursive \
|
||||
--local-sources GitRepository/flux-system/my-repo=./path/to/local/git`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)),
|
||||
RunE: buildKsCmdRun,
|
||||
}
|
||||
@@ -64,6 +69,8 @@ type buildKsFlags struct {
|
||||
ignorePaths []string
|
||||
dryRun bool
|
||||
strictSubst bool
|
||||
recursive bool
|
||||
localSources map[string]string
|
||||
}
|
||||
|
||||
var buildKsArgs buildKsFlags
|
||||
@@ -75,6 +82,8 @@ func init() {
|
||||
buildKsCmd.Flags().BoolVar(&buildKsArgs.dryRun, "dry-run", false, "Dry run mode.")
|
||||
buildKsCmd.Flags().BoolVar(&buildKsArgs.strictSubst, "strict-substitute", false,
|
||||
"When enabled, the post build substitutions will fail if a var without a default value is declared in files but is missing from the input vars.")
|
||||
buildKsCmd.Flags().BoolVarP(&buildKsArgs.recursive, "recursive", "r", false, "Recursively build Kustomizations")
|
||||
buildKsCmd.Flags().StringToStringVar(&buildKsArgs.localSources, "local-sources", nil, "Comma-separated list of repositories in format: Kind/namespace/name=path")
|
||||
buildCmd.AddCommand(buildKsCmd)
|
||||
}
|
||||
|
||||
@@ -111,6 +120,8 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
|
||||
build.WithNamespace(*kubeconfigArgs.Namespace),
|
||||
build.WithIgnore(buildKsArgs.ignorePaths),
|
||||
build.WithStrictSubstitute(buildKsArgs.strictSubst),
|
||||
build.WithRecursive(buildKsArgs.recursive),
|
||||
build.WithLocalSources(buildKsArgs.localSources),
|
||||
)
|
||||
} else {
|
||||
builder, err = build.NewBuilder(name, buildKsArgs.path,
|
||||
@@ -119,6 +130,8 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
|
||||
build.WithKustomizationFile(buildKsArgs.kustomizationFile),
|
||||
build.WithIgnore(buildKsArgs.ignorePaths),
|
||||
build.WithStrictSubstitute(buildKsArgs.strictSubst),
|
||||
build.WithRecursive(buildKsArgs.recursive),
|
||||
build.WithLocalSources(buildKsArgs.localSources),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"text/template"
|
||||
)
|
||||
@@ -69,6 +70,12 @@ func TestBuildKustomization(t *testing.T) {
|
||||
resultFile: "./testdata/build-kustomization/podinfo-with-ignore-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
{
|
||||
name: "build with recursive",
|
||||
args: "build kustomization podinfo --path ./testdata/build-kustomization/podinfo-with-my-app --recursive --local-sources GitRepository/default/podinfo=./testdata/build-kustomization",
|
||||
resultFile: "./testdata/build-kustomization/podinfo-with-my-app-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
}
|
||||
|
||||
tmpl := map[string]string{
|
||||
@@ -118,6 +125,8 @@ spec:
|
||||
cluster_region: "eu-central-1"
|
||||
`
|
||||
|
||||
tmpFile := filepath.Join(t.TempDir(), "podinfo.yaml")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args string
|
||||
@@ -132,28 +141,34 @@ spec:
|
||||
},
|
||||
{
|
||||
name: "build podinfo",
|
||||
args: "build kustomization podinfo --kustomization-file ./testdata/build-kustomization/podinfo.yaml --path ./testdata/build-kustomization/podinfo",
|
||||
args: "build kustomization podinfo --kustomization-file " + tmpFile + " --path ./testdata/build-kustomization/podinfo",
|
||||
resultFile: "./testdata/build-kustomization/podinfo-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
{
|
||||
name: "build podinfo without service",
|
||||
args: "build kustomization podinfo --kustomization-file ./testdata/build-kustomization/podinfo.yaml --path ./testdata/build-kustomization/delete-service",
|
||||
args: "build kustomization podinfo --kustomization-file " + tmpFile + " --path ./testdata/build-kustomization/delete-service",
|
||||
resultFile: "./testdata/build-kustomization/podinfo-without-service-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
{
|
||||
name: "build deployment and configmap with var substitution",
|
||||
args: "build kustomization podinfo --kustomization-file ./testdata/build-kustomization/podinfo.yaml --path ./testdata/build-kustomization/var-substitution",
|
||||
args: "build kustomization podinfo --kustomization-file " + tmpFile + " --path ./testdata/build-kustomization/var-substitution",
|
||||
resultFile: "./testdata/build-kustomization/podinfo-with-var-substitution-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
{
|
||||
name: "build deployment and configmap with var substitution in dry-run mode",
|
||||
args: "build kustomization podinfo --kustomization-file ./testdata/build-kustomization/podinfo.yaml --path ./testdata/build-kustomization/var-substitution --dry-run",
|
||||
args: "build kustomization podinfo --kustomization-file " + tmpFile + " --path ./testdata/build-kustomization/var-substitution --dry-run",
|
||||
resultFile: "./testdata/build-kustomization/podinfo-with-var-substitution-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
{
|
||||
name: "build with recursive",
|
||||
args: "build kustomization podinfo --kustomization-file " + tmpFile + " --path ./testdata/build-kustomization/podinfo-with-my-app --recursive --local-sources GitRepository/default/podinfo=./testdata/build-kustomization",
|
||||
resultFile: "./testdata/build-kustomization/podinfo-with-my-app-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
}
|
||||
|
||||
tmpl := map[string]string{
|
||||
@@ -161,8 +176,6 @@ spec:
|
||||
}
|
||||
setup(t, tmpl)
|
||||
|
||||
testEnv.CreateObjectFile("./testdata/build-kustomization/podinfo-source.yaml", tmpl, t)
|
||||
|
||||
temp, err := template.New("podinfo").Parse(podinfo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -174,11 +187,10 @@ spec:
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = os.WriteFile("./testdata/build-kustomization/podinfo.yaml", b.Bytes(), 0666)
|
||||
err = os.WriteFile(tmpFile, b.Bytes(), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = os.Remove("./testdata/build-kustomization/podinfo.yaml") })
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -60,7 +60,7 @@ type checkFlags struct {
|
||||
}
|
||||
|
||||
var kubernetesConstraints = []string{
|
||||
">=1.28.0-0",
|
||||
">=1.30.0-0",
|
||||
}
|
||||
|
||||
var checkArgs checkFlags
|
||||
|
||||
@@ -125,7 +125,7 @@ func (names apiType) upsertAndWait(object upsertWaitable, mutate func() error) e
|
||||
logger.Generatef("generating %s", names.kind)
|
||||
logger.Actionf("applying %s", names.kind)
|
||||
|
||||
namespacedName, err := imageRepositoryType.upsert(ctx, kubeClient, object, mutate)
|
||||
namespacedName, err := names.upsert(ctx, kubeClient, object, mutate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -87,7 +87,6 @@ type secretGitFlags struct {
|
||||
keyAlgorithm flags.PublicKeyAlgorithm
|
||||
rsaBits flags.RSAKeyBits
|
||||
ecdsaCurve flags.ECDSACurve
|
||||
caFile string
|
||||
caCrtFile string
|
||||
privateKeyFile string
|
||||
bearerToken string
|
||||
@@ -102,8 +101,7 @@ func init() {
|
||||
createSecretGitCmd.Flags().Var(&secretGitArgs.keyAlgorithm, "ssh-key-algorithm", secretGitArgs.keyAlgorithm.Description())
|
||||
createSecretGitCmd.Flags().Var(&secretGitArgs.rsaBits, "ssh-rsa-bits", secretGitArgs.rsaBits.Description())
|
||||
createSecretGitCmd.Flags().Var(&secretGitArgs.ecdsaCurve, "ssh-ecdsa-curve", secretGitArgs.ecdsaCurve.Description())
|
||||
createSecretGitCmd.Flags().StringVar(&secretGitArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates")
|
||||
createSecretGitCmd.Flags().StringVar(&secretGitArgs.caCrtFile, "ca-crt-file", "", "path to TLS CA certificate file used for validating self-signed certificates; takes precedence over --ca-file")
|
||||
createSecretGitCmd.Flags().StringVar(&secretGitArgs.caCrtFile, "ca-crt-file", "", "path to TLS CA certificate file used for validating self-signed certificates")
|
||||
createSecretGitCmd.Flags().StringVar(&secretGitArgs.privateKeyFile, "private-key-file", "", "path to a passwordless private key file used for authenticating to the Git SSH server")
|
||||
createSecretGitCmd.Flags().StringVar(&secretGitArgs.bearerToken, "bearer-token", "", "bearer authentication token")
|
||||
|
||||
@@ -169,11 +167,6 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
} else if secretGitArgs.caFile != "" {
|
||||
opts.CAFile, err = os.ReadFile(secretGitArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("git URL scheme '%s' not supported, can be: ssh, http and https", u.Scheme)
|
||||
|
||||
128
cmd/flux/create_secret_github_app.go
Normal file
128
cmd/flux/create_secret_github_app.go
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2024 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 (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/utils"
|
||||
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret"
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
var createSecretGitHubAppCmd = &cobra.Command{
|
||||
Use: "githubapp [name]",
|
||||
Short: "Create or update a github app secret",
|
||||
Long: withPreviewNote(`The create secret githubapp command generates a Kubernetes secret that can be used for GitRepository authentication with github app`),
|
||||
Example: ` # Create a githubapp authentication secret on disk and encrypt it with Mozilla SOPS
|
||||
flux create secret githubapp podinfo-auth \
|
||||
--app-id="1" \
|
||||
--app-installation-id="2" \
|
||||
--app-private-key=./private-key-file.pem \
|
||||
--export > githubapp-auth.yaml
|
||||
|
||||
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||
--in-place githubapp-auth.yaml
|
||||
`,
|
||||
RunE: createSecretGitHubAppCmdRun,
|
||||
}
|
||||
|
||||
type secretGitHubAppFlags struct {
|
||||
appID string
|
||||
appInstallationID string
|
||||
privateKeyFile string
|
||||
baseURL string
|
||||
}
|
||||
|
||||
var secretGitHubAppArgs = secretGitHubAppFlags{}
|
||||
|
||||
func init() {
|
||||
createSecretGitHubAppCmd.Flags().StringVar(&secretGitHubAppArgs.appID, "app-id", "", "github app ID")
|
||||
createSecretGitHubAppCmd.Flags().StringVar(&secretGitHubAppArgs.appInstallationID, "app-installation-id", "", "github app installation ID")
|
||||
createSecretGitHubAppCmd.Flags().StringVar(&secretGitHubAppArgs.privateKeyFile, "app-private-key", "", "github app private key file path")
|
||||
createSecretGitHubAppCmd.Flags().StringVar(&secretGitHubAppArgs.baseURL, "app-base-url", "", "github app base URL")
|
||||
|
||||
createSecretCmd.AddCommand(createSecretGitHubAppCmd)
|
||||
}
|
||||
|
||||
func createSecretGitHubAppCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("name is required")
|
||||
}
|
||||
|
||||
secretName := args[0]
|
||||
|
||||
if secretGitHubAppArgs.appID == "" {
|
||||
return fmt.Errorf("--app-id is required")
|
||||
}
|
||||
|
||||
if secretGitHubAppArgs.appInstallationID == "" {
|
||||
return fmt.Errorf("--app-installation-id is required")
|
||||
}
|
||||
|
||||
if secretGitHubAppArgs.privateKeyFile == "" {
|
||||
return fmt.Errorf("--app-private-key is required")
|
||||
}
|
||||
|
||||
privateKey, err := os.ReadFile(secretGitHubAppArgs.privateKeyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read private key file: %w", err)
|
||||
}
|
||||
|
||||
opts := sourcesecret.Options{
|
||||
Name: secretName,
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
GitHubAppID: secretGitHubAppArgs.appID,
|
||||
GitHubAppInstallationID: secretGitHubAppArgs.appInstallationID,
|
||||
GitHubAppPrivateKey: string(privateKey),
|
||||
}
|
||||
|
||||
if secretGitHubAppArgs.baseURL != "" {
|
||||
opts.GitHubAppBaseURL = secretGitHubAppArgs.baseURL
|
||||
}
|
||||
|
||||
secret, err := sourcesecret.Generate(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if createArgs.export {
|
||||
rootCmd.Println(secret.Content)
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var s corev1.Secret
|
||||
if err := yaml.Unmarshal([]byte(secret.Content), &s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := upsertSecret(ctx, kubeClient, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Actionf("githubapp secret '%s' created in '%s' namespace", secretName, *kubeconfigArgs.Namespace)
|
||||
return nil
|
||||
}
|
||||
74
cmd/flux/create_secret_githubapp_test.go
Normal file
74
cmd/flux/create_secret_githubapp_test.go
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2022 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 TestCreateSecretGitHubApp(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args string
|
||||
assert assertFunc
|
||||
}{
|
||||
{
|
||||
name: "create githubapp secret with missing name",
|
||||
args: "create secret githubapp",
|
||||
assert: assertError("name is required"),
|
||||
},
|
||||
{
|
||||
name: "create githubapp secret with missing app-id",
|
||||
args: "create secret githubapp appinfo",
|
||||
assert: assertError("--app-id is required"),
|
||||
},
|
||||
{
|
||||
name: "create githubapp secret with missing appInstallationID",
|
||||
args: "create secret githubapp appinfo --app-id 1",
|
||||
assert: assertError("--app-installation-id is required"),
|
||||
},
|
||||
{
|
||||
name: "create githubapp secret with missing private key file",
|
||||
args: "create secret githubapp appinfo --app-id 1 --app-installation-id 2",
|
||||
assert: assertError("--app-private-key is required"),
|
||||
},
|
||||
{
|
||||
name: "create githubapp secret with private key file that does not exist",
|
||||
args: "create secret githubapp appinfo --app-id 1 --app-installation-id 2 --app-private-key pk.pem",
|
||||
assert: assertError("unable to read private key file: open pk.pem: no such file or directory"),
|
||||
},
|
||||
{
|
||||
name: "create githubapp secret with app info",
|
||||
args: "create secret githubapp appinfo --namespace my-namespace --app-id 1 --app-installation-id 2 --app-private-key ./testdata/create_secret/githubapp/test-private-key.pem --export",
|
||||
assert: assertGoldenFile("testdata/create_secret/githubapp/secret.yaml"),
|
||||
},
|
||||
{
|
||||
name: "create githubapp secret with appinfo and base url",
|
||||
args: "create secret githubapp appinfo --namespace my-namespace --app-id 1 --app-installation-id 2 --app-private-key ./testdata/create_secret/githubapp/test-private-key.pem --app-base-url www.example.com/api/v3 --export",
|
||||
assert: assertGoldenFile("testdata/create_secret/githubapp/secret-with-baseurl.yaml"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: tt.args,
|
||||
assert: tt.assert,
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -58,12 +58,9 @@ func init() {
|
||||
flags := createSecretHelmCmd.Flags()
|
||||
flags.StringVarP(&secretHelmArgs.username, "username", "u", "", "basic authentication username")
|
||||
flags.StringVarP(&secretHelmArgs.password, "password", "p", "", "basic authentication password")
|
||||
|
||||
initSecretDeprecatedTLSFlags(flags, &secretHelmArgs.secretTLSFlags)
|
||||
deprecationMsg := "please use the command `flux create secret tls` to generate TLS secrets"
|
||||
flags.MarkDeprecated("cert-file", deprecationMsg)
|
||||
flags.MarkDeprecated("key-file", deprecationMsg)
|
||||
flags.MarkDeprecated("ca-file", deprecationMsg)
|
||||
flags.StringVar(&secretHelmArgs.tlsCrtFile, "tls-crt-file", "", "TLS authentication cert file path")
|
||||
flags.StringVar(&secretHelmArgs.tlsKeyFile, "tls-key-file", "", "TLS authentication key file path")
|
||||
flags.StringVar(&secretHelmArgs.caCrtFile, "ca-crt-file", "", "TLS authentication CA file path")
|
||||
|
||||
createSecretCmd.AddCommand(createSecretHelmCmd)
|
||||
}
|
||||
@@ -77,20 +74,20 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
caBundle := []byte{}
|
||||
if secretHelmArgs.caFile != "" {
|
||||
if secretHelmArgs.caCrtFile != "" {
|
||||
var err error
|
||||
caBundle, err = os.ReadFile(secretHelmArgs.caFile)
|
||||
caBundle, err = os.ReadFile(secretHelmArgs.caCrtFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var certFile, keyFile []byte
|
||||
if secretHelmArgs.certFile != "" && secretHelmArgs.keyFile != "" {
|
||||
if certFile, err = os.ReadFile(secretHelmArgs.certFile); err != nil {
|
||||
if secretHelmArgs.tlsCrtFile != "" && secretHelmArgs.tlsKeyFile != "" {
|
||||
if certFile, err = os.ReadFile(secretHelmArgs.tlsCrtFile); err != nil {
|
||||
return fmt.Errorf("failed to read cert file: %w", err)
|
||||
}
|
||||
if keyFile, err = os.ReadFile(secretHelmArgs.keyFile); err != nil {
|
||||
if keyFile, err = os.ReadFile(secretHelmArgs.tlsKeyFile); err != nil {
|
||||
return fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -101,9 +98,9 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
Labels: labels,
|
||||
Username: secretHelmArgs.username,
|
||||
Password: secretHelmArgs.password,
|
||||
CAFile: caBundle,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
CACrt: caBundle,
|
||||
TLSCrt: certFile,
|
||||
TLSKey: keyFile,
|
||||
}
|
||||
secret, err := sourcesecret.Generate(opts)
|
||||
if err != nil {
|
||||
|
||||
@@ -84,7 +84,7 @@ func TestCreateNotationSecret(t *testing.T) {
|
||||
{
|
||||
name: "invalid trust policy",
|
||||
args: fmt.Sprintf("create secret notation notation-config --ca-cert-file=%s --trust-policy-file=%s", t.TempDir(), invalidTrustPolicy),
|
||||
assert: assertError("invalid trust policy: a trust policy statement is missing a name, every statement requires a name"),
|
||||
assert: assertError("invalid trust policy: trust policy: a trust policy statement is missing a name, every statement requires a name"),
|
||||
},
|
||||
{
|
||||
name: "invalid trust policy json",
|
||||
|
||||
112
cmd/flux/create_secret_proxy.go
Normal file
112
cmd/flux/create_secret_proxy.go
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
Copyright 2024 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 (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/utils"
|
||||
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret"
|
||||
)
|
||||
|
||||
var createSecretProxyCmd = &cobra.Command{
|
||||
Use: "proxy [name]",
|
||||
Short: "Create or update a Kubernetes secret for proxy authentication",
|
||||
Long: `The create secret proxy command generates a Kubernetes secret with the
|
||||
proxy address and the basic authentication credentials.`,
|
||||
Example: ` # Create a proxy secret on disk and encrypt it with SOPS
|
||||
flux create secret proxy my-proxy \
|
||||
--namespace=my-namespace \
|
||||
--address=https://my-proxy.com \
|
||||
--username=my-username \
|
||||
--password=my-password \
|
||||
--export > proxy.yaml
|
||||
|
||||
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||
--in-place proxy.yaml`,
|
||||
|
||||
RunE: createSecretProxyCmdRun,
|
||||
}
|
||||
|
||||
type secretProxyFlags struct {
|
||||
address string
|
||||
username string
|
||||
password string
|
||||
}
|
||||
|
||||
var secretProxyArgs secretProxyFlags
|
||||
|
||||
func init() {
|
||||
createSecretProxyCmd.Flags().StringVar(&secretProxyArgs.address, "address", "", "proxy address")
|
||||
createSecretProxyCmd.Flags().StringVarP(&secretProxyArgs.username, "username", "u", "", "basic authentication username")
|
||||
createSecretProxyCmd.Flags().StringVarP(&secretProxyArgs.password, "password", "p", "", "basic authentication password")
|
||||
|
||||
createSecretCmd.AddCommand(createSecretProxyCmd)
|
||||
}
|
||||
|
||||
func createSecretProxyCmdRun(cmd *cobra.Command, args []string) error {
|
||||
name := args[0]
|
||||
|
||||
labels, err := parseLabels()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if secretProxyArgs.address == "" {
|
||||
return errors.New("address is required")
|
||||
}
|
||||
|
||||
opts := sourcesecret.Options{
|
||||
Name: name,
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Labels: labels,
|
||||
Address: secretProxyArgs.address,
|
||||
Username: secretProxyArgs.username,
|
||||
Password: secretProxyArgs.password,
|
||||
}
|
||||
secret, err := sourcesecret.Generate(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if createArgs.export {
|
||||
rootCmd.Println(secret.Content)
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var s corev1.Secret
|
||||
if err := yaml.Unmarshal([]byte(secret.Content), &s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := upsertSecret(ctx, kubeClient, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Actionf("proxy secret '%s' created in '%s' namespace", name, *kubeconfigArgs.Namespace)
|
||||
return nil
|
||||
}
|
||||
47
cmd/flux/create_secret_proxy_test.go
Normal file
47
cmd/flux/create_secret_proxy_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2024 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 TestCreateProxySecret(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args string
|
||||
assert assertFunc
|
||||
}{
|
||||
{
|
||||
args: "create secret proxy proxy-secret",
|
||||
assert: assertError("address is required"),
|
||||
},
|
||||
{
|
||||
args: "create secret proxy proxy-secret --address=https://my-proxy.com --username=my-username --password=my-password --namespace=my-namespace --export",
|
||||
assert: assertGoldenFile("testdata/create_secret/proxy/secret-proxy.yaml"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: tt.args,
|
||||
assert: tt.assert,
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
@@ -33,8 +32,8 @@ import (
|
||||
var createSecretTLSCmd = &cobra.Command{
|
||||
Use: "tls [name]",
|
||||
Short: "Create or update a Kubernetes secret with TLS certificates",
|
||||
Long: withPreviewNote(`The create secret tls command generates a Kubernetes secret with certificates for use with TLS.`),
|
||||
Example: ` # Create a TLS secret on disk and encrypt it with Mozilla SOPS.
|
||||
Long: `The create secret tls command generates a Kubernetes secret with certificates for use with TLS.`,
|
||||
Example: ` # Create a TLS secret on disk and encrypt it with SOPS.
|
||||
# Files are expected to be PEM-encoded.
|
||||
flux create secret tls certs \
|
||||
--namespace=my-namespace \
|
||||
@@ -49,9 +48,6 @@ var createSecretTLSCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
type secretTLSFlags struct {
|
||||
certFile string
|
||||
keyFile string
|
||||
caFile string
|
||||
caCrtFile string
|
||||
tlsKeyFile string
|
||||
tlsCrtFile string
|
||||
@@ -59,26 +55,10 @@ type secretTLSFlags struct {
|
||||
|
||||
var secretTLSArgs secretTLSFlags
|
||||
|
||||
func initSecretDeprecatedTLSFlags(flags *pflag.FlagSet, args *secretTLSFlags) {
|
||||
flags.StringVar(&args.certFile, "cert-file", "", "TLS authentication cert file path")
|
||||
flags.StringVar(&args.keyFile, "key-file", "", "TLS authentication key file path")
|
||||
flags.StringVar(&args.caFile, "ca-file", "", "TLS authentication CA file path")
|
||||
}
|
||||
|
||||
func initSecretTLSFlags(flags *pflag.FlagSet, args *secretTLSFlags) {
|
||||
flags.StringVar(&args.tlsCrtFile, "tls-crt-file", "", "TLS authentication cert file path")
|
||||
flags.StringVar(&args.tlsKeyFile, "tls-key-file", "", "TLS authentication key file path")
|
||||
flags.StringVar(&args.caCrtFile, "ca-crt-file", "", "TLS authentication CA file path")
|
||||
}
|
||||
|
||||
func init() {
|
||||
flags := createSecretTLSCmd.Flags()
|
||||
initSecretDeprecatedTLSFlags(flags, &secretTLSArgs)
|
||||
initSecretTLSFlags(flags, &secretTLSArgs)
|
||||
|
||||
flags.MarkDeprecated("cert-file", "please use --tls-crt-file instead")
|
||||
flags.MarkDeprecated("key-file", "please use --tls-key-file instead")
|
||||
flags.MarkDeprecated("ca-file", "please use --ca-crt-file instead")
|
||||
createSecretTLSCmd.Flags().StringVar(&secretTLSArgs.tlsCrtFile, "tls-crt-file", "", "TLS authentication cert file path")
|
||||
createSecretTLSCmd.Flags().StringVar(&secretTLSArgs.tlsKeyFile, "tls-key-file", "", "TLS authentication key file path")
|
||||
createSecretTLSCmd.Flags().StringVar(&secretTLSArgs.caCrtFile, "ca-crt-file", "", "TLS authentication CA file path")
|
||||
|
||||
createSecretCmd.AddCommand(createSecretTLSCmd)
|
||||
}
|
||||
@@ -102,11 +82,6 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
} else if secretTLSArgs.caFile != "" {
|
||||
opts.CAFile, err = os.ReadFile(secretTLSArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if secretTLSArgs.tlsCrtFile != "" && secretTLSArgs.tlsKeyFile != "" {
|
||||
@@ -116,13 +91,6 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if opts.TLSKey, err = os.ReadFile(secretTLSArgs.tlsKeyFile); err != nil {
|
||||
return fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
} else if secretTLSArgs.certFile != "" && secretTLSArgs.keyFile != "" {
|
||||
if opts.CertFile, err = os.ReadFile(secretTLSArgs.certFile); err != nil {
|
||||
return fmt.Errorf("failed to read cert file: %w", err)
|
||||
}
|
||||
if opts.KeyFile, err = os.ReadFile(secretTLSArgs.keyFile); err != nil {
|
||||
return fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
secret, err := sourcesecret.Generate(opts)
|
||||
|
||||
@@ -18,10 +18,6 @@ func TestCreateTlsSecret(t *testing.T) {
|
||||
args: "create secret tls certs --namespace=my-namespace --tls-crt-file=./testdata/create_secret/tls/test-cert.pem --tls-key-file=./testdata/create_secret/tls/test-key.pem --ca-crt-file=./testdata/create_secret/tls/test-ca.pem --export",
|
||||
assert: assertGoldenFile("testdata/create_secret/tls/secret-tls.yaml"),
|
||||
},
|
||||
{
|
||||
args: "create secret tls certs --namespace=my-namespace --cert-file=./testdata/create_secret/tls/test-cert.pem --key-file=./testdata/create_secret/tls/test-key.pem --ca-file=./testdata/create_secret/tls/test-ca.pem --export",
|
||||
assert: assertGoldenFile("testdata/create_secret/tls/deprecated-secret-tls.yaml"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
"github.com/fluxcd/flux2/v2/internal/utils"
|
||||
@@ -41,8 +41,8 @@ import (
|
||||
var createSourceBucketCmd = &cobra.Command{
|
||||
Use: "bucket [name]",
|
||||
Short: "Create or update a Bucket source",
|
||||
Long: withPreviewNote(`The create source bucket command generates a Bucket resource and waits for it to be downloaded.
|
||||
For Buckets with static authentication, the credentials are stored in a Kubernetes secret.`),
|
||||
Long: `The create source bucket command generates a Bucket resource and waits for it to be downloaded.
|
||||
For Buckets with static authentication, the credentials are stored in a Kubernetes secret.`,
|
||||
Example: ` # Create a source for a Bucket using static authentication
|
||||
flux create source bucket podinfo \
|
||||
--bucket-name=podinfo \
|
||||
@@ -63,15 +63,16 @@ For Buckets with static authentication, the credentials are stored in a Kubernet
|
||||
}
|
||||
|
||||
type sourceBucketFlags struct {
|
||||
name string
|
||||
provider flags.SourceBucketProvider
|
||||
endpoint string
|
||||
accessKey string
|
||||
secretKey string
|
||||
region string
|
||||
insecure bool
|
||||
secretRef string
|
||||
ignorePaths []string
|
||||
name string
|
||||
provider flags.SourceBucketProvider
|
||||
endpoint string
|
||||
accessKey string
|
||||
secretKey string
|
||||
region string
|
||||
insecure bool
|
||||
secretRef string
|
||||
proxySecretRef string
|
||||
ignorePaths []string
|
||||
}
|
||||
|
||||
var sourceBucketArgs = newSourceBucketFlags()
|
||||
@@ -85,6 +86,7 @@ func init() {
|
||||
createSourceBucketCmd.Flags().StringVar(&sourceBucketArgs.region, "region", "", "the bucket region")
|
||||
createSourceBucketCmd.Flags().BoolVar(&sourceBucketArgs.insecure, "insecure", false, "for when connecting to a non-TLS S3 HTTP endpoint")
|
||||
createSourceBucketCmd.Flags().StringVar(&sourceBucketArgs.secretRef, "secret-ref", "", "the name of an existing secret containing credentials")
|
||||
createSourceBucketCmd.Flags().StringVar(&sourceBucketArgs.proxySecretRef, "proxy-secret-ref", "", "the name of an existing secret containing the proxy address and credentials")
|
||||
createSourceBucketCmd.Flags().StringSliceVar(&sourceBucketArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore in bucket resource (can specify multiple paths with commas: path1,path2)")
|
||||
|
||||
createSourceCmd.AddCommand(createSourceBucketCmd)
|
||||
@@ -92,7 +94,7 @@ func init() {
|
||||
|
||||
func newSourceBucketFlags() sourceBucketFlags {
|
||||
return sourceBucketFlags{
|
||||
provider: flags.SourceBucketProvider(sourcev1.GenericBucketProvider),
|
||||
provider: flags.SourceBucketProvider(sourcev1.BucketProviderGeneric),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +155,12 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if sourceBucketArgs.proxySecretRef != "" {
|
||||
bucket.Spec.ProxySecretRef = &meta.LocalObjectReference{
|
||||
Name: sourceBucketArgs.proxySecretRef,
|
||||
}
|
||||
}
|
||||
|
||||
if createArgs.export {
|
||||
return printExport(exportBucket(bucket))
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ type sourceGitFlags struct {
|
||||
keyRSABits flags.RSAKeyBits
|
||||
keyECDSACurve flags.ECDSACurve
|
||||
secretRef string
|
||||
proxySecretRef string
|
||||
provider flags.SourceGitProvider
|
||||
caFile string
|
||||
privateKeyFile string
|
||||
recurseSubmodules bool
|
||||
@@ -119,7 +121,13 @@ For private Git repositories, the basic authentication credentials are stored in
|
||||
--url=https://github.com/stefanprodan/podinfo \
|
||||
--branch=master \
|
||||
--username=username \
|
||||
--password=password`,
|
||||
--password=password
|
||||
|
||||
# Create a source for a Git repository using azure provider
|
||||
flux create source git podinfo \
|
||||
--url=https://dev.azure.com/foo/bar/_git/podinfo \
|
||||
--branch=master \
|
||||
--provider=azure`,
|
||||
RunE: createSourceGitCmdRun,
|
||||
}
|
||||
|
||||
@@ -130,14 +138,16 @@ func init() {
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.branch, "branch", "", "git branch")
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.tag, "tag", "", "git tag")
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.semver, "tag-semver", "", "git tag semver range")
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.refName, "ref-name", "", " git reference name")
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.refName, "ref-name", "", "git reference name")
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.commit, "commit", "", "git commit")
|
||||
createSourceGitCmd.Flags().StringVarP(&sourceGitArgs.username, "username", "u", "", "basic authentication username")
|
||||
createSourceGitCmd.Flags().StringVarP(&sourceGitArgs.password, "password", "p", "", "basic authentication password")
|
||||
createSourceGitCmd.Flags().Var(&sourceGitArgs.keyAlgorithm, "ssh-key-algorithm", sourceGitArgs.keyAlgorithm.Description())
|
||||
createSourceGitCmd.Flags().Var(&sourceGitArgs.keyRSABits, "ssh-rsa-bits", sourceGitArgs.keyRSABits.Description())
|
||||
createSourceGitCmd.Flags().Var(&sourceGitArgs.keyECDSACurve, "ssh-ecdsa-curve", sourceGitArgs.keyECDSACurve.Description())
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.secretRef, "secret-ref", "", "the name of an existing secret containing SSH or basic credentials")
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.secretRef, "secret-ref", "", "the name of an existing secret containing SSH or basic credentials or github app authentication")
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.proxySecretRef, "proxy-secret-ref", "", "the name of an existing secret containing the proxy address and credentials")
|
||||
createSourceGitCmd.Flags().Var(&sourceGitArgs.provider, "provider", sourceGitArgs.provider.Description())
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates")
|
||||
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.privateKeyFile, "private-key-file", "", "path to a passwordless private key file used for authenticating to the Git SSH server")
|
||||
createSourceGitCmd.Flags().BoolVar(&sourceGitArgs.recurseSubmodules, "recurse-submodules", false,
|
||||
@@ -236,6 +246,16 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if sourceGitArgs.proxySecretRef != "" {
|
||||
gitRepository.Spec.ProxySecretRef = &meta.LocalObjectReference{
|
||||
Name: sourceGitArgs.proxySecretRef,
|
||||
}
|
||||
}
|
||||
|
||||
if provider := sourceGitArgs.provider.String(); provider != "" {
|
||||
gitRepository.Spec.Provider = provider
|
||||
}
|
||||
|
||||
if createArgs.export {
|
||||
return printExport(exportGit(&gitRepository))
|
||||
}
|
||||
@@ -273,7 +293,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
secretOpts.CAFile = caBundle
|
||||
secretOpts.CACrt = caBundle
|
||||
}
|
||||
secretOpts.Username = sourceGitArgs.username
|
||||
secretOpts.Password = sourceGitArgs.password
|
||||
|
||||
@@ -134,6 +134,36 @@ func TestCreateSourceGitExport(t *testing.T) {
|
||||
args: "create source git podinfo --namespace=flux-system --url=https://github.com/stefanprodan/podinfo --branch=test --interval=1m0s --export",
|
||||
assert: assertGoldenFile("testdata/create_source_git/source-git-branch.yaml"),
|
||||
},
|
||||
{
|
||||
name: "source with generic provider",
|
||||
args: "create source git podinfo --namespace=flux-system --url=https://github.com/stefanprodan/podinfo --provider generic --branch=test --interval=1m0s --export",
|
||||
assert: assertGoldenFile("testdata/create_source_git/source-git-provider-generic.yaml"),
|
||||
},
|
||||
{
|
||||
name: "source with azure provider",
|
||||
args: "create source git podinfo --namespace=flux-system --url=https://dev.azure.com/foo/bar/_git/podinfo --provider azure --branch=test --interval=1m0s --export",
|
||||
assert: assertGoldenFile("testdata/create_source_git/source-git-provider-azure.yaml"),
|
||||
},
|
||||
{
|
||||
name: "source with github provider",
|
||||
args: "create source git podinfo --namespace=flux-system --url=https://github.com/stefanprodan/podinfo --provider github --branch=test --interval=1m0s --secret-ref appinfo --export",
|
||||
assert: assertGoldenFile("testdata/create_source_git/source-git-provider-github.yaml"),
|
||||
},
|
||||
{
|
||||
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|azure|github"),
|
||||
},
|
||||
{
|
||||
name: "source with empty provider",
|
||||
args: "create source git podinfo --namespace=flux-system --url=https://dev.azure.com/foo/bar/_git/podinfo --provider \"\" --branch=test --interval=1m0s --export",
|
||||
assert: assertError("invalid argument \"\" for \"--provider\" flag: no source Git provider given, please specify the Git provider name"),
|
||||
},
|
||||
{
|
||||
name: "source with no provider",
|
||||
args: "create source git podinfo --namespace=flux-system --url=https://dev.azure.com/foo/bar/_git/podinfo --branch=test --interval=1m0s --export --provider",
|
||||
assert: assertError("flag needs an argument: --provider"),
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
@@ -197,9 +197,9 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Username: sourceHelmArgs.username,
|
||||
Password: sourceHelmArgs.password,
|
||||
CAFile: caBundle,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
CACrt: caBundle,
|
||||
TLSCrt: certFile,
|
||||
TLSKey: keyFile,
|
||||
ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile,
|
||||
}
|
||||
secret, err := sourcesecret.Generate(secretOpts)
|
||||
|
||||
@@ -65,6 +65,7 @@ type sourceOCIRepositoryFlags struct {
|
||||
semver string
|
||||
digest string
|
||||
secretRef string
|
||||
proxySecretRef string
|
||||
serviceAccount string
|
||||
certSecretRef string
|
||||
verifyProvider flags.SourceOCIVerifyProvider
|
||||
@@ -91,6 +92,7 @@ func init() {
|
||||
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.semver, "tag-semver", "", "the OCI artifact tag semver range")
|
||||
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.digest, "digest", "", "the OCI artifact digest")
|
||||
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.secretRef, "secret-ref", "", "the name of the Kubernetes image pull secret (type 'kubernetes.io/dockerconfigjson')")
|
||||
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.proxySecretRef, "proxy-secret-ref", "", "the name of an existing secret containing the proxy address and credentials")
|
||||
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.serviceAccount, "service-account", "", "the name of the Kubernetes service account that refers to an image pull secret")
|
||||
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.certSecretRef, "cert-ref", "", "the name of a secret to use for TLS certificates")
|
||||
createSourceOCIRepositoryCmd.Flags().Var(&sourceOCIRepositoryArgs.verifyProvider, "verify-provider", sourceOCIRepositoryArgs.verifyProvider.Description())
|
||||
@@ -167,6 +169,12 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if secretName := sourceOCIRepositoryArgs.proxySecretRef; secretName != "" {
|
||||
repository.Spec.ProxySecretRef = &meta.LocalObjectReference{
|
||||
Name: secretName,
|
||||
}
|
||||
}
|
||||
|
||||
if secretName := sourceOCIRepositoryArgs.certSecretRef; secretName != "" {
|
||||
repository.Spec.CertSecretRef = &meta.LocalObjectReference{
|
||||
Name: secretName,
|
||||
|
||||
31
cmd/flux/debug.go
Normal file
31
cmd/flux/debug.go
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright 2024 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 debugCmd = &cobra.Command{
|
||||
Use: "debug",
|
||||
Short: "Debug a flux resource",
|
||||
Long: `The debug command can be used to troubleshoot failing resource reconciliations.`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(debugCmd)
|
||||
}
|
||||
113
cmd/flux/debug_helmrelease.go
Normal file
113
cmd/flux/debug_helmrelease.go
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 2024 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 (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2"
|
||||
"github.com/fluxcd/pkg/chartutil"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/utils"
|
||||
)
|
||||
|
||||
var debugHelmReleaseCmd = &cobra.Command{
|
||||
Use: "helmrelease [name]",
|
||||
Aliases: []string{"hr"},
|
||||
Short: "Debug a HelmRelease resource",
|
||||
Long: withPreviewNote(`The debug helmrelease command can be used to troubleshoot failing Helm release reconciliations.
|
||||
WARNING: This command will print sensitive information if Kubernetes Secrets are referenced in the HelmRelease .spec.valuesFrom field.`),
|
||||
Example: ` # Print the status of a Helm release
|
||||
flux debug hr podinfo --show-status
|
||||
|
||||
# Export the final values of a Helm release composed from referred ConfigMaps and Secrets
|
||||
flux debug hr podinfo --show-values > values.yaml`,
|
||||
RunE: debugHelmReleaseCmdRun,
|
||||
Args: cobra.ExactArgs(1),
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)),
|
||||
}
|
||||
|
||||
type debugHelmReleaseFlags struct {
|
||||
showStatus bool
|
||||
showValues bool
|
||||
}
|
||||
|
||||
var debugHelmReleaseArgs debugHelmReleaseFlags
|
||||
|
||||
func init() {
|
||||
debugHelmReleaseCmd.Flags().BoolVar(&debugHelmReleaseArgs.showStatus, "show-status", false, "print the status of the Helm release")
|
||||
debugHelmReleaseCmd.Flags().BoolVar(&debugHelmReleaseArgs.showValues, "show-values", false, "print the final values of the Helm release")
|
||||
debugCmd.AddCommand(debugHelmReleaseCmd)
|
||||
}
|
||||
|
||||
func debugHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
|
||||
name := args[0]
|
||||
|
||||
if (!debugHelmReleaseArgs.showStatus && !debugHelmReleaseArgs.showValues) ||
|
||||
(debugHelmReleaseArgs.showStatus && debugHelmReleaseArgs.showValues) {
|
||||
return fmt.Errorf("either --show-status or --show-values must be set")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hr := &helmv2.HelmRelease{}
|
||||
hrName := types.NamespacedName{Namespace: *kubeconfigArgs.Namespace, Name: name}
|
||||
if err := kubeClient.Get(ctx, hrName, hr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if debugHelmReleaseArgs.showStatus {
|
||||
status, err := yaml.Marshal(hr.Status)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootCmd.Println("# Status documentation: https://fluxcd.io/flux/components/helm/helmreleases/#helmrelease-status")
|
||||
rootCmd.Print(string(status))
|
||||
return nil
|
||||
}
|
||||
|
||||
if debugHelmReleaseArgs.showValues {
|
||||
finalValues, err := chartutil.ChartValuesFromReferences(ctx,
|
||||
logr.Discard(),
|
||||
kubeClient,
|
||||
hr.GetNamespace(),
|
||||
hr.GetValues(),
|
||||
hr.Spec.ValuesFrom...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
values, err := yaml.Marshal(finalValues)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootCmd.Print(string(values))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
71
cmd/flux/debug_helmrelease_test.go
Normal file
71
cmd/flux/debug_helmrelease_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
//go:build unit
|
||||
// +build unit
|
||||
|
||||
/*
|
||||
Copyright 2024 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 TestDebugHelmRelease(t *testing.T) {
|
||||
namespace := allocateNamespace("debug")
|
||||
|
||||
objectFile := "testdata/debug_helmrelease/objects.yaml"
|
||||
tmpl := map[string]string{
|
||||
"fluxns": namespace,
|
||||
}
|
||||
testEnv.CreateObjectFile(objectFile, tmpl, t)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
arg string
|
||||
goldenFile string
|
||||
tmpl map[string]string
|
||||
}{
|
||||
{
|
||||
"debug status",
|
||||
"debug helmrelease test-values-inline --show-status --show-values=false",
|
||||
"testdata/debug_helmrelease/status.golden.yaml",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"debug values",
|
||||
"debug helmrelease test-values-inline --show-values --show-status=false",
|
||||
"testdata/debug_helmrelease/values-inline.golden.yaml",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"debug values from",
|
||||
"debug helmrelease test-values-from --show-values --show-status=false",
|
||||
"testdata/debug_helmrelease/values-from.golden.yaml",
|
||||
tmpl,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: tt.arg + " -n=" + namespace,
|
||||
assert: assertGoldenTemplateFile(tt.goldenFile, tmpl),
|
||||
}
|
||||
|
||||
cmd.runTestCmd(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
134
cmd/flux/debug_kustomization.go
Normal file
134
cmd/flux/debug_kustomization.go
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright 2024 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 (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
|
||||
"github.com/fluxcd/pkg/kustomize"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/utils"
|
||||
)
|
||||
|
||||
var debugKustomizationCmd = &cobra.Command{
|
||||
Use: "kustomization [name]",
|
||||
Aliases: []string{"ks"},
|
||||
Short: "Debug a Flux Kustomization resource",
|
||||
Long: withPreviewNote(`The debug kustomization command can be used to troubleshoot failing Flux Kustomization reconciliations.
|
||||
WARNING: This command will print sensitive information if Kubernetes Secrets are referenced in the Kustomization .spec.postBuild.substituteFrom field.`),
|
||||
Example: ` # Print the status of a Flux Kustomization
|
||||
flux debug ks podinfo --show-status
|
||||
|
||||
# Export the final variables used for post-build substitutions composed from referred ConfigMaps and Secrets
|
||||
flux debug ks podinfo --show-vars > vars.env`,
|
||||
RunE: debugKustomizationCmdRun,
|
||||
Args: cobra.ExactArgs(1),
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)),
|
||||
}
|
||||
|
||||
type debugKustomizationFlags struct {
|
||||
showStatus bool
|
||||
showVars bool
|
||||
}
|
||||
|
||||
var debugKustomizationArgs debugKustomizationFlags
|
||||
|
||||
func init() {
|
||||
debugKustomizationCmd.Flags().BoolVar(&debugKustomizationArgs.showStatus, "show-status", false, "print the status of the Flux Kustomization")
|
||||
debugKustomizationCmd.Flags().BoolVar(&debugKustomizationArgs.showVars, "show-vars", false, "print the final vars of the Flux Kustomization in dot env format")
|
||||
debugCmd.AddCommand(debugKustomizationCmd)
|
||||
}
|
||||
|
||||
func debugKustomizationCmdRun(cmd *cobra.Command, args []string) error {
|
||||
name := args[0]
|
||||
|
||||
if (!debugKustomizationArgs.showStatus && !debugKustomizationArgs.showVars) ||
|
||||
(debugKustomizationArgs.showStatus && debugKustomizationArgs.showVars) {
|
||||
return fmt.Errorf("either --show-status or --show-vars must be set")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ks := &kustomizev1.Kustomization{}
|
||||
ksName := types.NamespacedName{Namespace: *kubeconfigArgs.Namespace, Name: name}
|
||||
if err := kubeClient.Get(ctx, ksName, ks); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if debugKustomizationArgs.showStatus {
|
||||
status, err := yaml.Marshal(ks.Status)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootCmd.Println("# Status documentation: https://fluxcd.io/flux/components/kustomize/kustomizations/#kustomization-status")
|
||||
rootCmd.Print(string(status))
|
||||
return nil
|
||||
}
|
||||
|
||||
if debugKustomizationArgs.showVars {
|
||||
if ks.Spec.PostBuild == nil {
|
||||
return errors.New("no post build substitutions found")
|
||||
}
|
||||
|
||||
ksObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(ks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
finalVars, err := kustomize.LoadVariables(ctx, kubeClient, unstructured.Unstructured{Object: ksObj})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(ks.Spec.PostBuild.Substitute) > 0 {
|
||||
for k, v := range ks.Spec.PostBuild.Substitute {
|
||||
// Remove new lines from the values as they are not supported.
|
||||
// Replicates the controller behavior from
|
||||
// https://github.com/fluxcd/pkg/blob/main/kustomize/kustomize_varsub.go
|
||||
finalVars[k] = strings.ReplaceAll(v, "\n", "")
|
||||
}
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(finalVars))
|
||||
for k := range finalVars {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, k := range keys {
|
||||
rootCmd.Println(k + "=" + finalVars[k])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
71
cmd/flux/debug_kustomization_test.go
Normal file
71
cmd/flux/debug_kustomization_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
//go:build unit
|
||||
// +build unit
|
||||
|
||||
/*
|
||||
Copyright 2024 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 TestDebugKustomization(t *testing.T) {
|
||||
namespace := allocateNamespace("debug")
|
||||
|
||||
objectFile := "testdata/debug_kustomization/objects.yaml"
|
||||
tmpl := map[string]string{
|
||||
"fluxns": namespace,
|
||||
}
|
||||
testEnv.CreateObjectFile(objectFile, tmpl, t)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
arg string
|
||||
goldenFile string
|
||||
tmpl map[string]string
|
||||
}{
|
||||
{
|
||||
"debug status",
|
||||
"debug ks test --show-status --show-vars=false",
|
||||
"testdata/debug_kustomization/status.golden.yaml",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"debug vars",
|
||||
"debug ks test --show-vars --show-status=false",
|
||||
"testdata/debug_kustomization/vars.golden.env",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"debug vars from",
|
||||
"debug ks test-from --show-vars --show-status=false",
|
||||
"testdata/debug_kustomization/vars-from.golden.env",
|
||||
tmpl,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: tt.arg + " -n=" + namespace,
|
||||
assert: assertGoldenTemplateFile(tt.goldenFile, tmpl),
|
||||
}
|
||||
|
||||
cmd.runTestCmd(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -19,13 +19,13 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
var deleteSourceBucketCmd = &cobra.Command{
|
||||
Use: "bucket [name]",
|
||||
Short: "Delete a Bucket source",
|
||||
Long: withPreviewNote("The delete source bucket command deletes the given Bucket from the cluster."),
|
||||
Long: "The delete source bucket command deletes the given Bucket from the cluster.",
|
||||
Example: ` # Delete a Bucket source
|
||||
flux delete source bucket podinfo`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.BucketKind)),
|
||||
|
||||
@@ -44,7 +44,12 @@ flux diff kustomization my-app --path ./path/to/local/manifests \
|
||||
# Exclude files by providing a comma separated list of entries that follow the .gitignore pattern fromat.
|
||||
flux diff kustomization my-app --path ./path/to/local/manifests \
|
||||
--kustomization-file ./path/to/local/my-app.yaml \
|
||||
--ignore-paths "/to_ignore/**/*.yaml,ignore.yaml"`,
|
||||
--ignore-paths "/to_ignore/**/*.yaml,ignore.yaml"
|
||||
|
||||
# Run recursively on all encountered Kustomizations
|
||||
flux diff kustomization my-app --path ./path/to/local/manifests \
|
||||
--recursive \
|
||||
--local-sources GitRepository/flux-system/my-repo=./path/to/local/git`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)),
|
||||
RunE: diffKsCmdRun,
|
||||
}
|
||||
@@ -55,6 +60,8 @@ type diffKsFlags struct {
|
||||
ignorePaths []string
|
||||
progressBar bool
|
||||
strictSubst bool
|
||||
recursive bool
|
||||
localSources map[string]string
|
||||
}
|
||||
|
||||
var diffKsArgs diffKsFlags
|
||||
@@ -66,6 +73,8 @@ func init() {
|
||||
diffKsCmd.Flags().StringVar(&diffKsArgs.kustomizationFile, "kustomization-file", "", "Path to the Flux Kustomization YAML file.")
|
||||
diffKsCmd.Flags().BoolVar(&diffKsArgs.strictSubst, "strict-substitute", false,
|
||||
"When enabled, the post build substitutions will fail if a var without a default value is declared in files but is missing from the input vars.")
|
||||
diffKsCmd.Flags().BoolVarP(&diffKsArgs.recursive, "recursive", "r", false, "Recursively diff Kustomizations")
|
||||
diffKsCmd.Flags().StringToStringVar(&diffKsArgs.localSources, "local-sources", nil, "Comma-separated list of repositories in format: Kind/namespace/name=path")
|
||||
diffCmd.AddCommand(diffKsCmd)
|
||||
}
|
||||
|
||||
@@ -101,6 +110,9 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
build.WithProgressBar(),
|
||||
build.WithIgnore(diffKsArgs.ignorePaths),
|
||||
build.WithStrictSubstitute(diffKsArgs.strictSubst),
|
||||
build.WithRecursive(diffKsArgs.recursive),
|
||||
build.WithLocalSources(diffKsArgs.localSources),
|
||||
build.WithSingleKustomization(),
|
||||
)
|
||||
} else {
|
||||
builder, err = build.NewBuilder(name, diffKsArgs.path,
|
||||
@@ -109,6 +121,9 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
build.WithKustomizationFile(diffKsArgs.kustomizationFile),
|
||||
build.WithIgnore(diffKsArgs.ignorePaths),
|
||||
build.WithStrictSubstitute(diffKsArgs.strictSubst),
|
||||
build.WithRecursive(diffKsArgs.recursive),
|
||||
build.WithLocalSources(diffKsArgs.localSources),
|
||||
build.WithSingleKustomization(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -138,6 +153,12 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
|
||||
select {
|
||||
case <-sigc:
|
||||
if diffKsArgs.progressBar {
|
||||
err := builder.StopSpinner()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Println("Build cancelled... exiting.")
|
||||
return builder.Cancel()
|
||||
case err := <-errChan:
|
||||
|
||||
@@ -97,6 +97,12 @@ func TestDiffKustomization(t *testing.T) {
|
||||
objectFile: "",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/nothing-is-deployed.golden"),
|
||||
},
|
||||
{
|
||||
name: "diff with recursive",
|
||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo-with-my-app --progress-bar=false --recursive --local-sources GitRepository/default/podinfo=./testdata/build-kustomization",
|
||||
objectFile: "./testdata/diff-kustomization/my-app.yaml",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-recursive.golden"),
|
||||
},
|
||||
}
|
||||
|
||||
tmpl := map[string]string{
|
||||
|
||||
@@ -447,7 +447,7 @@ var fluxKindMap = refMap{
|
||||
},
|
||||
sourcev1.GitRepositoryKind: {gvk: sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)},
|
||||
sourcev1b2.OCIRepositoryKind: {gvk: sourcev1b2.GroupVersion.WithKind(sourcev1b2.OCIRepositoryKind)},
|
||||
sourcev1b2.BucketKind: {gvk: sourcev1b2.GroupVersion.WithKind(sourcev1b2.BucketKind)},
|
||||
sourcev1.BucketKind: {gvk: sourcev1.GroupVersion.WithKind(sourcev1.BucketKind)},
|
||||
sourcev1.HelmRepositoryKind: {gvk: sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)},
|
||||
autov1.ImageUpdateAutomationKind: {gvk: autov1.GroupVersion.WithKind(autov1.ImageUpdateAutomationKind)},
|
||||
imagev1.ImageRepositoryKind: {gvk: imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)},
|
||||
|
||||
@@ -21,13 +21,13 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
var exportSourceBucketCmd = &cobra.Command{
|
||||
Use: "bucket [name]",
|
||||
Short: "Export Bucket sources in YAML format",
|
||||
Long: withPreviewNote("The export source git command exports one or all Bucket sources in YAML format."),
|
||||
Long: "The export source git command exports one or all Bucket sources in YAML format.",
|
||||
Example: ` # Export all Bucket sources
|
||||
flux export source bucket --all > sources.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
//go:build unit
|
||||
// +build unit
|
||||
|
||||
/*
|
||||
Copyright 2024 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 (
|
||||
|
||||
@@ -46,7 +46,7 @@ var getSourceAllCmd = &cobra.Command{
|
||||
},
|
||||
{
|
||||
apiType: bucketType,
|
||||
list: &bucketListAdapter{&sourcev1b2.BucketList{}},
|
||||
list: &bucketListAdapter{&sourcev1.BucketList{}},
|
||||
},
|
||||
{
|
||||
apiType: gitRepositoryType,
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"golang.org/x/text/language"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/utils"
|
||||
)
|
||||
@@ -33,7 +33,7 @@ import (
|
||||
var getSourceBucketCmd = &cobra.Command{
|
||||
Use: "bucket",
|
||||
Short: "Get Bucket source statuses",
|
||||
Long: withPreviewNote("The get sources bucket command prints the status of the Bucket sources."),
|
||||
Long: "The get sources bucket command prints the status of the Bucket sources.",
|
||||
Example: ` # List all Buckets and their status
|
||||
flux get sources bucket
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ func parallelPodLogs(ctx context.Context, requests []rest.ResponseWrapper) error
|
||||
return errors.Join(<-stdoutErrCh, <-stderrErrCh)
|
||||
}
|
||||
|
||||
// asyncCopy copies all data from from dst to src asynchronously and returns a channel for reading an error value.
|
||||
// asyncCopy copies all data from dst to src asynchronously and returns a channel for reading an error value.
|
||||
// This is basically an asynchronous wrapper around `io.Copy`. The returned channel is unbuffered and always is sent
|
||||
// a value (either nil or the error from `io.Copy`) as soon as `io.Copy` returns.
|
||||
// This function lets you copy from multiple sources into multiple destinations in parallel.
|
||||
|
||||
@@ -429,7 +429,9 @@ func resetCmdArgs() {
|
||||
tail: -1,
|
||||
fluxNamespace: rootArgs.defaults.Namespace,
|
||||
}
|
||||
buildKsArgs = buildKsFlags{}
|
||||
buildKsArgs = buildKsFlags{
|
||||
localSources: map[string]string{},
|
||||
}
|
||||
checkArgs = checkFlags{}
|
||||
createArgs = createFlags{}
|
||||
deleteArgs = deleteFlags{}
|
||||
@@ -451,6 +453,7 @@ func resetCmdArgs() {
|
||||
rhrArgs = reconcileHelmReleaseFlags{}
|
||||
rksArgs = reconcileKsFlags{}
|
||||
secretGitArgs = NewSecretGitFlags()
|
||||
secretProxyArgs = secretProxyFlags{}
|
||||
secretHelmArgs = secretHelmFlags{}
|
||||
secretTLSArgs = secretTLSFlags{}
|
||||
sourceBucketArgs = sourceBucketFlags{}
|
||||
@@ -466,6 +469,8 @@ func resetCmdArgs() {
|
||||
output: "yaml",
|
||||
}
|
||||
envsubstArgs = envsubstFlags{}
|
||||
debugHelmReleaseArgs = debugHelmReleaseFlags{}
|
||||
debugKustomizationArgs = debugKustomizationFlags{}
|
||||
}
|
||||
|
||||
func isChangeError(err error) bool {
|
||||
|
||||
@@ -32,7 +32,7 @@ var reconcileHrCmd = &cobra.Command{
|
||||
Aliases: []string{"hr"},
|
||||
Short: "Reconcile a HelmRelease resource",
|
||||
Long: `
|
||||
The reconcile kustomization command triggers a reconciliation of a HelmRelease resource and waits for it to finish.`,
|
||||
The reconcile helmrelease command triggers a reconciliation of a HelmRelease resource and waits for it to finish.`,
|
||||
Example: ` # Trigger a HelmRelease apply outside of the reconciliation interval
|
||||
flux reconcile hr podinfo
|
||||
|
||||
|
||||
@@ -76,10 +76,10 @@ func (obj kustomizationAdapter) getSource() (reconcileSource, types.NamespacedNa
|
||||
apiType: gitRepositoryType,
|
||||
object: gitRepositoryAdapter{&sourcev1.GitRepository{}},
|
||||
}
|
||||
case sourcev1b2.BucketKind:
|
||||
case sourcev1.BucketKind:
|
||||
cmd = reconcileCommand{
|
||||
apiType: bucketType,
|
||||
object: bucketAdapter{&sourcev1b2.Bucket{}},
|
||||
object: bucketAdapter{&sourcev1.Bucket{}},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
var reconcileSourceBucketCmd = &cobra.Command{
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var reconcileSourceHelmChartCmd = &cobra.Command{
|
||||
@@ -72,10 +71,10 @@ func (obj helmChartAdapter) getSource() (reconcileSource, types.NamespacedName)
|
||||
apiType: gitRepositoryType,
|
||||
object: gitRepositoryAdapter{&sourcev1.GitRepository{}},
|
||||
}
|
||||
case sourcev1b2.BucketKind:
|
||||
case sourcev1.BucketKind:
|
||||
cmd = reconcileCommand{
|
||||
apiType: bucketType,
|
||||
object: bucketAdapter{&sourcev1b2.Bucket{}},
|
||||
object: bucketAdapter{&sourcev1.Bucket{}},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
|
||||
// If the args slice is empty, it patches all resumable objects in the given namespace.
|
||||
func (resume *resumeCommand) getPatchedResumables(ctx context.Context, args []string) ([]resumable, error) {
|
||||
if len(args) < 1 {
|
||||
objs, err := resume.patch(ctx, []client.ListOption{
|
||||
objs, err := resume.patch(ctx, args, []client.ListOption{
|
||||
client.InNamespace(resume.namespace),
|
||||
})
|
||||
if err != nil {
|
||||
@@ -151,7 +151,7 @@ func (resume *resumeCommand) getPatchedResumables(ctx context.Context, args []st
|
||||
}
|
||||
processed[arg] = struct{}{}
|
||||
|
||||
objs, err := resume.patch(ctx, []client.ListOption{
|
||||
objs, err := resume.patch(ctx, args, []client.ListOption{
|
||||
client.InNamespace(resume.namespace),
|
||||
client.MatchingFields{
|
||||
"metadata.name": arg,
|
||||
@@ -169,13 +169,17 @@ func (resume *resumeCommand) getPatchedResumables(ctx context.Context, args []st
|
||||
|
||||
// Patches resumable objects by setting their status to unsuspended.
|
||||
// Returns a slice of resumables that have been patched and any error encountered during patching.
|
||||
func (resume resumeCommand) patch(ctx context.Context, listOpts []client.ListOption) ([]resumable, error) {
|
||||
func (resume resumeCommand) patch(ctx context.Context, args []string, listOpts []client.ListOption) ([]resumable, error) {
|
||||
if err := resume.client.List(ctx, resume.list.asClientList(), listOpts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resume.list.len() == 0 {
|
||||
logger.Failuref("no %s objects found in %s namespace", resume.kind, resume.namespace)
|
||||
if len(args) < 1 {
|
||||
logger.Failuref("no %s objects found in %s namespace", resume.kind, resume.namespace)
|
||||
} else {
|
||||
logger.Failuref("%s object '%s' not found in %s namespace", resume.kind, args[0], resume.namespace)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
var resumeSourceBucketCmd = &cobra.Command{
|
||||
|
||||
@@ -61,16 +61,16 @@ func (a ociRepositoryListAdapter) len() int {
|
||||
return len(a.OCIRepositoryList.Items)
|
||||
}
|
||||
|
||||
// sourcev1b2.Bucket
|
||||
// sourcev1.Bucket
|
||||
|
||||
var bucketType = apiType{
|
||||
kind: sourcev1b2.BucketKind,
|
||||
kind: sourcev1.BucketKind,
|
||||
humanKind: "source bucket",
|
||||
groupVersion: sourcev1b2.GroupVersion,
|
||||
groupVersion: sourcev1.GroupVersion,
|
||||
}
|
||||
|
||||
type bucketAdapter struct {
|
||||
*sourcev1b2.Bucket
|
||||
*sourcev1.Bucket
|
||||
}
|
||||
|
||||
func (a bucketAdapter) asClientObject() client.Object {
|
||||
@@ -81,10 +81,10 @@ func (a bucketAdapter) deepCopyClientObject() client.Object {
|
||||
return a.Bucket.DeepCopy()
|
||||
}
|
||||
|
||||
// sourcev1b2.BucketList
|
||||
// sourcev1.BucketList
|
||||
|
||||
type bucketListAdapter struct {
|
||||
*sourcev1b2.BucketList
|
||||
*sourcev1.BucketList
|
||||
}
|
||||
|
||||
func (a bucketListAdapter) asClientList() client.ObjectList {
|
||||
|
||||
@@ -97,9 +97,9 @@ func runStatsCmd(cmd *cobra.Command, args []string) error {
|
||||
Group: sourcev1.GroupVersion.Group,
|
||||
},
|
||||
{
|
||||
Kind: sourcev1b2.BucketKind,
|
||||
Version: sourcev1b2.GroupVersion.Version,
|
||||
Group: sourcev1b2.GroupVersion.Group,
|
||||
Kind: sourcev1.BucketKind,
|
||||
Version: sourcev1.GroupVersion.Version,
|
||||
Group: sourcev1.GroupVersion.Group,
|
||||
},
|
||||
{
|
||||
Kind: kustomizev1.KustomizationKind,
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
var suspendSourceBucketCmd = &cobra.Command{
|
||||
|
||||
6
cmd/flux/testdata/build-kustomization/my-app/configmap.yaml
vendored
Normal file
6
cmd/flux/testdata/build-kustomization/my-app/configmap.yaml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: v1
|
||||
data:
|
||||
var: test
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: my-app
|
||||
29
cmd/flux/testdata/build-kustomization/podinfo-with-my-app-result.yaml
vendored
Normal file
29
cmd/flux/testdata/build-kustomization/podinfo-with-my-app-result.yaml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: podinfo
|
||||
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
|
||||
name: my-app
|
||||
namespace: default
|
||||
spec:
|
||||
force: true
|
||||
interval: 5m0s
|
||||
path: ./my-app
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: podinfo
|
||||
targetNamespace: default
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
var: test
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: my-app
|
||||
kustomize.toolkit.fluxcd.io/namespace: default
|
||||
name: my-app
|
||||
namespace: default
|
||||
---
|
||||
4
cmd/flux/testdata/build-kustomization/podinfo-with-my-app/kustomization.yaml
vendored
Normal file
4
cmd/flux/testdata/build-kustomization/podinfo-with-my-app/kustomization.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./my-app.yaml
|
||||
14
cmd/flux/testdata/build-kustomization/podinfo-with-my-app/my-app.yaml
vendored
Normal file
14
cmd/flux/testdata/build-kustomization/podinfo-with-my-app/my-app.yaml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: my-app
|
||||
spec:
|
||||
interval: 5m0s
|
||||
path: ./my-app
|
||||
force: true
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: podinfo
|
||||
targetNamespace: default
|
||||
2
cmd/flux/testdata/check/check_pre.golden
vendored
2
cmd/flux/testdata/check/check_pre.golden
vendored
@@ -1,3 +1,3 @@
|
||||
► checking prerequisites
|
||||
✔ Kubernetes {{ .serverVersion }} >=1.28.0-0
|
||||
✔ Kubernetes {{ .serverVersion }} >=1.30.0-0
|
||||
✔ prerequisites checks passed
|
||||
|
||||
39
cmd/flux/testdata/create_secret/githubapp/secret-with-baseurl.yaml
vendored
Normal file
39
cmd/flux/testdata/create_secret/githubapp/secret-with-baseurl.yaml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: appinfo
|
||||
namespace: my-namespace
|
||||
stringData:
|
||||
githubAppBaseURL: www.example.com/api/v3
|
||||
githubAppID: "1"
|
||||
githubAppInstallationID: "2"
|
||||
githubAppPrivateKey: |-
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap
|
||||
PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm
|
||||
zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm
|
||||
LsXqL2iZvVvCH0FiDwBIfxAMhl6fnPzuQsZBiRLPdD67jubPseN1P5JBRw3WTton
|
||||
Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T
|
||||
MROFeZmxBHYon1Y4Rw+jCSXovNyHbMBpMI67nwIDAQABAoIBAC4UrkusU8r7ilFu
|
||||
w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB
|
||||
FkhEBrwXKnh499iiO/SUo+7kaq0WLQ7mQ2Q9wpMmkkjnr0tgydAno/uNNITSaqmk
|
||||
YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap
|
||||
Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T
|
||||
zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm
|
||||
ihlXNkECgYEA3abZJZuVarHPlAqRYkprs0O+DrP6sPlmVQp+nq8y3Qg00U+N7AuP
|
||||
Y1riLo3gWq7LajkGTygWLmru2mhWsETxt+R4BtnREUq8kDEoCfEwPlHfqfphvBZL
|
||||
j5eL60QTKAqSOVqMgIzqJyxa5FGgPGqWpLDLopyVeoyNdZwcuCQzFgkCgYEA25dm
|
||||
PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm
|
||||
MkvaCGIAH+lfJrtTSujFaOIGFy+0ZwP+LNqHUKih14y8Qv9dEP0kaXkAD3fO3Y97
|
||||
Nj+Q2c06JpojgBKBMwVvT7M53w9KEoNKpoKBbmcCgYBelHyiRJJsdbVKyXuiAnmU
|
||||
g/qMkZYOgE1/SjwfgEjm8kJ/cj/wEjq8PaK4FMhAScf46p5blpJoei6zucQL8U9n
|
||||
lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s
|
||||
dNhf6gsKwQD3x4aluKSn6QKBgD8HbvBAKV6P4vIiFzS0QvWtpeKam2EDHI+h+WsP
|
||||
nD77QoG/EPvpjJS9/KWgZRPz6U+0M5V0y73MZVzkbbVT/uwfgF2G91lXAr4Kfuh5
|
||||
w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB
|
||||
qCEDAoGACl8ClvMJR2uNWdaWnCz9tyPdHYgEusJ0OIP+WUY2ToYQWSlA0zNpc21Y
|
||||
lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s
|
||||
bUytJtOhHbLRNxwgalhjBUNWICrDktqJmumNOEOOPBqVz7RGwUg=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
38
cmd/flux/testdata/create_secret/githubapp/secret.yaml
vendored
Normal file
38
cmd/flux/testdata/create_secret/githubapp/secret.yaml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: appinfo
|
||||
namespace: my-namespace
|
||||
stringData:
|
||||
githubAppID: "1"
|
||||
githubAppInstallationID: "2"
|
||||
githubAppPrivateKey: |-
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap
|
||||
PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm
|
||||
zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm
|
||||
LsXqL2iZvVvCH0FiDwBIfxAMhl6fnPzuQsZBiRLPdD67jubPseN1P5JBRw3WTton
|
||||
Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T
|
||||
MROFeZmxBHYon1Y4Rw+jCSXovNyHbMBpMI67nwIDAQABAoIBAC4UrkusU8r7ilFu
|
||||
w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB
|
||||
FkhEBrwXKnh499iiO/SUo+7kaq0WLQ7mQ2Q9wpMmkkjnr0tgydAno/uNNITSaqmk
|
||||
YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap
|
||||
Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T
|
||||
zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm
|
||||
ihlXNkECgYEA3abZJZuVarHPlAqRYkprs0O+DrP6sPlmVQp+nq8y3Qg00U+N7AuP
|
||||
Y1riLo3gWq7LajkGTygWLmru2mhWsETxt+R4BtnREUq8kDEoCfEwPlHfqfphvBZL
|
||||
j5eL60QTKAqSOVqMgIzqJyxa5FGgPGqWpLDLopyVeoyNdZwcuCQzFgkCgYEA25dm
|
||||
PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm
|
||||
MkvaCGIAH+lfJrtTSujFaOIGFy+0ZwP+LNqHUKih14y8Qv9dEP0kaXkAD3fO3Y97
|
||||
Nj+Q2c06JpojgBKBMwVvT7M53w9KEoNKpoKBbmcCgYBelHyiRJJsdbVKyXuiAnmU
|
||||
g/qMkZYOgE1/SjwfgEjm8kJ/cj/wEjq8PaK4FMhAScf46p5blpJoei6zucQL8U9n
|
||||
lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s
|
||||
dNhf6gsKwQD3x4aluKSn6QKBgD8HbvBAKV6P4vIiFzS0QvWtpeKam2EDHI+h+WsP
|
||||
nD77QoG/EPvpjJS9/KWgZRPz6U+0M5V0y73MZVzkbbVT/uwfgF2G91lXAr4Kfuh5
|
||||
w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB
|
||||
qCEDAoGACl8ClvMJR2uNWdaWnCz9tyPdHYgEusJ0OIP+WUY2ToYQWSlA0zNpc21Y
|
||||
lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s
|
||||
bUytJtOhHbLRNxwgalhjBUNWICrDktqJmumNOEOOPBqVz7RGwUg=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
27
cmd/flux/testdata/create_secret/githubapp/test-private-key.pem
vendored
Normal file
27
cmd/flux/testdata/create_secret/githubapp/test-private-key.pem
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap
|
||||
PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm
|
||||
zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm
|
||||
LsXqL2iZvVvCH0FiDwBIfxAMhl6fnPzuQsZBiRLPdD67jubPseN1P5JBRw3WTton
|
||||
Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T
|
||||
MROFeZmxBHYon1Y4Rw+jCSXovNyHbMBpMI67nwIDAQABAoIBAC4UrkusU8r7ilFu
|
||||
w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB
|
||||
FkhEBrwXKnh499iiO/SUo+7kaq0WLQ7mQ2Q9wpMmkkjnr0tgydAno/uNNITSaqmk
|
||||
YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap
|
||||
Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T
|
||||
zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm
|
||||
ihlXNkECgYEA3abZJZuVarHPlAqRYkprs0O+DrP6sPlmVQp+nq8y3Qg00U+N7AuP
|
||||
Y1riLo3gWq7LajkGTygWLmru2mhWsETxt+R4BtnREUq8kDEoCfEwPlHfqfphvBZL
|
||||
j5eL60QTKAqSOVqMgIzqJyxa5FGgPGqWpLDLopyVeoyNdZwcuCQzFgkCgYEA25dm
|
||||
PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm
|
||||
MkvaCGIAH+lfJrtTSujFaOIGFy+0ZwP+LNqHUKih14y8Qv9dEP0kaXkAD3fO3Y97
|
||||
Nj+Q2c06JpojgBKBMwVvT7M53w9KEoNKpoKBbmcCgYBelHyiRJJsdbVKyXuiAnmU
|
||||
g/qMkZYOgE1/SjwfgEjm8kJ/cj/wEjq8PaK4FMhAScf46p5blpJoei6zucQL8U9n
|
||||
lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s
|
||||
dNhf6gsKwQD3x4aluKSn6QKBgD8HbvBAKV6P4vIiFzS0QvWtpeKam2EDHI+h+WsP
|
||||
nD77QoG/EPvpjJS9/KWgZRPz6U+0M5V0y73MZVzkbbVT/uwfgF2G91lXAr4Kfuh5
|
||||
w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB
|
||||
qCEDAoGACl8ClvMJR2uNWdaWnCz9tyPdHYgEusJ0OIP+WUY2ToYQWSlA0zNpc21Y
|
||||
lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s
|
||||
bUytJtOhHbLRNxwgalhjBUNWICrDktqJmumNOEOOPBqVz7RGwUg=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
11
cmd/flux/testdata/create_secret/proxy/secret-proxy.yaml
vendored
Normal file
11
cmd/flux/testdata/create_secret/proxy/secret-proxy.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: proxy-secret
|
||||
namespace: my-namespace
|
||||
stringData:
|
||||
address: https://my-proxy.com
|
||||
password: my-password
|
||||
username: my-username
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
Flag --cert-file has been deprecated, please use --tls-crt-file instead
|
||||
Flag --key-file has been deprecated, please use --tls-key-file instead
|
||||
Flag --ca-file has been deprecated, please use --ca-crt-file instead
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: certs
|
||||
namespace: my-namespace
|
||||
stringData:
|
||||
caFile: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBhzCCAS2gAwIBAgIUdsAtiX3gN0uk7ddxASWYE/tdv0wwCgYIKoZIzj0EAwIw
|
||||
GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjAwNDE3MDgxODAwWhcNMjUw
|
||||
NDE2MDgxODAwWjAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49
|
||||
AgEGCCqGSM49AwEHA0IABK7h/5D8bV93MmEdhu02JsS6ugB8s6PzRl3PV4xs3Sbr
|
||||
RNkkM59+x3b0iWx/i76qPYpNLoiVUVXQmA9Y+4DbMxijUzBRMA4GA1UdDwEB/wQE
|
||||
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQGyUiU1QEZiMAqjsnIYTwZ
|
||||
4yp5wzAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIQDzdtvKdE8O
|
||||
1+WRTZ9MuSiFYcrEz7Zne7VXouDEKqKEigIgM4WlbDeuNCKbqhqj+xZV0pa3rweb
|
||||
OD8EjjCMY69RMO0=
|
||||
-----END CERTIFICATE-----
|
||||
certFile: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFazCCA1OgAwIBAgIUT84jeO/ncOrqI+FY05Fzbg8Ed7MwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTA4MDgxNDQyMzVaFw0yMjA4
|
||||
MDgxNDQyMzVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
|
||||
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB
|
||||
AQUAA4ICDwAwggIKAoICAQDn/rPsZ74oypiwCzLlx57zplTiCi/WLSF+MmLGuTvM
|
||||
EQnV+OND2zFgvDIV/vFs3brkd6rLVI4NcdgSj4YKULCMwwOl45hQPdCTEPJvUhCm
|
||||
M+FuQ0czmEEJSjZtdLFz1B7QB/JemNnbfigxM9mlg58AlBhVJqn8q64wd/kC/W/K
|
||||
JTLJuBiVf12ZiPoPfO4WSxAqD3opZ8gdbmK0KYQAhKjEto6ZrYGisfwU1gt3l8M7
|
||||
sCJSpEkOkpuQgJ8D+xzJS36VXBJQMMP9nAPps+x/rGFplsPMsXEFFiwvR1+FJZwz
|
||||
lg2sJ91bLGZQ7vn74MfsGrxpiJwllRThJyT7C9V0sjb5trT2lEqZlP2dRSJYt7aJ
|
||||
1crEcdGSl6RIKgxSV6Hk8dh/ZaTjrTwaKxVkPo2IeEXy5xrR7DyonOQ6Yes0KOCm
|
||||
JB5yHkFlIVEnLm/HZXEtm3bPHsFgTZuInyBCOMXpUESuVZIw8YK+Vd6AExGPPwZ4
|
||||
n5I/sCDxWII9owIj3LeLzdUG6JoroahhGmo8rgpbJpPnS+VgryQ/raUQjqDzDCuE
|
||||
9vKXKBlSUqK6H9A+NMc0mme7M8/GX7T7ewFGUB/xsdrcO4yXjqHnAe0yLf8epDjC
|
||||
hh76bYqwwinVrmfcNcRxFVJZW2z0gGdgkOkOLaVVb9ggPV2SNAHbN4A+St/iRYR5
|
||||
awIDAQABo1MwUTAdBgNVHQ4EFgQUzMaCqVM30EZFfTeNUIJ5fNPAhaQwHwYDVR0j
|
||||
BBgwFoAUzMaCqVM30EZFfTeNUIJ5fNPAhaQwDwYDVR0TAQH/BAUwAwEB/zANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEAVmk1rXtVkYR1Vs2Va/xrUaGXlFznhPU/Fft44kiEkkLp
|
||||
mLVelWyAqvXYioqssZwuZnTjGz0DQPqzJjqwuGy4CHwPLmhCtfHplrbWo8a0ivYC
|
||||
cL20KfZsG941siUh7LGBjTsq6mWBf2ytlFmg/fg93SgmqcEUAUcdps0JpZD8lgWB
|
||||
ZMstfr6E3jaEus3OsvDD6hJNYZ5clJ5+ynLoWZ99A9JC0U46hmIZpRjbdSvasKpD
|
||||
XrXTdpzyL/Do3znXE/yfoHv4//Rj2CpPHJLYRCIzvuf1mo1fWd53FjHvrbUvaHFz
|
||||
CGuZROd4dC4Rx5nZw2ogIYvJ8m6HpIDkL3pBNSQJtIsvAYEQcotJoa5D/e9fu2Wr
|
||||
+og37oCY4OXzViEBQvyxKD4cajNco1fgGKEaFROADwr3JceGI7Anq5W+xdUvAGNM
|
||||
QuGeCueqNyrJ0CbQ1zEhwgpk/VYfB0u9m0bjMellRlKMdojby+FDCJtAJesx9no4
|
||||
SQXyx+aNHhj3qReysjGNwZvBk1IHL04HAT+ogNiYhTl1J/YON4MB5UN6Y2PxP6uG
|
||||
KvJGPigx4fAwfR/d78o5ngwoH9m+8FUg8+qllJ8XgIbl/VXKTk3G4ceOm4eBmrel
|
||||
DwWuBhELSjtXWPWhMlkiebgejDbAear53Lia2Cc43zx/KuhMHBTlKY/vY4F2YiI=
|
||||
-----END CERTIFICATE-----
|
||||
keyFile: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDn/rPsZ74oypiw
|
||||
CzLlx57zplTiCi/WLSF+MmLGuTvMEQnV+OND2zFgvDIV/vFs3brkd6rLVI4NcdgS
|
||||
j4YKULCMwwOl45hQPdCTEPJvUhCmM+FuQ0czmEEJSjZtdLFz1B7QB/JemNnbfigx
|
||||
M9mlg58AlBhVJqn8q64wd/kC/W/KJTLJuBiVf12ZiPoPfO4WSxAqD3opZ8gdbmK0
|
||||
KYQAhKjEto6ZrYGisfwU1gt3l8M7sCJSpEkOkpuQgJ8D+xzJS36VXBJQMMP9nAPp
|
||||
s+x/rGFplsPMsXEFFiwvR1+FJZwzlg2sJ91bLGZQ7vn74MfsGrxpiJwllRThJyT7
|
||||
C9V0sjb5trT2lEqZlP2dRSJYt7aJ1crEcdGSl6RIKgxSV6Hk8dh/ZaTjrTwaKxVk
|
||||
Po2IeEXy5xrR7DyonOQ6Yes0KOCmJB5yHkFlIVEnLm/HZXEtm3bPHsFgTZuInyBC
|
||||
OMXpUESuVZIw8YK+Vd6AExGPPwZ4n5I/sCDxWII9owIj3LeLzdUG6JoroahhGmo8
|
||||
rgpbJpPnS+VgryQ/raUQjqDzDCuE9vKXKBlSUqK6H9A+NMc0mme7M8/GX7T7ewFG
|
||||
UB/xsdrcO4yXjqHnAe0yLf8epDjChh76bYqwwinVrmfcNcRxFVJZW2z0gGdgkOkO
|
||||
LaVVb9ggPV2SNAHbN4A+St/iRYR5awIDAQABAoICAQCTxuixQ/wbW8IbEWcgeyHD
|
||||
LkaPndGO6jyVeF73GvL+MDRFuj558NvpNLfqzvTWVf9AnQGMd5Xs9oGegRHu7Csp
|
||||
3ucp+moBYv7DT14+jtXQKOgGJpDqSqfS1RUKb/TBRXNDLGy02UScziWoAdE33zmf
|
||||
UraVNwW8z1crxKA3yVw2Na++UqhGQlVLAbfXucqnJLVtNWKpkVQlezUgcfmFovsm
|
||||
Iut+9MjI6/sZAqdXTLKuCKo0XjWzNKwnRecE0CYsCwzc80MvFYEiwQi1C0kwoouC
|
||||
iOi8MKM/jDok+5/a3nQ7X+/ho5sbApNCJpfSXAK9YOJ3ju93+RjNuvORfp4/sW3W
|
||||
OGXw6X30Ym7WS/7oYuwEILyqdyNOvKU7a+17d/W/YA60NOdA4iJI3aTfYFMD3l14
|
||||
Da+D/wkTlEN3Ye7GN21A9AsZwWWiT9G5FOxWWVv7nTPG+Ix5ewehQWt/3DxhSizR
|
||||
inMBizL5xpwx9LRWHnXX277lChYmPFAAMXINl1hnX6s0EY9pSDHN0IddibJkNKBD
|
||||
m1CN37rqxoXQz4zoAyJGfQVkakqe16ayqI9yuQwO6AUkZcD5DYQdz9QYOTnYrQc6
|
||||
6haC3D0Fmqg1s4v+6gpxZA/qTri0gVl/v/NN4Mk2/qWtK33imOedgD+5LXhZdBgJ
|
||||
Mqn53AErG/AT622jvSb5UQKCAQEA/DTGLh0Ct97PCm+c+PxRFyieaHNJLWENKyxp
|
||||
HoWGHfp2Bvt2Vphoi7GpRCM/yta4vCZgZmeWTQ0yBg6iPVPRA6Ho5hqh9OkUYVoh
|
||||
prL3JsIU20jTutYjo2aefO4qXnJfkkXxNO2FElUHDTwtWdlGJQKvlUJwTv6xO19v
|
||||
bQQkhZSpri6gIpi5Nkm2SGEtDofRJ+F6ThbQibEatL6DR00dh39MYQz+tZP5olzn
|
||||
kX5bHEBWB7gy+YxTGF8FdlCSQTBBtNSKsAv3Cxj4qEHm+fu09vnH6fOZKenT2nXD
|
||||
5QE/RpgQzLV1TumCjqLzqwp7bbzH+4mjsXpF3KHBZwnhMnDIRwKCAQEA63wYzjBy
|
||||
no0GBBz0hOWrOwQ/AjUHfi47o3Xvl4RBjZclM171HKH7oMCnQvVKTNq8jvakCZjc
|
||||
UI6i+H4R6aokiFS2xGbC2H3ZlSMFNwhb2xUs/C4Nr7JSOWZBtDy5QBspUsp26f7m
|
||||
9VNVRzCmnxWV9be/1TxHDzDhslNlL5TMejbMorWnrtNG41KWwGtwvv2gApr3894j
|
||||
eJNOh0WGfsMkXUM6+4v4WcCGrdV8Cr6Nvu96ZZe2PWu2dANtAfnxqogXXCoFE6r1
|
||||
vie7hFSfJ2QR/vEbanED4pYGTtGYP1oseScx0u0hLhGLGccVBUNZlRbox4rIOELI
|
||||
v9MLuiOL4YX7vQKCAQAGzMl3HtMe8AP3DRFXaT4qeK7ktA8KCS7YtibTatg14LXj
|
||||
9E25gfx3n7+nlae3qVhrwkEhIbPcuflaTnSzYJonFet4oMkzGEGzakG0A+lEA0Ga
|
||||
s/j5daKaWj71sVo1F7JZ+EbLnYfT+bTp93BllsUcZFkllhf/GUDgD++qKc1uSJbW
|
||||
mm044ZNE0nH2u6ACX0kVYS/yAQ14WO0WaHiTqJGeQKFnkHkhni7B4O1hb923AkkP
|
||||
hjjhn5Xx90Xnbb6zwUBURtLCcmAjzXWO29AFd3Lmoc9xEF9V0PckUb6JYyI4ngr9
|
||||
6fqSuRsLC3u0ZeD0EX322zwtodVWYIodZBfNS1srAoIBAQCjTUPGeUKDQTjS0WGg
|
||||
Z8T/AErRtQSlNFqXWMn2QPlUv2RE460HVi2xpOhZPtFvyqDIY7IOFbtzAfdya7rw
|
||||
V9VN1bGJMdodV+jzy31qVJmerGit2SIUnYz30TnvS80L78oQZ+dfDi4MIuYYoFxs
|
||||
JgQAipS1wz9kAXoCuGKLRJ0og6gVjfPjARE/w55XgiqFyEyWgfFBZOMkUsM6e7Rx
|
||||
Y9Jr+puEpeRsGV9MXafPq6WQq3It0a/HmFLG0TlfDX3RzN6mQ12R7hTM8bDQa/6S
|
||||
yorQSVPB1O3kzDVDo4X5KQd+XPfoVhmUYQYdsjmZlMMi6Og0uMFwgp/Epw6S3uO6
|
||||
WbfhAoIBAQCOp4iIc87GyxWL8u6HrJaqmFlqkfou0hI+y9h6FfzsBYU6y3+gRYdF
|
||||
wr2S9EUAb80kEQ1v0pt9417NOGc1pmYjKCZmDZ7qeGCGk2PR0U59+xJetXBWWhbq
|
||||
5JxcwdRYoHyrmC/LINxzzqYOQbQevbW0zcEskeKfJsOtj9WJt6U9B1YZbE8pu2QV
|
||||
xjvb+YekD2R+n/umV6eiaGfDau+EWudYVTqY0mR7y9hTiFR/KnqSsy2BUjljpacS
|
||||
XBQO4ig7vY8+1+L3w2xpTN95/rXAvB4BbO/DLea9ArikePoSJ+bVTj0YwrKBghep
|
||||
kOvbvVANrpsunlSAcpXm1qkV+G+xPnyJ
|
||||
-----END PRIVATE KEY-----
|
||||
12
cmd/flux/testdata/create_source_git/source-git-provider-azure.yaml
vendored
Normal file
12
cmd/flux/testdata/create_source_git/source-git-provider-azure.yaml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 1m0s
|
||||
provider: azure
|
||||
ref:
|
||||
branch: test
|
||||
url: https://dev.azure.com/foo/bar/_git/podinfo
|
||||
12
cmd/flux/testdata/create_source_git/source-git-provider-generic.yaml
vendored
Normal file
12
cmd/flux/testdata/create_source_git/source-git-provider-generic.yaml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 1m0s
|
||||
provider: generic
|
||||
ref:
|
||||
branch: test
|
||||
url: https://github.com/stefanprodan/podinfo
|
||||
14
cmd/flux/testdata/create_source_git/source-git-provider-github.yaml
vendored
Normal file
14
cmd/flux/testdata/create_source_git/source-git-provider-github.yaml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: GitRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 1m0s
|
||||
provider: github
|
||||
ref:
|
||||
branch: test
|
||||
secretRef:
|
||||
name: appinfo
|
||||
url: https://github.com/stefanprodan/podinfo
|
||||
68
cmd/flux/testdata/debug_helmrelease/objects.yaml
vendored
Normal file
68
cmd/flux/testdata/debug_helmrelease/objects.yaml
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ .fluxns }}
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: test-values-inline
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
chartRef:
|
||||
kind: OCIRepository
|
||||
name: podinfo
|
||||
interval: 5m0s
|
||||
values:
|
||||
image:
|
||||
repository: stefanprodan/podinfo
|
||||
tag: 5.0.0
|
||||
---
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: test-values-from
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
chartRef:
|
||||
kind: OCIRepository
|
||||
name: podinfo
|
||||
interval: 5m0s
|
||||
values:
|
||||
image:
|
||||
repository: stefanprodan/podinfo
|
||||
tag: 5.0.0
|
||||
valuesFrom:
|
||||
- kind: ConfigMap
|
||||
name: test
|
||||
- kind: Secret
|
||||
name: test
|
||||
valuesKey: secrets.yaml
|
||||
- kind: Secret
|
||||
name: test
|
||||
valuesKey: flatValue
|
||||
targetPath: aFlatValue
|
||||
- kind: ConfigMap
|
||||
name: none
|
||||
optional: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test
|
||||
namespace: {{ .fluxns }}
|
||||
data:
|
||||
values.yaml: |
|
||||
cm: "test"
|
||||
override: "cm"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: test
|
||||
namespace: {{ .fluxns }}
|
||||
stringData:
|
||||
secrets.yaml: |
|
||||
secret: "test"
|
||||
override: "secret"
|
||||
flatValue: some-flat-value
|
||||
2
cmd/flux/testdata/debug_helmrelease/status.golden.yaml
vendored
Normal file
2
cmd/flux/testdata/debug_helmrelease/status.golden.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Status documentation: https://fluxcd.io/flux/components/helm/helmreleases/#helmrelease-status
|
||||
observedGeneration: -1
|
||||
7
cmd/flux/testdata/debug_helmrelease/values-from.golden.yaml
vendored
Normal file
7
cmd/flux/testdata/debug_helmrelease/values-from.golden.yaml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
aFlatValue: some-flat-value
|
||||
cm: test
|
||||
image:
|
||||
repository: stefanprodan/podinfo
|
||||
tag: 5.0.0
|
||||
override: secret
|
||||
secret: test
|
||||
3
cmd/flux/testdata/debug_helmrelease/values-inline.golden.yaml
vendored
Normal file
3
cmd/flux/testdata/debug_helmrelease/values-inline.golden.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
image:
|
||||
repository: stefanprodan/podinfo
|
||||
tag: 5.0.0
|
||||
63
cmd/flux/testdata/debug_kustomization/objects.yaml
vendored
Normal file
63
cmd/flux/testdata/debug_kustomization/objects.yaml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ .fluxns }}
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: test
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: test
|
||||
interval: 1m
|
||||
path: "./"
|
||||
prune: true
|
||||
postBuild:
|
||||
substitute:
|
||||
TEST_OVERRIDE: "in-line"
|
||||
TEST_INLINE: "in-line"
|
||||
substituteFrom:
|
||||
- kind: ConfigMap
|
||||
name: test
|
||||
- kind: Secret
|
||||
name: test
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: test-from
|
||||
namespace: {{ .fluxns }}
|
||||
spec:
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: test
|
||||
interval: 1m
|
||||
path: "./"
|
||||
prune: true
|
||||
postBuild:
|
||||
substituteFrom:
|
||||
- kind: ConfigMap
|
||||
name: test
|
||||
- kind: Secret
|
||||
name: test
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test
|
||||
namespace: {{ .fluxns }}
|
||||
data:
|
||||
TEST_OVERRIDE: "cm"
|
||||
TEST_CM: "cm"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: test
|
||||
namespace: {{ .fluxns }}
|
||||
stringData:
|
||||
TEST_OVERRIDE: "secret"
|
||||
TEST_SECRET: "secret"
|
||||
2
cmd/flux/testdata/debug_kustomization/status.golden.yaml
vendored
Normal file
2
cmd/flux/testdata/debug_kustomization/status.golden.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Status documentation: https://fluxcd.io/flux/components/kustomize/kustomizations/#kustomization-status
|
||||
observedGeneration: -1
|
||||
3
cmd/flux/testdata/debug_kustomization/vars-from.golden.env
vendored
Normal file
3
cmd/flux/testdata/debug_kustomization/vars-from.golden.env
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
TEST_CM=cm
|
||||
TEST_OVERRIDE=secret
|
||||
TEST_SECRET=secret
|
||||
4
cmd/flux/testdata/debug_kustomization/vars.golden.env
vendored
Normal file
4
cmd/flux/testdata/debug_kustomization/vars.golden.env
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
TEST_CM=cm
|
||||
TEST_INLINE=in-line
|
||||
TEST_OVERRIDE=in-line
|
||||
TEST_SECRET=secret
|
||||
2
cmd/flux/testdata/diff-kustomization/diff-with-recursive.golden
vendored
Normal file
2
cmd/flux/testdata/diff-kustomization/diff-with-recursive.golden
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
📁 Kustomization/default/my-app changed
|
||||
► ConfigMap/default/my-app created
|
||||
18
cmd/flux/testdata/diff-kustomization/my-app.yaml
vendored
Normal file
18
cmd/flux/testdata/diff-kustomization/my-app.yaml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: podinfo
|
||||
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
|
||||
name: my-app
|
||||
namespace: default
|
||||
spec:
|
||||
interval: 5m0s
|
||||
path: ./my-app
|
||||
force: true
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: podinfo
|
||||
targetNamespace: default
|
||||
2
cmd/flux/testdata/export/bucket.yaml
vendored
2
cmd/flux/testdata/export/bucket.yaml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: flux-system
|
||||
|
||||
2
cmd/flux/testdata/export/objects.yaml
vendored
2
cmd/flux/testdata/export/objects.yaml
vendored
@@ -153,7 +153,7 @@ spec:
|
||||
name: flux-systen
|
||||
namespace: {{ .fluxns }}
|
||||
---
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: flux-system
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
✚ generating ImagePolicy
|
||||
► applying ImagePolicy
|
||||
✔ ImageRepository created
|
||||
✔ ImagePolicy created
|
||||
◎ waiting for ImagePolicy reconciliation
|
||||
✔ ImagePolicy reconciliation completed
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
► resuming kustomization tkfg in {{ .ns }} namespace
|
||||
✔ kustomization resumed
|
||||
✗ no Kustomization objects found in {{ .ns }} namespace
|
||||
✗ Kustomization object 'tkfg' not found in {{ .ns }} namespace
|
||||
◎ waiting for Kustomization reconciliation
|
||||
✔ Kustomization tkfg reconciliation completed
|
||||
✔ applied revision 6.3.5@sha1:67e2c98a60dc92283531412a9e604dd4bae005a9
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
//go:build unit
|
||||
// +build unit
|
||||
|
||||
/*
|
||||
Copyright 2024 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 (
|
||||
|
||||
@@ -43,6 +43,9 @@ The following template can be used for the GitHub release page:
|
||||
<!-- auto-generated list of pull requests to the CLI starts here -->
|
||||
```
|
||||
|
||||
Typically, you want to link the [Flux upgrade](https://fluxcd.io/flux/installation/upgrade/)
|
||||
guide to refer users for up to date information on upgrade options.
|
||||
|
||||
In some scenarios, you may want to include specific information about API
|
||||
changes and/or upgrade procedures. Consult [the formatting of
|
||||
`v2.0.0-rc.1`](https://github.com/fluxcd/flux2/releases/tag/v2.0.0-rc.1) for
|
||||
@@ -69,4 +72,4 @@ The following template can be used for the Slack release message:
|
||||
```
|
||||
|
||||
For more concrete examples, see the pinned messages in the [Flux Slack
|
||||
channel](https://cloud-native.slack.com/archives/CLAJ40HV3).
|
||||
channel](https://cloud-native.slack.com/archives/CLAJ40HV3).
|
||||
|
||||
317
go.mod
317
go.mod
@@ -1,253 +1,264 @@
|
||||
module github.com/fluxcd/flux2/v2
|
||||
|
||||
go 1.22.0
|
||||
go 1.23.0
|
||||
|
||||
// Fix CVE-2022-28948.
|
||||
replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver/v3 v3.2.1
|
||||
github.com/ProtonMail/go-crypto v1.0.0
|
||||
github.com/cyphar/filepath-securejoin v0.2.5
|
||||
github.com/distribution/distribution/v3 v3.0.0-alpha.1
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.7
|
||||
github.com/fluxcd/go-git-providers v0.20.1
|
||||
github.com/fluxcd/helm-controller/api v1.0.1
|
||||
github.com/fluxcd/image-automation-controller/api v0.38.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.32.0
|
||||
github.com/fluxcd/kustomize-controller/api v1.3.0
|
||||
github.com/fluxcd/notification-controller/api v1.3.0
|
||||
github.com/fluxcd/pkg/apis/event v0.9.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.5.0
|
||||
github.com/fluxcd/pkg/envsubst v1.1.0
|
||||
github.com/fluxcd/pkg/git v0.19.0
|
||||
github.com/fluxcd/pkg/git/gogit v0.19.0
|
||||
github.com/fluxcd/pkg/kustomize v1.11.0
|
||||
github.com/fluxcd/pkg/oci v0.37.1
|
||||
github.com/fluxcd/pkg/runtime v0.47.1
|
||||
github.com/fluxcd/pkg/sourceignore v0.7.0
|
||||
github.com/fluxcd/pkg/ssa v0.39.1
|
||||
github.com/fluxcd/pkg/ssh v0.13.0
|
||||
github.com/fluxcd/pkg/tar v0.7.0
|
||||
github.com/fluxcd/pkg/version v0.4.0
|
||||
github.com/fluxcd/source-controller/api v1.3.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/go-logr/logr v1.4.1
|
||||
github.com/gonvenience/bunt v1.3.5
|
||||
github.com/gonvenience/ytbx v1.4.4
|
||||
github.com/Masterminds/semver/v3 v3.3.1
|
||||
github.com/ProtonMail/go-crypto v1.1.5
|
||||
github.com/cyphar/filepath-securejoin v0.4.1
|
||||
github.com/distribution/distribution/v3 v3.0.0-rc.3
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.12
|
||||
github.com/fluxcd/go-git-providers v0.22.0
|
||||
github.com/fluxcd/helm-controller/api v1.2.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.40.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.34.0
|
||||
github.com/fluxcd/kustomize-controller/api v1.5.1
|
||||
github.com/fluxcd/notification-controller/api v1.5.0
|
||||
github.com/fluxcd/pkg/apis/event v0.16.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.10.0
|
||||
github.com/fluxcd/pkg/auth v0.3.0
|
||||
github.com/fluxcd/pkg/chartutil v1.2.0
|
||||
github.com/fluxcd/pkg/envsubst v1.3.0
|
||||
github.com/fluxcd/pkg/git v0.24.0
|
||||
github.com/fluxcd/pkg/git/gogit v0.24.0
|
||||
github.com/fluxcd/pkg/kustomize v1.16.0
|
||||
github.com/fluxcd/pkg/oci v0.45.0
|
||||
github.com/fluxcd/pkg/runtime v0.53.1
|
||||
github.com/fluxcd/pkg/sourceignore v0.11.0
|
||||
github.com/fluxcd/pkg/ssa v0.45.0
|
||||
github.com/fluxcd/pkg/ssh v0.17.0
|
||||
github.com/fluxcd/pkg/tar v0.11.0
|
||||
github.com/fluxcd/pkg/version v0.6.0
|
||||
github.com/fluxcd/source-controller/api v1.5.0
|
||||
github.com/go-git/go-git/v5 v5.13.2
|
||||
github.com/go-logr/logr v1.4.2
|
||||
github.com/gonvenience/bunt v1.4.0
|
||||
github.com/gonvenience/ytbx v1.4.6
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/go-containerregistry v0.19.1
|
||||
github.com/google/go-containerregistry v0.20.3
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2
|
||||
github.com/homeport/dyff v1.7.1
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||
github.com/manifoldco/promptui v0.9.0
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
github.com/notaryproject/notation-go v1.1.0
|
||||
github.com/notaryproject/notation-go v1.3.0
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/onsi/gomega v1.33.1
|
||||
github.com/onsi/gomega v1.36.2
|
||||
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/theckman/yacspin v0.13.12
|
||||
golang.org/x/crypto v0.22.0
|
||||
golang.org/x/term v0.19.0
|
||||
golang.org/x/text v0.14.0
|
||||
k8s.io/api v0.30.0
|
||||
k8s.io/apiextensions-apiserver v0.30.0
|
||||
k8s.io/apimachinery v0.30.0
|
||||
k8s.io/cli-runtime v0.30.0
|
||||
k8s.io/client-go v0.30.0
|
||||
k8s.io/kubectl v0.30.0
|
||||
sigs.k8s.io/controller-runtime v0.18.1
|
||||
sigs.k8s.io/kustomize/api v0.17.1
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.0
|
||||
golang.org/x/crypto v0.33.0
|
||||
golang.org/x/term v0.29.0
|
||||
golang.org/x/text v0.22.0
|
||||
k8s.io/api v0.32.2
|
||||
k8s.io/apiextensions-apiserver v0.32.2
|
||||
k8s.io/apimachinery v0.32.2
|
||||
k8s.io/cli-runtime v0.32.1
|
||||
k8s.io/client-go v0.32.2
|
||||
k8s.io/kubectl v0.32.1
|
||||
sigs.k8s.io/controller-runtime v0.20.2
|
||||
sigs.k8s.io/kustomize/api v0.19.0
|
||||
sigs.k8s.io/kustomize/kyaml v0.19.0
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
code.gitea.io/sdk/gitea v0.17.1 // indirect
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
|
||||
code.gitea.io/sdk/gitea v0.19.0 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 // indirect
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.27.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 // indirect
|
||||
github.com/aws/smithy-go v1.20.2 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.35.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.56 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.26 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.30 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.30 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.40.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.11 // indirect
|
||||
github.com/aws/smithy-go v1.22.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.13.0 // indirect
|
||||
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/cloudflare/circl v1.5.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // 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.5.0 // indirect
|
||||
github.com/docker/cli v24.0.9+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||
github.com/docker/docker v24.0.9+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/cli v27.5.0+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.2 // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.0 // 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.13.0 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.3.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.5.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.6.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.9.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.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
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/go-ldap/ldap/v3 v3.4.6 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.6.2 // indirect
|
||||
github.com/go-ldap/ldap/v3 v3.4.10 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/gonvenience/neat v1.3.13 // indirect
|
||||
github.com/gonvenience/term v1.0.2 // indirect
|
||||
github.com/gonvenience/text v1.0.7 // indirect
|
||||
github.com/gonvenience/wrap v1.2.0 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-github/v61 v61.0.0 // indirect
|
||||
github.com/gonvenience/neat v1.3.15 // indirect
|
||||
github.com/gonvenience/term v1.0.3 // indirect
|
||||
github.com/gonvenience/text v1.0.8 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/gnostic-models v0.6.9 // indirect
|
||||
github.com/google/go-github/v66 v66.0.0 // indirect
|
||||
github.com/google/go-github/v68 v68.0.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/handlers v1.5.2 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // 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/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // 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.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // 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.13 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // 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
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/spdystream v0.5.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/notaryproject/notation-core-go v1.0.2 // indirect
|
||||
github.com/notaryproject/notation-core-go v1.2.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.2 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.19.0 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.53.0 // indirect
|
||||
github.com/prometheus/procfs v0.14.0 // indirect
|
||||
github.com/prometheus/common v0.62.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect
|
||||
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect
|
||||
github.com/redis/go-redis/v9 v9.1.0 // indirect
|
||||
github.com/redis/go-redis/v9 v9.7.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/texttheater/golang-levenshtein v1.0.1 // indirect
|
||||
github.com/vbatts/tar-split v0.11.3 // indirect
|
||||
github.com/vbatts/tar-split v0.11.6 // indirect
|
||||
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 // indirect
|
||||
github.com/xanzy/go-gitlab v0.101.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xanzy/go-gitlab v0.114.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.opentelemetry.io/contrib/exporters/autoexport v0.46.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
|
||||
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.44.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.44.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
go.starlark.net v0.0.0-20231121155337-90ade8b19d09 // indirect
|
||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/oauth2 v0.19.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.20.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 // indirect
|
||||
go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
|
||||
go.opentelemetry.io/otel v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.54.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/log v0.8.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/log v0.8.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/oauth2 v0.25.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
google.golang.org/grpc v1.59.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
|
||||
google.golang.org/grpc v1.68.1 // indirect
|
||||
google.golang.org/protobuf v1.36.4 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/component-base v0.30.0 // indirect
|
||||
k8s.io/klog/v2 v2.120.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240411171206-dc4e619f62f3 // indirect
|
||||
k8s.io/utils v0.0.0-20240310230437-4693a0247e57 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
helm.sh/helm/v3 v3.17.0 // indirect
|
||||
k8s.io/component-base v0.32.2 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
|
||||
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
|
||||
)
|
||||
|
||||
@@ -25,11 +25,13 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/theckman/yacspin"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -51,13 +53,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
controllerName = "kustomize-controller"
|
||||
controllerGroup = "kustomize.toolkit.fluxcd.io"
|
||||
mask = "**SOPS**"
|
||||
dockercfgSecretType = "kubernetes.io/dockerconfigjson"
|
||||
typeField = "type"
|
||||
dataField = "data"
|
||||
stringDataField = "stringData"
|
||||
controllerName = "kustomize-controller"
|
||||
controllerGroup = "kustomize.toolkit.fluxcd.io"
|
||||
mask = "**SOPS**"
|
||||
dockercfgSecretType = "kubernetes.io/dockerconfigjson"
|
||||
typeField = "type"
|
||||
dataField = "data"
|
||||
stringDataField = "stringData"
|
||||
spinnerDryRunMessage = "running dry-run"
|
||||
)
|
||||
|
||||
var defaultTimeout = 80 * time.Second
|
||||
@@ -81,6 +84,10 @@ type Builder struct {
|
||||
spinner *yacspin.Spinner
|
||||
dryRun bool
|
||||
strictSubst bool
|
||||
recursive bool
|
||||
localSources map[string]string
|
||||
// diff needs to handle kustomizations one by one
|
||||
singleKustomization bool
|
||||
}
|
||||
|
||||
// BuilderOptionFunc is a function that configures a Builder
|
||||
@@ -110,7 +117,7 @@ func WithProgressBar() BuilderOptionFunc {
|
||||
CharSet: yacspin.CharSets[59],
|
||||
Suffix: "Kustomization diffing...",
|
||||
SuffixAutoColon: true,
|
||||
Message: "running dry-run",
|
||||
Message: spinnerDryRunMessage,
|
||||
StopCharacter: "✓",
|
||||
StopColors: []string{"fgGreen"},
|
||||
}
|
||||
@@ -175,6 +182,55 @@ func WithIgnore(ignore []string) BuilderOptionFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// WithRecursive sets the recursive field
|
||||
func WithRecursive(recursive bool) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.recursive = recursive
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithLocalSources sets the local sources field
|
||||
func WithLocalSources(localSources map[string]string) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.localSources = localSources
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSingleKustomization sets the single kustomization field to true
|
||||
func WithSingleKustomization() BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.singleKustomization = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// withClientConfigFrom copies client and restMapper fields
|
||||
func withClientConfigFrom(in *Builder) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.client = in.client
|
||||
b.restMapper = in.restMapper
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// withClientConfigFrom copies spinner field
|
||||
func withSpinnerFrom(in *Builder) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.spinner = in.spinner
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// withKustomization sets the kustomization field
|
||||
func withKustomization(k *kustomizev1.Kustomization) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.kustomization = k
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// NewBuilder returns a new Builder
|
||||
// It takes a kustomization name and a path to the resources
|
||||
// It also takes a list of BuilderOptionFunc to configure the builder
|
||||
@@ -269,6 +325,27 @@ func (b *Builder) Build() ([]*unstructured.Unstructured, error) {
|
||||
ssautil.SetCommonMetadata(objects, m.Labels, m.Annotations)
|
||||
}
|
||||
|
||||
if b.recursive && !b.singleKustomization {
|
||||
var objectsToAdd []*unstructured.Unstructured
|
||||
for _, obj := range objects {
|
||||
if isKustomization(obj) {
|
||||
k, err := toKustomization(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !kustomizationsEqual(k, b.kustomization) {
|
||||
subObjects, err := b.kustomizationBuild(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectsToAdd = append(objectsToAdd, subObjects...)
|
||||
}
|
||||
}
|
||||
}
|
||||
objects = append(objects, objectsToAdd...)
|
||||
}
|
||||
|
||||
return objects, nil
|
||||
}
|
||||
|
||||
@@ -281,7 +358,11 @@ func (b *Builder) build() (m resmap.ResMap, err error) {
|
||||
if !b.dryRun {
|
||||
liveKus, err = b.getKustomization(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get kustomization object: %w", err)
|
||||
if !apierrors.IsNotFound(err) || b.kustomization == nil {
|
||||
return nil, fmt.Errorf("failed to get kustomization object: %w", err)
|
||||
}
|
||||
// use provided Kustomization
|
||||
liveKus = b.kustomization
|
||||
}
|
||||
}
|
||||
k, err := b.resolveKustomization(liveKus)
|
||||
@@ -334,6 +415,46 @@ func (b *Builder) build() (m resmap.ResMap, err error) {
|
||||
|
||||
}
|
||||
|
||||
func (b *Builder) kustomizationBuild(k *kustomizev1.Kustomization) ([]*unstructured.Unstructured, error) {
|
||||
resourcesPath, err := b.kustomizationPath(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subBuilder, err := NewBuilder(k.Name, resourcesPath,
|
||||
// use same client
|
||||
withClientConfigFrom(b),
|
||||
// kustomization will be used if there is no live kustomization
|
||||
withKustomization(k),
|
||||
WithTimeout(b.timeout),
|
||||
WithNamespace(k.Namespace),
|
||||
WithIgnore(b.ignore),
|
||||
WithStrictSubstitute(b.strictSubst),
|
||||
WithRecursive(b.recursive),
|
||||
WithLocalSources(b.localSources),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return subBuilder.Build()
|
||||
}
|
||||
|
||||
func (b *Builder) kustomizationPath(k *kustomizev1.Kustomization) (string, error) {
|
||||
sourceRef := k.Spec.SourceRef.DeepCopy()
|
||||
if sourceRef.Namespace == "" {
|
||||
sourceRef.Namespace = k.Namespace
|
||||
}
|
||||
|
||||
sourceKey := sourceRef.String()
|
||||
localPath, ok := b.localSources[sourceKey]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("cannot get local path for %s of kustomization %s", sourceKey, k.Name)
|
||||
}
|
||||
|
||||
return filepath.Join(localPath, k.Spec.Path), nil
|
||||
}
|
||||
|
||||
func (b *Builder) unMarshallKustomization() (*kustomizev1.Kustomization, error) {
|
||||
data, err := os.ReadFile(b.kustomizationFile)
|
||||
if err != nil {
|
||||
@@ -423,6 +544,28 @@ func (b *Builder) do(ctx context.Context, kustomization kustomizev1.Kustomizatio
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func isKustomization(object *unstructured.Unstructured) bool {
|
||||
return strings.HasPrefix(object.GetAPIVersion(), kustomizev1.GroupVersion.Group+"/") &&
|
||||
object.GetKind() == kustomizev1.KustomizationKind
|
||||
}
|
||||
|
||||
func toKustomization(object *unstructured.Unstructured) (*kustomizev1.Kustomization, error) {
|
||||
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(object)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert to unstructured: %w", err)
|
||||
}
|
||||
k := &kustomizev1.Kustomization{}
|
||||
err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj, k)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert to kustomization: %w", err)
|
||||
}
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func kustomizationsEqual(k1 *kustomizev1.Kustomization, k2 *kustomizev1.Kustomization) bool {
|
||||
return k1.Name == k2.Name && k1.Namespace == k2.Namespace
|
||||
}
|
||||
|
||||
func (b *Builder) setOwnerLabels(res *resource.Resource) error {
|
||||
labels := res.GetLabels()
|
||||
|
||||
@@ -590,3 +733,32 @@ func (b *Builder) Cancel() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Builder) StartSpinner() error {
|
||||
if b.spinner == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := b.spinner.Start()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to start spinner: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Builder) StopSpinner() error {
|
||||
if b.spinner == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
status := b.spinner.Status()
|
||||
if status == yacspin.SpinnerRunning || status == yacspin.SpinnerPaused {
|
||||
err := b.spinner.Stop()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to stop spinner: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
@@ -361,3 +362,242 @@ func Test_ResolveKustomization(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_isKustomization(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
expected bool
|
||||
object *unstructured.Unstructured
|
||||
}{
|
||||
{
|
||||
name: "flux kustomization",
|
||||
object: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "kustomize.toolkit.fluxcd.io/v1",
|
||||
"kind": "Kustomization",
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "other kustomization",
|
||||
object: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "kustomize.config.k8s.io/v1beta1",
|
||||
"kind": "Kustomization",
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "wrong kind",
|
||||
object: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "kustomize.toolkit.fluxcd.io/v1",
|
||||
"kind": "ConfigMap",
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "wrong object",
|
||||
object: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := isKustomization(tt.object)
|
||||
if actual != tt.expected {
|
||||
t.Fatalf("got '%v', want '%v'", actual, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_kustomizationsEqual(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
kustomization1 *kustomizev1.Kustomization
|
||||
kustomization2 *kustomizev1.Kustomization
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "equal",
|
||||
kustomization1: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
},
|
||||
kustomization2: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "wrong name",
|
||||
kustomization1: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
},
|
||||
kustomization2: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-app",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "wrong namespace",
|
||||
kustomization1: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
},
|
||||
kustomization2: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: "my-ns",
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "wrong name and namespace",
|
||||
kustomization1: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
},
|
||||
kustomization2: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-app",
|
||||
Namespace: "my-ns",
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := kustomizationsEqual(tt.kustomization1, tt.kustomization2)
|
||||
if actual != tt.expected {
|
||||
t.Fatalf("got '%v', want '%v'", actual, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_kustomizationPath(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
kustomization *kustomizev1.Kustomization
|
||||
expected string
|
||||
wantErr bool
|
||||
errString string
|
||||
}{
|
||||
{
|
||||
name: "full repo",
|
||||
kustomization: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-app",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
Spec: kustomizev1.KustomizationSpec{
|
||||
Path: "my-path",
|
||||
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
||||
Kind: "GitRepository",
|
||||
Name: "my-repo",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "path/to/local/git/my-path",
|
||||
},
|
||||
{
|
||||
name: "repo without namespace",
|
||||
kustomization: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-app",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
Spec: kustomizev1.KustomizationSpec{
|
||||
Path: "my-path",
|
||||
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
||||
Kind: "GitRepository",
|
||||
Name: "my-repo",
|
||||
Namespace: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "path/to/local/git/my-path",
|
||||
},
|
||||
{
|
||||
name: "repo not found",
|
||||
kustomization: &kustomizev1.Kustomization{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-app",
|
||||
Namespace: "flux-system",
|
||||
},
|
||||
Spec: kustomizev1.KustomizationSpec{
|
||||
Path: "my-path",
|
||||
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
||||
Kind: "GitRepository",
|
||||
Name: "my-repo",
|
||||
Namespace: "my-ns",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
errString: "cannot get local path",
|
||||
},
|
||||
}
|
||||
|
||||
b := &Builder{
|
||||
name: "podinfo",
|
||||
namespace: "flux-system",
|
||||
localSources: map[string]string{
|
||||
"GitRepository/flux-system/my-repo": "./path/to/local/git",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual, err := b.kustomizationPath(tt.kustomization)
|
||||
if !tt.wantErr {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err '%s'", err)
|
||||
}
|
||||
|
||||
if actual != tt.expected {
|
||||
t.Errorf("got '%v', want '%v'", actual, tt.expected)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Fatal("expected error but got nil")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), tt.errString) {
|
||||
t.Errorf("expected error '%s' to contain string '%s'", err.Error(), tt.errString)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,22 @@ func (b *Builder) Manager() (*ssa.ResourceManager, error) {
|
||||
}
|
||||
|
||||
func (b *Builder) Diff() (string, bool, error) {
|
||||
err := b.StartSpinner()
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
output, createdOrDrifted, diffErr := b.diff()
|
||||
|
||||
err = b.StopSpinner()
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
return output, createdOrDrifted, diffErr
|
||||
}
|
||||
|
||||
func (b *Builder) diff() (string, bool, error) {
|
||||
output := strings.Builder{}
|
||||
createdOrDrifted := false
|
||||
objects, err := b.Build()
|
||||
@@ -77,13 +93,6 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
|
||||
defer cancel()
|
||||
|
||||
if b.spinner != nil {
|
||||
err = b.spinner.Start()
|
||||
if err != nil {
|
||||
return "", false, fmt.Errorf("failed to start spinner: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var diffErrs []error
|
||||
// create an inventory of objects to be reconciled
|
||||
newInventory := newInventory()
|
||||
@@ -91,6 +100,10 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
diffOptions := ssa.DiffOptions{
|
||||
Exclusions: map[string]string{
|
||||
"kustomize.toolkit.fluxcd.io/reconcile": "disabled",
|
||||
"kustomize.toolkit.fluxcd.io/ssa": "ignore",
|
||||
},
|
||||
IfNotPresentSelector: map[string]string{
|
||||
"kustomize.toolkit.fluxcd.io/ssa": "ifnotpresent",
|
||||
},
|
||||
}
|
||||
change, liveObject, mergedObject, err := resourceManager.Diff(ctx, obj, diffOptions)
|
||||
@@ -129,6 +142,34 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
}
|
||||
|
||||
addObjectsToInventory(newInventory, change)
|
||||
|
||||
if b.recursive && isKustomization(obj) && change.Action != ssa.CreatedAction {
|
||||
k, err := toKustomization(obj)
|
||||
if err != nil {
|
||||
return "", createdOrDrifted, err
|
||||
}
|
||||
|
||||
if !kustomizationsEqual(k, b.kustomization) {
|
||||
if k.Spec.KubeConfig != nil {
|
||||
output.WriteString(writeString(fmt.Sprintf("⚠️ %s skipped: diff not supported for remote clusters\n", ssautil.FmtUnstructured(obj)), bunt.Orange))
|
||||
} else {
|
||||
subOutput, subCreatedOrDrifted, err := b.kustomizationDiff(k)
|
||||
if err != nil {
|
||||
diffErrs = append(diffErrs, err)
|
||||
}
|
||||
if subCreatedOrDrifted {
|
||||
createdOrDrifted = true
|
||||
output.WriteString(bunt.Sprint(fmt.Sprintf("📁 %s changed\n", ssautil.FmtUnstructured(obj))))
|
||||
output.WriteString(subOutput)
|
||||
}
|
||||
}
|
||||
|
||||
// finished with Kustomization diff
|
||||
if b.spinner != nil {
|
||||
b.spinner.Message(spinnerDryRunMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if b.spinner != nil {
|
||||
@@ -151,14 +192,43 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return output.String(), createdOrDrifted, errors.Reduce(errors.Flatten(errors.NewAggregate(diffErrs)))
|
||||
}
|
||||
|
||||
func (b *Builder) kustomizationDiff(kustomization *kustomizev1.Kustomization) (string, bool, error) {
|
||||
if b.spinner != nil {
|
||||
err = b.spinner.Stop()
|
||||
if err != nil {
|
||||
return "", createdOrDrifted, fmt.Errorf("failed to stop spinner: %w", err)
|
||||
}
|
||||
b.spinner.Message(fmt.Sprintf("%s in %s", spinnerDryRunMessage, kustomization.Name))
|
||||
}
|
||||
|
||||
return output.String(), createdOrDrifted, errors.Reduce(errors.Flatten(errors.NewAggregate(diffErrs)))
|
||||
sourceRef := kustomization.Spec.SourceRef.DeepCopy()
|
||||
if sourceRef.Namespace == "" {
|
||||
sourceRef.Namespace = kustomization.Namespace
|
||||
}
|
||||
|
||||
sourceKey := sourceRef.String()
|
||||
localPath, ok := b.localSources[sourceKey]
|
||||
if !ok {
|
||||
return "", false, fmt.Errorf("cannot get local path for %s of kustomization %s", sourceKey, kustomization.Name)
|
||||
}
|
||||
|
||||
resourcesPath := filepath.Join(localPath, kustomization.Spec.Path)
|
||||
subBuilder, err := NewBuilder(kustomization.Name, resourcesPath,
|
||||
// use same client and spinner
|
||||
withClientConfigFrom(b),
|
||||
withSpinnerFrom(b),
|
||||
WithTimeout(b.timeout),
|
||||
WithNamespace(kustomization.Namespace),
|
||||
WithIgnore(b.ignore),
|
||||
WithStrictSubstitute(b.strictSubst),
|
||||
WithRecursive(b.recursive),
|
||||
WithLocalSources(b.localSources),
|
||||
WithSingleKustomization(),
|
||||
)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
return subBuilder.diff()
|
||||
}
|
||||
|
||||
func writeYamls(liveObject, mergedObject *unstructured.Unstructured) (string, string, string, error) {
|
||||
|
||||
66
internal/flags/gitlab_visibility.go
Normal file
66
internal/flags/gitlab_visibility.go
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2024 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 flags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fluxcd/go-git-providers/gitprovider"
|
||||
"github.com/fluxcd/go-git-providers/validation"
|
||||
)
|
||||
|
||||
var supportedGitLabVisibilities = map[gitprovider.RepositoryVisibility]struct{}{
|
||||
gitprovider.RepositoryVisibilityPublic: {},
|
||||
gitprovider.RepositoryVisibilityInternal: {},
|
||||
gitprovider.RepositoryVisibilityPrivate: {},
|
||||
}
|
||||
|
||||
// ValidateRepositoryVisibility validates a given RepositoryVisibility.
|
||||
func ValidateRepositoryVisibility(r gitprovider.RepositoryVisibility) error {
|
||||
_, ok := supportedGitLabVisibilities[r]
|
||||
if !ok {
|
||||
return validation.ErrFieldEnumInvalid
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GitLabVisibility gitprovider.RepositoryVisibility
|
||||
|
||||
func (d *GitLabVisibility) String() string {
|
||||
return string(*d)
|
||||
}
|
||||
|
||||
func (d *GitLabVisibility) Set(str string) error {
|
||||
if strings.TrimSpace(str) == "" {
|
||||
str = string(gitprovider.RepositoryVisibilityPrivate)
|
||||
}
|
||||
var visibility = gitprovider.RepositoryVisibility(str)
|
||||
if ValidateRepositoryVisibility(visibility) != nil {
|
||||
return fmt.Errorf("unsupported visibility '%s'", str)
|
||||
}
|
||||
*d = GitLabVisibility(visibility)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *GitLabVisibility) Type() string {
|
||||
return "gitLabVisibility"
|
||||
}
|
||||
|
||||
func (d *GitLabVisibility) Description() string {
|
||||
return fmt.Sprintf("specifies the visibility of the repository. Valid values are public, private, internal")
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user