Compare commits
349 Commits
Author | SHA1 | Date |
---|---|---|
|
c77a9799fb | |
|
fd132e2846 | |
|
124fd9fe8f | |
|
3999c651b1 | |
|
b8e667d558 | |
|
d8366598f0 | |
|
a4fbfa885b | |
|
009d764d7f | |
|
42af3383fc | |
|
17e585c90d | |
|
45e34fd5b3 | |
|
48e677ab26 | |
|
b4ad41bef5 | |
|
b09cceb8b9 | |
|
4f207d5108 | |
|
e5ae4097be | |
|
48b16c2e51 | |
|
806d41081a | |
|
4addc4e215 | |
|
82f08530f8 | |
|
f7387ccbef | |
|
3d434f0fe7 | |
|
6c5ffee6c0 | |
|
07058a1f60 | |
|
498ec11b09 | |
|
91c2f594b6 | |
|
d86ccc497f | |
|
493ce833b0 | |
|
d48392519c | |
|
081f333a3a | |
|
369d9eb107 | |
|
68b9bc7d0d | |
|
8aa8679f5b | |
|
41a0e4d324 | |
|
e9ed331572 | |
|
640aa7a79b | |
|
80cb694b10 | |
|
b1fc97f6c6 | |
|
a77cd6263f | |
|
93534085af | |
|
ba238df57b | |
|
3d295cc9c1 | |
|
68d9744428 | |
|
6ec657048d | |
|
59b50fae29 | |
|
6ca182eade | |
|
3efde8d870 | |
|
148bd07a1f | |
|
9feaa2cdf6 | |
|
19ebeeb56f | |
|
ef9608d41d | |
|
a67596e3cf | |
|
d5746c5a0a | |
|
2d6cf83f55 | |
|
227559c60a | |
|
8414fa2aa0 | |
|
bb3e96f68c | |
|
9a8e210df8 | |
|
3ae89361df | |
|
e4b925aa9c | |
|
1066a57871 | |
|
6dafa5ce9a | |
|
904289de75 | |
|
c8284d90f0 | |
|
4654113ca4 | |
|
e721c2016a | |
|
674490569e | |
|
bd119da4c8 | |
|
aa24c35eb4 | |
|
5e98055e29 | |
|
f6eed853e3 | |
|
03b9190c45 | |
|
8d5084bbea | |
|
02b165fcda | |
|
79136ad34a | |
|
d5c29a3133 | |
|
f03a53d73e | |
|
4bdd80f0d5 | |
|
9f17c8b21d | |
|
4c9cc99c76 | |
|
9e6023dbf5 | |
|
c243beeb50 | |
|
75e708baff | |
|
28f2164eea | |
|
6b7d26bdf1 | |
|
735f515d03 | |
|
9c7037771c | |
|
a7b5389aaa | |
|
d3550173d6 | |
|
fabeff2876 | |
|
d2763e6d74 | |
|
65f2a43c9b | |
|
d02dec2e6c | |
|
6cd33ab88c | |
|
6d59fcebc8 | |
|
6655e25469 | |
|
e3cd0be322 | |
|
9a32e0c10a | |
|
90821a7925 | |
|
3c846ebaa8 | |
|
67e9cf40d9 | |
|
b1d5d38b37 | |
|
d9ba54b8e0 | |
|
aaeaf52925 | |
|
891d82618e | |
|
7c9408fcda | |
|
0b463c27c8 | |
|
12dfef1342 | |
|
db0998a44c | |
|
8fa6c76df5 | |
|
b205745e5c | |
|
ddd4d61874 | |
|
b25e69b1a9 | |
|
870da77897 | |
|
c2d6a59235 | |
|
d9db01d360 | |
|
b88af04335 | |
|
5b945f7424 | |
|
e1a9080d46 | |
|
54b9f5106c | |
|
8160146a76 | |
|
7294a62885 | |
|
6c91870e91 | |
|
1e0220c016 | |
|
c5ace72c36 | |
|
ea43c5ecb6 | |
|
fcc5b78845 | |
|
ce2617afa0 | |
|
5729d1c094 | |
|
45c61bfe1b | |
|
36b5271988 | |
|
23687d65a9 | |
|
7500b46874 | |
|
1259a519c7 | |
|
5d74f31d3e | |
|
644ef7c9f7 | |
|
ae49037eab | |
|
ebeead0e14 | |
|
189ba5894b | |
|
711504944c | |
|
8599ef13b7 | |
|
131bcd76bc | |
|
ee6f36262f | |
|
e8f1f12349 | |
|
632a84bf48 | |
|
d534149ddc | |
|
3ff8476fbb | |
|
443ef35e64 | |
|
de958604e8 | |
|
87ab708624 | |
|
1d01d43a2a | |
|
1f6b3577fc | |
|
2ccad39527 | |
|
4da0650005 | |
|
34557726e9 | |
|
438705a1b8 | |
|
474e4c39d4 | |
|
d2b33d1165 | |
|
a7cebe3622 | |
|
1a7d0fe5f0 | |
|
e16d086808 | |
|
a9af390d2d | |
|
5755a87be2 | |
|
87bff0e6fd | |
|
b24fb414c3 | |
|
7203b194c5 | |
|
646646bd6e | |
|
d56ac02a95 | |
|
e189b0c271 | |
|
a716f8b292 | |
|
e5343d4f7f | |
|
b93308f488 | |
|
14e5969687 | |
|
649188c828 | |
|
c1c5cc14a8 | |
|
168d33c430 | |
|
1aa234649c | |
|
26cdb3659c | |
|
9a59f96178 | |
|
66256a4f84 | |
|
e11935b48f | |
|
e34881d370 | |
|
0f17d9d9f0 | |
|
2940e1bb8f | |
|
176bf9528a | |
|
db92b7b92b | |
|
f5af4aafe1 | |
|
2902dfa072 | |
|
d5e9ad4e79 | |
|
1aa87f8d79 | |
|
e207b2f81c | |
|
2387dd94a5 | |
|
dc1a6154b8 | |
|
c6a6747474 | |
|
3361a1378c | |
|
beba7d90d2 | |
|
3419b2416b | |
|
af1b13de06 | |
|
edb686882a | |
|
9a9ed7b5f9 | |
|
56bfc37cab | |
|
47c19b4f88 | |
|
0ad8d3904b | |
|
7c22c990ad | |
|
4aba4c1d79 | |
|
50ab2644f2 | |
|
c79407da83 | |
|
d8e7395c9a | |
|
27dc1dca10 | |
|
e6a1f2388d | |
|
b8d2ffb8bf | |
|
6d051b2abc | |
|
fe5bb8d350 | |
|
0fb81f08d9 | |
|
425e3daf37 | |
|
ab64fb477d | |
|
121edb604e | |
|
90b9e0abd1 | |
|
164b992277 | |
|
8e6783fd96 | |
|
0863e022a5 | |
|
b22453a781 | |
|
f78b82579f | |
|
008c5c0634 | |
|
ede9104c40 | |
|
30f4c3dbf3 | |
|
242604b5e3 | |
|
fe8e3a2f18 | |
|
8694e4949d | |
|
25730b122d | |
|
52030916a3 | |
|
7a581f31d9 | |
|
cc5c84431d | |
|
fd99f8c989 | |
|
142eb5ca22 | |
|
2826dde7ea | |
|
4875677707 | |
|
cf8e9917c9 | |
|
88206032dc | |
|
f453888f1f | |
|
3e83225a98 | |
|
32e891a564 | |
|
102e2b3a19 | |
|
317d322803 | |
|
9d4afa9e4b | |
|
12afc54ab1 | |
|
08bd89dc1f | |
|
2b714c5193 | |
|
74c14e48ef | |
|
02f66f4198 | |
|
cb9f657c05 | |
|
651751aaac | |
|
f48e791162 | |
|
df1a9ab6e2 | |
|
6a238db493 | |
|
2cc10fc14a | |
|
799d505696 | |
|
c00665d1af | |
|
0c5cc851cc | |
|
e6507779c7 | |
|
6dc5b34312 | |
|
b49999cfc0 | |
|
02fc3223c8 | |
|
e392237e4a | |
|
f86008ff0c | |
|
587a7501fd | |
|
1653230f3d | |
|
aecec57a9c | |
|
1c7b8896b8 | |
|
0c7b287048 | |
|
8fb20fe3ec | |
|
7bc2cbe3c0 | |
|
44912bd43f | |
|
a523f66f22 | |
|
a33bb0eedb | |
|
e093c3ecd3 | |
|
e028cd962f | |
|
ec6d6871f6 | |
|
785b5f7ca4 | |
|
8743ead5dc | |
|
e722b5f800 | |
|
2948f7ad76 | |
|
7c2a8f6951 | |
|
79788ab52e | |
|
96898c99e3 | |
|
bb485c031a | |
|
dfe6927676 | |
|
899272f208 | |
|
af6c529e4c | |
|
1c829502bf | |
|
5fb7af7441 | |
|
ffcb4d1f31 | |
|
d0a24940d6 | |
|
fd4a40d941 | |
|
6f7010771b | |
|
f5a2940cd7 | |
|
edc5cee43d | |
|
d810aa6a46 | |
|
5789c00945 | |
|
83865d39c9 | |
|
5b3b1e5fba | |
|
e0d0885e32 | |
|
862e56c5e6 | |
|
45b79b2320 | |
|
f5daf358a8 | |
|
9dbcffa35e | |
|
9271c9b6d6 | |
|
682c598e30 | |
|
9728b403b2 | |
|
6fc3712761 | |
|
a43a3e9cc9 | |
|
73f6943de7 | |
|
bf3cf4be0a | |
|
1c4db83b08 | |
|
1698305f77 | |
|
4397249c7f | |
|
0b25ac93c6 | |
|
b424607308 | |
|
f1b8d339ca | |
|
415ef43135 | |
|
65b8b1d5c3 | |
|
cd988f19be | |
|
6e093957e1 | |
|
853a7608ce | |
|
ef6226b5d1 | |
|
4325802e06 | |
|
0f2432c520 | |
|
e50916952a | |
|
2b0b732be5 | |
|
59bb5767ce | |
|
45e5f426b2 | |
|
580ac1a41c | |
|
beca50a1d7 | |
|
021a40ea10 | |
|
c90491e3d0 | |
|
c04ed6521f | |
|
783e2ea9eb | |
|
ca4aa24ee1 | |
|
abefa7a2e8 | |
|
690341e3f4 | |
|
316278ad48 | |
|
8e10e572a5 | |
|
db060d62c5 | |
|
056311120e | |
|
2645767c05 | |
|
1439a5cc64 | |
|
1345d4b1f2 | |
|
540b4e080f | |
|
ca55b11d6f |
|
@ -1,16 +1,32 @@
|
|||
version: 2
|
||||
|
||||
updates:
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
labels: ["dependencies"]
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
go-deps:
|
||||
patterns:
|
||||
- "*"
|
||||
allow:
|
||||
- dependency-type: "direct"
|
||||
ignore:
|
||||
# Kubernetes deps are updated by fluxcd/pkg
|
||||
- dependency-name: "k8s.io/*"
|
||||
- dependency-name: "sigs.k8s.io/*"
|
||||
- dependency-name: "github.com/go-logr/*"
|
||||
# Flux APIs are updated at release time
|
||||
- dependency-name: "github.com/fluxcd/image-automation-controller/api"
|
||||
- dependency-name: "github.com/fluxcd/image-reflector-controller/api"
|
||||
- dependency-name: "github.com/fluxcd/source-controller/api"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
labels: ["area/ci", "dependencies"]
|
||||
schedule:
|
||||
# By default, this will be on a monday.
|
||||
interval: "weekly"
|
||||
groups:
|
||||
# Group all updates together, so that they are all applied in a single PR.
|
||||
# Grouped updates are currently in beta and is subject to change.
|
||||
# xref: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups
|
||||
ci:
|
||||
patterns:
|
||||
- "*"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
|
|
|
@ -13,11 +13,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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Create backport PRs
|
||||
uses: korthout/backport-action@b982d297e31f500652b2246cf26714796312bd23 # v2.2.0
|
||||
uses: korthout/backport-action@436145e922f9561fc5ea157ff406f21af2d6b363 # v3.2.0
|
||||
# xref: https://github.com/korthout/backport-action#inputs
|
||||
with:
|
||||
# Use token to allow workflows to be triggered for the created PR
|
||||
|
|
|
@ -12,11 +12,11 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
go-version: 1.24.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
|
@ -26,28 +26,21 @@ jobs:
|
|||
run: make verify
|
||||
|
||||
kind-linux-arm64:
|
||||
# Hosted on Equinix
|
||||
# Docs: https://github.com/fluxcd/flux2/tree/main/.github/runners
|
||||
runs-on: [self-hosted, Linux, ARM64, equinix]
|
||||
runs-on:
|
||||
group: "ARM64"
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
go-version: 1.24.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Run tests
|
||||
run: make test
|
||||
env:
|
||||
# Temporarily disabling -race for arm64 as our GitHub action
|
||||
# runners don't seem to like it.
|
||||
#
|
||||
# We should reenable go test -race for arm64 runners once the
|
||||
# current issue is resolved.
|
||||
GO_TEST_ARGS: ""
|
||||
SKIP_COSIGN_VERIFICATION: true
|
||||
- name: Verify
|
||||
run: make verify
|
||||
|
|
|
@ -11,11 +11,11 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
go-version: 1.24.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
|
|
|
@ -15,14 +15,14 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
|
||||
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
|
||||
- name: Build multi-arch container image
|
||||
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
|
||||
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0
|
||||
with:
|
||||
push: false
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
|
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
packages: write # for pushing and signing container images.
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
- name: Prepare
|
||||
|
@ -42,24 +42,24 @@ jobs:
|
|||
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
|
||||
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
with:
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
- name: Generate images meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@31cebacef4805868f9ce9a0cb03ee36c32df2ac4 # v5.3.0
|
||||
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
|
||||
with:
|
||||
images: |
|
||||
fluxcd/${{ env.CONTROLLER }}
|
||||
|
@ -68,7 +68,7 @@ jobs:
|
|||
type=raw,value=${{ steps.prep.outputs.VERSION }}
|
||||
- name: Publish images
|
||||
id: build-push
|
||||
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0
|
||||
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0
|
||||
with:
|
||||
sbom: true
|
||||
provenance: true
|
||||
|
@ -79,7 +79,7 @@ jobs:
|
|||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
- uses: sigstore/cosign-installer@1fc5bd396d372bee37d608f955b336615edf79c8 # v3.2.0
|
||||
- uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2
|
||||
- name: Sign images
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: 1
|
||||
|
@ -92,14 +92,14 @@ jobs:
|
|||
mkdir -p config/release
|
||||
kustomize build ./config/crd > ./config/release/${{ env.CONTROLLER }}.crds.yaml
|
||||
kustomize build ./config/manager > ./config/release/${{ env.CONTROLLER }}.deployment.yaml
|
||||
- uses: anchore/sbom-action/download-syft@5ecf649a417b8ae17dc8383dc32d46c03f2312df # v0.15.1
|
||||
- uses: anchore/sbom-action/download-syft@e11c554f704a0b820cbf8c51673f6945e0731532 # v0.20.0
|
||||
- name: Create release and SBOM
|
||||
id: run-goreleaser
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0
|
||||
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
|
||||
with:
|
||||
version: latest
|
||||
args: release --clean --skip-validate
|
||||
args: release --clean --skip=validate
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Generate SLSA metadata
|
||||
|
@ -123,7 +123,7 @@ jobs:
|
|||
id-token: write # for creating OIDC tokens for signing.
|
||||
contents: write # for uploading attestations to GitHub releases.
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
|
||||
with:
|
||||
provenance-name: "provenance.intoto.jsonl"
|
||||
base64-subjects: "${{ needs.release.outputs.hashes }}"
|
||||
|
@ -136,7 +136,7 @@ jobs:
|
|||
id-token: write # for creating OIDC tokens for signing.
|
||||
packages: write # for uploading attestations.
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
|
||||
with:
|
||||
image: ${{ needs.release.outputs.image_url }}
|
||||
digest: ${{ needs.release.outputs.image_digest }}
|
||||
|
@ -151,7 +151,7 @@ jobs:
|
|||
id-token: write # for creating OIDC tokens for signing.
|
||||
packages: write # for uploading attestations.
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
|
||||
with:
|
||||
image: ghcr.io/${{ needs.release.outputs.image_url }}
|
||||
digest: ${{ needs.release.outputs.image_digest }}
|
||||
|
|
|
@ -18,9 +18,9 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Run FOSSA scan and upload build data
|
||||
uses: fossa-contrib/fossa-action@cdc5065bcdee31a32e47d4585df72d66e8e941c2 # v3.0.0
|
||||
uses: fossa-contrib/fossa-action@3d2ef181b1820d6dcd1972f86a767d18167fa19b # v3.0.1
|
||||
with:
|
||||
# FOSSA Push-Only API Token
|
||||
fossa-api-key: 5ee8bf422db1471e0bcf2bcb289185de
|
||||
|
@ -31,22 +31,22 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
go-version: 1.24.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
|
||||
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
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@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
|
||||
uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
|
||||
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
|
|
|
@ -17,8 +17,8 @@ jobs:
|
|||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: EndBug/label-sync@da00f2c11fdb78e4fae44adac2fdd713778ea3e8 # v2.3.2
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2.3.3
|
||||
with:
|
||||
# Configuration file
|
||||
config-file: |
|
||||
|
|
|
@ -23,7 +23,7 @@ release:
|
|||
To verify the images and their provenance (SLSA level 3), please see the [security documentation](https://fluxcd.io/flux/security/).
|
||||
|
||||
changelog:
|
||||
skip: true
|
||||
disable: true
|
||||
|
||||
checksum:
|
||||
extra_files:
|
||||
|
|
365
CHANGELOG.md
365
CHANGELOG.md
|
@ -1,5 +1,370 @@
|
|||
# Changelog
|
||||
|
||||
## 0.41.1
|
||||
|
||||
**Release date:** 2025-06-13
|
||||
|
||||
This patch release comes with a fix for the `knownhosts: key mismatch` error.
|
||||
|
||||
Fixes:
|
||||
- Fix `knownhosts key mismatch` regression bug
|
||||
[#923](https://github.com/fluxcd/image-automation-controller/pull/923)
|
||||
- Upgrade dependencies (includes `github.com/go-git/go-git/v5` `v5.16.2`)
|
||||
[#919](https://github.com/fluxcd/image-automation-controller/pull/919)
|
||||
|
||||
## 0.41.0
|
||||
|
||||
**Release date:** 2025-05-28
|
||||
|
||||
This prerelease comes with support for updating image digests, for
|
||||
configuring mTLS with HTTPS Git repositories, and with caching Git
|
||||
provider access tokens.
|
||||
|
||||
ImagePolicy API now supports reflecting image digests in-cluster. By
|
||||
integrating with this feature the ImageUpdateAutomation API can now
|
||||
update image digests in YAML manifests. See this
|
||||
[guide](https://fluxcd.io/flux/guides/image-update/#digest-pinning)
|
||||
for more details.
|
||||
|
||||
The controller now caches Git provider access tokens by default.
|
||||
This behavior can be disabled or fine-tuned by adjusting the
|
||||
token cache controller flags (see
|
||||
[docs](https://fluxcd.io/flux/components/image/options/#image-automation-flags)).
|
||||
The token cache also exposes metrics that are documented
|
||||
[here](https://fluxcd.io/flux/monitoring/metrics/#controller-metrics).
|
||||
|
||||
For configuring mTLS with HTTPS Git repositories see the GitRepository
|
||||
[docs](https://fluxcd.io/flux/components/source/gitrepositories/#secret-reference).
|
||||
|
||||
In addition, the Kubernetes dependencies have been updated to v1.33
|
||||
and various other controller dependencies have been updated to their latest
|
||||
version. The controller is now built with Go 1.24.
|
||||
|
||||
Fixes:
|
||||
- Fix tag parsing logic misinterpreting host:port registry url
|
||||
[#893](https://github.com/fluxcd/image-automation-controller/pull/893)
|
||||
|
||||
Improvements:
|
||||
- Update digest of latest image
|
||||
[#902](https://github.com/fluxcd/image-automation-controller/pull/902)
|
||||
- Introduce token cache for Git provider access tokens
|
||||
[#861](https://github.com/fluxcd/image-automation-controller/pull/861)
|
||||
[#895](https://github.com/fluxcd/image-automation-controller/pull/895)
|
||||
[#897](https://github.com/fluxcd/image-automation-controller/pull/897)
|
||||
- Add support for mutual TLS to Git HTTP/S operations
|
||||
[#886](https://github.com/fluxcd/image-automation-controller/pull/886)
|
||||
- Support for all recognized Kustomize config file names
|
||||
[#864](https://github.com/fluxcd/image-automation-controller/pull/864)
|
||||
- Various dependency updates
|
||||
[#916](https://github.com/fluxcd/image-automation-controller/pull/916)
|
||||
[#908](https://github.com/fluxcd/image-automation-controller/pull/908)
|
||||
[#900](https://github.com/fluxcd/image-automation-controller/pull/900)
|
||||
[#896](https://github.com/fluxcd/image-automation-controller/pull/896)
|
||||
[#898](https://github.com/fluxcd/image-automation-controller/pull/898)
|
||||
[#891](https://github.com/fluxcd/image-automation-controller/pull/891)
|
||||
[#890](https://github.com/fluxcd/image-automation-controller/pull/890)
|
||||
[#881](https://github.com/fluxcd/image-automation-controller/pull/881)
|
||||
[#880](https://github.com/fluxcd/image-automation-controller/pull/880)
|
||||
[#878](https://github.com/fluxcd/image-automation-controller/pull/878)
|
||||
[#856](https://github.com/fluxcd/image-automation-controller/pull/856)
|
||||
[#854](https://github.com/fluxcd/image-automation-controller/pull/854)
|
||||
[#852](https://github.com/fluxcd/image-automation-controller/pull/852)
|
||||
[#850](https://github.com/fluxcd/image-automation-controller/pull/850)
|
||||
|
||||
## 0.40.0
|
||||
|
||||
**Release date:** 2025-02-14
|
||||
|
||||
This prerelease comes with support for GitHub App authentication for GitHub
|
||||
repositories using the `.spec.provider` field by setting it to `github` on the
|
||||
`GitRepository` object associated with an `ImageUpdateAutomation` object.
|
||||
|
||||
In addition, the Kubernetes dependencies have been updated to v1.32.1
|
||||
and various other controller dependencies have been updated to their latest
|
||||
version.
|
||||
|
||||
Fixes:
|
||||
|
||||
Improvements:
|
||||
- Additional values for commit message template
|
||||
[#772](https://github.com/fluxcd/image-automation-controller/pull/772)
|
||||
- [RFC-007] Implement GitHub app authentication for git repositories in IAC
|
||||
[#780](https://github.com/fluxcd/image-automation-controller/pull/780)
|
||||
- Various dependency updates
|
||||
[#765](https://github.com/fluxcd/image-automation-controller/pull/765)
|
||||
[#766](https://github.com/fluxcd/image-automation-controller/pull/766)
|
||||
[#768](https://github.com/fluxcd/image-automation-controller/pull/768)
|
||||
[#769](https://github.com/fluxcd/image-automation-controller/pull/769)
|
||||
[#770](https://github.com/fluxcd/image-automation-controller/pull/770)
|
||||
[#774](https://github.com/fluxcd/image-automation-controller/pull/774)
|
||||
[#776](https://github.com/fluxcd/image-automation-controller/pull/776)
|
||||
[#777](https://github.com/fluxcd/image-automation-controller/pull/777)
|
||||
[#778](https://github.com/fluxcd/image-automation-controller/pull/778)
|
||||
[#782](https://github.com/fluxcd/image-automation-controller/pull/782)
|
||||
[#784](https://github.com/fluxcd/image-automation-controller/pull/784)
|
||||
[#787](https://github.com/fluxcd/image-automation-controller/pull/787)
|
||||
[#789](https://github.com/fluxcd/image-automation-controller/pull/789)
|
||||
[#790](https://github.com/fluxcd/image-automation-controller/pull/790)
|
||||
[#791](https://github.com/fluxcd/image-automation-controller/pull/791)
|
||||
[#794](https://github.com/fluxcd/image-automation-controller/pull/794)
|
||||
[#795](https://github.com/fluxcd/image-automation-controller/pull/795)
|
||||
[#798](https://github.com/fluxcd/image-automation-controller/pull/798)
|
||||
[#799](https://github.com/fluxcd/image-automation-controller/pull/799)
|
||||
[#801](https://github.com/fluxcd/image-automation-controller/pull/801)
|
||||
[#802](https://github.com/fluxcd/image-automation-controller/pull/802)
|
||||
[#804](https://github.com/fluxcd/image-automation-controller/pull/804)
|
||||
[#805](https://github.com/fluxcd/image-automation-controller/pull/805)
|
||||
[#806](https://github.com/fluxcd/image-automation-controller/pull/806)
|
||||
[#808](https://github.com/fluxcd/image-automation-controller/pull/808)
|
||||
[#815](https://github.com/fluxcd/image-automation-controller/pull/815)
|
||||
[#819](https://github.com/fluxcd/image-automation-controller/pull/819)
|
||||
[#821](https://github.com/fluxcd/image-automation-controller/pull/821)
|
||||
[#824](https://github.com/fluxcd/image-automation-controller/pull/824)
|
||||
[#826](https://github.com/fluxcd/image-automation-controller/pull/826)
|
||||
[#828](https://github.com/fluxcd/image-automation-controller/pull/828)
|
||||
[#831](https://github.com/fluxcd/image-automation-controller/pull/831)
|
||||
[#832](https://github.com/fluxcd/image-automation-controller/pull/832)
|
||||
[#835](https://github.com/fluxcd/image-automation-controller/pull/835)
|
||||
[#839](https://github.com/fluxcd/image-automation-controller/pull/839)
|
||||
[#840](https://github.com/fluxcd/image-automation-controller/pull/840)
|
||||
[#842](https://github.com/fluxcd/image-automation-controller/pull/842)
|
||||
[#843](https://github.com/fluxcd/image-automation-controller/pull/843)
|
||||
[#845](https://github.com/fluxcd/image-automation-controller/pull/845)
|
||||
|
||||
## 0.39.0
|
||||
|
||||
**Release date:** 2024-09-26
|
||||
|
||||
This prerelease comes with support for OIDC authentication for Azure DevOps
|
||||
Repositories using the `.spec.provider` field by setting it to `azure` on the
|
||||
`GitRepository` object associated with `ImageUpdateAutomation` object.
|
||||
|
||||
In addition, the Kubernetes dependencies have been updated to v1.31.1
|
||||
and various other controller dependencies have been updated to their latest
|
||||
version. The controller is now built with Go 1.23.
|
||||
|
||||
Fixes:
|
||||
- Fix incorrect use of format strings with the conditions package.
|
||||
[#711](https://github.com/fluxcd/image-automation-controller/pull/711)
|
||||
- Fix RBAC role generation for IAC
|
||||
[#745](https://github.com/fluxcd/image-automation-controller/pull/745)
|
||||
|
||||
Improvements:
|
||||
- [RFC-0007] Enable Azure OIDC for Azure DevOps Repository
|
||||
[#747](https://github.com/fluxcd/image-automation-controller/pull/747)
|
||||
- Build with Go 1.23
|
||||
[#736](https://github.com/fluxcd/image-automation-controller/pull/736)
|
||||
- Run ARM64 tests on GitHub runners
|
||||
[#696](https://github.com/fluxcd/image-automation-controller/pull/696)
|
||||
- Various dependency updates
|
||||
[#680](https://github.com/fluxcd/image-automation-controller/pull/680)
|
||||
[#683](https://github.com/fluxcd/image-automation-controller/pull/683)
|
||||
[#685](https://github.com/fluxcd/image-automation-controller/pull/685)
|
||||
[#690](https://github.com/fluxcd/image-automation-controller/pull/690)
|
||||
[#691](https://github.com/fluxcd/image-automation-controller/pull/691)
|
||||
[#693](https://github.com/fluxcd/image-automation-controller/pull/693)
|
||||
[#694](https://github.com/fluxcd/image-automation-controller/pull/694)
|
||||
[#695](https://github.com/fluxcd/image-automation-controller/pull/695)
|
||||
[#698](https://github.com/fluxcd/image-automation-controller/pull/698)
|
||||
[#697](https://github.com/fluxcd/image-automation-controller/pull/697)
|
||||
[#700](https://github.com/fluxcd/image-automation-controller/pull/700)
|
||||
[#701](https://github.com/fluxcd/image-automation-controller/pull/701)
|
||||
[#702](https://github.com/fluxcd/image-automation-controller/pull/702)
|
||||
[#703](https://github.com/fluxcd/image-automation-controller/pull/703)
|
||||
[#704](https://github.com/fluxcd/image-automation-controller/pull/704)
|
||||
[#706](https://github.com/fluxcd/image-automation-controller/pull/706)
|
||||
[#707](https://github.com/fluxcd/image-automation-controller/pull/707)
|
||||
[#708](https://github.com/fluxcd/image-automation-controller/pull/708)
|
||||
[#709](https://github.com/fluxcd/image-automation-controller/pull/709)
|
||||
[#712](https://github.com/fluxcd/image-automation-controller/pull/712)
|
||||
[#710](https://github.com/fluxcd/image-automation-controller/pull/710)
|
||||
[#714](https://github.com/fluxcd/image-automation-controller/pull/714)
|
||||
[#716](https://github.com/fluxcd/image-automation-controller/pull/716)
|
||||
[#718](https://github.com/fluxcd/image-automation-controller/pull/718)
|
||||
[#719](https://github.com/fluxcd/image-automation-controller/pull/719)
|
||||
[#720](https://github.com/fluxcd/image-automation-controller/pull/720)
|
||||
[#724](https://github.com/fluxcd/image-automation-controller/pull/724)
|
||||
[#722](https://github.com/fluxcd/image-automation-controller/pull/722)
|
||||
[#727](https://github.com/fluxcd/image-automation-controller/pull/727)
|
||||
[#726](https://github.com/fluxcd/image-automation-controller/pull/726)
|
||||
[#728](https://github.com/fluxcd/image-automation-controller/pull/728)
|
||||
[#729](https://github.com/fluxcd/image-automation-controller/pull/729)
|
||||
[#730](https://github.com/fluxcd/image-automation-controller/pull/730)
|
||||
[#731](https://github.com/fluxcd/image-automation-controller/pull/731)
|
||||
[#732](https://github.com/fluxcd/image-automation-controller/pull/732)
|
||||
[#734](https://github.com/fluxcd/image-automation-controller/pull/734)
|
||||
[#733](https://github.com/fluxcd/image-automation-controller/pull/733)
|
||||
[#737](https://github.com/fluxcd/image-automation-controller/pull/737)
|
||||
[#738](https://github.com/fluxcd/image-automation-controller/pull/738)
|
||||
[#739](https://github.com/fluxcd/image-automation-controller/pull/739)
|
||||
[#740](https://github.com/fluxcd/image-automation-controller/pull/740)
|
||||
[#741](https://github.com/fluxcd/image-automation-controller/pull/741)
|
||||
[#742](https://github.com/fluxcd/image-automation-controller/pull/742)
|
||||
[#743](https://github.com/fluxcd/image-automation-controller/pull/743)
|
||||
[#748](https://github.com/fluxcd/image-automation-controller/pull/748)
|
||||
[#750](https://github.com/fluxcd/image-automation-controller/pull/750)
|
||||
[#752](https://github.com/fluxcd/image-automation-controller/pull/752)
|
||||
[#755](https://github.com/fluxcd/image-automation-controller/pull/755)
|
||||
[#757](https://github.com/fluxcd/image-automation-controller/pull/757)
|
||||
[#759](https://github.com/fluxcd/image-automation-controller/pull/759)
|
||||
|
||||
## 0.38.0
|
||||
|
||||
**Release date:** 2024-05-06
|
||||
|
||||
This prerelease graduates the `ImageUpdateAutomation` API to v1beta2.
|
||||
|
||||
### `image.toolkit.fluxcd.io/v1beta2`
|
||||
|
||||
After upgrading the controller to v0.38.0, please update the
|
||||
`ImageUpdateAutomation` **Custom Resources** in Git by replacing
|
||||
`image.toolkit.fluxcd.io/v1beta1` with `image.toolkit.fluxcd.io/v1beta2` in all
|
||||
YAML manifests. Bumping the API version in manifests can be done gradually. It
|
||||
is advised not to delay this procedure as the `v1beta1` version will be removed
|
||||
after 6 months.
|
||||
|
||||
### Highlights
|
||||
|
||||
#### New API specification format
|
||||
|
||||
[The specification for the `v1beta2`
|
||||
API](https://github.com/fluxcd/image-automation-controller/tree/v0.38.0/docs/spec/v1beta2)
|
||||
has been written in a new format with the aim to be more valuable to a user.
|
||||
Featuring separate sections with examples, and information on how to write and
|
||||
work with them.
|
||||
|
||||
#### New template data `Changed` and deprecation of `Updated`
|
||||
|
||||
A new Git commit message template data named `Changed` is introduced to replace
|
||||
`Updated` template data. `Changed` is designed to accommodate for all the types
|
||||
of updates made by ImaegUpdateAutomation, unlike only full image reference
|
||||
updates captured by `Updated`. The message template can now be used to render
|
||||
the old and new values for better presentation of the updates. For example:
|
||||
|
||||
```
|
||||
Automation: default/test-update-auto
|
||||
|
||||
- File: foo-deployment.yaml
|
||||
- Object: Deployment/default/foo
|
||||
Changes:
|
||||
- 2.2.2 -> 5.0.3
|
||||
|
||||
- File: podinfo-deployment.yaml
|
||||
- Object: Deployment/default/infopod
|
||||
Changes:
|
||||
- v1.0 -> 5.0.3
|
||||
- Object: Deployment/default/podinfo
|
||||
Changes:
|
||||
- ghcr.io/stefanprodan/podinfo:4.0.6 -> ghcr.io/stefanprodan/podinfo:5.0.3
|
||||
- bar -> ghcr.io/stefanprodan/podinfo
|
||||
- 4.0.6 -> 5.0.3
|
||||
```
|
||||
|
||||
`Updated` template data is deprecated, but is still available in the message
|
||||
template, for existing users. It is recommended to migrate to `Changed` template
|
||||
data. See the new API specification docs for details about the new template
|
||||
data.
|
||||
|
||||
#### ImagePolicy selector support
|
||||
|
||||
`ImageUpdateAutomation` now supports selecting `ImagePolicies` using label
|
||||
selectors in the new field `.spec.policySelector`. For example:
|
||||
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1beta2
|
||||
kind: ImageUpdateAutomation
|
||||
metadata:
|
||||
name: update-app
|
||||
spec:
|
||||
policySelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/component: foo
|
||||
app.kubernetes.io/instance: bar
|
||||
...
|
||||
```
|
||||
|
||||
See the new API specification docs for details and more examples.
|
||||
|
||||
#### short-circuit reconciliations
|
||||
|
||||
For same push branch and checkout branch, the controller now checks with the
|
||||
remote Git repository if there's any new commit and the image policies for any
|
||||
new latest image before performing full reconciliation, otherwise the
|
||||
reconciliation returns early. This helps avoid cloning the Git repository every
|
||||
reconciliation even when there is no new change.
|
||||
|
||||
#### Enhancements in events and notifications
|
||||
|
||||
The events and notifications have been improved to provide better information.
|
||||
Notifications are sent for: initial successful reconciliation, update
|
||||
pushes, failures and successful failure recovery.
|
||||
|
||||
|
||||
In addition, the controller is now built with Go 1.22, the Kubernetes
|
||||
dependencies have been updated to v1.30.0, and various other dependencies have
|
||||
been updated to their latest version.
|
||||
|
||||
### Full changelog
|
||||
|
||||
Improvements:
|
||||
- Deprecate v1beta1 API
|
||||
[#677](https://github.com/fluxcd/image-automation-controller/pull/677)
|
||||
- Update source-controller API to v1.3.0
|
||||
[#676](https://github.com/fluxcd/image-automation-controller/pull/676)
|
||||
- Update dependencies to Kubernetes 1.30
|
||||
[#670](https://github.com/fluxcd/image-automation-controller/pull/670)
|
||||
- ImageUpdateAutomation v1beta2 API with refactored controller
|
||||
[#647](https://github.com/fluxcd/image-automation-controller/pull/647)
|
||||
- Update dependencies to Kustomize v5.4.0
|
||||
[#662](https://github.com/fluxcd/image-automation-controller/pull/662)
|
||||
- Update dependencies to Go 1.22 and Kubernetes 1.29.3
|
||||
[#661](https://github.com/fluxcd/image-automation-controller/pull/661)
|
||||
- Add tests for getExtFromSchema
|
||||
[#658](https://github.com/fluxcd/image-automation-controller/pull/658)
|
||||
- Introduce ResultV2 for update results
|
||||
[#642](https://github.com/fluxcd/image-automation-controller/pull/642)
|
||||
- updating controller-gen to v0.14.0
|
||||
[#649](https://github.com/fluxcd/image-automation-controller/pull/649)
|
||||
- Add predicates for GitRepo and ImagePolicy watches
|
||||
[#639](https://github.com/fluxcd/image-automation-controller/pull/639)
|
||||
- adding tests for update accept function
|
||||
[#636](https://github.com/fluxcd/image-automation-controller/pull/636)
|
||||
- Various dependency updates
|
||||
[#637](https://github.com/fluxcd/image-automation-controller/pull/637)
|
||||
[#652](https://github.com/fluxcd/image-automation-controller/pull/652)
|
||||
[#660](https://github.com/fluxcd/image-automation-controller/pull/660)
|
||||
[#668](https://github.com/fluxcd/image-automation-controller/pull/668)
|
||||
[#665](https://github.com/fluxcd/image-automation-controller/pull/665)
|
||||
[#666](https://github.com/fluxcd/image-automation-controller/pull/666)
|
||||
[#673](https://github.com/fluxcd/image-automation-controller/pull/673)
|
||||
|
||||
## 0.37.1
|
||||
|
||||
**Release date:** 2024-02-01
|
||||
|
||||
This prerelease comes with an update to the Kubernetes dependencies to
|
||||
v1.28.6 and various other dependencies have been updated to their latest version
|
||||
to patch upstream CVEs.
|
||||
|
||||
In addition, the controller is now built with Go 1.21.
|
||||
|
||||
Improvements:
|
||||
- ci: Enable dependabot gomod updates
|
||||
[#627](https://github.com/fluxcd/image-automation-controller/pull/627)
|
||||
- Update Go to 1.21
|
||||
[#625](https://github.com/fluxcd/image-automation-controller/pull/625)
|
||||
- Various dependency updates
|
||||
[#635](https://github.com/fluxcd/image-automation-controller/pull/635)
|
||||
[#632](https://github.com/fluxcd/image-automation-controller/pull/632)
|
||||
[#630](https://github.com/fluxcd/image-automation-controller/pull/630)
|
||||
[#631](https://github.com/fluxcd/image-automation-controller/pull/631)
|
||||
[#629](https://github.com/fluxcd/image-automation-controller/pull/629)
|
||||
[#626](https://github.com/fluxcd/image-automation-controller/pull/626)
|
||||
[#623](https://github.com/fluxcd/image-automation-controller/pull/623)
|
||||
[#622](https://github.com/fluxcd/image-automation-controller/pull/622)
|
||||
[#618](https://github.com/fluxcd/image-automation-controller/pull/618)
|
||||
[#615](https://github.com/fluxcd/image-automation-controller/pull/615)
|
||||
|
||||
## 0.37.0
|
||||
|
||||
**Release date:** 2023-12-11
|
||||
|
|
|
@ -24,7 +24,7 @@ If any of the above dependencies are not present on your system, the first invoc
|
|||
## How to run the test suite
|
||||
|
||||
Prerequisites:
|
||||
* Go >= 1.20
|
||||
* Go >= 1.24
|
||||
|
||||
You can run the test suite by simply doing
|
||||
|
||||
|
|
10
Dockerfile
10
Dockerfile
|
@ -1,10 +1,10 @@
|
|||
ARG BASE_VARIANT=alpine
|
||||
ARG GO_VERSION=1.20
|
||||
ARG XX_VERSION=1.3.0
|
||||
ARG GO_VERSION=1.24
|
||||
ARG XX_VERSION=1.6.1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} as gostable
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} AS gostable
|
||||
|
||||
FROM gostable AS go-linux
|
||||
|
||||
|
@ -17,7 +17,7 @@ RUN apk add clang lld
|
|||
COPY --from=xx / /
|
||||
|
||||
# build can still be cached at build platform architecture.
|
||||
FROM build-base as build
|
||||
FROM build-base AS build
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
|
||||
|
@ -60,7 +60,7 @@ RUN export CGO_LDFLAGS="-static -fuse-ld=lld" && \
|
|||
# Ensure that the binary was cross-compiled correctly to the target platform.
|
||||
RUN xx-verify --static /image-automation-controller
|
||||
|
||||
FROM alpine:3.19
|
||||
FROM alpine:3.21
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
RUN apk --no-cache add ca-certificates \
|
||||
|
|
|
@ -9,6 +9,7 @@ from the main Flux v2 git repository, as listed in
|
|||
|
||||
In alphabetical order:
|
||||
|
||||
Dipti Pai, Microsoft <diptipai@microsoft.com> (github: @dipti-pai, slack: Dipti Pai)
|
||||
Paulo Gomes, SUSE <pjbgf@linux.com> (github: @pjbgf, slack: pjbgf)
|
||||
|
||||
Retired maintainers:
|
||||
|
|
9
Makefile
9
Makefile
|
@ -46,7 +46,7 @@ ifeq ($(shell uname -s),Linux)
|
|||
endif
|
||||
|
||||
# API (doc) generation utilities
|
||||
CONTROLLER_GEN_VERSION ?= v0.12.0
|
||||
CONTROLLER_GEN_VERSION ?= v0.16.1
|
||||
GEN_API_REF_DOCS_VERSION ?= e327d0730470cbd61b06300f81c5fcf91c23c113
|
||||
|
||||
# If gobin not set, create one on ./build and add to path.
|
||||
|
@ -139,14 +139,15 @@ dev-deploy: manifests
|
|||
rm -rf config/dev
|
||||
|
||||
manifests: controller-gen ## Generate manifests e.g. CRD, RBAC etc.
|
||||
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role paths="./..." output:crd:artifacts:config="config/crd/bases"
|
||||
cd api; $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role paths="./..." output:crd:artifacts:config="../config/crd/bases"
|
||||
|
||||
api-docs: gen-crd-api-reference-docs ## Generate API reference documentation
|
||||
$(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1beta1 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/v1beta1/image-automation.md
|
||||
$(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1beta2 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/v1beta2/image-automation.md
|
||||
|
||||
tidy: ## Run go mod tidy
|
||||
cd api; rm -f go.sum; go mod tidy -compat=1.20
|
||||
rm -f go.sum; go mod tidy -compat=1.20
|
||||
cd api; rm -f go.sum; go mod tidy -compat=1.24
|
||||
rm -f go.sum; go mod tidy -compat=1.24
|
||||
|
||||
fmt: ## Run go fmt against code
|
||||
go fmt ./...
|
||||
|
|
3
PROJECT
3
PROJECT
|
@ -4,4 +4,7 @@ resources:
|
|||
- group: image
|
||||
kind: ImageUpdateAutomation
|
||||
version: v1beta1
|
||||
- group: image
|
||||
kind: ImageUpdateAutomation
|
||||
version: v1beta2
|
||||
version: "2"
|
||||
|
|
33
api/go.mod
33
api/go.mod
|
@ -1,27 +1,32 @@
|
|||
module github.com/fluxcd/image-automation-controller/api
|
||||
|
||||
go 1.20
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/fluxcd/pkg/apis/meta v1.2.0
|
||||
github.com/fluxcd/source-controller/api v1.2.1
|
||||
k8s.io/apimachinery v0.28.4
|
||||
sigs.k8s.io/controller-runtime v0.16.3
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0
|
||||
github.com/fluxcd/source-controller/api v1.6.1
|
||||
k8s.io/apimachinery v0.33.0
|
||||
sigs.k8s.io/controller-runtime v0.21.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
k8s.io/klog/v2 v2.110.1 // indirect
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
|
102
api/go.sum
102
api/go.sum
|
@ -1,41 +1,57 @@
|
|||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fluxcd/pkg/apis/meta v1.2.0 h1:O766PzGAdMdQKybSflGL8oV0+GgCNIkdsxfalRyzeO8=
|
||||
github.com/fluxcd/pkg/apis/meta v1.2.0/go.mod h1:fU/Az9AoVyIxC0oI4ihG0NVMNnvrcCzdEym3wxjIQsc=
|
||||
github.com/fluxcd/source-controller/api v1.2.1 h1:zWRfwMB/BkV0A/duZQwHEcrE/abWJQt7DUgYTzn4IzM=
|
||||
github.com/fluxcd/source-controller/api v1.2.1/go.mod h1:n+PMCJXl/AYCjWHn5N/MUuoIFKfDg4kCDviFIa7fDvI=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5ooOE0=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
|
||||
github.com/fluxcd/source-controller/api v1.6.1 h1:ZPTA9lNzBYHmwHfFX978qb8xVkdnQZHF1ggo6BoFm4w=
|
||||
github.com/fluxcd/source-controller/api v1.6.1/go.mod h1:ZJcAi0nemsnBxjVgmJl0WQzNvB0rMETxQMTdoFosmMw=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
|
||||
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
|
||||
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
|
@ -47,47 +63,53 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM=
|
||||
k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8=
|
||||
k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg=
|
||||
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
|
||||
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6RxQGZDnzuLcrUTI=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4=
|
||||
sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
|
||||
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
|
||||
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
|
||||
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
|
||||
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
|
|
@ -133,9 +133,9 @@ func SetImageUpdateAutomationReadiness(auto *ImageUpdateAutomation, status metav
|
|||
apimeta.SetStatusCondition(auto.GetStatusConditions(), newCondition)
|
||||
}
|
||||
|
||||
//+kubebuilder:storageversion
|
||||
//+kubebuilder:object:root=true
|
||||
//+kubebuilder:subresource:status
|
||||
//+kubebuilder:deprecatedversion:warning="v1beta1 ImageUpdateAutomation is deprecated, upgrade to v1beta2"
|
||||
//+kubebuilder:printcolumn:name="Last run",type=string,JSONPath=`.status.lastAutomationRunTime`
|
||||
|
||||
// ImageUpdateAutomation is the Schema for the imageupdateautomations API
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2020 The Flux authors
|
||||
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.
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
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 v1beta2
|
||||
|
||||
const (
|
||||
// InvalidUpdateStrategyReason represents an invalid image update strategy
|
||||
// configuration.
|
||||
InvalidUpdateStrategyReason string = "InvalidUpdateStrategy"
|
||||
|
||||
// InvalidSourceConfigReason represents an invalid source configuration.
|
||||
InvalidSourceConfigReason string = "InvalidSourceConfiguration"
|
||||
|
||||
// SourceManagerFailedReason represents a failure in the SourceManager which
|
||||
// manages the source.
|
||||
SourceManagerFailedReason string = "SourceManagerFailed"
|
||||
|
||||
// GitOperationFailedReason represents a failure in Git source operation.
|
||||
GitOperationFailedReason string = "GitOperationFailed"
|
||||
|
||||
// UpdateFailedReason represents a failure during source update.
|
||||
UpdateFailedReason string = "UpdateFailed"
|
||||
|
||||
// InvalidPolicySelectorReason represents an invalid policy selector.
|
||||
InvalidPolicySelectorReason string = "InvalidPolicySelector"
|
||||
)
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
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 v1beta2 contains API types for the image API group, version
|
||||
// v1beta2. The types here are concerned with automated updates to
|
||||
// git, based on metadata from OCI image registries gathered by the
|
||||
// image-reflector-controller.
|
||||
//
|
||||
// +kubebuilder:object:generate=true
|
||||
// +groupName=image.toolkit.fluxcd.io
|
||||
package v1beta2
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
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 v1beta2
|
||||
|
||||
import (
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
type GitSpec struct {
|
||||
// Checkout gives the parameters for cloning the git repository,
|
||||
// ready to make changes. If not present, the `spec.ref` field from the
|
||||
// referenced `GitRepository` or its default will be used.
|
||||
// +optional
|
||||
Checkout *GitCheckoutSpec `json:"checkout,omitempty"`
|
||||
|
||||
// Commit specifies how to commit to the git repository.
|
||||
// +required
|
||||
Commit CommitSpec `json:"commit"`
|
||||
|
||||
// Push specifies how and where to push commits made by the
|
||||
// automation. If missing, commits are pushed (back) to
|
||||
// `.spec.checkout.branch` or its default.
|
||||
// +optional
|
||||
Push *PushSpec `json:"push,omitempty"`
|
||||
}
|
||||
|
||||
// HasRefspec returns if the GitSpec has a Refspec.
|
||||
func (gs GitSpec) HasRefspec() bool {
|
||||
if gs.Push == nil {
|
||||
return false
|
||||
}
|
||||
return gs.Push.Refspec != ""
|
||||
}
|
||||
|
||||
type GitCheckoutSpec struct {
|
||||
// Reference gives a branch, tag or commit to clone from the Git
|
||||
// repository.
|
||||
// +required
|
||||
Reference sourcev1.GitRepositoryRef `json:"ref"`
|
||||
}
|
||||
|
||||
// CommitSpec specifies how to commit changes to the git repository
|
||||
type CommitSpec struct {
|
||||
// Author gives the email and optionally the name to use as the
|
||||
// author of commits.
|
||||
// +required
|
||||
Author CommitUser `json:"author"`
|
||||
// SigningKey provides the option to sign commits with a GPG key
|
||||
// +optional
|
||||
SigningKey *SigningKey `json:"signingKey,omitempty"`
|
||||
// MessageTemplate provides a template for the commit message,
|
||||
// into which will be interpolated the details of the change made.
|
||||
// +optional
|
||||
MessageTemplate string `json:"messageTemplate,omitempty"`
|
||||
|
||||
// MessageTemplateValues provides additional values to be available to the
|
||||
// templating rendering.
|
||||
// +optional
|
||||
MessageTemplateValues map[string]string `json:"messageTemplateValues,omitempty"`
|
||||
}
|
||||
|
||||
type CommitUser struct {
|
||||
// Name gives the name to provide when making a commit.
|
||||
// +optional
|
||||
Name string `json:"name,omitempty"`
|
||||
// Email gives the email to provide when making a commit.
|
||||
// +required
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// SigningKey references a Kubernetes secret that contains a GPG keypair
|
||||
type SigningKey struct {
|
||||
// SecretRef holds the name to a secret that contains a 'git.asc' key
|
||||
// corresponding to the ASCII Armored file containing the GPG signing
|
||||
// keypair as the value. It must be in the same namespace as the
|
||||
// ImageUpdateAutomation.
|
||||
// +required
|
||||
SecretRef meta.LocalObjectReference `json:"secretRef,omitempty"`
|
||||
}
|
||||
|
||||
// PushSpec specifies how and where to push commits.
|
||||
type PushSpec struct {
|
||||
// Branch specifies that commits should be pushed to the branch
|
||||
// named. The branch is created using `.spec.checkout.branch` as the
|
||||
// starting point, if it doesn't already exist.
|
||||
// +optional
|
||||
Branch string `json:"branch,omitempty"`
|
||||
|
||||
// Refspec specifies the Git Refspec to use for a push operation.
|
||||
// If both Branch and Refspec are provided, then the commit is pushed
|
||||
// to the branch and also using the specified refspec.
|
||||
// For more details about Git Refspecs, see:
|
||||
// https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
|
||||
// +optional
|
||||
Refspec string `json:"refspec,omitempty"`
|
||||
|
||||
// Options specifies the push options that are sent to the Git
|
||||
// server when performing a push operation. For details, see:
|
||||
// https://git-scm.com/docs/git-push#Documentation/git-push.txt---push-optionltoptiongt
|
||||
// +optional
|
||||
Options map[string]string `json:"options,omitempty"`
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
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 v1beta2 contains API Schema definitions for the image v1beta2 API group
|
||||
// +kubebuilder:object:generate=true
|
||||
// +groupName=image.toolkit.fluxcd.io
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/controller-runtime/pkg/scheme"
|
||||
)
|
||||
|
||||
var (
|
||||
// GroupVersion is group version used to register these objects
|
||||
GroupVersion = schema.GroupVersion{Group: "image.toolkit.fluxcd.io", Version: "v1beta2"}
|
||||
|
||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
|
||||
|
||||
// AddToScheme adds the types in this group-version to the given scheme.
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
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 v1beta2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
)
|
||||
|
||||
const (
|
||||
ImageUpdateAutomationKind = "ImageUpdateAutomation"
|
||||
ImageUpdateAutomationFinalizer = "finalizers.fluxcd.io"
|
||||
)
|
||||
|
||||
// ImageUpdateAutomationSpec defines the desired state of ImageUpdateAutomation
|
||||
type ImageUpdateAutomationSpec struct {
|
||||
// SourceRef refers to the resource giving access details
|
||||
// to a git repository.
|
||||
// +required
|
||||
SourceRef CrossNamespaceSourceReference `json:"sourceRef"`
|
||||
|
||||
// GitSpec contains all the git-specific definitions. This is
|
||||
// technically optional, but in practice mandatory until there are
|
||||
// other kinds of source allowed.
|
||||
// +optional
|
||||
GitSpec *GitSpec `json:"git,omitempty"`
|
||||
|
||||
// Interval gives an lower bound for how often the automation
|
||||
// run should be attempted.
|
||||
// +kubebuilder:validation:Type=string
|
||||
// +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$"
|
||||
// +required
|
||||
Interval metav1.Duration `json:"interval"`
|
||||
|
||||
// PolicySelector allows to filter applied policies based on labels.
|
||||
// By default includes all policies in namespace.
|
||||
// +optional
|
||||
PolicySelector *metav1.LabelSelector `json:"policySelector,omitempty"`
|
||||
|
||||
// Update gives the specification for how to update the files in
|
||||
// the repository. This can be left empty, to use the default
|
||||
// value.
|
||||
// +kubebuilder:default={"strategy":"Setters"}
|
||||
Update *UpdateStrategy `json:"update,omitempty"`
|
||||
|
||||
// Suspend tells the controller to not run this automation, until
|
||||
// it is unset (or set to false). Defaults to false.
|
||||
// +optional
|
||||
Suspend bool `json:"suspend,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateStrategyName is the type for names that go in
|
||||
// .update.strategy. NB the value in the const immediately below.
|
||||
// +kubebuilder:validation:Enum=Setters
|
||||
type UpdateStrategyName string
|
||||
|
||||
const (
|
||||
// UpdateStrategySetters is the name of the update strategy that
|
||||
// uses kyaml setters. NB the value in the enum annotation for the
|
||||
// type, above.
|
||||
UpdateStrategySetters UpdateStrategyName = "Setters"
|
||||
)
|
||||
|
||||
// UpdateStrategy is a union of the various strategies for updating
|
||||
// the Git repository. Parameters for each strategy (if any) can be
|
||||
// inlined here.
|
||||
type UpdateStrategy struct {
|
||||
// Strategy names the strategy to be used.
|
||||
// +required
|
||||
// +kubebuilder:default=Setters
|
||||
Strategy UpdateStrategyName `json:"strategy"`
|
||||
|
||||
// Path to the directory containing the manifests to be updated.
|
||||
// Defaults to 'None', which translates to the root path
|
||||
// of the GitRepositoryRef.
|
||||
// +optional
|
||||
Path string `json:"path,omitempty"`
|
||||
}
|
||||
|
||||
// ImageUpdateAutomationStatus defines the observed state of ImageUpdateAutomation
|
||||
type ImageUpdateAutomationStatus struct {
|
||||
// LastAutomationRunTime records the last time the controller ran
|
||||
// this automation through to completion (even if no updates were
|
||||
// made).
|
||||
// +optional
|
||||
LastAutomationRunTime *metav1.Time `json:"lastAutomationRunTime,omitempty"`
|
||||
// LastPushCommit records the SHA1 of the last commit made by the
|
||||
// controller, for this automation object
|
||||
// +optional
|
||||
LastPushCommit string `json:"lastPushCommit,omitempty"`
|
||||
// LastPushTime records the time of the last pushed change.
|
||||
// +optional
|
||||
LastPushTime *metav1.Time `json:"lastPushTime,omitempty"`
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
// +optional
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty"`
|
||||
// ObservedPolicies is the list of observed ImagePolicies that were
|
||||
// considered by the ImageUpdateAutomation update process.
|
||||
// +optional
|
||||
ObservedPolicies ObservedPolicies `json:"observedPolicies,omitempty"`
|
||||
// ObservedPolicies []ObservedPolicy `json:"observedPolicies,omitempty"`
|
||||
// ObservedSourceRevision is the last observed source revision. This can be
|
||||
// used to determine if the source has been updated since last observation.
|
||||
// +optional
|
||||
ObservedSourceRevision string `json:"observedSourceRevision,omitempty"`
|
||||
|
||||
meta.ReconcileRequestStatus `json:",inline"`
|
||||
}
|
||||
|
||||
// ObservedPolicies is a map of policy name and ImageRef of their latest
|
||||
// ImageRef.
|
||||
type ObservedPolicies map[string]ImageRef
|
||||
|
||||
//+kubebuilder:storageversion
|
||||
//+kubebuilder:object:root=true
|
||||
//+kubebuilder:subresource:status
|
||||
//+kubebuilder:printcolumn:name="Last run",type=string,JSONPath=`.status.lastAutomationRunTime`
|
||||
|
||||
// ImageUpdateAutomation is the Schema for the imageupdateautomations API
|
||||
type ImageUpdateAutomation struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec ImageUpdateAutomationSpec `json:"spec,omitempty"`
|
||||
// +kubebuilder:default={"observedGeneration":-1}
|
||||
Status ImageUpdateAutomationStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// GetRequeueAfter returns the duration after which the ImageUpdateAutomation
|
||||
// must be reconciled again.
|
||||
func (auto ImageUpdateAutomation) GetRequeueAfter() time.Duration {
|
||||
return auto.Spec.Interval.Duration
|
||||
}
|
||||
|
||||
// GetConditions returns the status conditions of the object.
|
||||
func (auto ImageUpdateAutomation) GetConditions() []metav1.Condition {
|
||||
return auto.Status.Conditions
|
||||
}
|
||||
|
||||
// SetConditions sets the status conditions on the object.
|
||||
func (auto *ImageUpdateAutomation) SetConditions(conditions []metav1.Condition) {
|
||||
auto.Status.Conditions = conditions
|
||||
}
|
||||
|
||||
//+kubebuilder:object:root=true
|
||||
|
||||
// ImageUpdateAutomationList contains a list of ImageUpdateAutomation
|
||||
type ImageUpdateAutomationList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []ImageUpdateAutomation `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&ImageUpdateAutomation{}, &ImageUpdateAutomationList{})
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
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 v1beta2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// CrossNamespaceSourceReference contains enough information to let you locate the
|
||||
// typed Kubernetes resource object at cluster level.
|
||||
type CrossNamespaceSourceReference struct {
|
||||
// API version of the referent.
|
||||
// +optional
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
|
||||
// Kind of the referent.
|
||||
// +kubebuilder:validation:Enum=GitRepository
|
||||
// +kubebuilder:default=GitRepository
|
||||
// +required
|
||||
Kind string `json:"kind"`
|
||||
|
||||
// Name of the referent.
|
||||
// +required
|
||||
Name string `json:"name"`
|
||||
|
||||
// Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference.
|
||||
// +optional
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
func (s *CrossNamespaceSourceReference) String() string {
|
||||
if s.Namespace != "" {
|
||||
return fmt.Sprintf("%s/%s/%s", s.Kind, s.Namespace, s.Name)
|
||||
}
|
||||
return fmt.Sprintf("%s/%s", s.Kind, s.Name)
|
||||
}
|
||||
|
||||
// ImageRef represents an image reference.
|
||||
type ImageRef struct {
|
||||
// Name is the bare image's name.
|
||||
// +required
|
||||
Name string `json:"name"`
|
||||
// Tag is the image's tag.
|
||||
// +required
|
||||
Tag string `json:"tag"`
|
||||
// Digest is the image's digest.
|
||||
// +optional
|
||||
Digest string `json:"digest,omitempty"`
|
||||
}
|
||||
|
||||
func (in *ImageRef) String() string {
|
||||
res := in.Name + ":" + in.Tag
|
||||
if in.Digest != "" {
|
||||
res += "@" + in.Digest
|
||||
}
|
||||
return res
|
||||
}
|
|
@ -0,0 +1,344 @@
|
|||
//go:build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CommitSpec) DeepCopyInto(out *CommitSpec) {
|
||||
*out = *in
|
||||
out.Author = in.Author
|
||||
if in.SigningKey != nil {
|
||||
in, out := &in.SigningKey, &out.SigningKey
|
||||
*out = new(SigningKey)
|
||||
**out = **in
|
||||
}
|
||||
if in.MessageTemplateValues != nil {
|
||||
in, out := &in.MessageTemplateValues, &out.MessageTemplateValues
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitSpec.
|
||||
func (in *CommitSpec) DeepCopy() *CommitSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CommitSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CommitUser) DeepCopyInto(out *CommitUser) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitUser.
|
||||
func (in *CommitUser) DeepCopy() *CommitUser {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CommitUser)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CrossNamespaceSourceReference) DeepCopyInto(out *CrossNamespaceSourceReference) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CrossNamespaceSourceReference.
|
||||
func (in *CrossNamespaceSourceReference) DeepCopy() *CrossNamespaceSourceReference {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CrossNamespaceSourceReference)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GitCheckoutSpec) DeepCopyInto(out *GitCheckoutSpec) {
|
||||
*out = *in
|
||||
out.Reference = in.Reference
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitCheckoutSpec.
|
||||
func (in *GitCheckoutSpec) DeepCopy() *GitCheckoutSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GitCheckoutSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GitSpec) DeepCopyInto(out *GitSpec) {
|
||||
*out = *in
|
||||
if in.Checkout != nil {
|
||||
in, out := &in.Checkout, &out.Checkout
|
||||
*out = new(GitCheckoutSpec)
|
||||
**out = **in
|
||||
}
|
||||
in.Commit.DeepCopyInto(&out.Commit)
|
||||
if in.Push != nil {
|
||||
in, out := &in.Push, &out.Push
|
||||
*out = new(PushSpec)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitSpec.
|
||||
func (in *GitSpec) DeepCopy() *GitSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GitSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImageRef) DeepCopyInto(out *ImageRef) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageRef.
|
||||
func (in *ImageRef) DeepCopy() *ImageRef {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImageRef)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImageUpdateAutomation) DeepCopyInto(out *ImageUpdateAutomation) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageUpdateAutomation.
|
||||
func (in *ImageUpdateAutomation) DeepCopy() *ImageUpdateAutomation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImageUpdateAutomation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ImageUpdateAutomation) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImageUpdateAutomationList) DeepCopyInto(out *ImageUpdateAutomationList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]ImageUpdateAutomation, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageUpdateAutomationList.
|
||||
func (in *ImageUpdateAutomationList) DeepCopy() *ImageUpdateAutomationList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImageUpdateAutomationList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ImageUpdateAutomationList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImageUpdateAutomationSpec) DeepCopyInto(out *ImageUpdateAutomationSpec) {
|
||||
*out = *in
|
||||
out.SourceRef = in.SourceRef
|
||||
if in.GitSpec != nil {
|
||||
in, out := &in.GitSpec, &out.GitSpec
|
||||
*out = new(GitSpec)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
out.Interval = in.Interval
|
||||
if in.PolicySelector != nil {
|
||||
in, out := &in.PolicySelector, &out.PolicySelector
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Update != nil {
|
||||
in, out := &in.Update, &out.Update
|
||||
*out = new(UpdateStrategy)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageUpdateAutomationSpec.
|
||||
func (in *ImageUpdateAutomationSpec) DeepCopy() *ImageUpdateAutomationSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImageUpdateAutomationSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ImageUpdateAutomationStatus) DeepCopyInto(out *ImageUpdateAutomationStatus) {
|
||||
*out = *in
|
||||
if in.LastAutomationRunTime != nil {
|
||||
in, out := &in.LastAutomationRunTime, &out.LastAutomationRunTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.LastPushTime != nil {
|
||||
in, out := &in.LastPushTime, &out.LastPushTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]v1.Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.ObservedPolicies != nil {
|
||||
in, out := &in.ObservedPolicies, &out.ObservedPolicies
|
||||
*out = make(ObservedPolicies, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
out.ReconcileRequestStatus = in.ReconcileRequestStatus
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageUpdateAutomationStatus.
|
||||
func (in *ImageUpdateAutomationStatus) DeepCopy() *ImageUpdateAutomationStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ImageUpdateAutomationStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in ObservedPolicies) DeepCopyInto(out *ObservedPolicies) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(ObservedPolicies, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObservedPolicies.
|
||||
func (in ObservedPolicies) DeepCopy() ObservedPolicies {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ObservedPolicies)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PushSpec) DeepCopyInto(out *PushSpec) {
|
||||
*out = *in
|
||||
if in.Options != nil {
|
||||
in, out := &in.Options, &out.Options
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PushSpec.
|
||||
func (in *PushSpec) DeepCopy() *PushSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PushSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SigningKey) DeepCopyInto(out *SigningKey) {
|
||||
*out = *in
|
||||
out.SecretRef = in.SecretRef
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SigningKey.
|
||||
func (in *SigningKey) DeepCopy() *SigningKey {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(SigningKey)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpdateStrategy) DeepCopyInto(out *UpdateStrategy) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateStrategy.
|
||||
func (in *UpdateStrategy) DeepCopy() *UpdateStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpdateStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
|
@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
|||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.12.0
|
||||
controller-gen.kubebuilder.io/version: v0.16.1
|
||||
name: imageupdateautomations.image.toolkit.fluxcd.io
|
||||
spec:
|
||||
group: image.toolkit.fluxcd.io
|
||||
|
@ -18,6 +18,8 @@ spec:
|
|||
- jsonPath: .status.lastAutomationRunTime
|
||||
name: Last run
|
||||
type: string
|
||||
deprecated: true
|
||||
deprecationWarning: v1beta1 ImageUpdateAutomation is deprecated, upgrade to v1beta2
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
|
@ -25,14 +27,19 @@ spec:
|
|||
API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
|
@ -40,36 +47,39 @@ spec:
|
|||
description: ImageUpdateAutomationSpec defines the desired state of ImageUpdateAutomation
|
||||
properties:
|
||||
git:
|
||||
description: GitSpec contains all the git-specific definitions. This
|
||||
is technically optional, but in practice mandatory until there are
|
||||
description: |-
|
||||
GitSpec contains all the git-specific definitions. This is
|
||||
technically optional, but in practice mandatory until there are
|
||||
other kinds of source allowed.
|
||||
properties:
|
||||
checkout:
|
||||
description: Checkout gives the parameters for cloning the git
|
||||
repository, ready to make changes. If not present, the `spec.ref`
|
||||
field from the referenced `GitRepository` or its default will
|
||||
be used.
|
||||
description: |-
|
||||
Checkout gives the parameters for cloning the git repository,
|
||||
ready to make changes. If not present, the `spec.ref` field from the
|
||||
referenced `GitRepository` or its default will be used.
|
||||
properties:
|
||||
ref:
|
||||
description: Reference gives a branch, tag or commit to clone
|
||||
from the Git repository.
|
||||
description: |-
|
||||
Reference gives a branch, tag or commit to clone from the Git
|
||||
repository.
|
||||
properties:
|
||||
branch:
|
||||
description: Branch to check out, defaults to 'master'
|
||||
if no other field is defined.
|
||||
type: string
|
||||
commit:
|
||||
description: "Commit SHA to check out, takes precedence
|
||||
over all reference fields. \n This can be combined with
|
||||
Branch to shallow clone the branch, in which the commit
|
||||
is expected to exist."
|
||||
description: |-
|
||||
Commit SHA to check out, takes precedence over all reference fields.
|
||||
|
||||
This can be combined with Branch to shallow clone the branch, in which
|
||||
the commit is expected to exist.
|
||||
type: string
|
||||
name:
|
||||
description: "Name of the reference to check out; takes
|
||||
precedence over Branch, Tag and SemVer. \n It must be
|
||||
a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description
|
||||
Examples: \"refs/heads/main\", \"refs/tags/v0.1.0\",
|
||||
\"refs/pull/420/head\", \"refs/merge-requests/1/head\""
|
||||
description: |-
|
||||
Name of the reference to check out; takes precedence over Branch, Tag and SemVer.
|
||||
|
||||
It must be a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description
|
||||
Examples: "refs/heads/main", "refs/tags/v0.1.0", "refs/pull/420/head", "refs/merge-requests/1/head"
|
||||
type: string
|
||||
semver:
|
||||
description: SemVer tag expression to check out, takes
|
||||
|
@ -86,8 +96,9 @@ spec:
|
|||
description: Commit specifies how to commit to the git repository.
|
||||
properties:
|
||||
author:
|
||||
description: Author gives the email and optionally the name
|
||||
to use as the author of commits.
|
||||
description: |-
|
||||
Author gives the email and optionally the name to use as the
|
||||
author of commits.
|
||||
properties:
|
||||
email:
|
||||
description: Email gives the email to provide when making
|
||||
|
@ -101,19 +112,20 @@ spec:
|
|||
- email
|
||||
type: object
|
||||
messageTemplate:
|
||||
description: MessageTemplate provides a template for the commit
|
||||
message, into which will be interpolated the details of
|
||||
the change made.
|
||||
description: |-
|
||||
MessageTemplate provides a template for the commit message,
|
||||
into which will be interpolated the details of the change made.
|
||||
type: string
|
||||
signingKey:
|
||||
description: SigningKey provides the option to sign commits
|
||||
with a GPG key
|
||||
properties:
|
||||
secretRef:
|
||||
description: SecretRef holds the name to a secret that
|
||||
contains a 'git.asc' key corresponding to the ASCII
|
||||
Armored file containing the GPG signing keypair as the
|
||||
value. It must be in the same namespace as the ImageUpdateAutomation.
|
||||
description: |-
|
||||
SecretRef holds the name to a secret that contains a 'git.asc' key
|
||||
corresponding to the ASCII Armored file containing the GPG signing
|
||||
keypair as the value. It must be in the same namespace as the
|
||||
ImageUpdateAutomation.
|
||||
properties:
|
||||
name:
|
||||
description: Name of the referent.
|
||||
|
@ -121,45 +133,53 @@ spec:
|
|||
required:
|
||||
- name
|
||||
type: object
|
||||
required:
|
||||
- secretRef
|
||||
type: object
|
||||
required:
|
||||
- author
|
||||
type: object
|
||||
push:
|
||||
description: Push specifies how and where to push commits made
|
||||
by the automation. If missing, commits are pushed (back) to
|
||||
description: |-
|
||||
Push specifies how and where to push commits made by the
|
||||
automation. If missing, commits are pushed (back) to
|
||||
`.spec.checkout.branch` or its default.
|
||||
properties:
|
||||
branch:
|
||||
description: Branch specifies that commits should be pushed
|
||||
to the branch named. The branch is created using `.spec.checkout.branch`
|
||||
as the starting point, if it doesn't already exist.
|
||||
description: |-
|
||||
Branch specifies that commits should be pushed to the branch
|
||||
named. The branch is created using `.spec.checkout.branch` as the
|
||||
starting point, if it doesn't already exist.
|
||||
type: string
|
||||
options:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: 'Options specifies the push options that are
|
||||
sent to the Git server when performing a push operation.
|
||||
For details, see: https://git-scm.com/docs/git-push#Documentation/git-push.txt---push-optionltoptiongt'
|
||||
description: |-
|
||||
Options specifies the push options that are sent to the Git
|
||||
server when performing a push operation. For details, see:
|
||||
https://git-scm.com/docs/git-push#Documentation/git-push.txt---push-optionltoptiongt
|
||||
type: object
|
||||
refspec:
|
||||
description: 'Refspec specifies the Git Refspec to use for
|
||||
a push operation. If both Branch and Refspec are provided,
|
||||
then the commit is pushed to the branch and also using the
|
||||
specified refspec. For more details about Git Refspecs,
|
||||
see: https://git-scm.com/book/en/v2/Git-Internals-The-Refspec'
|
||||
description: |-
|
||||
Refspec specifies the Git Refspec to use for a push operation.
|
||||
If both Branch and Refspec are provided, then the commit is pushed
|
||||
to the branch and also using the specified refspec.
|
||||
For more details about Git Refspecs, see:
|
||||
https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- commit
|
||||
type: object
|
||||
interval:
|
||||
description: Interval gives an lower bound for how often the automation
|
||||
description: |-
|
||||
Interval gives an lower bound for how often the automation
|
||||
run should be attempted.
|
||||
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
|
||||
type: string
|
||||
sourceRef:
|
||||
description: SourceRef refers to the resource giving access details
|
||||
description: |-
|
||||
SourceRef refers to the resource giving access details
|
||||
to a git repository.
|
||||
properties:
|
||||
apiVersion:
|
||||
|
@ -183,20 +203,23 @@ spec:
|
|||
- name
|
||||
type: object
|
||||
suspend:
|
||||
description: Suspend tells the controller to not run this automation,
|
||||
until it is unset (or set to false). Defaults to false.
|
||||
description: |-
|
||||
Suspend tells the controller to not run this automation, until
|
||||
it is unset (or set to false). Defaults to false.
|
||||
type: boolean
|
||||
update:
|
||||
default:
|
||||
strategy: Setters
|
||||
description: Update gives the specification for how to update the
|
||||
files in the repository. This can be left empty, to use the default
|
||||
description: |-
|
||||
Update gives the specification for how to update the files in
|
||||
the repository. This can be left empty, to use the default
|
||||
value.
|
||||
properties:
|
||||
path:
|
||||
description: Path to the directory containing the manifests to
|
||||
be updated. Defaults to 'None', which translates to the root
|
||||
path of the GitRepositoryRef.
|
||||
description: |-
|
||||
Path to the directory containing the manifests to be updated.
|
||||
Defaults to 'None', which translates to the root path
|
||||
of the GitRepositoryRef.
|
||||
type: string
|
||||
strategy:
|
||||
default: Setters
|
||||
|
@ -219,43 +242,35 @@ spec:
|
|||
properties:
|
||||
conditions:
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current
|
||||
state of this API Resource. --- This struct is intended for direct
|
||||
use as an array at the field path .status.conditions. For example,
|
||||
\n type FooStatus struct{ // Represents the observations of a
|
||||
foo's current state. // Known .status.conditions.type are: \"Available\",
|
||||
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
|
||||
// +listType=map // +listMapKey=type Conditions []metav1.Condition
|
||||
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
|
||||
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
||||
description: Condition contains details for one aspect of the current
|
||||
state of this API Resource.
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time the condition
|
||||
transitioned from one status to another. This should be when
|
||||
the underlying condition changed. If that is not known, then
|
||||
using the time when the API field changed is acceptable.
|
||||
description: |-
|
||||
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message indicating
|
||||
details about the transition. This may be an empty string.
|
||||
description: |-
|
||||
message is a human readable message indicating details about the transition.
|
||||
This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation
|
||||
that the condition was set based upon. For instance, if .metadata.generation
|
||||
is currently 12, but the .status.conditions[x].observedGeneration
|
||||
is 9, the condition is out of date with respect to the current
|
||||
state of the instance.
|
||||
description: |-
|
||||
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
with respect to the current state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier indicating
|
||||
the reason for the condition's last transition. Producers
|
||||
of specific condition types may define expected values and
|
||||
meanings for this field, and whether the values are considered
|
||||
a guaranteed API. The value should be a CamelCase string.
|
||||
description: |-
|
||||
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
Producers of specific condition types may define expected values and meanings for this field,
|
||||
and whether the values are considered a guaranteed API.
|
||||
The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
|
@ -270,10 +285,6 @@ spec:
|
|||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
--- Many .condition.type values are consistent across resources
|
||||
like Available, but because arbitrary conditions can be useful
|
||||
(see .node.status.conditions), the ability to deconflict is
|
||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
|
@ -286,19 +297,22 @@ spec:
|
|||
type: object
|
||||
type: array
|
||||
lastAutomationRunTime:
|
||||
description: LastAutomationRunTime records the last time the controller
|
||||
ran this automation through to completion (even if no updates were
|
||||
description: |-
|
||||
LastAutomationRunTime records the last time the controller ran
|
||||
this automation through to completion (even if no updates were
|
||||
made).
|
||||
format: date-time
|
||||
type: string
|
||||
lastHandledReconcileAt:
|
||||
description: LastHandledReconcileAt holds the value of the most recent
|
||||
reconcile request value, so a change of the annotation value can
|
||||
be detected.
|
||||
description: |-
|
||||
LastHandledReconcileAt holds the value of the most recent
|
||||
reconcile request value, so a change of the annotation value
|
||||
can be detected.
|
||||
type: string
|
||||
lastPushCommit:
|
||||
description: LastPushCommit records the SHA1 of the last commit made
|
||||
by the controller, for this automation object
|
||||
description: |-
|
||||
LastPushCommit records the SHA1 of the last commit made by the
|
||||
controller, for this automation object
|
||||
type: string
|
||||
lastPushTime:
|
||||
description: LastPushTime records the time of the last pushed change.
|
||||
|
@ -310,6 +324,399 @@ spec:
|
|||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: false
|
||||
subresources:
|
||||
status: {}
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .status.lastAutomationRunTime
|
||||
name: Last run
|
||||
type: string
|
||||
name: v1beta2
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: ImageUpdateAutomation is the Schema for the imageupdateautomations
|
||||
API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: ImageUpdateAutomationSpec defines the desired state of ImageUpdateAutomation
|
||||
properties:
|
||||
git:
|
||||
description: |-
|
||||
GitSpec contains all the git-specific definitions. This is
|
||||
technically optional, but in practice mandatory until there are
|
||||
other kinds of source allowed.
|
||||
properties:
|
||||
checkout:
|
||||
description: |-
|
||||
Checkout gives the parameters for cloning the git repository,
|
||||
ready to make changes. If not present, the `spec.ref` field from the
|
||||
referenced `GitRepository` or its default will be used.
|
||||
properties:
|
||||
ref:
|
||||
description: |-
|
||||
Reference gives a branch, tag or commit to clone from the Git
|
||||
repository.
|
||||
properties:
|
||||
branch:
|
||||
description: Branch to check out, defaults to 'master'
|
||||
if no other field is defined.
|
||||
type: string
|
||||
commit:
|
||||
description: |-
|
||||
Commit SHA to check out, takes precedence over all reference fields.
|
||||
|
||||
This can be combined with Branch to shallow clone the branch, in which
|
||||
the commit is expected to exist.
|
||||
type: string
|
||||
name:
|
||||
description: |-
|
||||
Name of the reference to check out; takes precedence over Branch, Tag and SemVer.
|
||||
|
||||
It must be a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description
|
||||
Examples: "refs/heads/main", "refs/tags/v0.1.0", "refs/pull/420/head", "refs/merge-requests/1/head"
|
||||
type: string
|
||||
semver:
|
||||
description: SemVer tag expression to check out, takes
|
||||
precedence over Tag.
|
||||
type: string
|
||||
tag:
|
||||
description: Tag to check out, takes precedence over Branch.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- ref
|
||||
type: object
|
||||
commit:
|
||||
description: Commit specifies how to commit to the git repository.
|
||||
properties:
|
||||
author:
|
||||
description: |-
|
||||
Author gives the email and optionally the name to use as the
|
||||
author of commits.
|
||||
properties:
|
||||
email:
|
||||
description: Email gives the email to provide when making
|
||||
a commit.
|
||||
type: string
|
||||
name:
|
||||
description: Name gives the name to provide when making
|
||||
a commit.
|
||||
type: string
|
||||
required:
|
||||
- email
|
||||
type: object
|
||||
messageTemplate:
|
||||
description: |-
|
||||
MessageTemplate provides a template for the commit message,
|
||||
into which will be interpolated the details of the change made.
|
||||
type: string
|
||||
messageTemplateValues:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: |-
|
||||
MessageTemplateValues provides additional values to be available to the
|
||||
templating rendering.
|
||||
type: object
|
||||
signingKey:
|
||||
description: SigningKey provides the option to sign commits
|
||||
with a GPG key
|
||||
properties:
|
||||
secretRef:
|
||||
description: |-
|
||||
SecretRef holds the name to a secret that contains a 'git.asc' key
|
||||
corresponding to the ASCII Armored file containing the GPG signing
|
||||
keypair as the value. It must be in the same namespace as the
|
||||
ImageUpdateAutomation.
|
||||
properties:
|
||||
name:
|
||||
description: Name of the referent.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
required:
|
||||
- secretRef
|
||||
type: object
|
||||
required:
|
||||
- author
|
||||
type: object
|
||||
push:
|
||||
description: |-
|
||||
Push specifies how and where to push commits made by the
|
||||
automation. If missing, commits are pushed (back) to
|
||||
`.spec.checkout.branch` or its default.
|
||||
properties:
|
||||
branch:
|
||||
description: |-
|
||||
Branch specifies that commits should be pushed to the branch
|
||||
named. The branch is created using `.spec.checkout.branch` as the
|
||||
starting point, if it doesn't already exist.
|
||||
type: string
|
||||
options:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: |-
|
||||
Options specifies the push options that are sent to the Git
|
||||
server when performing a push operation. For details, see:
|
||||
https://git-scm.com/docs/git-push#Documentation/git-push.txt---push-optionltoptiongt
|
||||
type: object
|
||||
refspec:
|
||||
description: |-
|
||||
Refspec specifies the Git Refspec to use for a push operation.
|
||||
If both Branch and Refspec are provided, then the commit is pushed
|
||||
to the branch and also using the specified refspec.
|
||||
For more details about Git Refspecs, see:
|
||||
https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- commit
|
||||
type: object
|
||||
interval:
|
||||
description: |-
|
||||
Interval gives an lower bound for how often the automation
|
||||
run should be attempted.
|
||||
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
|
||||
type: string
|
||||
policySelector:
|
||||
description: |-
|
||||
PolicySelector allows to filter applied policies based on labels.
|
||||
By default includes all policies in namespace.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label selector requirements.
|
||||
The requirements are ANDed.
|
||||
items:
|
||||
description: |-
|
||||
A label selector requirement is a selector that contains values, a key, and an operator that
|
||||
relates the key and values.
|
||||
properties:
|
||||
key:
|
||||
description: key is the label key that the selector applies
|
||||
to.
|
||||
type: string
|
||||
operator:
|
||||
description: |-
|
||||
operator represents a key's relationship to a set of values.
|
||||
Valid operators are In, NotIn, Exists and DoesNotExist.
|
||||
type: string
|
||||
values:
|
||||
description: |-
|
||||
values is an array of string values. If the operator is In or NotIn,
|
||||
the values array must be non-empty. If the operator is Exists or DoesNotExist,
|
||||
the values array must be empty. This array is replaced during a strategic
|
||||
merge patch.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
matchLabels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: |-
|
||||
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
|
||||
map is equivalent to an element of matchExpressions, whose key field is "key", the
|
||||
operator is "In", and the values array contains only "value". The requirements are ANDed.
|
||||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
sourceRef:
|
||||
description: |-
|
||||
SourceRef refers to the resource giving access details
|
||||
to a git repository.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: API version of the referent.
|
||||
type: string
|
||||
kind:
|
||||
default: GitRepository
|
||||
description: Kind of the referent.
|
||||
enum:
|
||||
- GitRepository
|
||||
type: string
|
||||
name:
|
||||
description: Name of the referent.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace of the referent, defaults to the namespace
|
||||
of the Kubernetes resource object that contains the reference.
|
||||
type: string
|
||||
required:
|
||||
- kind
|
||||
- name
|
||||
type: object
|
||||
suspend:
|
||||
description: |-
|
||||
Suspend tells the controller to not run this automation, until
|
||||
it is unset (or set to false). Defaults to false.
|
||||
type: boolean
|
||||
update:
|
||||
default:
|
||||
strategy: Setters
|
||||
description: |-
|
||||
Update gives the specification for how to update the files in
|
||||
the repository. This can be left empty, to use the default
|
||||
value.
|
||||
properties:
|
||||
path:
|
||||
description: |-
|
||||
Path to the directory containing the manifests to be updated.
|
||||
Defaults to 'None', which translates to the root path
|
||||
of the GitRepositoryRef.
|
||||
type: string
|
||||
strategy:
|
||||
default: Setters
|
||||
description: Strategy names the strategy to be used.
|
||||
enum:
|
||||
- Setters
|
||||
type: string
|
||||
required:
|
||||
- strategy
|
||||
type: object
|
||||
required:
|
||||
- interval
|
||||
- sourceRef
|
||||
type: object
|
||||
status:
|
||||
default:
|
||||
observedGeneration: -1
|
||||
description: ImageUpdateAutomationStatus defines the observed state of
|
||||
ImageUpdateAutomation
|
||||
properties:
|
||||
conditions:
|
||||
items:
|
||||
description: Condition contains details for one aspect of the current
|
||||
state of this API Resource.
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: |-
|
||||
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: |-
|
||||
message is a human readable message indicating details about the transition.
|
||||
This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: |-
|
||||
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||
with respect to the current state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: |-
|
||||
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||
Producers of specific condition types may define expected values and meanings for this field,
|
||||
and whether the values are considered a guaranteed API.
|
||||
The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastAutomationRunTime:
|
||||
description: |-
|
||||
LastAutomationRunTime records the last time the controller ran
|
||||
this automation through to completion (even if no updates were
|
||||
made).
|
||||
format: date-time
|
||||
type: string
|
||||
lastHandledReconcileAt:
|
||||
description: |-
|
||||
LastHandledReconcileAt holds the value of the most recent
|
||||
reconcile request value, so a change of the annotation value
|
||||
can be detected.
|
||||
type: string
|
||||
lastPushCommit:
|
||||
description: |-
|
||||
LastPushCommit records the SHA1 of the last commit made by the
|
||||
controller, for this automation object
|
||||
type: string
|
||||
lastPushTime:
|
||||
description: LastPushTime records the time of the last pushed change.
|
||||
format: date-time
|
||||
type: string
|
||||
observedGeneration:
|
||||
format: int64
|
||||
type: integer
|
||||
observedPolicies:
|
||||
additionalProperties:
|
||||
description: ImageRef represents an image reference.
|
||||
properties:
|
||||
digest:
|
||||
description: Digest is the image's digest.
|
||||
type: string
|
||||
name:
|
||||
description: Name is the bare image's name.
|
||||
type: string
|
||||
tag:
|
||||
description: Tag is the image's tag.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- tag
|
||||
type: object
|
||||
description: |-
|
||||
ObservedPolicies is the list of observed ImagePolicies that were
|
||||
considered by the ImageUpdateAutomation update process.
|
||||
type: object
|
||||
observedSourceRevision:
|
||||
description: |-
|
||||
ObservedPolicies []ObservedPolicy `json:"observedPolicies,omitempty"`
|
||||
ObservedSourceRevision is the last observed source revision. This can be
|
||||
used to determine if the source has been updated since last observation.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
|
|
|
@ -5,4 +5,4 @@ resources:
|
|||
images:
|
||||
- name: fluxcd/image-automation-controller
|
||||
newName: fluxcd/image-automation-controller
|
||||
newTag: v0.37.0
|
||||
newTag: v0.41.1
|
||||
|
|
|
@ -1,11 +1,38 @@
|
|||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: manager-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- events
|
||||
verbs:
|
||||
- create
|
||||
- patch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- image.toolkit.fluxcd.io
|
||||
resources:
|
||||
- imagepolicies
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- image.toolkit.fluxcd.io
|
||||
resources:
|
||||
- imagepolicies/status
|
||||
verbs:
|
||||
- get
|
||||
- apiGroups:
|
||||
- image.toolkit.fluxcd.io
|
||||
resources:
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
apiVersion: image.toolkit.fluxcd.io/v1beta2
|
||||
kind: ImageUpdateAutomation
|
||||
metadata:
|
||||
name: imageupdateautomation-sample
|
||||
spec:
|
||||
interval: 5m
|
||||
sourceRef:
|
||||
kind: GitRepository # the only valid value, but good practice to be explicit here
|
||||
name: sample-repo
|
||||
git:
|
||||
checkout:
|
||||
ref:
|
||||
branch: main
|
||||
commit:
|
||||
author:
|
||||
name: fluxbot
|
||||
email: fluxbot@example.com
|
||||
messageTemplate: |
|
||||
An automated update from FluxBot
|
||||
|
||||
[ci skip]
|
||||
signingKey:
|
||||
secretRef:
|
||||
name: git-pgp
|
||||
push:
|
||||
branch: auto
|
||||
update:
|
||||
strategy: Setters
|
||||
path: ./cluster/sample
|
|
@ -0,0 +1,907 @@
|
|||
<h1>Image update automation API reference v1beta2</h1>
|
||||
<p>Packages:</p>
|
||||
<ul class="simple">
|
||||
<li>
|
||||
<a href="#image.toolkit.fluxcd.io%2fv1beta2">image.toolkit.fluxcd.io/v1beta2</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="image.toolkit.fluxcd.io/v1beta2">image.toolkit.fluxcd.io/v1beta2</h2>
|
||||
<p>Package v1beta2 contains API types for the image API group, version
|
||||
v1beta2. The types here are concerned with automated updates to
|
||||
git, based on metadata from OCI image registries gathered by the
|
||||
image-reflector-controller.</p>
|
||||
Resource Types:
|
||||
<ul class="simple"></ul>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.CommitSpec">CommitSpec
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.GitSpec">GitSpec</a>)
|
||||
</p>
|
||||
<p>CommitSpec specifies how to commit changes to the git repository</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>author</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.CommitUser">
|
||||
CommitUser
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Author gives the email and optionally the name to use as the
|
||||
author of commits.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>signingKey</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.SigningKey">
|
||||
SigningKey
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>SigningKey provides the option to sign commits with a GPG key</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>messageTemplate</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>MessageTemplate provides a template for the commit message,
|
||||
into which will be interpolated the details of the change made.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>messageTemplateValues</code><br>
|
||||
<em>
|
||||
map[string]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>MessageTemplateValues provides additional values to be available to the
|
||||
templating rendering.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.CommitUser">CommitUser
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.CommitSpec">CommitSpec</a>)
|
||||
</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>name</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Name gives the name to provide when making a commit.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>email</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Email gives the email to provide when making a commit.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.CrossNamespaceSourceReference">CrossNamespaceSourceReference
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomationSpec">ImageUpdateAutomationSpec</a>)
|
||||
</p>
|
||||
<p>CrossNamespaceSourceReference contains enough information to let you locate the
|
||||
typed Kubernetes resource object at cluster level.</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>apiVersion</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>API version of the referent.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>kind</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Kind of the referent.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>name</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Name of the referent.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>namespace</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.GitCheckoutSpec">GitCheckoutSpec
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.GitSpec">GitSpec</a>)
|
||||
</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>ref</code><br>
|
||||
<em>
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/source-controller/api/v1#GitRepositoryRef">
|
||||
Source /v1.GitRepositoryRef
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Reference gives a branch, tag or commit to clone from the Git
|
||||
repository.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.GitSpec">GitSpec
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomationSpec">ImageUpdateAutomationSpec</a>)
|
||||
</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>checkout</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.GitCheckoutSpec">
|
||||
GitCheckoutSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Checkout gives the parameters for cloning the git repository,
|
||||
ready to make changes. If not present, the <code>spec.ref</code> field from the
|
||||
referenced <code>GitRepository</code> or its default will be used.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>commit</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.CommitSpec">
|
||||
CommitSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Commit specifies how to commit to the git repository.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>push</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.PushSpec">
|
||||
PushSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Push specifies how and where to push commits made by the
|
||||
automation. If missing, commits are pushed (back) to
|
||||
<code>.spec.checkout.branch</code> or its default.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.ImageRef">ImageRef
|
||||
</h3>
|
||||
<p>ImageRef represents an image reference.</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>name</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Name is the bare image’s name.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>tag</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Tag is the image’s tag.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>digest</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Digest is the image’s digest.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomation">ImageUpdateAutomation
|
||||
</h3>
|
||||
<p>ImageUpdateAutomation is the Schema for the imageupdateautomations API</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>metadata</code><br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta">
|
||||
Kubernetes meta/v1.ObjectMeta
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
Refer to the Kubernetes API documentation for the fields of the
|
||||
<code>metadata</code> field.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>spec</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomationSpec">
|
||||
ImageUpdateAutomationSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<br/>
|
||||
<br/>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<code>sourceRef</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.CrossNamespaceSourceReference">
|
||||
CrossNamespaceSourceReference
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>SourceRef refers to the resource giving access details
|
||||
to a git repository.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>git</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.GitSpec">
|
||||
GitSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>GitSpec contains all the git-specific definitions. This is
|
||||
technically optional, but in practice mandatory until there are
|
||||
other kinds of source allowed.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>interval</code><br>
|
||||
<em>
|
||||
<a href="https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
|
||||
Kubernetes meta/v1.Duration
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Interval gives an lower bound for how often the automation
|
||||
run should be attempted.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>policySelector</code><br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#labelselector-v1-meta">
|
||||
Kubernetes meta/v1.LabelSelector
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>PolicySelector allows to filter applied policies based on labels.
|
||||
By default includes all policies in namespace.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>update</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.UpdateStrategy">
|
||||
UpdateStrategy
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Update gives the specification for how to update the files in
|
||||
the repository. This can be left empty, to use the default
|
||||
value.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>suspend</code><br>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Suspend tells the controller to not run this automation, until
|
||||
it is unset (or set to false). Defaults to false.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>status</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomationStatus">
|
||||
ImageUpdateAutomationStatus
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomationSpec">ImageUpdateAutomationSpec
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomation">ImageUpdateAutomation</a>)
|
||||
</p>
|
||||
<p>ImageUpdateAutomationSpec defines the desired state of ImageUpdateAutomation</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>sourceRef</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.CrossNamespaceSourceReference">
|
||||
CrossNamespaceSourceReference
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>SourceRef refers to the resource giving access details
|
||||
to a git repository.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>git</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.GitSpec">
|
||||
GitSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>GitSpec contains all the git-specific definitions. This is
|
||||
technically optional, but in practice mandatory until there are
|
||||
other kinds of source allowed.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>interval</code><br>
|
||||
<em>
|
||||
<a href="https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
|
||||
Kubernetes meta/v1.Duration
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Interval gives an lower bound for how often the automation
|
||||
run should be attempted.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>policySelector</code><br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#labelselector-v1-meta">
|
||||
Kubernetes meta/v1.LabelSelector
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>PolicySelector allows to filter applied policies based on labels.
|
||||
By default includes all policies in namespace.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>update</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.UpdateStrategy">
|
||||
UpdateStrategy
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Update gives the specification for how to update the files in
|
||||
the repository. This can be left empty, to use the default
|
||||
value.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>suspend</code><br>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Suspend tells the controller to not run this automation, until
|
||||
it is unset (or set to false). Defaults to false.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomationStatus">ImageUpdateAutomationStatus
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomation">ImageUpdateAutomation</a>)
|
||||
</p>
|
||||
<p>ImageUpdateAutomationStatus defines the observed state of ImageUpdateAutomation</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>lastAutomationRunTime</code><br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#time-v1-meta">
|
||||
Kubernetes meta/v1.Time
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>LastAutomationRunTime records the last time the controller ran
|
||||
this automation through to completion (even if no updates were
|
||||
made).</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>lastPushCommit</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>LastPushCommit records the SHA1 of the last commit made by the
|
||||
controller, for this automation object</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>lastPushTime</code><br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#time-v1-meta">
|
||||
Kubernetes meta/v1.Time
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>LastPushTime records the time of the last pushed change.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>observedGeneration</code><br>
|
||||
<em>
|
||||
int64
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>conditions</code><br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#condition-v1-meta">
|
||||
[]Kubernetes meta/v1.Condition
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>observedPolicies</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.ObservedPolicies">
|
||||
ObservedPolicies
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>ObservedPolicies is the list of observed ImagePolicies that were
|
||||
considered by the ImageUpdateAutomation update process.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>observedSourceRevision</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>ObservedPolicies []ObservedPolicy <code>json:"observedPolicies,omitempty"</code>
|
||||
ObservedSourceRevision is the last observed source revision. This can be
|
||||
used to determine if the source has been updated since last observation.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>ReconcileRequestStatus</code><br>
|
||||
<em>
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#ReconcileRequestStatus">
|
||||
github.com/fluxcd/pkg/apis/meta.ReconcileRequestStatus
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
(Members of <code>ReconcileRequestStatus</code> are embedded into this type.)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.ObservedPolicies">ObservedPolicies
|
||||
(<code>map[string]./api/v1beta2.ImageRef</code> alias)</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomationStatus">ImageUpdateAutomationStatus</a>)
|
||||
</p>
|
||||
<p>ObservedPolicies is a map of policy name and ImageRef of their latest
|
||||
ImageRef.</p>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.PushSpec">PushSpec
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.GitSpec">GitSpec</a>)
|
||||
</p>
|
||||
<p>PushSpec specifies how and where to push commits.</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>branch</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Branch specifies that commits should be pushed to the branch
|
||||
named. The branch is created using <code>.spec.checkout.branch</code> as the
|
||||
starting point, if it doesn’t already exist.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>refspec</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Refspec specifies the Git Refspec to use for a push operation.
|
||||
If both Branch and Refspec are provided, then the commit is pushed
|
||||
to the branch and also using the specified refspec.
|
||||
For more details about Git Refspecs, see:
|
||||
<a href="https://git-scm.com/book/en/v2/Git-Internals-The-Refspec">https://git-scm.com/book/en/v2/Git-Internals-The-Refspec</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>options</code><br>
|
||||
<em>
|
||||
map[string]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Options specifies the push options that are sent to the Git
|
||||
server when performing a push operation. For details, see:
|
||||
<a href="https://git-scm.com/docs/git-push#Documentation/git-push.txt---push-optionltoptiongt">https://git-scm.com/docs/git-push#Documentation/git-push.txt—push-optionltoptiongt</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.SigningKey">SigningKey
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.CommitSpec">CommitSpec</a>)
|
||||
</p>
|
||||
<p>SigningKey references a Kubernetes secret that contains a GPG keypair</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>secretRef</code><br>
|
||||
<em>
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
|
||||
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>SecretRef holds the name to a secret that contains a ‘git.asc’ key
|
||||
corresponding to the ASCII Armored file containing the GPG signing
|
||||
keypair as the value. It must be in the same namespace as the
|
||||
ImageUpdateAutomation.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.UpdateStrategy">UpdateStrategy
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.ImageUpdateAutomationSpec">ImageUpdateAutomationSpec</a>)
|
||||
</p>
|
||||
<p>UpdateStrategy is a union of the various strategies for updating
|
||||
the Git repository. Parameters for each strategy (if any) can be
|
||||
inlined here.</p>
|
||||
<div class="md-typeset__scrollwrap">
|
||||
<div class="md-typeset__table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>strategy</code><br>
|
||||
<em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.UpdateStrategyName">
|
||||
UpdateStrategyName
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Strategy names the strategy to be used.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>path</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Path to the directory containing the manifests to be updated.
|
||||
Defaults to ‘None’, which translates to the root path
|
||||
of the GitRepositoryRef.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h3 id="image.toolkit.fluxcd.io/v1beta2.UpdateStrategyName">UpdateStrategyName
|
||||
(<code>string</code> alias)</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#image.toolkit.fluxcd.io/v1beta2.UpdateStrategy">UpdateStrategy</a>)
|
||||
</p>
|
||||
<p>UpdateStrategyName is the type for names that go in
|
||||
.update.strategy. NB the value in the const immediately below.</p>
|
||||
<div class="admonition note">
|
||||
<p class="last">This page was automatically generated with <code>gen-crd-api-reference-docs</code></p>
|
||||
</div>
|
File diff suppressed because it is too large
Load Diff
232
go.mod
232
go.mod
|
@ -1,154 +1,180 @@
|
|||
module github.com/fluxcd/image-automation-controller
|
||||
|
||||
go 1.20
|
||||
go 1.24.0
|
||||
|
||||
replace github.com/fluxcd/image-automation-controller/api => ./api
|
||||
|
||||
// Pin kustomize to v5.3.0
|
||||
// Pin kustomize to v5.6.0
|
||||
replace (
|
||||
sigs.k8s.io/kustomize/api => sigs.k8s.io/kustomize/api v0.16.0
|
||||
sigs.k8s.io/kustomize/kyaml => sigs.k8s.io/kustomize/kyaml v0.16.0
|
||||
sigs.k8s.io/kustomize/api => sigs.k8s.io/kustomize/api v0.19.0
|
||||
sigs.k8s.io/kustomize/kyaml => sigs.k8s.io/kustomize/kyaml v0.19.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20231012073058-a7379d079e0e
|
||||
github.com/cyphar/filepath-securejoin v0.2.4
|
||||
github.com/fluxcd/image-automation-controller/api v0.37.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.31.1
|
||||
github.com/fluxcd/pkg/apis/acl v0.1.0
|
||||
github.com/fluxcd/pkg/apis/event v0.6.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.2.0
|
||||
github.com/fluxcd/pkg/git v0.16.0
|
||||
github.com/fluxcd/pkg/git/gogit v0.16.1
|
||||
github.com/fluxcd/pkg/gittestserver v0.9.0
|
||||
github.com/fluxcd/pkg/runtime v0.43.2
|
||||
github.com/fluxcd/pkg/ssh v0.10.0
|
||||
github.com/fluxcd/source-controller/api v1.2.2
|
||||
github.com/go-git/go-billy/v5 v5.5.0
|
||||
github.com/go-git/go-git/v5 v5.11.0
|
||||
github.com/go-logr/logr v1.3.0
|
||||
github.com/google/go-containerregistry v0.17.0
|
||||
github.com/onsi/gomega v1.30.0
|
||||
github.com/otiai10/copy v1.14.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
k8s.io/api v0.28.4
|
||||
k8s.io/apimachinery v0.28.4
|
||||
k8s.io/client-go v0.28.4
|
||||
k8s.io/kube-openapi v0.0.0-20231206194836-bf4651e18aa8
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661
|
||||
sigs.k8s.io/controller-runtime v0.16.3
|
||||
sigs.k8s.io/kustomize/kyaml v0.16.0
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6
|
||||
github.com/Masterminds/sprig/v3 v3.3.0
|
||||
github.com/ProtonMail/go-crypto v1.2.0
|
||||
github.com/cyphar/filepath-securejoin v0.4.1
|
||||
github.com/fluxcd/image-automation-controller/api v0.41.1
|
||||
github.com/fluxcd/image-reflector-controller/api v0.35.2
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0
|
||||
github.com/fluxcd/pkg/apis/event v0.17.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0
|
||||
github.com/fluxcd/pkg/auth v0.17.0
|
||||
github.com/fluxcd/pkg/cache v0.9.0
|
||||
github.com/fluxcd/pkg/git v0.32.0
|
||||
github.com/fluxcd/pkg/git/gogit v0.35.0
|
||||
github.com/fluxcd/pkg/gittestserver v0.17.0
|
||||
github.com/fluxcd/pkg/runtime v0.60.0
|
||||
github.com/fluxcd/pkg/ssh v0.19.0
|
||||
github.com/fluxcd/source-controller/api v1.6.1
|
||||
github.com/go-git/go-billy/v5 v5.6.2
|
||||
github.com/go-git/go-git/v5 v5.16.2
|
||||
github.com/go-logr/logr v1.4.2
|
||||
github.com/google/go-containerregistry v0.20.3
|
||||
github.com/onsi/gomega v1.37.0
|
||||
github.com/otiai10/copy v1.14.1
|
||||
github.com/spf13/pflag v1.0.6
|
||||
k8s.io/api v0.33.0
|
||||
k8s.io/apimachinery v0.33.0
|
||||
k8s.io/client-go v0.33.0
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e
|
||||
sigs.k8s.io/controller-runtime v0.21.0
|
||||
sigs.k8s.io/kustomize/kyaml v0.19.0
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.43.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect
|
||||
github.com/aws/smithy-go v1.22.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/cloudflare/circl v1.3.6 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.15.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.3 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v27.5.0+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.2 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 // 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.7.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/fluxcd/cli-utils v0.36.0-flux.2 // indirect
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.13 // indirect
|
||||
github.com/fluxcd/gitkit v0.6.0 // indirect
|
||||
github.com/fluxcd/pkg/version v0.2.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/fluxcd/pkg/version v0.7.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
||||
github.com/go-errors/errors v1.5.1 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-logr/zapr v1.3.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/gnostic-models v0.6.9 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-github/v71 v71.0.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.3.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||
github.com/huandu/xstrings v1.3.3 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||
github.com/huandu/xstrings v1.5.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/moby/spdystream v0.5.0 // indirect
|
||||
github.com/moby/term v0.5.2 // 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/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/otiai10/mint v1.6.3 // 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.17.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/prometheus/client_golang v1.22.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.63.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/skeema/knownhosts v1.2.1 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.8.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/spf13/cast v1.8.0 // indirect
|
||||
github.com/spf13/cobra v1.9.1 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.starlark.net v0.0.0-20231121155337-90ade8b19d09 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/crypto v0.16.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/oauth2 v0.15.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/term v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.16.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/evanphx/json-patch.v5 v5.7.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.39.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/oauth2 v0.29.0 // indirect
|
||||
golang.org/x/sync v0.15.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // 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/apiextensions-apiserver v0.28.4 // indirect
|
||||
k8s.io/cli-runtime v0.28.4 // indirect
|
||||
k8s.io/component-base v0.28.4 // indirect
|
||||
k8s.io/klog/v2 v2.110.1 // indirect
|
||||
k8s.io/kubectl v0.28.4 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kustomize/api v0.16.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.33.0 // indirect
|
||||
k8s.io/cli-runtime v0.33.0 // indirect
|
||||
k8s.io/component-base v0.33.0 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kubectl v0.33.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.19.0 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
|
577
go.sum
577
go.sum
|
@ -1,152 +1,220 @@
|
|||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
|
||||
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20231012073058-a7379d079e0e h1:NfjGPY2A8SSRJvXny111ZPoB57LT5lWgX4XiUjW10eY=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20231012073058-a7379d079e0e/go.mod h1:K4vciqCJaZ1Ghw/SvtJbEAM4soEtwDCNVqkdQIIujwU=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/ProtonMail/go-crypto v1.2.0 h1:+PhXXn4SPGd+qk76TlEePBfOfivE0zkWFenhGhFLzWs=
|
||||
github.com/ProtonMail/go-crypto v1.2.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.43.3 h1:YyH8Hk73bYzdbvf6S8NF5z/fb/1stpiMnFSfL6jSfRA=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.43.3/go.mod h1:iQ1skgw1XRK+6Lgkb0I9ODatAP72WoTILh0zXQ5DtbU=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.0 h1:wA2O6pZ2r5smqJunFP4hp7qptMW4EQxs8O6RVHPulOE=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.33.0/go.mod h1:RZL7ov7c72wSmoM8bIiVxRHgcVdzhNkVW2J36C8RF4s=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4=
|
||||
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
||||
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
|
||||
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
|
||||
github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.15.0 h1:7r2rPUM04rgszMP0U1UZ1M5VoVVIlsaBSnpABfYxcQY=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.15.0/go.mod h1:PoH9Vhy82OeRFZfxsVrk3mfQhVkEzou9OOwPOsEhiXE=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chai2010/gettext-go v1.0.3 h1:9liNh8t+u26xl5ddmWLmsOsdNLwkdRTg5AG+JnTiM80=
|
||||
github.com/chai2010/gettext-go v1.0.3/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
|
||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
|
||||
github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 h1:m62nsMU279qRD9PQSWD1l66kmkXzuYcnVJqL4XLeV2M=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM=
|
||||
github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
||||
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
||||
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc=
|
||||
github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
|
||||
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.2 h1:7nlXfAJ7iaDF34IdbyId+wBf7beL2qvzDBLmVBJSDVo=
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.2/go.mod h1:TQtgRf9OjQBzE5FJ9UDV6WNz9Po3pzAtk3NQmQEN5l8=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.13 h1:2X5yjz/rk9mg7+bMFBDZKGKzeZpAmY2s6iwbNZz7OzM=
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.13/go.mod h1:b2iSoIeDTtjfCB0IKtGgqlhhvWa1oux3e90CjOf81oA=
|
||||
github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg=
|
||||
github.com/fluxcd/gitkit v0.6.0/go.mod h1:svOHuKi0fO9HoawdK4HfHAJJseZDHHjk7I3ihnCIqNo=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.31.1 h1:nc44G0JjLgSvqglJSiXQJZcrRw+eY01j7fHRUDB3FMw=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.31.1/go.mod h1:KopMbC92Cw2ypZZeMytzTLr3EfOj2hoL6MizrdpBDhc=
|
||||
github.com/fluxcd/pkg/apis/acl v0.1.0 h1:EoAl377hDQYL3WqanWCdifauXqXbMyFuK82NnX6pH4Q=
|
||||
github.com/fluxcd/pkg/apis/acl v0.1.0/go.mod h1:zfEZzz169Oap034EsDhmCAGgnWlcWmIObZjYMusoXS8=
|
||||
github.com/fluxcd/pkg/apis/event v0.6.0 h1:AUaeee1CGWb65BLqVximHXG8Gcu6vWuYONIq6tVpjgo=
|
||||
github.com/fluxcd/pkg/apis/event v0.6.0/go.mod h1:OEzWcX/oPbMmkCvC9QGoK27JXFvUZgBhLD+zgxZe47A=
|
||||
github.com/fluxcd/pkg/apis/meta v1.2.0 h1:O766PzGAdMdQKybSflGL8oV0+GgCNIkdsxfalRyzeO8=
|
||||
github.com/fluxcd/pkg/apis/meta v1.2.0/go.mod h1:fU/Az9AoVyIxC0oI4ihG0NVMNnvrcCzdEym3wxjIQsc=
|
||||
github.com/fluxcd/pkg/git v0.16.0 h1:xgfMpgsVaxGLechKNaSUif9jnt2Ji/HkwIwxXeDoADk=
|
||||
github.com/fluxcd/pkg/git v0.16.0/go.mod h1:ZsaxXDBHIUjNeRf+3qDGyHD22KpqbjuNPCbHy2Xid5U=
|
||||
github.com/fluxcd/pkg/git/gogit v0.16.1 h1:byimVk7VLbERRxJDkVktithN03GC0y7fyc8Ur9Uka8U=
|
||||
github.com/fluxcd/pkg/git/gogit v0.16.1/go.mod h1:nx3PumOFe5e3fMsh2HPLSlAeOk2wC+jVg7H9BTRKEmg=
|
||||
github.com/fluxcd/pkg/gittestserver v0.9.0 h1:OthMahtKmmpwCRw8LmSGrceqVhHywGg/QiytxHGSgeY=
|
||||
github.com/fluxcd/pkg/gittestserver v0.9.0/go.mod h1:yZFnYMriw96f/F6PzIMOIgZw6ko+HzZuD5x/qTt/QP4=
|
||||
github.com/fluxcd/pkg/runtime v0.43.2 h1:xH2BvttUqJ7wS0zjuBETr2pLXG62QY6f0mdxg5UQKio=
|
||||
github.com/fluxcd/pkg/runtime v0.43.2/go.mod h1:dhhNV45B3tekg7qPzATFTuWOulvUzMoO1bV+vc2pSts=
|
||||
github.com/fluxcd/pkg/ssh v0.10.0 h1:JFz0u/CPEf3hXvmrEvUvXsc70eKh8xphqjXxZuSby9g=
|
||||
github.com/fluxcd/pkg/ssh v0.10.0/go.mod h1:1lFTj3MhU9xQuaJ5PJJoh/FyRYzK54ll9NY/s2KqOZM=
|
||||
github.com/fluxcd/pkg/version v0.2.2 h1:ZpVXECeLA5hIQMft11iLp6gN3cKcz6UNuVTQPw/bRdI=
|
||||
github.com/fluxcd/pkg/version v0.2.2/go.mod h1:NGnh/no8S6PyfCDxRFrPY3T5BUnqP48MxfxNRU0z8C0=
|
||||
github.com/fluxcd/source-controller/api v1.2.2 h1:OUivb1UHDmY8+hlxjRx3k8i1w3jMSytdOYRMfmeeZhY=
|
||||
github.com/fluxcd/source-controller/api v1.2.2/go.mod h1:5gaIVVH7hgb8p3HKFp8P6hGmZEC8fKSt4EcrG3g5vZI=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.35.2 h1:EzjtUpyx8kbTFx7ugdi5LRMaCpQW4kX/vjFCIPpPD38=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.35.2/go.mod h1:mjpokoQhFs2RxfFjY4rHpn3ZAUvee8TiELyROFN4wiA=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5ooOE0=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ=
|
||||
github.com/fluxcd/pkg/apis/event v0.17.0 h1:foEINE++pCJlWVhWjYDXfkVmGKu8mQ4BDBlbYi5NU7M=
|
||||
github.com/fluxcd/pkg/apis/event v0.17.0/go.mod h1:0fLhLFiHlRTDKPDXdRnv+tS7mCMIQ0fJxnEfmvGM/5A=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
|
||||
github.com/fluxcd/pkg/auth v0.17.0 h1:jgum55f5K7Db6yI2bi4WeKojTzQS9KxlHCC0CsFs5x8=
|
||||
github.com/fluxcd/pkg/auth v0.17.0/go.mod h1:4h6s8VBNuec3tWd4xIReLw8BYPOKaIegjNMEbA4ikTU=
|
||||
github.com/fluxcd/pkg/cache v0.9.0 h1:EGKfOLMG3fOwWnH/4Axl5xd425mxoQbZzlZoLfd8PDk=
|
||||
github.com/fluxcd/pkg/cache v0.9.0/go.mod h1:jMwabjWfsC5lW8hE7NM3wtGNwSJ38Javx6EKbEi7INU=
|
||||
github.com/fluxcd/pkg/git v0.32.0 h1:agSE4Ia8saj5eg075qhLhZvjuTg/Hnj8mZU0meGKOyc=
|
||||
github.com/fluxcd/pkg/git v0.32.0/go.mod h1:rUgLXVQGBkBggHOLVMhHMHaweQ8Oc6HwZiN2Zm08Zxs=
|
||||
github.com/fluxcd/pkg/git/gogit v0.35.0 h1:uMFFwhg3X4H2GaJtXBG/sEv5yrIUk7gIdIpayTLXdC0=
|
||||
github.com/fluxcd/pkg/git/gogit v0.35.0/go.mod h1:/WcAqTDBrjF+6cwFTaK7kNM791j/pXmw0fy8xbd1YWo=
|
||||
github.com/fluxcd/pkg/gittestserver v0.17.0 h1:JlBvWZQTDOI+np5Z+084m3DkeAH1hMusEybyRUDF63k=
|
||||
github.com/fluxcd/pkg/gittestserver v0.17.0/go.mod h1:E/40EmLoXcMqd6gLuLDC9F6KJxqHVGbBBeMNKk5XdxU=
|
||||
github.com/fluxcd/pkg/runtime v0.60.0 h1:d++EkV3FlycB+bzakB5NumwY4J8xts8i7lbvD6jBLeU=
|
||||
github.com/fluxcd/pkg/runtime v0.60.0/go.mod h1:UeU0/eZLErYC/1bTmgzBfNXhiHy9fuQzjfLK0HxRgxY=
|
||||
github.com/fluxcd/pkg/ssh v0.19.0 h1:njSwNJQZ+3TGhBXshU/2TbqvooMbf6lQzFn7w6vuaKI=
|
||||
github.com/fluxcd/pkg/ssh v0.19.0/go.mod h1:0e7sqpyekj65A4y/UUCVUxxVw8HonwFtJJ2KhvJQq1o=
|
||||
github.com/fluxcd/pkg/version v0.7.0 h1:jZT5I6WFy1KlM40nHCSqlHmjC1VT1/DfmbAdOkIVVJc=
|
||||
github.com/fluxcd/pkg/version v0.7.0/go.mod h1:3BjQDJXIZJmeJLXnfa2yG/sNAT1t5oeLAPfnSjOHNuA=
|
||||
github.com/fluxcd/source-controller/api v1.6.1 h1:ZPTA9lNzBYHmwHfFX978qb8xVkdnQZHF1ggo6BoFm4w=
|
||||
github.com/fluxcd/source-controller/api v1.6.1/go.mod h1:ZJcAi0nemsnBxjVgmJl0WQzNvB0rMETxQMTdoFosmMw=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
|
||||
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
|
||||
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM=
|
||||
github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
|
||||
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
|
||||
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
|
||||
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.17.0 h1:5p+zYs/R4VGHkhyvgWurWrpJ2hW4Vv9fQI+GzdcwXLk=
|
||||
github.com/google/go-containerregistry v0.17.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI=
|
||||
github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI=
|
||||
github.com/google/go-github/v71 v71.0.0 h1:Zi16OymGKZZMm8ZliffVVJ/Q9YZreDKONCr+WUd0Z30=
|
||||
github.com/google/go-github/v71 v71.0.0/go.mod h1:URZXObp2BLlMjwu0O8g4y6VBneUj2bCHgnI8FfgZ51M=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo=
|
||||
github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
|
||||
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
|
||||
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
|
||||
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
|
@ -157,41 +225,41 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
|||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
|
||||
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
|
||||
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
|
||||
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
@ -201,225 +269,192 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/
|
|||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
|
||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
|
||||
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
|
||||
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
||||
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
||||
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
||||
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
|
||||
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
||||
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
|
||||
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||
github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk=
|
||||
github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
||||
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.starlark.net v0.0.0-20231121155337-90ade8b19d09 h1:hzy3LFnSN8kuQK8h9tHl4ndF6UruMj47OqwqsS+/Ai4=
|
||||
go.starlark.net v0.0.0-20231121155337-90ade8b19d09/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM=
|
||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
|
||||
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
|
||||
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/evanphx/json-patch.v5 v5.7.0 h1:dGKGylPlZ/jus2g1YqhhyzfH0gPy2R8/MYUpW/OslTY=
|
||||
gopkg.in/evanphx/json-patch.v5 v5.7.0/go.mod h1:/kvTRh1TVm5wuM6OkHxqXtE/1nUZZpihg29RtuIyfvk=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY=
|
||||
k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0=
|
||||
k8s.io/apiextensions-apiserver v0.28.4 h1:AZpKY/7wQ8n+ZYDtNHbAJBb+N4AXXJvyZx6ww6yAJvU=
|
||||
k8s.io/apiextensions-apiserver v0.28.4/go.mod h1:pgQIZ1U8eJSMQcENew/0ShUTlePcSGFq6dxSxf2mwPM=
|
||||
k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8=
|
||||
k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg=
|
||||
k8s.io/cli-runtime v0.28.4 h1:IW3aqSNFXiGDllJF4KVYM90YX4cXPGxuCxCVqCD8X+Q=
|
||||
k8s.io/cli-runtime v0.28.4/go.mod h1:MLGRB7LWTIYyYR3d/DOgtUC8ihsAPA3P8K8FDNIqJ0k=
|
||||
k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY=
|
||||
k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4=
|
||||
k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo=
|
||||
k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU=
|
||||
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
|
||||
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
|
||||
k8s.io/kube-openapi v0.0.0-20231206194836-bf4651e18aa8 h1:vzKzxN5uyJZLY8HL1/OovW7BJefnsBIWt8T7Gjh2boQ=
|
||||
k8s.io/kube-openapi v0.0.0-20231206194836-bf4651e18aa8/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
|
||||
k8s.io/kubectl v0.28.4 h1:gWpUXW/T7aFne+rchYeHkyB8eVDl5UZce8G4X//kjUQ=
|
||||
k8s.io/kubectl v0.28.4/go.mod h1:CKOccVx3l+3MmDbkXtIUtibq93nN2hkDR99XDCn7c/c=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6RxQGZDnzuLcrUTI=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4=
|
||||
sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/kustomize/api v0.16.0 h1:/zAR4FOQDCkgSDmVzV2uiFbuy9bhu3jEzthrHCuvm1g=
|
||||
sigs.k8s.io/kustomize/api v0.16.0/go.mod h1:MnFZ7IP2YqVyVwMWoRxPtgl/5hpA+eCCrQR/866cm5c=
|
||||
sigs.k8s.io/kustomize/kyaml v0.16.0 h1:6J33uKSoATlKZH16unr2XOhDI+otoe2sR3M8PDzW3K0=
|
||||
sigs.k8s.io/kustomize/kyaml v0.16.0/go.mod h1:xOK/7i+vmE14N2FdFyugIshB8eF6ALpy7jI87Q2nRh4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
|
||||
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
|
||||
k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs=
|
||||
k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc=
|
||||
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
|
||||
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/cli-runtime v0.33.0 h1:Lbl/pq/1o8BaIuyn+aVLdEPHVN665tBAXUePs8wjX7c=
|
||||
k8s.io/cli-runtime v0.33.0/go.mod h1:QcA+r43HeUM9jXFJx7A+yiTPfCooau/iCcP1wQh4NFw=
|
||||
k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=
|
||||
k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=
|
||||
k8s.io/component-base v0.33.0 h1:Ot4PyJI+0JAD9covDhwLp9UNkUja209OzsJ4FzScBNk=
|
||||
k8s.io/component-base v0.33.0/go.mod h1:aXYZLbw3kihdkOPMDhWbjGCO6sg+luw554KP51t8qCU=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
|
||||
k8s.io/kubectl v0.33.0 h1:HiRb1yqibBSCqic4pRZP+viiOBAnIdwYDpzUFejs07g=
|
||||
k8s.io/kubectl v0.33.0/go.mod h1:gAlGBuS1Jq1fYZ9AjGWbI/5Vk3M/VW2DK4g10Fpyn/0=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
|
||||
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/kustomize/api v0.19.0 h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ=
|
||||
sigs.k8s.io/kustomize/api v0.19.0/go.mod h1:/BbwnivGVcBh1r+8m3tH1VNxJmHSk1PzP5fkP6lbL1o=
|
||||
sigs.k8s.io/kustomize/kyaml v0.19.0 h1:RFge5qsO1uHhwJsu3ipV7RNolC7Uozc0jUBC/61XSlA=
|
||||
sigs.k8s.io/kustomize/kyaml v0.19.0/go.mod h1:FeKD5jEOH+FbZPpqUghBP8mrLjJ3+zD3/rf9NNu1cwY=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2020 The Flux authors
|
||||
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.
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright 2025 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 constants
|
||||
|
||||
const (
|
||||
// SetterShortHand is a shorthand that can be used to mark
|
||||
// setters; instead of
|
||||
// # { "$ref": "#/definitions/
|
||||
SetterShortHand = "$imagepolicy"
|
||||
)
|
|
@ -57,7 +57,7 @@ import (
|
|||
"github.com/fluxcd/pkg/runtime/testenv"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
|
||||
image_automationv1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
image_automationv1 "github.com/fluxcd/image-automation-controller/api/v1beta2"
|
||||
"github.com/fluxcd/image-automation-controller/pkg/update"
|
||||
)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
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 controller
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
// latestImageChangePredicate implements a predicate for latest image change.
|
||||
// This can be used to filter events from ImagePolicies for change in the latest
|
||||
// image.
|
||||
type latestImageChangePredicate struct {
|
||||
predicate.Funcs
|
||||
}
|
||||
|
||||
func (latestImageChangePredicate) Create(e event.CreateEvent) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (latestImageChangePredicate) Delete(e event.DeleteEvent) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (latestImageChangePredicate) Update(e event.UpdateEvent) bool {
|
||||
if e.ObjectOld == nil || e.ObjectNew == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
oldSource, ok := e.ObjectOld.(*imagev1_reflect.ImagePolicy)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
newSource, ok := e.ObjectNew.(*imagev1_reflect.ImagePolicy)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if newSource.Status.LatestRef == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if oldSource.Status.LatestRef == nil || *oldSource.Status.LatestRef != *newSource.Status.LatestRef {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// sourceConfigChangePredicate implements a predicate for source configuration
|
||||
// change. This can be used to filter events from source objects for change in
|
||||
// source configuration.
|
||||
type sourceConfigChangePredicate struct {
|
||||
predicate.Funcs
|
||||
}
|
||||
|
||||
func (sourceConfigChangePredicate) Create(e event.CreateEvent) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (sourceConfigChangePredicate) Delete(e event.DeleteEvent) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (sourceConfigChangePredicate) Update(e event.UpdateEvent) bool {
|
||||
if e.ObjectOld == nil || e.ObjectNew == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return e.ObjectOld.GetGeneration() != e.ObjectNew.GetGeneration()
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
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 controller
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
func Test_latestImageChangePredicate_Update(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
beforeFunc func(oldObj, newObj *imagev1_reflect.ImagePolicy)
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "no latest image",
|
||||
beforeFunc: func(oldObj, newObj *imagev1_reflect.ImagePolicy) {
|
||||
oldObj.Status.LatestRef = nil
|
||||
newObj.Status.LatestRef = nil
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new image, no old image",
|
||||
beforeFunc: func(oldObj, newObj *imagev1_reflect.ImagePolicy) {
|
||||
oldObj.Status.LatestRef = nil
|
||||
newObj.Status.LatestRef = &imagev1_reflect.ImageRef{Name: "foo"}
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "different old and new image",
|
||||
beforeFunc: func(oldObj, newObj *imagev1_reflect.ImagePolicy) {
|
||||
oldObj.Status.LatestRef = &imagev1_reflect.ImageRef{Name: "bar"}
|
||||
newObj.Status.LatestRef = &imagev1_reflect.ImageRef{Name: "foo"}
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
oldObj := &imagev1_reflect.ImagePolicy{}
|
||||
newObj := oldObj.DeepCopy()
|
||||
if tt.beforeFunc != nil {
|
||||
tt.beforeFunc(oldObj, newObj)
|
||||
}
|
||||
e := event.UpdateEvent{
|
||||
ObjectOld: oldObj,
|
||||
ObjectNew: newObj,
|
||||
}
|
||||
p := latestImageChangePredicate{}
|
||||
g.Expect(p.Update(e)).To(Equal(tt.want))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_sourceConfigChangePredicate_Update(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
beforeFunc func(oldObj, newObj *sourcev1.GitRepository)
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "no generation change, same config",
|
||||
beforeFunc: func(oldObj, newObj *sourcev1.GitRepository) {
|
||||
oldObj.Generation = 0
|
||||
newObj.Generation = 0
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new generation, config change",
|
||||
beforeFunc: func(oldObj, newObj *sourcev1.GitRepository) {
|
||||
oldObj.Generation = 1
|
||||
newObj.Generation = 2
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
oldObj := &sourcev1.GitRepository{}
|
||||
newObj := oldObj.DeepCopy()
|
||||
if tt.beforeFunc != nil {
|
||||
tt.beforeFunc(oldObj, newObj)
|
||||
}
|
||||
e := event.UpdateEvent{
|
||||
ObjectOld: oldObj,
|
||||
ObjectNew: newObj,
|
||||
}
|
||||
p := sourceConfigChangePredicate{}
|
||||
g.Expect(p.Update(e)).To(Equal(tt.want))
|
||||
})
|
||||
}
|
||||
|
||||
}
|
|
@ -26,6 +26,7 @@ import (
|
|||
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/tools/record"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
|
@ -34,7 +35,7 @@ import (
|
|||
"github.com/fluxcd/pkg/runtime/testenv"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta2"
|
||||
// +kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
|
@ -85,9 +86,10 @@ func runTestsWithFeatures(m *testing.M, feats map[string]bool) int {
|
|||
|
||||
controllerName := "image-automation-controller"
|
||||
if err := (&ImageUpdateAutomationReconciler{
|
||||
Client: testEnv,
|
||||
EventRecorder: testEnv.GetEventRecorderFor(controllerName),
|
||||
features: feats,
|
||||
Client: testEnv,
|
||||
EventRecorder: record.NewFakeRecorder(32),
|
||||
features: feats,
|
||||
ControllerName: controllerName,
|
||||
}).SetupWithManager(ctx, testEnv, ImageUpdateAutomationReconcilerOptions{
|
||||
RateLimiter: controller.GetDefaultRateLimiter(),
|
||||
}); err != nil {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/surely/does/not/exist
|
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,10 @@ limitations under the License.
|
|||
// states.
|
||||
package features
|
||||
|
||||
import feathelper "github.com/fluxcd/pkg/runtime/features"
|
||||
import (
|
||||
"github.com/fluxcd/pkg/auth"
|
||||
feathelper "github.com/fluxcd/pkg/runtime/features"
|
||||
)
|
||||
|
||||
const (
|
||||
// GitForcePushBranch enables the use of "force push" when push branches
|
||||
|
@ -31,6 +34,9 @@ const (
|
|||
// GitAllBranchReferences enables the download of all branch head references
|
||||
// when push branches are configured. When enabled fixes fluxcd/flux2#3384.
|
||||
GitAllBranchReferences = "GitAllBranchReferences"
|
||||
// GitSparseCheckout enables the use of sparse checkout when pulling source from
|
||||
// Git repositories.
|
||||
GitSparseCheckout = "GitSparseCheckout"
|
||||
// CacheSecretsAndConfigMaps controls whether Secrets and ConfigMaps should
|
||||
// be cached.
|
||||
//
|
||||
|
@ -52,11 +58,19 @@ var features = map[string]bool{
|
|||
// opt-out from v0.28
|
||||
GitAllBranchReferences: true,
|
||||
|
||||
// GitSparseCheckout
|
||||
// opt-in from v0.42
|
||||
GitSparseCheckout: false,
|
||||
|
||||
// CacheSecretsAndConfigMaps
|
||||
// opt-in from v0.29
|
||||
CacheSecretsAndConfigMaps: false,
|
||||
}
|
||||
|
||||
func init() {
|
||||
auth.SetFeatureGates(features)
|
||||
}
|
||||
|
||||
// FeatureGates contains a list of all supported feature gates and
|
||||
// their default values.
|
||||
func FeatureGates() map[string]bool {
|
||||
|
|
|
@ -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 policy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
securejoin "github.com/cyphar/filepath-securejoin"
|
||||
"github.com/fluxcd/pkg/runtime/logger"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta2"
|
||||
"github.com/fluxcd/image-automation-controller/pkg/update"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoUpdateStrategy is an update error when the update strategy is not
|
||||
// specified.
|
||||
ErrNoUpdateStrategy = errors.New("no update strategy")
|
||||
// ErrUnsupportedUpdateStrategy is an update error when the provided update
|
||||
// strategy is not supported.
|
||||
ErrUnsupportedUpdateStrategy = errors.New("unsupported update strategy")
|
||||
)
|
||||
|
||||
// ApplyPolicies applies the given set of policies on the source present in the
|
||||
// workDir based on the provided ImageUpdateAutomation configuration.
|
||||
func ApplyPolicies(ctx context.Context, workDir string, obj *imagev1.ImageUpdateAutomation, policies []imagev1_reflect.ImagePolicy) (update.ResultV2, error) {
|
||||
var result update.ResultV2
|
||||
if obj.Spec.Update == nil {
|
||||
return result, ErrNoUpdateStrategy
|
||||
}
|
||||
if obj.Spec.Update.Strategy != imagev1.UpdateStrategySetters {
|
||||
return result, fmt.Errorf("%w: %s", ErrUnsupportedUpdateStrategy, obj.Spec.Update.Strategy)
|
||||
}
|
||||
|
||||
// Resolve the path to the manifests to apply policies on.
|
||||
manifestPath := workDir
|
||||
if obj.Spec.Update.Path != "" {
|
||||
p, err := securejoin.SecureJoin(workDir, obj.Spec.Update.Path)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("failed to secure join manifest path: %w", err)
|
||||
}
|
||||
manifestPath = p
|
||||
}
|
||||
|
||||
tracelog := log.FromContext(ctx).V(logger.TraceLevel)
|
||||
return update.UpdateV2WithSetters(tracelog, manifestPath, manifestPath, policies)
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
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 policy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/otiai10/copy"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta2"
|
||||
"github.com/fluxcd/image-automation-controller/internal/testutil"
|
||||
"github.com/fluxcd/image-automation-controller/pkg/test"
|
||||
"github.com/fluxcd/image-automation-controller/pkg/update"
|
||||
)
|
||||
|
||||
func testdataPath(path string) string {
|
||||
return filepath.Join("testdata", path)
|
||||
}
|
||||
|
||||
func Test_applyPolicies(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
updateStrategy *imagev1.UpdateStrategy
|
||||
policyLatestImages map[string]string
|
||||
targetPolicyName string
|
||||
replaceMarkerFunc func(g *WithT, path string, policyKey types.NamespacedName)
|
||||
inputPath string
|
||||
expectedPath string
|
||||
wantErr bool
|
||||
wantResult update.Result
|
||||
}{
|
||||
{
|
||||
name: "valid update strategy and one policy",
|
||||
updateStrategy: &imagev1.UpdateStrategy{
|
||||
Strategy: imagev1.UpdateStrategySetters,
|
||||
},
|
||||
policyLatestImages: map[string]string{
|
||||
"policy1": "helloworld:1.0.1",
|
||||
},
|
||||
targetPolicyName: "policy1",
|
||||
inputPath: testdataPath("appconfig"),
|
||||
expectedPath: testdataPath("appconfig-setters-expected"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "no update strategy",
|
||||
updateStrategy: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "unknown update strategy",
|
||||
updateStrategy: &imagev1.UpdateStrategy{
|
||||
Strategy: "foo",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid update strategy and multiple policies",
|
||||
updateStrategy: &imagev1.UpdateStrategy{
|
||||
Strategy: imagev1.UpdateStrategySetters,
|
||||
},
|
||||
policyLatestImages: map[string]string{
|
||||
"policy1": "foo:1.1.1",
|
||||
"policy2": "helloworld:1.0.1",
|
||||
"policy3": "bar:2.2.2",
|
||||
},
|
||||
targetPolicyName: "policy2",
|
||||
inputPath: testdataPath("appconfig"),
|
||||
expectedPath: testdataPath("appconfig-setters-expected"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid update strategy with update path",
|
||||
updateStrategy: &imagev1.UpdateStrategy{
|
||||
Strategy: imagev1.UpdateStrategySetters,
|
||||
Path: "./yes",
|
||||
},
|
||||
policyLatestImages: map[string]string{
|
||||
"policy1": "helloworld:1.0.1",
|
||||
},
|
||||
targetPolicyName: "policy1",
|
||||
replaceMarkerFunc: func(g *WithT, path string, policyKey types.NamespacedName) {
|
||||
g.Expect(testutil.ReplaceMarker(filepath.Join(path, "yes", "deploy.yaml"), policyKey)).ToNot(HaveOccurred())
|
||||
g.Expect(testutil.ReplaceMarker(filepath.Join(path, "no", "deploy.yaml"), policyKey)).ToNot(HaveOccurred())
|
||||
},
|
||||
inputPath: testdataPath("pathconfig"),
|
||||
expectedPath: testdataPath("pathconfig-expected"),
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
testNS := "test-ns"
|
||||
workDir := t.TempDir()
|
||||
|
||||
// Create all the policy objects.
|
||||
policyList := []imagev1_reflect.ImagePolicy{}
|
||||
for name, image := range tt.policyLatestImages {
|
||||
policy := &imagev1_reflect.ImagePolicy{}
|
||||
policy.Name = name
|
||||
policy.Namespace = testNS
|
||||
policy.Status = imagev1_reflect.ImagePolicyStatus{
|
||||
LatestRef: testutil.ImageToRef(image),
|
||||
}
|
||||
policyList = append(policyList, *policy)
|
||||
}
|
||||
targetPolicyKey := types.NamespacedName{
|
||||
Name: tt.targetPolicyName, Namespace: testNS,
|
||||
}
|
||||
|
||||
if tt.inputPath != "" {
|
||||
g.Expect(copy.Copy(tt.inputPath, workDir)).ToNot(HaveOccurred())
|
||||
// Update the test files with the target policy.
|
||||
if tt.replaceMarkerFunc != nil {
|
||||
tt.replaceMarkerFunc(g, workDir, targetPolicyKey)
|
||||
} else {
|
||||
g.Expect(testutil.ReplaceMarker(filepath.Join(workDir, "deploy.yaml"), targetPolicyKey)).ToNot(HaveOccurred())
|
||||
}
|
||||
}
|
||||
|
||||
updateAuto := &imagev1.ImageUpdateAutomation{}
|
||||
updateAuto.Name = "test-update"
|
||||
updateAuto.Namespace = testNS
|
||||
updateAuto.Spec = imagev1.ImageUpdateAutomationSpec{
|
||||
Update: tt.updateStrategy,
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
imagev1_reflect.AddToScheme(scheme)
|
||||
imagev1.AddToScheme(scheme)
|
||||
|
||||
_, err := ApplyPolicies(context.TODO(), workDir, updateAuto, policyList)
|
||||
g.Expect(err != nil).To(Equal(tt.wantErr))
|
||||
|
||||
// Check the results if there wasn't any error.
|
||||
if !tt.wantErr {
|
||||
expected := t.TempDir()
|
||||
copy.Copy(tt.expectedPath, expected)
|
||||
// Update the markers in the expected test data.
|
||||
if tt.replaceMarkerFunc != nil {
|
||||
tt.replaceMarkerFunc(g, expected, targetPolicyKey)
|
||||
} else {
|
||||
g.Expect(testutil.ReplaceMarker(filepath.Join(expected, "deploy.yaml"), targetPolicyKey)).ToNot(HaveOccurred())
|
||||
}
|
||||
test.ExpectMatchingDirectories(g, workDir, expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -7,4 +7,4 @@ spec:
|
|||
spec:
|
||||
containers:
|
||||
- name: hello
|
||||
image: helloworld:1.2.0 # SETTER_SITE
|
||||
image: helloworld:1.0.0 # SETTER_SITE
|
|
@ -0,0 +1,10 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: update-no
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: hello
|
||||
image: helloworld:1.0.0 # SETTER_SITE
|
|
@ -0,0 +1,10 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: update-yes
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: hello
|
||||
image: helloworld:1.0.1 # SETTER_SITE
|
|
@ -0,0 +1,10 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: update-no
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: hello
|
||||
image: helloworld:1.0.0 # SETTER_SITE
|
|
@ -0,0 +1,10 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: update-yes
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: hello
|
||||
image: helloworld:1.0.0 # SETTER_SITE
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
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 source
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/fluxcd/pkg/auth"
|
||||
authutils "github.com/fluxcd/pkg/auth/utils"
|
||||
"github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/github"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
const (
|
||||
signingSecretKey = "git.asc"
|
||||
signingPassphraseKey = "passphrase"
|
||||
)
|
||||
|
||||
// gitSrcCfg contains all the Git configurations related to a source derived
|
||||
// from the given configurations and the environment.
|
||||
type gitSrcCfg struct {
|
||||
srcKey types.NamespacedName
|
||||
url string
|
||||
pushBranch string
|
||||
switchBranch bool
|
||||
timeout *metav1.Duration
|
||||
checkoutRef *sourcev1.GitRepositoryRef
|
||||
authOpts *git.AuthOptions
|
||||
clientOpts []gogit.ClientOption
|
||||
signingEntity *openpgp.Entity
|
||||
}
|
||||
|
||||
func buildGitConfig(ctx context.Context, c client.Client, originKey, srcKey types.NamespacedName, gitSpec *imagev1.GitSpec, opts SourceOptions) (*gitSrcCfg, error) {
|
||||
cfg := &gitSrcCfg{
|
||||
srcKey: srcKey,
|
||||
}
|
||||
|
||||
// Get the repo.
|
||||
repo := &sourcev1.GitRepository{}
|
||||
if err := c.Get(ctx, srcKey, repo); err != nil {
|
||||
if client.IgnoreNotFound(err) == nil {
|
||||
return nil, fmt.Errorf("referenced git repository does not exist: %w", err)
|
||||
}
|
||||
}
|
||||
cfg.url = repo.Spec.URL
|
||||
|
||||
// Configure Git operation timeout from the GitRepository configuration.
|
||||
if repo.Spec.Timeout != nil {
|
||||
cfg.timeout = repo.Spec.Timeout
|
||||
} else {
|
||||
cfg.timeout = &metav1.Duration{Duration: time.Minute}
|
||||
}
|
||||
|
||||
// Get the checkout ref for the source, prioritizing the image automation
|
||||
// object gitSpec checkout reference and falling back to the GitRepository
|
||||
// reference if not provided.
|
||||
// var checkoutRef *sourcev1.GitRepositoryRef
|
||||
if gitSpec.Checkout != nil {
|
||||
cfg.checkoutRef = &gitSpec.Checkout.Reference
|
||||
} else if repo.Spec.Reference != nil {
|
||||
cfg.checkoutRef = repo.Spec.Reference
|
||||
} // else remain as `nil` and git.DefaultBranch will be used.
|
||||
|
||||
// Configure push first as the client options below depend on the push
|
||||
// configuration.
|
||||
if err := configurePush(cfg, gitSpec, cfg.checkoutRef); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
proxyOpts, proxyURL, err := getProxyOpts(ctx, c, repo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.authOpts, err = getAuthOpts(ctx, c, repo, opts, proxyURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.clientOpts = []gogit.ClientOption{gogit.WithDiskStorage()}
|
||||
if cfg.authOpts.Transport == git.HTTP {
|
||||
cfg.clientOpts = append(cfg.clientOpts, gogit.WithInsecureCredentialsOverHTTP())
|
||||
}
|
||||
if proxyOpts != nil {
|
||||
cfg.clientOpts = append(cfg.clientOpts, gogit.WithProxy(*proxyOpts))
|
||||
}
|
||||
// If the push branch is different from the checkout ref, we need to
|
||||
// have all the references downloaded at clone time, to ensure that
|
||||
// SwitchBranch will have access to the target branch state. fluxcd/flux2#3384
|
||||
//
|
||||
// To always overwrite the push branch, the feature gate
|
||||
// GitAllBranchReferences can be set to false, which will cause
|
||||
// the SwitchBranch operation to ignore the remote branch state.
|
||||
if cfg.switchBranch {
|
||||
cfg.clientOpts = append(cfg.clientOpts, gogit.WithSingleBranch(!opts.gitAllBranchReferences))
|
||||
}
|
||||
|
||||
if gitSpec.Commit.SigningKey != nil {
|
||||
if cfg.signingEntity, err = getSigningEntity(ctx, c, originKey.Namespace, gitSpec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func configurePush(cfg *gitSrcCfg, gitSpec *imagev1.GitSpec, checkoutRef *sourcev1.GitRepositoryRef) error {
|
||||
if gitSpec.Push != nil && gitSpec.Push.Branch != "" {
|
||||
cfg.pushBranch = gitSpec.Push.Branch
|
||||
|
||||
if checkoutRef != nil {
|
||||
if cfg.pushBranch != checkoutRef.Branch {
|
||||
cfg.switchBranch = true
|
||||
}
|
||||
} else {
|
||||
// Compare with the git default branch when no checkout ref is
|
||||
// explicitly defined.
|
||||
if cfg.pushBranch != git.DefaultBranch {
|
||||
cfg.switchBranch = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// If no push branch is configured above, use the branch from checkoutRef.
|
||||
|
||||
// Here's where it gets constrained. If there's no push branch
|
||||
// given, then the checkout ref must include a branch, and
|
||||
// that can be used.
|
||||
if checkoutRef == nil || checkoutRef.Branch == "" {
|
||||
return errors.New("push spec not provided, and cannot be inferred from .spec.git.checkout.ref or GitRepository .spec.ref")
|
||||
}
|
||||
cfg.pushBranch = checkoutRef.Branch
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAuthOpts(ctx context.Context, c client.Client, repo *sourcev1.GitRepository,
|
||||
srcOpts SourceOptions, proxyURL *url.URL) (*git.AuthOptions, error) {
|
||||
var data map[string][]byte
|
||||
var err error
|
||||
if repo.Spec.SecretRef != nil {
|
||||
data, err = getSecretData(ctx, c, repo.Spec.SecretRef.Name, repo.GetNamespace())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get auth secret '%s/%s': %w", repo.GetNamespace(), repo.Spec.SecretRef.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
u, err := url.Parse(repo.Spec.URL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse URL '%s': %w", repo.Spec.URL, err)
|
||||
}
|
||||
|
||||
opts, err := git.NewAuthOptions(*u, data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to configure authentication options: %w", err)
|
||||
}
|
||||
|
||||
var getCreds func() (*authutils.GitCredentials, error)
|
||||
switch provider := repo.GetProvider(); provider {
|
||||
case sourcev1.GitProviderAzure: // If AWS or GCP are added in the future they can be added here separated by a comma.
|
||||
getCreds = func() (*authutils.GitCredentials, error) {
|
||||
var opts []auth.Option
|
||||
|
||||
if srcOpts.tokenCache != nil {
|
||||
involvedObject := cache.InvolvedObject{
|
||||
Kind: imagev1.ImageUpdateAutomationKind,
|
||||
Name: srcOpts.objName,
|
||||
Namespace: srcOpts.objNamespace,
|
||||
Operation: cache.OperationReconcile,
|
||||
}
|
||||
opts = append(opts, auth.WithCache(*srcOpts.tokenCache, involvedObject))
|
||||
}
|
||||
|
||||
if proxyURL != nil {
|
||||
opts = append(opts, auth.WithProxyURL(*proxyURL))
|
||||
}
|
||||
|
||||
return authutils.GetGitCredentials(ctx, provider, opts...)
|
||||
}
|
||||
case sourcev1.GitProviderGitHub:
|
||||
// if provider is github, but secret ref is not specified
|
||||
if repo.Spec.SecretRef == nil {
|
||||
return nil, fmt.Errorf("secretRef with github app data must be specified when provider is set to github: %w", ErrInvalidSourceConfiguration)
|
||||
}
|
||||
|
||||
getCreds = func() (*authutils.GitCredentials, error) {
|
||||
var opts []github.OptFunc
|
||||
|
||||
if len(data) > 0 {
|
||||
opts = append(opts, github.WithAppData(data))
|
||||
}
|
||||
|
||||
if proxyURL != nil {
|
||||
opts = append(opts, github.WithProxyURL(proxyURL))
|
||||
}
|
||||
|
||||
if srcOpts.tokenCache != nil {
|
||||
opts = append(opts, github.WithCache(srcOpts.tokenCache, imagev1.ImageUpdateAutomationKind,
|
||||
srcOpts.objName, srcOpts.objNamespace, cache.OperationReconcile))
|
||||
}
|
||||
|
||||
username, password, err := github.GetCredentials(ctx, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &authutils.GitCredentials{
|
||||
Username: username,
|
||||
Password: password,
|
||||
}, nil
|
||||
}
|
||||
default:
|
||||
// analyze secret, if it has github app data, perhaps provider should have been github.
|
||||
if appID := data[github.AppIDKey]; len(appID) != 0 {
|
||||
return nil, fmt.Errorf("secretRef '%s/%s' has github app data but provider is not set to github: %w", repo.GetNamespace(), repo.Spec.SecretRef.Name, ErrInvalidSourceConfiguration)
|
||||
}
|
||||
}
|
||||
if getCreds != nil {
|
||||
creds, err := getCreds()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to configure authentication options: %w", err)
|
||||
}
|
||||
opts.BearerToken = creds.BearerToken
|
||||
opts.Username = creds.Username
|
||||
opts.Password = creds.Password
|
||||
}
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func getProxyOpts(ctx context.Context, c client.Client, repo *sourcev1.GitRepository) (*transport.ProxyOptions, *url.URL, error) {
|
||||
if repo.Spec.ProxySecretRef == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
name := repo.Spec.ProxySecretRef.Name
|
||||
namespace := repo.GetNamespace()
|
||||
proxyData, err := getSecretData(ctx, c, name, namespace)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to get proxy secret '%s/%s': %w", namespace, name, err)
|
||||
}
|
||||
b, ok := proxyData["address"]
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("invalid proxy secret '%s/%s': key 'address' is missing", namespace, name)
|
||||
}
|
||||
|
||||
address := string(b)
|
||||
username := string(proxyData["username"])
|
||||
password := string(proxyData["password"])
|
||||
|
||||
proxyOpts := &transport.ProxyOptions{
|
||||
URL: address,
|
||||
Username: username,
|
||||
Password: password,
|
||||
}
|
||||
|
||||
proxyURL, err := url.Parse(string(address))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("invalid address in proxy secret '%s/%s': %w", namespace, name, err)
|
||||
}
|
||||
switch {
|
||||
case username != "" && password == "":
|
||||
proxyURL.User = url.User(username)
|
||||
case username != "" && password != "":
|
||||
proxyURL.User = url.UserPassword(username, password)
|
||||
}
|
||||
|
||||
return proxyOpts, proxyURL, nil
|
||||
}
|
||||
|
||||
func getSigningEntity(ctx context.Context, c client.Client, namespace string, gitSpec *imagev1.GitSpec) (*openpgp.Entity, error) {
|
||||
secretName := gitSpec.Commit.SigningKey.SecretRef.Name
|
||||
secretData, err := getSecretData(ctx, c, secretName, namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not find signing key secret '%s': %w", secretName, err)
|
||||
}
|
||||
|
||||
data, ok := secretData[signingSecretKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("signing key secret '%s' does not contain a 'git.asc' key", secretName)
|
||||
}
|
||||
|
||||
// Read entity from secret value
|
||||
entities, err := openpgp.ReadArmoredKeyRing(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read signing key from secret '%s': %w", secretName, err)
|
||||
}
|
||||
if len(entities) > 1 {
|
||||
return nil, fmt.Errorf("multiple entities read from secret '%s', could not determine which signing key to use", secretName)
|
||||
}
|
||||
|
||||
entity := entities[0]
|
||||
if entity.PrivateKey != nil && entity.PrivateKey.Encrypted {
|
||||
passphrase, ok := secretData[signingPassphraseKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("can not use passphrase protected signing key without '%s' field present in secret %s",
|
||||
"passphrase", secretName)
|
||||
}
|
||||
if err = entity.PrivateKey.Decrypt([]byte(passphrase)); err != nil {
|
||||
return nil, fmt.Errorf("could not decrypt private key of the signing key present in secret %s: %w", secretName, err)
|
||||
}
|
||||
}
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
func getSecretData(ctx context.Context, c client.Client, name, namespace string) (map[string][]byte, error) {
|
||||
key := types.NamespacedName{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
}
|
||||
var secret corev1.Secret
|
||||
if err := c.Get(ctx, key, &secret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return secret.Data, nil
|
||||
}
|
|
@ -0,0 +1,685 @@
|
|||
/*
|
||||
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 source
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta2"
|
||||
"github.com/fluxcd/image-automation-controller/internal/testutil"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/github"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
)
|
||||
|
||||
func Test_getAuthOpts(t *testing.T) {
|
||||
namespace := "default"
|
||||
|
||||
invalidAuthSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "invalid-auth",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"password": []byte("pass"),
|
||||
},
|
||||
}
|
||||
|
||||
validAuthSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "valid-auth",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"username": []byte("user"),
|
||||
"password": []byte("pass"),
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
secretName string
|
||||
want *git.AuthOptions
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "non-existing secret",
|
||||
secretName: "non-existing",
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid secret",
|
||||
url: "https://example.com",
|
||||
secretName: "invalid-auth",
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid secret",
|
||||
url: "https://example.com",
|
||||
secretName: "valid-auth",
|
||||
want: &git.AuthOptions{
|
||||
Transport: git.HTTPS,
|
||||
Host: "example.com",
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "no secret",
|
||||
url: "https://example.com",
|
||||
want: &git.AuthOptions{
|
||||
Transport: git.HTTPS,
|
||||
Host: "example.com",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid URL",
|
||||
url: "://example.com",
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
clientBuilder := fakeclient.NewClientBuilder().
|
||||
WithScheme(scheme.Scheme).
|
||||
WithObjects(invalidAuthSecret, validAuthSecret)
|
||||
c := clientBuilder.Build()
|
||||
|
||||
gitRepo := &sourcev1.GitRepository{}
|
||||
gitRepo.Namespace = namespace
|
||||
gitRepo.Spec = sourcev1.GitRepositorySpec{
|
||||
URL: tt.url,
|
||||
}
|
||||
if tt.secretName != "" {
|
||||
gitRepo.Spec.SecretRef = &meta.LocalObjectReference{Name: tt.secretName}
|
||||
}
|
||||
|
||||
got, err := getAuthOpts(context.TODO(), c, gitRepo, SourceOptions{}, nil)
|
||||
if (err != nil) != tt.wantErr {
|
||||
g.Fail(fmt.Sprintf("unexpected error: %v", err))
|
||||
return
|
||||
}
|
||||
g.Expect(got).To(Equal(tt.want))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getAuthOpts_providerAuth(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
secret *corev1.Secret
|
||||
beforeFunc func(obj *sourcev1.GitRepository)
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "azure provider",
|
||||
url: "https://dev.azure.com/foo/bar/_git/baz",
|
||||
beforeFunc: func(obj *sourcev1.GitRepository) {
|
||||
obj.Spec.Provider = sourcev1.GitProviderAzure
|
||||
},
|
||||
wantErr: "ManagedIdentityCredential",
|
||||
},
|
||||
{
|
||||
name: "github provider with no secret ref",
|
||||
url: "https://github.com/org/repo.git",
|
||||
beforeFunc: func(obj *sourcev1.GitRepository) {
|
||||
obj.Spec.Provider = sourcev1.GitProviderGitHub
|
||||
},
|
||||
wantErr: "secretRef with github app data must be specified when provider is set to github: invalid source configuration",
|
||||
},
|
||||
{
|
||||
name: "github provider with secret ref that does not exist",
|
||||
url: "https://github.com/org/repo.git",
|
||||
beforeFunc: func(obj *sourcev1.GitRepository) {
|
||||
obj.Spec.Provider = sourcev1.GitProviderGitHub
|
||||
obj.Spec.SecretRef = &meta.LocalObjectReference{
|
||||
Name: "githubAppSecret",
|
||||
}
|
||||
},
|
||||
wantErr: "failed to get auth secret '/githubAppSecret': secrets \"githubAppSecret\" not found",
|
||||
},
|
||||
{
|
||||
name: "github provider with github app data in secret",
|
||||
url: "https://example.com/org/repo",
|
||||
secret: &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "githubAppSecret",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
github.AppIDKey: []byte("123"),
|
||||
github.AppInstallationIDKey: []byte("456"),
|
||||
github.AppPrivateKey: []byte("abc"),
|
||||
},
|
||||
},
|
||||
beforeFunc: func(obj *sourcev1.GitRepository) {
|
||||
obj.Spec.Provider = sourcev1.GitProviderGitHub
|
||||
obj.Spec.SecretRef = &meta.LocalObjectReference{
|
||||
Name: "githubAppSecret",
|
||||
}
|
||||
},
|
||||
wantErr: "Key must be a PEM encoded PKCS1 or PKCS8 key",
|
||||
},
|
||||
{
|
||||
name: "generic provider with github app data in secret",
|
||||
url: "https://example.com/org/repo",
|
||||
secret: &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "githubAppSecret",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
github.AppIDKey: []byte("123"),
|
||||
},
|
||||
},
|
||||
beforeFunc: func(obj *sourcev1.GitRepository) {
|
||||
obj.Spec.Provider = sourcev1.GitProviderGeneric
|
||||
obj.Spec.SecretRef = &meta.LocalObjectReference{
|
||||
Name: "githubAppSecret",
|
||||
}
|
||||
},
|
||||
wantErr: "secretRef '/githubAppSecret' has github app data but provider is not set to github: invalid source configuration",
|
||||
},
|
||||
{
|
||||
name: "generic provider",
|
||||
url: "https://example.com/org/repo",
|
||||
beforeFunc: func(obj *sourcev1.GitRepository) {
|
||||
obj.Spec.Provider = sourcev1.GitProviderGeneric
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no provider",
|
||||
url: "https://example.com/org/repo",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
clientBuilder := fakeclient.NewClientBuilder().
|
||||
WithScheme(scheme.Scheme).
|
||||
WithStatusSubresource(&sourcev1.GitRepository{})
|
||||
|
||||
if tt.secret != nil {
|
||||
clientBuilder.WithObjects(tt.secret)
|
||||
}
|
||||
c := clientBuilder.Build()
|
||||
obj := &sourcev1.GitRepository{
|
||||
Spec: sourcev1.GitRepositorySpec{
|
||||
URL: tt.url,
|
||||
},
|
||||
}
|
||||
|
||||
if tt.beforeFunc != nil {
|
||||
tt.beforeFunc(obj)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
opts, err := getAuthOpts(ctx, c, obj, SourceOptions{}, nil)
|
||||
|
||||
if tt.wantErr != "" {
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
g.Expect(err.Error()).To(ContainSubstring(tt.wantErr))
|
||||
} else {
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(opts).ToNot(BeNil())
|
||||
g.Expect(opts.BearerToken).To(BeEmpty())
|
||||
g.Expect(opts.Username).To(BeEmpty())
|
||||
g.Expect(opts.Password).To(BeEmpty())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getProxyOpts(t *testing.T) {
|
||||
namespace := "default"
|
||||
invalidProxy := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "invalid-proxy",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"url": []byte("https://example.com"),
|
||||
},
|
||||
}
|
||||
validProxy := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "valid-proxy",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"address": []byte("https://example.com"),
|
||||
"username": []byte("user"),
|
||||
"password": []byte("pass"),
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
secretName string
|
||||
want *transport.ProxyOptions
|
||||
wantProxyURL *url.URL
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "non-existing secret",
|
||||
secretName: "non-existing",
|
||||
want: nil,
|
||||
wantProxyURL: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid proxy secret",
|
||||
secretName: "invalid-proxy",
|
||||
want: nil,
|
||||
wantProxyURL: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid proxy secret",
|
||||
secretName: "valid-proxy",
|
||||
want: &transport.ProxyOptions{
|
||||
URL: "https://example.com",
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
wantProxyURL: &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "example.com",
|
||||
User: url.UserPassword("user", "pass"),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
clientBuilder := fakeclient.NewClientBuilder().
|
||||
WithScheme(scheme.Scheme).
|
||||
WithObjects(invalidProxy, validProxy)
|
||||
c := clientBuilder.Build()
|
||||
|
||||
gitRepo := &sourcev1.GitRepository{}
|
||||
gitRepo.Namespace = namespace
|
||||
if tt.secretName != "" {
|
||||
gitRepo.Spec = sourcev1.GitRepositorySpec{
|
||||
ProxySecretRef: &meta.LocalObjectReference{Name: tt.secretName},
|
||||
}
|
||||
}
|
||||
|
||||
got, gotProxyURL, err := getProxyOpts(context.TODO(), c, gitRepo)
|
||||
if (err != nil) != tt.wantErr {
|
||||
g.Fail(fmt.Sprintf("unexpected error: %v", err))
|
||||
return
|
||||
}
|
||||
g.Expect(got).To(Equal(tt.want))
|
||||
g.Expect(gotProxyURL).To(Equal(tt.wantProxyURL))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getSigningEntity(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
namespace := "default"
|
||||
|
||||
passphrase := "abcde12345"
|
||||
_, keyEncrypted := testutil.GetSigningKeyPair(g, passphrase)
|
||||
encryptedKeySecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "encrypted-key",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
signingSecretKey: keyEncrypted,
|
||||
signingPassphraseKey: []byte(passphrase),
|
||||
},
|
||||
}
|
||||
|
||||
_, keyUnencrypted := testutil.GetSigningKeyPair(g, "")
|
||||
unencryptedKeySecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "unencrypted-key",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
signingSecretKey: keyUnencrypted,
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
secretName string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "non-existing secret",
|
||||
secretName: "non-existing",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "unencrypted key",
|
||||
secretName: "unencrypted-key",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "encrypted key",
|
||||
secretName: "encrypted-key",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
clientBuilder := fakeclient.NewClientBuilder().
|
||||
WithScheme(scheme.Scheme).
|
||||
WithObjects(encryptedKeySecret, unencryptedKeySecret)
|
||||
c := clientBuilder.Build()
|
||||
|
||||
gitSpec := &imagev1.GitSpec{}
|
||||
if tt.secretName != "" {
|
||||
gitSpec.Commit = imagev1.CommitSpec{
|
||||
SigningKey: &imagev1.SigningKey{
|
||||
SecretRef: meta.LocalObjectReference{Name: tt.secretName},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
_, err := getSigningEntity(context.TODO(), c, namespace, gitSpec)
|
||||
if (err != nil) != tt.wantErr {
|
||||
g.Fail(fmt.Sprintf("unexpected error: %v", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_buildGitConfig(t *testing.T) {
|
||||
testGitRepoName := "test-gitrepo"
|
||||
namespace := "foo-ns"
|
||||
testTimeout := &metav1.Duration{Duration: time.Minute}
|
||||
testGitURL := "https://example.com"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
gitSpec *imagev1.GitSpec
|
||||
gitRepoName string
|
||||
gitRepoRef *sourcev1.GitRepositoryRef
|
||||
gitRepoTimeout *metav1.Duration
|
||||
gitRepoURL string
|
||||
gitRepoProxyData map[string][]byte
|
||||
srcOpts SourceOptions
|
||||
wantErr bool
|
||||
wantCheckoutRef *sourcev1.GitRepositoryRef
|
||||
wantPushBranch string
|
||||
wantSwitchBranch bool
|
||||
wantTimeout *metav1.Duration
|
||||
}{
|
||||
{
|
||||
name: "same branch, gitSpec checkoutRef",
|
||||
gitSpec: &imagev1.GitSpec{
|
||||
Checkout: &imagev1.GitCheckoutSpec{
|
||||
Reference: sourcev1.GitRepositoryRef{Branch: "aaa"},
|
||||
},
|
||||
},
|
||||
gitRepoName: testGitRepoName,
|
||||
gitRepoURL: testGitURL,
|
||||
wantErr: false,
|
||||
wantCheckoutRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "aaa",
|
||||
},
|
||||
wantPushBranch: "aaa",
|
||||
wantSwitchBranch: false,
|
||||
wantTimeout: testTimeout,
|
||||
},
|
||||
{
|
||||
name: "different branch, gitSpec checkoutRef",
|
||||
gitSpec: &imagev1.GitSpec{
|
||||
Checkout: &imagev1.GitCheckoutSpec{
|
||||
Reference: sourcev1.GitRepositoryRef{Branch: "aaa"},
|
||||
},
|
||||
Push: &imagev1.PushSpec{
|
||||
Branch: "bbb",
|
||||
},
|
||||
},
|
||||
gitRepoName: testGitRepoName,
|
||||
gitRepoURL: testGitURL,
|
||||
wantErr: false,
|
||||
wantCheckoutRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "aaa",
|
||||
},
|
||||
wantPushBranch: "bbb",
|
||||
wantSwitchBranch: true,
|
||||
wantTimeout: testTimeout,
|
||||
},
|
||||
{
|
||||
name: "same branch, gitrepo checkoutRef",
|
||||
gitSpec: &imagev1.GitSpec{},
|
||||
gitRepoName: testGitRepoName,
|
||||
gitRepoURL: testGitURL,
|
||||
gitRepoRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
wantErr: false,
|
||||
wantCheckoutRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
wantPushBranch: "ccc",
|
||||
wantSwitchBranch: false,
|
||||
wantTimeout: testTimeout,
|
||||
},
|
||||
{
|
||||
name: "different branch, gitrepo checkoutRef",
|
||||
gitSpec: &imagev1.GitSpec{
|
||||
Push: &imagev1.PushSpec{
|
||||
Branch: "ddd",
|
||||
},
|
||||
},
|
||||
gitRepoName: testGitRepoName,
|
||||
gitRepoURL: testGitURL,
|
||||
gitRepoRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
wantErr: false,
|
||||
wantCheckoutRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
wantPushBranch: "ddd",
|
||||
wantSwitchBranch: true,
|
||||
wantTimeout: testTimeout,
|
||||
},
|
||||
{
|
||||
name: "no checkoutRef defined",
|
||||
gitSpec: &imagev1.GitSpec{
|
||||
Push: &imagev1.PushSpec{
|
||||
Branch: "aaa",
|
||||
},
|
||||
},
|
||||
gitRepoName: testGitRepoName,
|
||||
gitRepoURL: testGitURL,
|
||||
wantErr: false,
|
||||
wantCheckoutRef: nil, // Use the git default checkout branch.
|
||||
wantPushBranch: "aaa",
|
||||
wantSwitchBranch: true,
|
||||
wantTimeout: testTimeout,
|
||||
},
|
||||
{
|
||||
name: "gitSpec override gitRepo checkout config",
|
||||
gitSpec: &imagev1.GitSpec{
|
||||
Checkout: &imagev1.GitCheckoutSpec{
|
||||
Reference: sourcev1.GitRepositoryRef{Branch: "aaa"},
|
||||
},
|
||||
Push: &imagev1.PushSpec{
|
||||
Branch: "bbb",
|
||||
},
|
||||
},
|
||||
gitRepoName: testGitRepoName,
|
||||
gitRepoURL: testGitURL,
|
||||
gitRepoRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
wantErr: false,
|
||||
wantCheckoutRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "aaa",
|
||||
},
|
||||
wantPushBranch: "bbb",
|
||||
wantSwitchBranch: true,
|
||||
wantTimeout: testTimeout,
|
||||
},
|
||||
{
|
||||
name: "non-existing gitRepo",
|
||||
gitSpec: &imagev1.GitSpec{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "use gitrepo timeout",
|
||||
gitSpec: &imagev1.GitSpec{},
|
||||
gitRepoName: testGitRepoName,
|
||||
gitRepoURL: testGitURL,
|
||||
gitRepoRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
gitRepoTimeout: &metav1.Duration{Duration: 30 * time.Second},
|
||||
wantErr: false,
|
||||
wantCheckoutRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
wantPushBranch: "ccc",
|
||||
wantSwitchBranch: false,
|
||||
wantTimeout: &metav1.Duration{Duration: 30 * time.Second},
|
||||
},
|
||||
{
|
||||
name: "bad git URL",
|
||||
gitSpec: &imagev1.GitSpec{},
|
||||
gitRepoName: testGitRepoName,
|
||||
gitRepoURL: "://example.com",
|
||||
gitRepoRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "proxy config",
|
||||
gitSpec: &imagev1.GitSpec{},
|
||||
gitRepoName: testGitRepoName,
|
||||
gitRepoURL: testGitURL,
|
||||
gitRepoRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
gitRepoProxyData: map[string][]byte{
|
||||
"address": []byte("http://example.com"),
|
||||
},
|
||||
wantErr: false,
|
||||
wantCheckoutRef: &sourcev1.GitRepositoryRef{
|
||||
Branch: "ccc",
|
||||
},
|
||||
wantPushBranch: "ccc",
|
||||
wantSwitchBranch: false,
|
||||
wantTimeout: testTimeout,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
testObjects := []client.Object{}
|
||||
|
||||
var proxySecret *corev1.Secret
|
||||
if tt.gitRepoProxyData != nil {
|
||||
proxySecret = &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "valid-proxy",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: tt.gitRepoProxyData,
|
||||
}
|
||||
testObjects = append(testObjects, proxySecret)
|
||||
}
|
||||
|
||||
var gitRepo *sourcev1.GitRepository
|
||||
if tt.gitRepoName != "" {
|
||||
gitRepo = &sourcev1.GitRepository{}
|
||||
gitRepo.Name = testGitRepoName
|
||||
gitRepo.Namespace = namespace
|
||||
gitRepo.Spec = sourcev1.GitRepositorySpec{}
|
||||
if tt.gitRepoURL != "" {
|
||||
gitRepo.Spec.URL = tt.gitRepoURL
|
||||
}
|
||||
if tt.gitRepoRef != nil {
|
||||
gitRepo.Spec.Reference = tt.gitRepoRef
|
||||
}
|
||||
if tt.gitRepoTimeout != nil {
|
||||
gitRepo.Spec.Timeout = tt.gitRepoTimeout
|
||||
}
|
||||
if proxySecret != nil {
|
||||
gitRepo.Spec.ProxySecretRef = &meta.LocalObjectReference{Name: proxySecret.Name}
|
||||
}
|
||||
testObjects = append(testObjects, gitRepo)
|
||||
}
|
||||
|
||||
clientBuilder := fakeclient.NewClientBuilder().
|
||||
WithScheme(scheme.Scheme).
|
||||
WithObjects(testObjects...)
|
||||
c := clientBuilder.Build()
|
||||
|
||||
gitRepoKey := types.NamespacedName{
|
||||
Namespace: namespace,
|
||||
Name: tt.gitRepoName,
|
||||
}
|
||||
|
||||
updateAutoKey := types.NamespacedName{
|
||||
Namespace: namespace,
|
||||
Name: "test-update",
|
||||
}
|
||||
|
||||
gitSrcCfg, err := buildGitConfig(context.TODO(), c, updateAutoKey, gitRepoKey, tt.gitSpec, tt.srcOpts)
|
||||
if (err != nil) != tt.wantErr {
|
||||
g.Fail(fmt.Sprintf("unexpected error: %v", err))
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
g.Expect(gitSrcCfg.checkoutRef).To(Equal(tt.wantCheckoutRef), "unexpected checkoutRef")
|
||||
g.Expect(gitSrcCfg.pushBranch).To(Equal(tt.wantPushBranch), "unexpected push branch")
|
||||
g.Expect(gitSrcCfg.switchBranch).To(Equal(tt.wantSwitchBranch), "unexpected switch branch")
|
||||
g.Expect(gitSrcCfg.timeout).To(Equal(tt.wantTimeout), "unexpected git operation timeout")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,441 @@
|
|||
/*
|
||||
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 source
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/sprig/v3"
|
||||
"github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/fluxcd/pkg/git/repository"
|
||||
"github.com/fluxcd/pkg/runtime/acl"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
"github.com/fluxcd/pkg/runtime/logger"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta2"
|
||||
"github.com/fluxcd/image-automation-controller/pkg/update"
|
||||
)
|
||||
|
||||
// ErrInvalidSourceConfiguration is an error for invalid source configuration.
|
||||
var ErrInvalidSourceConfiguration = errors.New("invalid source configuration")
|
||||
|
||||
const defaultMessageTemplate = `Update from image update automation`
|
||||
|
||||
// TemplateData is the type of the value given to the commit message
|
||||
// template.
|
||||
type TemplateData struct {
|
||||
AutomationObject types.NamespacedName
|
||||
Updated update.Result
|
||||
Changed update.ResultV2
|
||||
Values map[string]string
|
||||
}
|
||||
|
||||
// SourceManager manages source.
|
||||
type SourceManager struct {
|
||||
srcCfg *gitSrcCfg
|
||||
automationObjKey types.NamespacedName
|
||||
gitClient *gogit.Client
|
||||
workingDir string
|
||||
}
|
||||
|
||||
// SourceOptions contains the optional attributes of SourceManager.
|
||||
type SourceOptions struct {
|
||||
noCrossNamespaceRef bool
|
||||
gitAllBranchReferences bool
|
||||
tokenCache *cache.TokenCache
|
||||
objName string
|
||||
objNamespace string
|
||||
}
|
||||
|
||||
// SourceOption configures the SourceManager options.
|
||||
type SourceOption func(*SourceOptions)
|
||||
|
||||
// WithSourceOptionNoCrossNamespaceRef configures the SourceManager to disable
|
||||
// cross namespace references.
|
||||
func WithSourceOptionNoCrossNamespaceRef() SourceOption {
|
||||
return func(so *SourceOptions) {
|
||||
so.noCrossNamespaceRef = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithSourceOptionGitAllBranchReferences configures the SourceManager to fetch
|
||||
// all the Git branch references that are present in the remote repository.
|
||||
func WithSourceOptionGitAllBranchReferences() SourceOption {
|
||||
return func(so *SourceOptions) {
|
||||
so.gitAllBranchReferences = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithSourceOptionTokenCache configures the SourceManager to use the provided
|
||||
// token cache.
|
||||
func WithSourceOptionTokenCache(tc *cache.TokenCache) SourceOption {
|
||||
return func(so *SourceOptions) {
|
||||
so.tokenCache = tc
|
||||
}
|
||||
}
|
||||
|
||||
// WithSourceOptionInvolvedObject configures the SourceManager to use the
|
||||
// provided ImageUpdateAutomation object.
|
||||
func WithSourceOptionInvolvedObject(name, namespace string) SourceOption {
|
||||
return func(so *SourceOptions) {
|
||||
so.objName = name
|
||||
so.objNamespace = namespace
|
||||
}
|
||||
}
|
||||
|
||||
// NewSourceManager takes all the provided inputs, validates them and returns a
|
||||
// SourceManager which can be used to operate on the configured source.
|
||||
func NewSourceManager(ctx context.Context, c client.Client, obj *imagev1.ImageUpdateAutomation, options ...SourceOption) (*SourceManager, error) {
|
||||
opts := &SourceOptions{}
|
||||
for _, o := range options {
|
||||
o(opts)
|
||||
}
|
||||
|
||||
// Only GitRepository source is supported.
|
||||
if obj.Spec.SourceRef.Kind != sourcev1.GitRepositoryKind {
|
||||
return nil, fmt.Errorf("source kind '%s' not supported: %w", obj.Spec.SourceRef.Kind, ErrInvalidSourceConfiguration)
|
||||
}
|
||||
|
||||
if obj.Spec.GitSpec == nil {
|
||||
return nil, fmt.Errorf("source kind '%s' necessitates field .spec.git: %w", sourcev1.GitRepositoryKind, ErrInvalidSourceConfiguration)
|
||||
}
|
||||
|
||||
// Build source reference configuration to fetch and validate it.
|
||||
srcNamespace := obj.GetNamespace()
|
||||
if obj.Spec.SourceRef.Namespace != "" {
|
||||
srcNamespace = obj.Spec.SourceRef.Namespace
|
||||
}
|
||||
|
||||
// srcKey is the GitRepository object key.
|
||||
srcKey := types.NamespacedName{Name: obj.Spec.SourceRef.Name, Namespace: srcNamespace}
|
||||
// originKey is the update automation object key.
|
||||
originKey := client.ObjectKeyFromObject(obj)
|
||||
|
||||
// Check if the source is accessible.
|
||||
if opts.noCrossNamespaceRef && srcKey.Namespace != obj.GetNamespace() {
|
||||
return nil, acl.AccessDeniedError(fmt.Sprintf("can't access '%s/%s', cross-namespace references have been blocked", sourcev1.GitRepositoryKind, srcKey))
|
||||
}
|
||||
|
||||
gitSrcCfg, err := buildGitConfig(ctx, c, originKey, srcKey, obj.Spec.GitSpec, *opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
workDir, err := os.MkdirTemp("", fmt.Sprintf("%s-%s", gitSrcCfg.srcKey.Namespace, gitSrcCfg.srcKey.Name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sm := &SourceManager{
|
||||
srcCfg: gitSrcCfg,
|
||||
automationObjKey: originKey,
|
||||
workingDir: workDir,
|
||||
}
|
||||
return sm, nil
|
||||
}
|
||||
|
||||
// CreateWorkingDirectory creates a working directory for the SourceManager.
|
||||
func (sm SourceManager) WorkDirectory() string {
|
||||
return sm.workingDir
|
||||
}
|
||||
|
||||
// Cleanup deletes the working directory of the SourceManager.
|
||||
func (sm SourceManager) Cleanup() error {
|
||||
return os.RemoveAll(sm.workingDir)
|
||||
}
|
||||
|
||||
// SwitchBranch returns if the checkout branch and push branch are different.
|
||||
func (sm SourceManager) SwitchBranch() bool {
|
||||
return sm.srcCfg.switchBranch
|
||||
}
|
||||
|
||||
// CheckoutOption allows configuring the checkout options.
|
||||
type CheckoutOption func(*repository.CloneConfig)
|
||||
|
||||
// WithCheckoutOptionLastObserved is a CheckoutOption option to configure the
|
||||
// last observed commit.
|
||||
func WithCheckoutOptionLastObserved(commit string) CheckoutOption {
|
||||
return func(cc *repository.CloneConfig) {
|
||||
cc.LastObservedCommit = commit
|
||||
}
|
||||
}
|
||||
|
||||
// WithCheckoutOptionShallowClone is a CheckoutOption option to configure
|
||||
// shallow clone.
|
||||
func WithCheckoutOptionShallowClone() CheckoutOption {
|
||||
return func(cc *repository.CloneConfig) {
|
||||
cc.ShallowClone = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithCheckoutOptionSparseCheckoutDirectories is a CheckoutOption option to configure
|
||||
// SparseCheckoutDirectories.
|
||||
func WithCheckoutOptionSparseCheckoutDirectories(updatePath string) CheckoutOption {
|
||||
return func(cc *repository.CloneConfig) {
|
||||
cleanedPath := filepath.Clean(updatePath)
|
||||
if cleanedPath == "." {
|
||||
// Do not set SparseCheckoutDirectories if repository root is specified
|
||||
return
|
||||
}
|
||||
cc.SparseCheckoutDirectories = []string{cleanedPath}
|
||||
}
|
||||
}
|
||||
|
||||
// CheckoutSource clones and checks out the source. If a push branch is
|
||||
// configured that doesn't match with the checkout branch, a checkout to the
|
||||
// push branch is also performed. This ensures any change and push operation
|
||||
// following the checkout happens on the push branch.
|
||||
func (sm *SourceManager) CheckoutSource(ctx context.Context, options ...CheckoutOption) (*git.Commit, error) {
|
||||
// Configuration clone options.
|
||||
cloneCfg := repository.CloneConfig{}
|
||||
if sm.srcCfg.checkoutRef != nil {
|
||||
cloneCfg.Tag = sm.srcCfg.checkoutRef.Tag
|
||||
cloneCfg.SemVer = sm.srcCfg.checkoutRef.SemVer
|
||||
cloneCfg.Commit = sm.srcCfg.checkoutRef.Commit
|
||||
cloneCfg.Branch = sm.srcCfg.checkoutRef.Branch
|
||||
}
|
||||
// Apply checkout configurations.
|
||||
for _, o := range options {
|
||||
o(&cloneCfg)
|
||||
}
|
||||
|
||||
var err error
|
||||
sm.gitClient, err = gogit.NewClient(sm.workingDir, sm.srcCfg.authOpts, sm.srcCfg.clientOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gitOpCtx, cancel := context.WithTimeout(ctx, sm.srcCfg.timeout.Duration)
|
||||
defer cancel()
|
||||
commit, err := sm.gitClient.Clone(gitOpCtx, sm.srcCfg.url, cloneCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sm.srcCfg.switchBranch {
|
||||
if err := sm.gitClient.SwitchBranch(gitOpCtx, sm.srcCfg.pushBranch); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return commit, nil
|
||||
}
|
||||
|
||||
// PushConfig configures the options used in push operation.
|
||||
type PushConfig func(*repository.PushConfig)
|
||||
|
||||
// WithPushConfigForce configures the PushConfig to use force.
|
||||
func WithPushConfigForce() PushConfig {
|
||||
return func(pc *repository.PushConfig) {
|
||||
pc.Force = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithPushConfigOptions configures the PushConfig Options that are used in
|
||||
// push.
|
||||
func WithPushConfigOptions(opts map[string]string) PushConfig {
|
||||
return func(pc *repository.PushConfig) {
|
||||
pc.Options = opts
|
||||
}
|
||||
}
|
||||
|
||||
// CommitAndPush performs a commit in the source and pushes it to the remote
|
||||
// repository.
|
||||
func (sm SourceManager) CommitAndPush(ctx context.Context, obj *imagev1.ImageUpdateAutomation, policyResult update.ResultV2, pushOptions ...PushConfig) (*PushResult, error) {
|
||||
tracelog := log.FromContext(ctx).V(logger.TraceLevel)
|
||||
|
||||
// Make sure there were file changes that need to be committed.
|
||||
if len(policyResult.FileChanges) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Perform a Git commit.
|
||||
templateValues := &TemplateData{
|
||||
AutomationObject: sm.automationObjKey,
|
||||
Updated: policyResult.ImageResult,
|
||||
Changed: policyResult,
|
||||
Values: obj.Spec.GitSpec.Commit.MessageTemplateValues,
|
||||
}
|
||||
commitMsg, err := templateMsg(obj.Spec.GitSpec.Commit.MessageTemplate, templateValues)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signature := git.Signature{
|
||||
Name: obj.Spec.GitSpec.Commit.Author.Name,
|
||||
Email: obj.Spec.GitSpec.Commit.Author.Email,
|
||||
When: time.Now(),
|
||||
}
|
||||
|
||||
var rev string
|
||||
var commitErr error
|
||||
rev, commitErr = sm.gitClient.Commit(
|
||||
git.Commit{
|
||||
Author: signature,
|
||||
Message: commitMsg,
|
||||
},
|
||||
repository.WithSigner(sm.srcCfg.signingEntity),
|
||||
)
|
||||
|
||||
if commitErr != nil {
|
||||
if !errors.Is(commitErr, git.ErrNoStagedFiles) {
|
||||
return nil, commitErr
|
||||
}
|
||||
log.FromContext(ctx).Info("no changes made in the source; no commit")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Push the commit to push branch.
|
||||
gitOpCtx, cancel := context.WithTimeout(ctx, sm.srcCfg.timeout.Duration)
|
||||
defer cancel()
|
||||
pushConfig := repository.PushConfig{}
|
||||
for _, po := range pushOptions {
|
||||
po(&pushConfig)
|
||||
}
|
||||
if err := sm.gitClient.Push(gitOpCtx, pushConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tracelog.Info("pushed commit to push branch", "revision", rev, "branch", sm.srcCfg.pushBranch)
|
||||
|
||||
// Push to any provided refspec.
|
||||
if obj.Spec.GitSpec.HasRefspec() {
|
||||
pushConfig.Refspecs = append(pushConfig.Refspecs, obj.Spec.GitSpec.Push.Refspec)
|
||||
if err := sm.gitClient.Push(gitOpCtx, pushConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tracelog.Info("pushed commit to refspec", "revision", rev, "refspecs", pushConfig.Refspecs)
|
||||
}
|
||||
|
||||
// Construct the result of the push operation and return.
|
||||
prOpts := []PushResultOption{WithPushResultRefspec(pushConfig.Refspecs)}
|
||||
if sm.srcCfg.switchBranch {
|
||||
prOpts = append(prOpts, WithPushResultSwitchBranch())
|
||||
}
|
||||
return NewPushResult(sm.srcCfg.pushBranch, rev, commitMsg, prOpts...)
|
||||
}
|
||||
|
||||
// templateMsg renders a msg template, returning the message or an error.
|
||||
func templateMsg(messageTemplate string, templateValues *TemplateData) (string, error) {
|
||||
if messageTemplate == "" {
|
||||
messageTemplate = defaultMessageTemplate
|
||||
}
|
||||
|
||||
// Includes only functions that are guaranteed to always evaluate to the same result for given input.
|
||||
// This removes the possibility of accidentally relying on where or when the template runs.
|
||||
// https://github.com/Masterminds/sprig/blob/3ac42c7bc5e4be6aa534e036fb19dde4a996da2e/functions.go#L70
|
||||
t, err := template.New("commit message").Funcs(sprig.HermeticTxtFuncMap()).Parse(messageTemplate)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to create commit message template from spec: %w", err)
|
||||
}
|
||||
|
||||
b := &strings.Builder{}
|
||||
if err := t.Execute(b, *templateValues); err != nil {
|
||||
return "", fmt.Errorf("failed to run template from spec: %w", err)
|
||||
}
|
||||
return b.String(), nil
|
||||
}
|
||||
|
||||
// PushResultOption allows configuring the options of PushResult.
|
||||
type PushResultOption func(*PushResult)
|
||||
|
||||
// WithPushResultSwitchBranch marks the PushResult with switchBranch.
|
||||
func WithPushResultSwitchBranch() func(*PushResult) {
|
||||
return func(pr *PushResult) {
|
||||
pr.switchBranch = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithPushResultRefspec sets the refspecs in the PushResult.
|
||||
func WithPushResultRefspec(refspecs []string) func(*PushResult) {
|
||||
return func(pr *PushResult) {
|
||||
pr.refspecs = append(pr.refspecs, refspecs...)
|
||||
}
|
||||
}
|
||||
|
||||
// PushResult is the result of a push operation.
|
||||
type PushResult struct {
|
||||
commit *git.Commit
|
||||
switchBranch bool
|
||||
branch string
|
||||
refspecs []string
|
||||
creationTime *metav1.Time
|
||||
}
|
||||
|
||||
// NewPushResult returns a new PushResult.
|
||||
func NewPushResult(branch string, rev string, commitMsg string, opts ...PushResultOption) (*PushResult, error) {
|
||||
if rev == "" {
|
||||
return nil, errors.New("empty push commit revision")
|
||||
}
|
||||
|
||||
pr := &PushResult{}
|
||||
for _, o := range opts {
|
||||
o(pr)
|
||||
}
|
||||
pr.commit = &git.Commit{
|
||||
Hash: git.ExtractHashFromRevision(rev),
|
||||
Reference: plumbing.NewBranchReferenceName(branch).String(),
|
||||
Message: commitMsg,
|
||||
}
|
||||
pr.branch = branch
|
||||
pr.creationTime = &metav1.Time{Time: time.Now()}
|
||||
|
||||
return pr, nil
|
||||
}
|
||||
|
||||
// Commit returns the revision of the pushed commit.
|
||||
func (pr PushResult) Commit() *git.Commit {
|
||||
return pr.commit
|
||||
}
|
||||
|
||||
// Time returns the time at which the push was performed.
|
||||
func (pr PushResult) Time() *metav1.Time {
|
||||
return pr.creationTime
|
||||
}
|
||||
|
||||
// SwitchBranch returns if the source has different checkout and push branch.
|
||||
func (pr PushResult) SwitchBranch() bool {
|
||||
return pr.switchBranch
|
||||
}
|
||||
|
||||
// Summary returns a summary of the PushResult.
|
||||
func (pr PushResult) Summary() string {
|
||||
var summary strings.Builder
|
||||
shortCommitHash := pr.Commit().Hash.String()
|
||||
if len(shortCommitHash) > 7 {
|
||||
shortCommitHash = shortCommitHash[:7]
|
||||
}
|
||||
summary.WriteString(fmt.Sprintf("pushed commit '%s' to branch '%s'", shortCommitHash, pr.branch))
|
||||
if len(pr.refspecs) > 0 {
|
||||
summary.WriteString(fmt.Sprintf(" and refspecs '%s'", strings.Join(pr.refspecs, "', '")))
|
||||
}
|
||||
if pr.Commit().Message != "" {
|
||||
summary.WriteString(fmt.Sprintf("\n%s", pr.Commit().Message))
|
||||
}
|
||||
return summary.String()
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,10 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: test
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: hello
|
||||
image: helloworld:1.0.0 # SETTER_SITE
|
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
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 testutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||
securejoin "github.com/cyphar/filepath-securejoin"
|
||||
"github.com/go-git/go-billy/v5/osfs"
|
||||
extgogit "github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/cache"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/storage/filesystem"
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
|
||||
"github.com/fluxcd/pkg/gittestserver"
|
||||
|
||||
"github.com/fluxcd/image-automation-controller/internal/constants"
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
const (
|
||||
signingSecretKey = "git.asc"
|
||||
signingPassphraseKey = "passphrase"
|
||||
)
|
||||
|
||||
func CheckoutBranch(g *WithT, repo *extgogit.Repository, branch string) {
|
||||
g.THelper()
|
||||
|
||||
wt, err := repo.Worktree()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = wt.Checkout(&extgogit.CheckoutOptions{
|
||||
Branch: plumbing.NewBranchReferenceName(branch),
|
||||
})
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func ReplaceMarker(path string, policyKey types.NamespacedName) error {
|
||||
return ReplaceMarkerWithMarker(path, policyKey, "SETTER_SITE")
|
||||
}
|
||||
|
||||
func ReplaceMarkerWithMarker(path string, policyKey types.NamespacedName, marker string) error {
|
||||
filebytes, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newfilebytes := bytes.ReplaceAll(filebytes, []byte(marker), []byte(setterRef(policyKey)))
|
||||
if err = os.WriteFile(path, newfilebytes, os.FileMode(0666)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setterRef(name types.NamespacedName) string {
|
||||
return fmt.Sprintf(`{"%s": "%s:%s"}`, constants.SetterShortHand, name.Namespace, name.Name)
|
||||
}
|
||||
|
||||
func CommitInRepo(ctx context.Context, g *WithT, repoURL, branch, remote, msg string, changeFiles func(path string)) plumbing.Hash {
|
||||
g.THelper()
|
||||
|
||||
repo, cloneDir, err := Clone(ctx, repoURL, branch, remote)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
defer func() { os.RemoveAll(cloneDir) }()
|
||||
|
||||
wt, err := repo.Worktree()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
changeFiles(wt.Filesystem.Root())
|
||||
|
||||
id := CommitWorkDir(g, repo, branch, msg)
|
||||
|
||||
origin, err := repo.Remote(remote)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
g.Expect(origin.Push(&extgogit.PushOptions{
|
||||
RemoteName: remote,
|
||||
RefSpecs: []config.RefSpec{config.RefSpec(BranchRefName(branch))},
|
||||
})).To(Succeed())
|
||||
return id
|
||||
}
|
||||
|
||||
func WaitForNewHead(g *WithT, repo *extgogit.Repository, branch, remote, preChangeHash string) {
|
||||
g.THelper()
|
||||
|
||||
var commitToResetTo *object.Commit
|
||||
|
||||
origin, err := repo.Remote(remote)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Now try to fetch new commits from that remote branch
|
||||
g.Eventually(func() bool {
|
||||
err := origin.Fetch(&extgogit.FetchOptions{
|
||||
RemoteName: remote,
|
||||
RefSpecs: []config.RefSpec{config.RefSpec(BranchRefName(branch))},
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
wt, err := repo.Worktree()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
err = wt.Checkout(&extgogit.CheckoutOptions{
|
||||
Branch: plumbing.NewBranchReferenceName(branch),
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
remoteHeadRef, err := repo.Head()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
remoteHeadHash := remoteHeadRef.Hash()
|
||||
|
||||
if preChangeHash != remoteHeadHash.String() {
|
||||
commitToResetTo, _ = repo.CommitObject(remoteHeadHash)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}, 10*time.Second, time.Second).Should(BeTrue())
|
||||
|
||||
if commitToResetTo != nil {
|
||||
wt, err := repo.Worktree()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// New commits in the remote branch -- reset the working tree head
|
||||
// to that. Note this does not create a local branch tracking the
|
||||
// remote, so it is a detached head.
|
||||
g.Expect(wt.Reset(&extgogit.ResetOptions{
|
||||
Commit: commitToResetTo.Hash,
|
||||
Mode: extgogit.HardReset,
|
||||
})).To(Succeed())
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise a git server with a repo including the files in dir.
|
||||
func InitGitRepo(g *WithT, gitServer *gittestserver.GitServer, fixture, branch, repoPath string) *extgogit.Repository {
|
||||
g.THelper()
|
||||
|
||||
workDir, err := securejoin.SecureJoin(gitServer.Root(), repoPath)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
repo := InitGitRepoPlain(g, fixture, workDir)
|
||||
|
||||
headRef, err := repo.Head()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
ref := plumbing.NewHashReference(
|
||||
plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branch)),
|
||||
headRef.Hash())
|
||||
|
||||
g.Expect(repo.Storer.SetReference(ref)).ToNot(HaveOccurred())
|
||||
|
||||
return repo
|
||||
}
|
||||
|
||||
func InitGitRepoPlain(g *WithT, fixture, repoPath string) *extgogit.Repository {
|
||||
g.THelper()
|
||||
|
||||
wt := osfs.New(repoPath)
|
||||
dot := osfs.New(filepath.Join(repoPath, extgogit.GitDirName))
|
||||
storer := filesystem.NewStorage(dot, cache.NewObjectLRUDefault())
|
||||
|
||||
repo, err := extgogit.Init(storer, wt)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
g.Expect(copyDir(fixture, repoPath)).ToNot(HaveOccurred())
|
||||
|
||||
_ = CommitWorkDir(g, repo, "main", "Initial commit")
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
return repo
|
||||
}
|
||||
|
||||
func HeadFromBranch(repo *extgogit.Repository, branchName string) (*object.Commit, error) {
|
||||
ref, err := repo.Storer.Reference(plumbing.ReferenceName("refs/heads/" + branchName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return repo.CommitObject(ref.Hash())
|
||||
}
|
||||
|
||||
func CommitWorkDir(g *WithT, repo *extgogit.Repository, branchName, message string) plumbing.Hash {
|
||||
g.THelper()
|
||||
|
||||
wt, err := repo.Worktree()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Checkout to an existing branch. If this is the first commit,
|
||||
// this is a no-op.
|
||||
_ = wt.Checkout(&extgogit.CheckoutOptions{
|
||||
Branch: plumbing.ReferenceName("refs/heads/" + branchName),
|
||||
})
|
||||
|
||||
status, err := wt.Status()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
for file := range status {
|
||||
wt.Add(file)
|
||||
}
|
||||
|
||||
sig := mockSignature(time.Now())
|
||||
c, err := wt.Commit(message, &extgogit.CommitOptions{
|
||||
All: true,
|
||||
Author: sig,
|
||||
Committer: sig,
|
||||
})
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = repo.Branch(branchName)
|
||||
if err == extgogit.ErrBranchNotFound {
|
||||
ref := plumbing.NewHashReference(
|
||||
plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branchName)), c)
|
||||
err = repo.Storer.SetReference(ref)
|
||||
}
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Now the target branch exists, we can checkout to it.
|
||||
err = wt.Checkout(&extgogit.CheckoutOptions{
|
||||
Branch: plumbing.ReferenceName("refs/heads/" + branchName),
|
||||
})
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func TagCommit(g *WithT, repo *extgogit.Repository, commit plumbing.Hash, annotated bool, tag string, time time.Time) (*plumbing.Reference, error) {
|
||||
g.THelper()
|
||||
|
||||
var opts *extgogit.CreateTagOptions
|
||||
if annotated {
|
||||
opts = &extgogit.CreateTagOptions{
|
||||
Tagger: mockSignature(time),
|
||||
Message: "Annotated tag for: " + tag,
|
||||
}
|
||||
}
|
||||
return repo.CreateTag(tag, commit, opts)
|
||||
}
|
||||
|
||||
func copyDir(src string, dest string) error {
|
||||
file, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !file.IsDir() {
|
||||
return fmt.Errorf("source %q must be a directory", file.Name())
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(dest, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files, err := ioutil.ReadDir(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
srcFile := filepath.Join(src, f.Name())
|
||||
destFile := filepath.Join(dest, f.Name())
|
||||
|
||||
if f.IsDir() {
|
||||
if err = copyDir(srcFile, destFile); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !f.IsDir() {
|
||||
// ignore symlinks
|
||||
if f.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
continue
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(srcFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = os.WriteFile(destFile, content, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func BranchRefName(branch string) string {
|
||||
return fmt.Sprintf("refs/heads/%s:refs/heads/%s", branch, branch)
|
||||
}
|
||||
|
||||
func mockSignature(time time.Time) *object.Signature {
|
||||
return &object.Signature{
|
||||
Name: "Jane Doe",
|
||||
Email: "author@example.com",
|
||||
When: time,
|
||||
}
|
||||
}
|
||||
|
||||
func Clone(ctx context.Context, repoURL, branchName, remote string) (*extgogit.Repository, string, error) {
|
||||
dir, err := os.MkdirTemp("", "iac-clone-*")
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
opts := &extgogit.CloneOptions{
|
||||
URL: repoURL,
|
||||
RemoteName: remote,
|
||||
ReferenceName: plumbing.NewBranchReferenceName(branchName),
|
||||
}
|
||||
|
||||
wt := osfs.New(dir, osfs.WithBoundOS())
|
||||
dot := osfs.New(filepath.Join(dir, extgogit.GitDirName), osfs.WithBoundOS())
|
||||
storer := filesystem.NewStorage(dot, cache.NewObjectLRUDefault())
|
||||
|
||||
repo, err := extgogit.Clone(storer, wt, opts)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
w, err := repo.Worktree()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
err = w.Checkout(&extgogit.CheckoutOptions{
|
||||
Branch: plumbing.NewBranchReferenceName(branchName),
|
||||
Create: false,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return repo, dir, nil
|
||||
}
|
||||
|
||||
func CommitIdFromBranch(repo *extgogit.Repository, branchName string) string {
|
||||
commitId := ""
|
||||
head, err := HeadFromBranch(repo, branchName)
|
||||
|
||||
if err == nil {
|
||||
commitId = head.Hash.String()
|
||||
}
|
||||
return commitId
|
||||
}
|
||||
|
||||
func GetRemoteHead(repo *extgogit.Repository, branchName, remote string) (plumbing.Hash, error) {
|
||||
rmt, err := repo.Remote(remote)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
err = rmt.Fetch(&extgogit.FetchOptions{
|
||||
RemoteName: remote,
|
||||
RefSpecs: []config.RefSpec{config.RefSpec(BranchRefName(branchName))},
|
||||
})
|
||||
if err != nil && !errors.Is(err, extgogit.NoErrAlreadyUpToDate) {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
remoteHeadRef, err := HeadFromBranch(repo, branchName)
|
||||
if err != nil {
|
||||
return plumbing.ZeroHash, err
|
||||
}
|
||||
|
||||
return remoteHeadRef.Hash, nil
|
||||
}
|
||||
|
||||
// SetUpGitTestServer creates and returns a git test server. The caller must
|
||||
// ensure it's stopped and cleaned up.
|
||||
func SetUpGitTestServer(g *WithT) *gittestserver.GitServer {
|
||||
g.THelper()
|
||||
|
||||
gitServer, err := gittestserver.NewTempGitServer()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
username := rand.String(5)
|
||||
password := rand.String(5)
|
||||
|
||||
gitServer.Auth(username, password)
|
||||
gitServer.AutoCreate()
|
||||
g.Expect(gitServer.StartHTTP()).ToNot(HaveOccurred())
|
||||
gitServer.KeyDir(filepath.Join(gitServer.Root(), "keys"))
|
||||
g.Expect(gitServer.ListenSSH()).ToNot(HaveOccurred())
|
||||
return gitServer
|
||||
}
|
||||
|
||||
func GetSigningKeyPairSecret(g *WithT, name, namespace string) (*corev1.Secret, *openpgp.Entity) {
|
||||
g.THelper()
|
||||
|
||||
passphrase := "abcde12345"
|
||||
pgpEntity, key := GetSigningKeyPair(g, passphrase)
|
||||
|
||||
// Create the secret containing signing key.
|
||||
sec := &corev1.Secret{
|
||||
Data: map[string][]byte{
|
||||
signingSecretKey: key,
|
||||
signingPassphraseKey: []byte(passphrase),
|
||||
},
|
||||
}
|
||||
sec.Name = name
|
||||
sec.Namespace = namespace
|
||||
return sec, pgpEntity
|
||||
}
|
||||
|
||||
func GetSigningKeyPair(g *WithT, passphrase string) (*openpgp.Entity, []byte) {
|
||||
g.THelper()
|
||||
|
||||
pgpEntity, err := openpgp.NewEntity("", "", "", nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// Configure OpenPGP armor encoder.
|
||||
b := bytes.NewBuffer(nil)
|
||||
w, err := armor.Encode(b, openpgp.PrivateKeyType, nil)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
// Serialize private key.
|
||||
g.Expect(pgpEntity.SerializePrivate(w, nil)).To(Succeed())
|
||||
g.Expect(w.Close()).To(Succeed())
|
||||
|
||||
if passphrase != "" {
|
||||
g.Expect(pgpEntity.PrivateKey.Encrypt([]byte(passphrase))).To(Succeed())
|
||||
}
|
||||
|
||||
return pgpEntity, b.Bytes()
|
||||
}
|
||||
|
||||
func ImageToRef(image string) *imagev1_reflect.ImageRef {
|
||||
var digest string
|
||||
|
||||
if idx := strings.LastIndex(image, "@"); idx != -1 {
|
||||
image, digest = image[:idx], image[idx+1:]
|
||||
}
|
||||
|
||||
var tag string
|
||||
|
||||
if idx := strings.LastIndex(image, ":"); idx != -1 {
|
||||
image, tag = image[:idx], image[idx+1:]
|
||||
}
|
||||
|
||||
return &imagev1_reflect.ImageRef{
|
||||
Name: image,
|
||||
Tag: tag,
|
||||
Digest: digest,
|
||||
}
|
||||
}
|
37
main.go
37
main.go
|
@ -31,9 +31,12 @@ import (
|
|||
ctrlcache "sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
ctrlcfg "sigs.k8s.io/controller-runtime/pkg/config"
|
||||
ctrlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
|
||||
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
||||
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/auth"
|
||||
cache "github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/runtime/acl"
|
||||
"github.com/fluxcd/pkg/runtime/client"
|
||||
helper "github.com/fluxcd/pkg/runtime/controller"
|
||||
|
@ -48,7 +51,7 @@ import (
|
|||
|
||||
"github.com/fluxcd/pkg/git"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta2"
|
||||
"github.com/fluxcd/image-automation-controller/internal/features"
|
||||
|
||||
// +kubebuilder:scaffold:imports
|
||||
|
@ -57,9 +60,6 @@ import (
|
|||
|
||||
const (
|
||||
controllerName = "image-automation-controller"
|
||||
|
||||
// recoverPanic indicates whether panic caused by reconciles should be recovered.
|
||||
recoverPanic = true
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -76,6 +76,10 @@ func init() {
|
|||
}
|
||||
|
||||
func main() {
|
||||
const (
|
||||
tokenCacheDefaultMaxSize = 100
|
||||
)
|
||||
|
||||
var (
|
||||
metricsAddr string
|
||||
eventsAddr string
|
||||
|
@ -88,6 +92,7 @@ func main() {
|
|||
featureGates feathelper.FeatureGates
|
||||
watchOptions helper.WatchOptions
|
||||
concurrent int
|
||||
tokenCacheOptions cache.TokenFlags
|
||||
)
|
||||
|
||||
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
|
||||
|
@ -106,6 +111,7 @@ func main() {
|
|||
rateLimiterOptions.BindFlags(flag.CommandLine)
|
||||
featureGates.BindFlags(flag.CommandLine)
|
||||
watchOptions.BindFlags(flag.CommandLine)
|
||||
tokenCacheOptions.BindFlags(flag.CommandLine, tokenCacheDefaultMaxSize)
|
||||
|
||||
flag.Parse()
|
||||
|
||||
|
@ -118,6 +124,14 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
switch enabled, err := features.Enabled(auth.FeatureGateObjectLevelWorkloadIdentity); {
|
||||
case err != nil:
|
||||
setupLog.Error(err, "unable to check feature gate "+auth.FeatureGateObjectLevelWorkloadIdentity)
|
||||
os.Exit(1)
|
||||
case enabled:
|
||||
auth.EnableObjectLevelWorkloadIdentity()
|
||||
}
|
||||
|
||||
watchNamespace := ""
|
||||
if !watchOptions.AllNamespaces {
|
||||
watchNamespace = os.Getenv("RUNTIME_NAMESPACE")
|
||||
|
@ -197,6 +211,19 @@ func main() {
|
|||
|
||||
metricsH := helper.NewMetrics(mgr, metrics.MustMakeRecorder(), imagev1.ImageUpdateAutomationFinalizer)
|
||||
|
||||
var tokenCache *cache.TokenCache
|
||||
if tokenCacheOptions.MaxSize > 0 {
|
||||
var err error
|
||||
tokenCache, err = cache.NewTokenCache(tokenCacheOptions.MaxSize,
|
||||
cache.WithMaxDuration(tokenCacheOptions.MaxDuration),
|
||||
cache.WithMetricsRegisterer(ctrlmetrics.Registry),
|
||||
cache.WithMetricsPrefix("gotk_token_"))
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to create token cache")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
ctx := ctrl.SetupSignalHandler()
|
||||
|
||||
if err := (&controller.ImageUpdateAutomationReconciler{
|
||||
|
@ -204,8 +231,10 @@ func main() {
|
|||
EventRecorder: eventRecorder,
|
||||
Metrics: metricsH,
|
||||
NoCrossNamespaceRef: aclOptions.NoCrossNamespaceRefs,
|
||||
ControllerName: controllerName,
|
||||
}).SetupWithManager(ctx, mgr, controller.ImageUpdateAutomationReconcilerOptions{
|
||||
RateLimiter: helper.GetRateLimiter(rateLimiterOptions),
|
||||
TokenCache: tokenCache,
|
||||
}); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "ImageUpdateAutomation")
|
||||
os.Exit(1)
|
||||
|
|
|
@ -93,7 +93,7 @@ func (r *ScreeningLocalReader) Read() ([]*yaml.RNode, error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
if ext := filepath.Ext(p); ext != ".yaml" && ext != ".yml" {
|
||||
if ext := filepath.Ext(p); ext != ".yaml" && ext != ".yml" && filepath.Base(p) != "Kustomization" {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -33,11 +33,12 @@ func TestScreeningLocalReader(t *testing.T) {
|
|||
}
|
||||
nodes, err := r.Read()
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
// the test fixture has three files that contain the marker:
|
||||
// - otherns.yaml
|
||||
// the test fixture has four files that contain the marker:
|
||||
// - marked.yaml
|
||||
// - kustomization.yaml
|
||||
g.Expect(len(nodes)).To(Equal(3))
|
||||
// - otherns.yaml
|
||||
// - kustomization.yml
|
||||
// - Kustomization
|
||||
g.Expect(len(nodes)).To(Equal(4))
|
||||
filesSeen := map[string]struct{}{}
|
||||
for i := range nodes {
|
||||
path, _, err := kioutil.GetFileAnnotations(nodes[i])
|
||||
|
@ -45,9 +46,10 @@ func TestScreeningLocalReader(t *testing.T) {
|
|||
filesSeen[path] = struct{}{}
|
||||
}
|
||||
g.Expect(filesSeen).To(Equal(map[string]struct{}{
|
||||
"marked.yaml": {},
|
||||
"kustomization.yaml": {},
|
||||
"otherns.yaml": {},
|
||||
"marked.yaml": {},
|
||||
"otherns.yaml": {},
|
||||
"kustomization.yml": {},
|
||||
"Kustomization": {},
|
||||
}))
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package update
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
. "github.com/onsi/gomega"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
func TestSetAllCallbackAccept(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
object *yaml.RNode
|
||||
settersSchema *spec.Schema
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "Accept - Scalar Node",
|
||||
object: yaml.NewRNode(&yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Value: "test",
|
||||
}),
|
||||
settersSchema: &spec.Schema{},
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Accept - Scalar Node - Error",
|
||||
object: yaml.NewRNode(&yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Value: "test",
|
||||
}),
|
||||
settersSchema: nil,
|
||||
expectedError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
callbackInstance := SetAllCallback{
|
||||
SettersSchema: test.settersSchema,
|
||||
Trace: logr.Discard(),
|
||||
}
|
||||
|
||||
err := accept(&callbackInstance, test.object, "", test.settersSchema)
|
||||
g := NewWithT(t)
|
||||
if test.expectedError {
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
} else {
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExtFromSchema(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
schema *spec.Schema
|
||||
expectedExtension *extension
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "Extension Present",
|
||||
schema: &spec.Schema{
|
||||
VendorExtensible: spec.VendorExtensible{
|
||||
Extensions: map[string]interface{}{
|
||||
K8sCliExtensionKey: &extension{
|
||||
Setter: &setter{
|
||||
Name: "testSetter",
|
||||
Value: "testValue",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedExtension: &extension{
|
||||
Setter: &setter{
|
||||
Name: "testSetter",
|
||||
Value: "testValue",
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Extension Not Present",
|
||||
schema: &spec.Schema{},
|
||||
expectedError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
ext, err := getExtFromSchema(test.schema)
|
||||
|
||||
if test.expectedError {
|
||||
g.Expect(err).To(HaveOccurred())
|
||||
} else {
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
g.Expect(ext).To(Equal(test.expectedExtension))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -96,3 +96,66 @@ func (r Result) Objects() map[ObjectIdentifier][]ImageRef {
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ResultV2 contains Result of update and also the file changes made during the
|
||||
// update. This extends the Result to include details about the exact changes
|
||||
// made to the files and the objects in them. It has a nested structure
|
||||
// file->objects->changes.
|
||||
type ResultV2 struct {
|
||||
ImageResult Result
|
||||
FileChanges map[string]ObjectChanges
|
||||
}
|
||||
|
||||
// ObjectChanges contains all the changes made to objects.
|
||||
type ObjectChanges map[ObjectIdentifier][]Change
|
||||
|
||||
// Change contains the setter that resulted in a Change, the old and the new
|
||||
// value after the Change.
|
||||
type Change struct {
|
||||
OldValue string
|
||||
NewValue string
|
||||
Setter string
|
||||
}
|
||||
|
||||
// AddChange adds changes to Resultv2 for a given file, object and changes
|
||||
// associated with it.
|
||||
func (r *ResultV2) AddChange(file string, objectID ObjectIdentifier, changes ...Change) {
|
||||
if r.FileChanges == nil {
|
||||
r.FileChanges = map[string]ObjectChanges{}
|
||||
}
|
||||
// Create an entry for the file if not present.
|
||||
_, ok := r.FileChanges[file]
|
||||
if !ok {
|
||||
r.FileChanges[file] = ObjectChanges{}
|
||||
}
|
||||
// Append to the changes for the object.
|
||||
r.FileChanges[file][objectID] = append(r.FileChanges[file][objectID], changes...)
|
||||
}
|
||||
|
||||
// Changes returns all the changes that were made in at least one update.
|
||||
func (r ResultV2) Changes() []Change {
|
||||
seen := make(map[Change]struct{})
|
||||
var result []Change
|
||||
for _, objChanges := range r.FileChanges {
|
||||
for _, changes := range objChanges {
|
||||
for _, change := range changes {
|
||||
if _, ok := seen[change]; !ok {
|
||||
seen[change] = struct{}{}
|
||||
result = append(result, change)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Objects returns ObjectChanges, regardless of which file they appear in.
|
||||
func (r ResultV2) Objects() ObjectChanges {
|
||||
result := make(ObjectChanges)
|
||||
for _, objChanges := range r.FileChanges {
|
||||
for obj, change := range objChanges {
|
||||
result[obj] = change
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -92,3 +92,80 @@ func TestUpdateResults(t *testing.T) {
|
|||
},
|
||||
}))
|
||||
}
|
||||
|
||||
func TestResultV2(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
var result ResultV2
|
||||
objectNames := []ObjectIdentifier{
|
||||
{yaml.ResourceIdentifier{
|
||||
NameMeta: yaml.NameMeta{Namespace: "ns", Name: "foo"},
|
||||
}},
|
||||
{yaml.ResourceIdentifier{
|
||||
NameMeta: yaml.NameMeta{Namespace: "ns", Name: "bar"},
|
||||
}},
|
||||
}
|
||||
|
||||
result.AddChange("foo.yaml", objectNames[0], Change{
|
||||
OldValue: "aaa",
|
||||
NewValue: "bbb",
|
||||
Setter: "foo-ns:policy:name",
|
||||
})
|
||||
result.AddChange("bar.yaml", objectNames[1], Change{
|
||||
OldValue: "cccc:v1.0",
|
||||
NewValue: "cccc:v1.2",
|
||||
Setter: "foo-ns:policy",
|
||||
})
|
||||
|
||||
result = ResultV2{
|
||||
FileChanges: map[string]ObjectChanges{
|
||||
"foo.yaml": {
|
||||
objectNames[0]: []Change{
|
||||
{
|
||||
OldValue: "aaa",
|
||||
NewValue: "bbb",
|
||||
Setter: "foo-ns:policy:name",
|
||||
},
|
||||
},
|
||||
},
|
||||
"bar.yaml": {
|
||||
objectNames[1]: []Change{
|
||||
{
|
||||
OldValue: "cccc:v1.0",
|
||||
NewValue: "cccc:v1.2",
|
||||
Setter: "foo-ns:policy",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
g.Expect(result.Changes()).To(ContainElements([]Change{
|
||||
{
|
||||
OldValue: "aaa",
|
||||
NewValue: "bbb",
|
||||
Setter: "foo-ns:policy:name",
|
||||
},
|
||||
{
|
||||
OldValue: "cccc:v1.0",
|
||||
NewValue: "cccc:v1.2",
|
||||
Setter: "foo-ns:policy",
|
||||
},
|
||||
}))
|
||||
g.Expect(result.Objects()).To(Equal(ObjectChanges{
|
||||
objectNames[0]: []Change{
|
||||
{
|
||||
OldValue: "aaa",
|
||||
NewValue: "bbb",
|
||||
Setter: "foo-ns:policy:name",
|
||||
},
|
||||
},
|
||||
objectNames[1]: []Change{
|
||||
{
|
||||
OldValue: "cccc:v1.0",
|
||||
NewValue: "cccc:v1.2",
|
||||
Setter: "foo-ns:policy",
|
||||
},
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package update
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
|
@ -31,21 +30,17 @@ import (
|
|||
"sigs.k8s.io/kustomize/kyaml/sets"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
|
||||
"github.com/fluxcd/image-automation-controller/internal/constants"
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
const (
|
||||
// This is preserved from setters2
|
||||
K8sCliExtensionKey = "x-k8s-cli"
|
||||
|
||||
// SetterShortHand is a shorthand that can be used to mark
|
||||
// setters; instead of
|
||||
// # { "$ref": "#/definitions/
|
||||
SetterShortHand = "$imagepolicy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fieldmeta.SetShortHandRef(SetterShortHand)
|
||||
fieldmeta.SetShortHandRef(constants.SetterShortHand)
|
||||
// this prevents the global schema, should it be initialised, from
|
||||
// parsing all the Kubernetes openAPI definitions, which is not
|
||||
// necessary.
|
||||
|
@ -56,6 +51,15 @@ func init() {
|
|||
// that contain an "in scope" image policy marker, and writes files it
|
||||
// updated (and only those files) back to `outpath`.
|
||||
func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []imagev1_reflect.ImagePolicy) (Result, error) {
|
||||
result, err := UpdateV2WithSetters(tracelog, inpath, outpath, policies)
|
||||
return result.ImageResult, err
|
||||
}
|
||||
|
||||
// UpdateV2WithSetters takes all YAML files from `inpath`, updates any
|
||||
// that contain an "in scope" image policy marker, and writes files it
|
||||
// updated (and only those files) back to `outpath`. It also returns the result
|
||||
// of the changes it made as ResultV2.
|
||||
func UpdateV2WithSetters(tracelog logr.Logger, inpath, outpath string, policies []imagev1_reflect.ImagePolicy) (ResultV2, error) {
|
||||
// the OpenAPI schema is a package variable in kyaml/openapi. In
|
||||
// lieu of being able to isolate invocations (per
|
||||
// https://github.com/kubernetes-sigs/kustomize/issues/3058), I
|
||||
|
@ -99,13 +103,15 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
Files: make(map[string]FileResult),
|
||||
}
|
||||
|
||||
var resultV2 ResultV2
|
||||
|
||||
// Compilng the result needs the file, the image ref used, and the
|
||||
// object. Each setter will supply its own name to its callback,
|
||||
// which can be used to look up the image ref; the file and object
|
||||
// we will get from `setAll` which keeps track of those as it
|
||||
// iterates.
|
||||
imageRefs := make(map[string]imageRef)
|
||||
setAllCallback := func(file, setterName string, node *yaml.RNode) {
|
||||
setAllCallback := func(file, setterName string, node *yaml.RNode, old, new string) {
|
||||
ref, ok := imageRefs[setterName]
|
||||
if !ok {
|
||||
return
|
||||
|
@ -117,6 +123,15 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
}
|
||||
oid := ObjectIdentifier{meta.GetIdentifier()}
|
||||
|
||||
// Record the change.
|
||||
ch := Change{
|
||||
OldValue: old,
|
||||
NewValue: new,
|
||||
Setter: setterName,
|
||||
}
|
||||
// Append the change for the file and identifier.
|
||||
resultV2.AddChange(file, oid, ch)
|
||||
|
||||
fileres, ok := result.Files[file]
|
||||
if !ok {
|
||||
fileres = FileResult{
|
||||
|
@ -124,7 +139,7 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
}
|
||||
result.Files[file] = fileres
|
||||
}
|
||||
objres, ok := fileres.Objects[oid]
|
||||
objres := fileres.Objects[oid]
|
||||
for _, n := range objres {
|
||||
if n == ref {
|
||||
return
|
||||
|
@ -136,7 +151,7 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
|
||||
defs := map[string]spec.Schema{}
|
||||
for _, policy := range policies {
|
||||
if policy.Status.LatestImage == "" {
|
||||
if policy.Status.LatestRef == nil {
|
||||
continue
|
||||
}
|
||||
// Using strict validation would mean any image that omits the
|
||||
|
@ -145,10 +160,10 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
// filled in. Usually this would mean the tag would end up
|
||||
// being `latest` if empty in the input; but I'm assuming here
|
||||
// that the policy won't have a tagless ref.
|
||||
image := policy.Status.LatestImage
|
||||
image := policy.Status.LatestRef.String()
|
||||
r, err := name.ParseReference(image, name.WeakValidation)
|
||||
if err != nil {
|
||||
return Result{}, fmt.Errorf("encountered invalid image ref %q: %w", policy.Status.LatestImage, err)
|
||||
return ResultV2{}, fmt.Errorf("encountered invalid image ref %q: %w", image, err)
|
||||
}
|
||||
ref := imageRef{
|
||||
Reference: r,
|
||||
|
@ -158,15 +173,13 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
},
|
||||
}
|
||||
|
||||
tag := ref.Identifier()
|
||||
// annoyingly, neither the library imported above, nor an
|
||||
// alternative I found, will yield the original image name;
|
||||
// this is an easy way to get it
|
||||
name := strings.TrimSuffix(image, ":"+tag)
|
||||
tag := policy.Status.LatestRef.Tag
|
||||
name := policy.Status.LatestRef.Name
|
||||
digest := policy.Status.LatestRef.Digest
|
||||
|
||||
imageSetter := fmt.Sprintf("%s:%s", policy.GetNamespace(), policy.GetName())
|
||||
tracelog.Info("adding setter", "name", imageSetter)
|
||||
defs[fieldmeta.SetterDefinitionPrefix+imageSetter] = setterSchema(imageSetter, policy.Status.LatestImage)
|
||||
defs[fieldmeta.SetterDefinitionPrefix+imageSetter] = setterSchema(imageSetter, image)
|
||||
imageRefs[imageSetter] = ref
|
||||
|
||||
tagSetter := imageSetter + ":tag"
|
||||
|
@ -174,11 +187,15 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
defs[fieldmeta.SetterDefinitionPrefix+tagSetter] = setterSchema(tagSetter, tag)
|
||||
imageRefs[tagSetter] = ref
|
||||
|
||||
// Context().Name() gives the image repository _as supplied_
|
||||
nameSetter := imageSetter + ":name"
|
||||
tracelog.Info("adding setter", "name", nameSetter)
|
||||
defs[fieldmeta.SetterDefinitionPrefix+nameSetter] = setterSchema(nameSetter, name)
|
||||
imageRefs[nameSetter] = ref
|
||||
|
||||
digestSetter := imageSetter + ":digest"
|
||||
tracelog.Info("adding setter", "name", digestSetter)
|
||||
defs[fieldmeta.SetterDefinitionPrefix+digestSetter] = setterSchema(digestSetter, digest)
|
||||
imageRefs[digestSetter] = ref
|
||||
}
|
||||
|
||||
settersSchema.Definitions = defs
|
||||
|
@ -186,7 +203,7 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
// get ready with the reader and writer
|
||||
reader := &ScreeningLocalReader{
|
||||
Path: inpath,
|
||||
Token: fmt.Sprintf("%q", SetterShortHand),
|
||||
Token: fmt.Sprintf("%q", constants.SetterShortHand),
|
||||
Trace: tracelog,
|
||||
}
|
||||
writer := &kio.LocalPackageWriter{
|
||||
|
@ -204,9 +221,12 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
// go!
|
||||
err := pipeline.Execute()
|
||||
if err != nil {
|
||||
return Result{}, err
|
||||
return ResultV2{}, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
// Combine the results.
|
||||
resultV2.ImageResult = result
|
||||
return resultV2, nil
|
||||
}
|
||||
|
||||
// setAll returns a kio.Filter using the supplied SetAllCallback
|
||||
|
@ -215,7 +235,7 @@ func UpdateWithSetters(tracelog logr.Logger, inpath, outpath string, policies []
|
|||
// files with changed nodes. This is based on
|
||||
// [`SetAll`](https://github.com/kubernetes-sigs/kustomize/blob/kyaml/v0.10.16/kyaml/setters2/set.go#L503
|
||||
// from kyaml/kio.
|
||||
func setAll(schema *spec.Schema, tracelog logr.Logger, callback func(file, setterName string, node *yaml.RNode)) kio.Filter {
|
||||
func setAll(schema *spec.Schema, tracelog logr.Logger, callback func(file, setterName string, node *yaml.RNode, old, new string)) kio.Filter {
|
||||
filter := &SetAllCallback{
|
||||
SettersSchema: schema,
|
||||
Trace: tracelog,
|
||||
|
@ -231,7 +251,7 @@ func setAll(schema *spec.Schema, tracelog logr.Logger, callback func(file, sette
|
|||
|
||||
filter.Callback = func(setter, oldValue, newValue string) {
|
||||
if newValue != oldValue {
|
||||
callback(path, setter, nodes[i])
|
||||
callback(path, setter, nodes[i], oldValue, newValue)
|
||||
filesToUpdate.Insert(path)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# This is not intended to be a working kustomization
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- irrelevant.yaml
|
||||
images:
|
||||
- name: container
|
||||
newName: index.repo.fake/updated # {"$imagepolicy": "automation-ns:policy:name"}
|
||||
newTag: v1.0.1 # {"$imagepolicy": "automation-ns:policy:tag"}
|
|
@ -7,6 +7,7 @@ images:
|
|||
- name: container
|
||||
newName: index.repo.fake/updated # {"$imagepolicy": "automation-ns:policy:name"}
|
||||
newTag: v1.0.1 # {"$imagepolicy": "automation-ns:policy:tag"}
|
||||
newDigest: sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be # {"$imagepolicy": "automation-ns:policy-with-digest:digest"}
|
||||
# Prove fix for https://github.com/fluxcd/flux2/issues/3284
|
||||
patches:
|
||||
- patch: |
|
||||
|
@ -24,3 +25,4 @@ patches:
|
|||
version: v1
|
||||
kind: Deployment
|
||||
name: sxxxxdadminservice
|
||||
image: image:v1.0.0@sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be # {"$imagepolicy": "automation-ns:policy-with-digest"}
|
|
@ -0,0 +1,9 @@
|
|||
# This is not intended to be a working kustomization
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- irrelevant.yaml
|
||||
images:
|
||||
- name: container
|
||||
newName: replaced # {"$imagepolicy": "automation-ns:policy:name"}
|
||||
newTag: v1 # {"$imagepolicy": "automation-ns:policy:tag"}
|
|
@ -7,6 +7,7 @@ images:
|
|||
- name: container
|
||||
newName: replaced # {"$imagepolicy": "automation-ns:policy:name"}
|
||||
newTag: v1 # {"$imagepolicy": "automation-ns:policy:tag"}
|
||||
newDigest: sha256:1234567890abcdef # {"$imagepolicy": "automation-ns:policy-with-digest:digest"}
|
||||
# Prove fix for https://github.com/fluxcd/flux2/issues/3284
|
||||
patches:
|
||||
- patch: |
|
||||
|
@ -24,3 +25,4 @@ patches:
|
|||
version: v1
|
||||
kind: Deployment
|
||||
name: sxxxxdadminservice
|
||||
image: image # {"$imagepolicy": "automation-ns:policy-with-digest"}
|
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||
package update
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
|
@ -28,6 +26,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
|
||||
"github.com/fluxcd/image-automation-controller/internal/testutil"
|
||||
"github.com/fluxcd/image-automation-controller/pkg/test"
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
)
|
||||
|
@ -37,29 +36,35 @@ func TestUpdateWithSetters(t *testing.T) {
|
|||
|
||||
policies := []imagev1_reflect.ImagePolicy{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{ // name matches marker used in testdata/setters/{original,expected}
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "automation-ns",
|
||||
Name: "policy",
|
||||
},
|
||||
Status: imagev1_reflect.ImagePolicyStatus{
|
||||
LatestImage: "index.repo.fake/updated:v1.0.1",
|
||||
LatestRef: testutil.ImageToRef("index.repo.fake/updated:v1.0.1"),
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{ // name matches marker used in testdata/setters/{original,expected}
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "automation-ns",
|
||||
Name: "unchanged",
|
||||
},
|
||||
Status: imagev1_reflect.ImagePolicyStatus{
|
||||
LatestImage: "image:v1.0.0",
|
||||
LatestRef: testutil.ImageToRef("image:v1.0.0"),
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "automation-ns",
|
||||
Name: "policy-with-digest",
|
||||
},
|
||||
Status: imagev1_reflect.ImagePolicyStatus{
|
||||
LatestRef: testutil.ImageToRef("image:v1.0.0@sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tmp, err := ioutil.TempDir("", "gotest")
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
tmp := t.TempDir()
|
||||
result, err := UpdateWithSetters(logr.Discard(), "testdata/setters/original", tmp, policies)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
test.ExpectMatchingDirectories(g, tmp, "testdata/setters/expected")
|
||||
|
@ -80,15 +85,30 @@ func TestUpdateWithSetters(t *testing.T) {
|
|||
Name: "foo",
|
||||
},
|
||||
}}
|
||||
|
||||
r, _ := name.ParseReference("index.repo.fake/updated:v1.0.1")
|
||||
expectedImageRef := imageRef{r, types.NamespacedName{
|
||||
Name: "policy",
|
||||
Namespace: "automation-ns",
|
||||
}}
|
||||
|
||||
r, _ = name.ParseReference("image:v1.0.0@sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be")
|
||||
expectedImageRefDigest := imageRef{r, types.NamespacedName{
|
||||
Name: "policy-with-digest",
|
||||
Namespace: "automation-ns",
|
||||
}}
|
||||
|
||||
expectedResult := Result{
|
||||
Files: map[string]FileResult{
|
||||
"kustomization.yaml": {
|
||||
"kustomization.yml": {
|
||||
Objects: map[ObjectIdentifier][]ImageRef{
|
||||
kustomizeResourceID: {
|
||||
expectedImageRef,
|
||||
expectedImageRefDigest,
|
||||
},
|
||||
},
|
||||
},
|
||||
"Kustomization": {
|
||||
Objects: map[ObjectIdentifier][]ImageRef{
|
||||
kustomizeResourceID: {
|
||||
expectedImageRef,
|
||||
|
@ -106,4 +126,65 @@ func TestUpdateWithSetters(t *testing.T) {
|
|||
}
|
||||
|
||||
g.Expect(result).To(Equal(expectedResult))
|
||||
|
||||
// Test ResultV2.
|
||||
tmp2 := t.TempDir()
|
||||
resultV2, err := UpdateV2WithSetters(logr.Discard(), "testdata/setters/original", tmp2, policies)
|
||||
g.Expect(err).ToNot(HaveOccurred())
|
||||
test.ExpectMatchingDirectories(g, tmp2, "testdata/setters/expected")
|
||||
|
||||
expectedResultV2 := ResultV2{
|
||||
ImageResult: expectedResult,
|
||||
FileChanges: map[string]ObjectChanges{
|
||||
"kustomization.yml": {
|
||||
kustomizeResourceID: []Change{
|
||||
{
|
||||
OldValue: "replaced",
|
||||
NewValue: "index.repo.fake/updated",
|
||||
Setter: "automation-ns:policy:name",
|
||||
},
|
||||
{
|
||||
OldValue: "v1",
|
||||
NewValue: "v1.0.1",
|
||||
Setter: "automation-ns:policy:tag",
|
||||
},
|
||||
{
|
||||
OldValue: "sha256:1234567890abcdef",
|
||||
NewValue: "sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be",
|
||||
Setter: "automation-ns:policy-with-digest:digest",
|
||||
},
|
||||
{
|
||||
OldValue: "image",
|
||||
NewValue: "image:v1.0.0@sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be",
|
||||
Setter: "automation-ns:policy-with-digest",
|
||||
},
|
||||
},
|
||||
},
|
||||
"Kustomization": {
|
||||
kustomizeResourceID: []Change{
|
||||
{
|
||||
OldValue: "replaced",
|
||||
NewValue: "index.repo.fake/updated",
|
||||
Setter: "automation-ns:policy:name",
|
||||
},
|
||||
{
|
||||
OldValue: "v1",
|
||||
NewValue: "v1.0.1",
|
||||
Setter: "automation-ns:policy:tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
"marked.yaml": {
|
||||
markedResourceID: []Change{
|
||||
{
|
||||
OldValue: "image:v1.0.0",
|
||||
NewValue: "index.repo.fake/updated:v1.0.1",
|
||||
Setter: "automation-ns:policy",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
g.Expect(resultV2).To(Equal(expectedResultV2))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
FROM gcr.io/oss-fuzz-base/base-builder-go
|
||||
|
||||
RUN wget https://go.dev/dl/go1.20.5.linux-amd64.tar.gz \
|
||||
RUN wget https://go.dev/dl/go1.24.0.linux-amd64.tar.gz \
|
||||
&& mkdir temp-go \
|
||||
&& rm -rf /root/.go/* \
|
||||
&& tar -C temp-go/ -xzf go1.20.5.linux-amd64.tar.gz \
|
||||
&& tar -C temp-go/ -xzf go1.24.0.linux-amd64.tar.gz \
|
||||
&& mv temp-go/go/* /root/.go/
|
||||
|
||||
ENV SRC=$GOPATH/src/github.com/fluxcd/image-automation-controller
|
||||
|
|
Loading…
Reference in New Issue