mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-02-20 09:38:49 +01:00
Compare commits
58 Commits
commit-ser
...
cherry-pic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09eede0c17 | ||
|
|
f260510f38 | ||
|
|
079754c639 | ||
|
|
dc43124058 | ||
|
|
b6af657295 | ||
|
|
a3624a3f20 | ||
|
|
01ae20d1b3 | ||
|
|
89ef3563db | ||
|
|
831e4525c3 | ||
|
|
f8d6665c67 | ||
|
|
0680ddbdf9 | ||
|
|
ad36916ec4 | ||
|
|
af54ef8db5 | ||
|
|
68606c6caf | ||
|
|
6a8cb6eff0 | ||
|
|
d03ccf305c | ||
|
|
7f45c9e093 | ||
|
|
449e6939b2 | ||
|
|
99aab9a5f3 | ||
|
|
347f221adb | ||
|
|
1fcbe3f511 | ||
|
|
d417417c21 | ||
|
|
e7f98814a9 | ||
|
|
3f708b8b14 | ||
|
|
7bc333d193 | ||
|
|
e3b1d9327d | ||
|
|
deb07ee698 | ||
|
|
435989c07e | ||
|
|
2503eb32af | ||
|
|
be57dfe1fa | ||
|
|
e99c8b754b | ||
|
|
2076b4f73c | ||
|
|
5c595d8410 | ||
|
|
8340e1e43f | ||
|
|
1cddb8e607 | ||
|
|
262c8fa529 | ||
|
|
97a49a24cc | ||
|
|
a9a8d0e45f | ||
|
|
92de225ce5 | ||
|
|
a713e5023a | ||
|
|
ec60abd4d8 | ||
|
|
c6d9d50ee9 | ||
|
|
7244b8b40f | ||
|
|
8e81bb6c80 | ||
|
|
3bc2e1ae4c | ||
|
|
61f63f35ae | ||
|
|
5eb1f9bd16 | ||
|
|
4149f484bf | ||
|
|
0b2895977e | ||
|
|
99b30a87a6 | ||
|
|
9fc6ec116d | ||
|
|
f7f553f675 | ||
|
|
a9d9d07edd | ||
|
|
0f083c9e58 | ||
|
|
5392ca7e79 | ||
|
|
243ecc2f25 | ||
|
|
425b4087f3 | ||
|
|
74a367d10e |
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
@@ -31,11 +31,6 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
ignore:
|
||||
# We use consistent go and node versions across a lot of different files, and updating via dependabot would cause
|
||||
# drift among those files, instead we let renovate bot handle them.
|
||||
- dependency-name: "library/golang"
|
||||
- dependency-name: "library/node"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/test/container/"
|
||||
|
||||
71
.github/workflows/ci-build.yaml
vendored
71
.github/workflows/ci-build.yaml
vendored
@@ -13,8 +13,7 @@ on:
|
||||
|
||||
env:
|
||||
# Golang version to use across CI steps
|
||||
# renovate: datasource=golang-version packageName=golang
|
||||
GOLANG_VERSION: '1.23.3'
|
||||
GOLANG_VERSION: '1.22'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -32,7 +31,7 @@ jobs:
|
||||
docs: ${{ steps.filter.outputs.docs_any_changed }}
|
||||
steps:
|
||||
- uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
- uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366 # v45.0.5
|
||||
- uses: tj-actions/changed-files@e9772d140489982e0e3704fea5ee93d536f1e275 # v45.0.1
|
||||
id: filter
|
||||
with:
|
||||
# Any file which is not under docs/, ui/ or is not a markdown file is counted as a backend file
|
||||
@@ -57,7 +56,7 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
- name: Download all Go modules
|
||||
@@ -78,11 +77,11 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
- name: Restore go build cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: ~/.cache/go-build
|
||||
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
|
||||
@@ -105,14 +104,13 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
- name: Run golangci-lint
|
||||
uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1
|
||||
uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0
|
||||
with:
|
||||
# renovate: datasource=go packageName=github.com/golangci/golangci-lint versioning=regex:^v(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)?$
|
||||
version: v1.62.2
|
||||
version: v1.58.2
|
||||
args: --verbose
|
||||
|
||||
test-go:
|
||||
@@ -133,7 +131,7 @@ jobs:
|
||||
- name: Create symlink in GOPATH
|
||||
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
- name: Install required packages
|
||||
@@ -153,7 +151,7 @@ jobs:
|
||||
run: |
|
||||
echo "/usr/local/bin" >> $GITHUB_PATH
|
||||
- name: Restore go build cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: ~/.cache/go-build
|
||||
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
|
||||
@@ -174,7 +172,7 @@ jobs:
|
||||
- name: Run all unit tests
|
||||
run: make test-local
|
||||
- name: Generate test results artifacts
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: test-results
|
||||
path: test-results
|
||||
@@ -197,7 +195,7 @@ jobs:
|
||||
- name: Create symlink in GOPATH
|
||||
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
- name: Install required packages
|
||||
@@ -217,7 +215,7 @@ jobs:
|
||||
run: |
|
||||
echo "/usr/local/bin" >> $GITHUB_PATH
|
||||
- name: Restore go build cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: ~/.cache/go-build
|
||||
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
|
||||
@@ -238,7 +236,7 @@ jobs:
|
||||
- name: Run all unit tests
|
||||
run: make test-race-local
|
||||
- name: Generate test results artifacts
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: race-results
|
||||
path: test-results/
|
||||
@@ -253,7 +251,7 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
- name: Create symlink in GOPATH
|
||||
@@ -305,13 +303,12 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
- name: Setup NodeJS
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
with:
|
||||
# renovate: datasource=node-version packageName=node versioning=node
|
||||
node-version: '22.9.0'
|
||||
node-version: '21.6.1'
|
||||
- name: Restore node dependency cache
|
||||
id: cache-dependencies
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: ui/node_modules
|
||||
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
|
||||
@@ -351,7 +348,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- name: Restore node dependency cache
|
||||
id: cache-dependencies
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: ui/node_modules
|
||||
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
|
||||
@@ -370,13 +367,13 @@ jobs:
|
||||
path: test-results
|
||||
- name: combine-go-coverage
|
||||
# We generate coverage reports for all Argo CD components, but only the applicationset-controller,
|
||||
# app-controller, repo-server, and commit-server report contain coverage data. The other components currently
|
||||
# don't shut down gracefully, so no coverage data is produced. Once those components are fixed, we can add
|
||||
# references to their coverage output directories.
|
||||
# app-controller, and repo-server report contain coverage data. The other components currently don't shut down
|
||||
# gracefully, so no coverage data is produced. Once those components are fixed, we can add references to their
|
||||
# coverage output directories.
|
||||
run: |
|
||||
go tool covdata percent -i=test-results,e2e-code-coverage/applicationset-controller,e2e-code-coverage/repo-server,e2e-code-coverage/app-controller,e2e-code-coverage/commit-server -o test-results/full-coverage.out
|
||||
go tool covdata percent -i=test-results,e2e-code-coverage/applicationset-controller,e2e-code-coverage/repo-server,e2e-code-coverage/app-controller -o test-results/full-coverage.out
|
||||
- name: Upload code coverage information to codecov.io
|
||||
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
|
||||
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
||||
with:
|
||||
file: test-results/full-coverage.out
|
||||
fail_ci_if_error: true
|
||||
@@ -384,7 +381,7 @@ jobs:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
- name: Upload test results to Codecov
|
||||
if: github.ref == 'refs/heads/master' && github.event_name == 'push' && github.repository == 'argoproj/argo-cd'
|
||||
uses: codecov/test-results-action@9739113ad922ea0a9abb4b2c0f8bf6a4aa8ef820 # v1.0.1
|
||||
uses: codecov/test-results-action@1b5b448b98e58ba90d1a1a1d9fcb72ca2263be46 # v1.0.0
|
||||
with:
|
||||
file: test-results/junit.xml
|
||||
fail_ci_if_error: true
|
||||
@@ -393,7 +390,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
uses: SonarSource/sonarqube-scan-action@1b442ee39ac3fa7c2acdd410208dcb2bcfaae6c4 # v4.1.0
|
||||
uses: SonarSource/sonarqube-scan-action@aecaf43ae57e412bd97d70ef9ce6076e672fe0a9 # v2.2
|
||||
if: env.sonar_secret != ''
|
||||
test-e2e:
|
||||
name: Run end-to-end tests
|
||||
@@ -403,14 +400,14 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
k3s:
|
||||
- version: v1.31.0
|
||||
- version: v1.30.2
|
||||
# We designate the latest version because we only collect code coverage for that version.
|
||||
latest: true
|
||||
- version: v1.30.4
|
||||
- version: v1.29.6
|
||||
latest: false
|
||||
- version: v1.29.8
|
||||
- version: v1.28.11
|
||||
latest: false
|
||||
- version: v1.28.13
|
||||
- version: v1.27.15
|
||||
latest: false
|
||||
needs:
|
||||
- build-go
|
||||
@@ -432,7 +429,7 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
- name: GH actions workaround - Kill XSP4 process
|
||||
@@ -451,7 +448,7 @@ jobs:
|
||||
sudo chmod go-r $HOME/.kube/config
|
||||
kubectl version
|
||||
- name: Restore go build cache
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: ~/.cache/go-build
|
||||
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
|
||||
@@ -509,13 +506,13 @@ jobs:
|
||||
goreman run stop-all || echo "goreman trouble"
|
||||
sleep 30
|
||||
- name: Upload e2e coverage report
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: e2e-code-coverage
|
||||
path: /tmp/coverage
|
||||
if: ${{ matrix.k3s.latest }}
|
||||
- name: Upload e2e-server logs
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: e2e-server-k8s${{ matrix.k3s.version }}.log
|
||||
path: /tmp/e2e-server.log
|
||||
|
||||
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
actions: read # for github/codeql-action/init to get workflow details
|
||||
contents: read # for actions/checkout to fetch code
|
||||
security-events: write # for github/codeql-action/autobuild to send a status report
|
||||
if: github.repository == 'argoproj/argo-cd' || vars.enable_codeql
|
||||
if: github.repository == 'argoproj/argo-cd'
|
||||
|
||||
# CodeQL runs on ubuntu-latest and windows-latest
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
# Use correct go version. https://github.com/github/codeql-action/issues/1842#issuecomment-1704398087
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
|
||||
8
.github/workflows/image-reuse.yaml
vendored
8
.github/workflows/image-reuse.yaml
vendored
@@ -69,15 +69,15 @@ jobs:
|
||||
if: ${{ github.ref_type != 'tag'}}
|
||||
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ inputs.go-version }}
|
||||
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
|
||||
uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0
|
||||
|
||||
- uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
|
||||
- uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
|
||||
- uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1
|
||||
|
||||
- name: Setup tags for container image as a CSV type
|
||||
run: |
|
||||
@@ -143,7 +143,7 @@ jobs:
|
||||
|
||||
- name: Build and push container image
|
||||
id: image
|
||||
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 #v6.10.0
|
||||
uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 #v6.7.0
|
||||
with:
|
||||
context: .
|
||||
platforms: ${{ inputs.platforms }}
|
||||
|
||||
6
.github/workflows/image.yaml
vendored
6
.github/workflows/image.yaml
vendored
@@ -52,8 +52,7 @@ jobs:
|
||||
uses: ./.github/workflows/image-reuse.yaml
|
||||
with:
|
||||
# Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
|
||||
# renovate: datasource=golang-version packageName=golang
|
||||
go-version: 1.23.3
|
||||
go-version: 1.22
|
||||
platforms: ${{ needs.set-vars.outputs.platforms }}
|
||||
push: false
|
||||
|
||||
@@ -69,8 +68,7 @@ jobs:
|
||||
quay_image_name: quay.io/argoproj/argocd:latest
|
||||
ghcr_image_name: ghcr.io/argoproj/argo-cd/argocd:${{ needs.set-vars.outputs.image-tag }}
|
||||
# Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
|
||||
# renovate: datasource=golang-version packageName=golang
|
||||
go-version: 1.23.3
|
||||
go-version: 1.22
|
||||
platforms: ${{ needs.set-vars.outputs.platforms }}
|
||||
push: true
|
||||
secrets:
|
||||
|
||||
2
.github/workflows/init-release.yaml
vendored
2
.github/workflows/init-release.yaml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
git stash pop
|
||||
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
|
||||
uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 # v7.0.2
|
||||
with:
|
||||
commit-message: "Bump version to ${{ inputs.TARGET_VERSION }}"
|
||||
title: "Bump version to ${{ inputs.TARGET_VERSION }} on ${{ inputs.TARGET_BRANCH }} branch"
|
||||
|
||||
2
.github/workflows/pr-title-check.yml
vendored
2
.github/workflows/pr-title-check.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
name: Validate PR Title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: thehanimo/pr-title-checker@7fbfe05602bdd86f926d3fb3bccb6f3aed43bc70 # v1.4.3
|
||||
- uses: thehanimo/pr-title-checker@1d8cd483a2b73118406a187f54dca8a9415f1375 # v1.4.2
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
configuration_path: ".github/pr-title-checker-config.json"
|
||||
|
||||
44
.github/workflows/release.yaml
vendored
44
.github/workflows/release.yaml
vendored
@@ -10,8 +10,7 @@ on:
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
# renovate: datasource=golang-version packageName=golang
|
||||
GOLANG_VERSION: '1.23.3' # Note: go-version must also be set in job argocd-image.with.go-version
|
||||
GOLANG_VERSION: '1.22' # Note: go-version must also be set in job argocd-image.with.go-version
|
||||
|
||||
jobs:
|
||||
argocd-image:
|
||||
@@ -24,8 +23,7 @@ jobs:
|
||||
with:
|
||||
quay_image_name: quay.io/argoproj/argocd:${{ github.ref_name }}
|
||||
# Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
|
||||
# renovate: datasource=golang-version packageName=golang
|
||||
go-version: 1.23.3
|
||||
go-version: 1.22
|
||||
platforms: linux/amd64,linux/arm64,linux/s390x,linux/ppc64le
|
||||
push: true
|
||||
secrets:
|
||||
@@ -69,15 +67,19 @@ jobs:
|
||||
- name: Fetch all tags
|
||||
run: git fetch --force --tags
|
||||
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
|
||||
- name: Set GORELEASER_PREVIOUS_TAG # Workaround, GoReleaser uses 'git-describe' to determine a previous tag. Our tags are created in release branches.
|
||||
- name: Set GORELEASER_PREVIOUS_TAG # Workaround, GoReleaser uses 'git-describe' to determine a previous tag. Our tags are created in realease branches.
|
||||
run: |
|
||||
set -xue
|
||||
echo "GORELEASER_PREVIOUS_TAG=$(go run hack/get-previous-release/get-previous-version-for-release-notes.go ${{ github.ref_name }})" >> $GITHUB_ENV
|
||||
if echo ${{ github.ref_name }} | grep -E -- '-rc1+$';then
|
||||
echo "GORELEASER_PREVIOUS_TAG=$(git -c 'versionsort.suffix=-rc' tag --list --sort=version:refname | tail -n 2 | head -n 1)" >> $GITHUB_ENV
|
||||
else
|
||||
echo "This is not the first release on the branch, Using GoReleaser defaults"
|
||||
fi
|
||||
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
|
||||
- name: Set environment variables for ldflags
|
||||
id: set_ldflag
|
||||
@@ -94,14 +96,14 @@ jobs:
|
||||
tool-cache: false
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@9ed2f89a662bf1735a48bc8557fd212fa902bebf # v6.1.0
|
||||
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
|
||||
id: run-goreleaser
|
||||
with:
|
||||
version: latest
|
||||
args: release --clean --timeout 55m
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
KUBECTL_VERSION: ${{ env.KUBECTL_VERSION }}
|
||||
KUBECTL_VERSION: ${{ env.KUBECTL_VERSION }}
|
||||
GIT_TREE_STATE: ${{ env.GIT_TREE_STATE }}
|
||||
|
||||
- name: Generate subject for provenance
|
||||
@@ -151,7 +153,7 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GOLANG_VERSION }}
|
||||
|
||||
@@ -184,7 +186,7 @@ jobs:
|
||||
fi
|
||||
|
||||
cd /tmp && tar -zcf sbom.tar.gz *.spdx
|
||||
|
||||
|
||||
- name: Generate SBOM hash
|
||||
shell: bash
|
||||
id: sbom-hash
|
||||
@@ -193,15 +195,15 @@ jobs:
|
||||
# base64 -w0 encodes to base64 and outputs on a single line.
|
||||
# sha256sum /tmp/sbom.tar.gz ... | base64 -w0
|
||||
echo "hashes=$(sha256sum /tmp/sbom.tar.gz | base64 -w0)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
|
||||
- name: Upload SBOM
|
||||
uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.0
|
||||
uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
files: |
|
||||
/tmp/sbom.tar.gz
|
||||
|
||||
|
||||
sbom-provenance:
|
||||
needs: [generate-sbom]
|
||||
permissions:
|
||||
@@ -209,13 +211,13 @@ jobs:
|
||||
id-token: write # Needed for provenance signing and ID
|
||||
contents: write # Needed for release uploads
|
||||
if: github.repository == 'argoproj/argo-cd'
|
||||
# Must be referenced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
|
||||
# Must be refernced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
|
||||
with:
|
||||
base64-subjects: "${{ needs.generate-sbom.outputs.hashes }}"
|
||||
provenance-name: "argocd-sbom.intoto.jsonl"
|
||||
upload-assets: true
|
||||
|
||||
|
||||
post-release:
|
||||
needs:
|
||||
- argocd-image
|
||||
@@ -293,7 +295,7 @@ jobs:
|
||||
if: ${{ env.UPDATE_VERSION == 'true' }}
|
||||
|
||||
- name: Create PR to update VERSION on master branch
|
||||
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
|
||||
uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 # v7.0.2
|
||||
with:
|
||||
commit-message: Bump version in master
|
||||
title: "chore: Bump version in master"
|
||||
|
||||
2
.github/workflows/scorecard.yaml
vendored
2
.github/workflows/scorecard.yaml
vendored
@@ -54,7 +54,7 @@ jobs:
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
.vscode/
|
||||
.idea/
|
||||
.DS_Store
|
||||
.run/
|
||||
vendor/
|
||||
dist/*
|
||||
ui/dist/app/*
|
||||
|
||||
@@ -18,13 +18,10 @@ linters:
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- perfsprint
|
||||
- staticcheck
|
||||
- testifylint
|
||||
- thelper
|
||||
- unparam
|
||||
- unused
|
||||
- usestdlibvars
|
||||
- whitespace
|
||||
linters-settings:
|
||||
gocritic:
|
||||
@@ -40,17 +37,6 @@ linters-settings:
|
||||
- typeSwitchVar
|
||||
goimports:
|
||||
local-prefixes: github.com/argoproj/argo-cd/v2
|
||||
perfsprint:
|
||||
# Optimizes even if it requires an int or uint type cast.
|
||||
int-conversion: true
|
||||
# Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.
|
||||
err-error: false
|
||||
# Optimizes `fmt.Errorf`.
|
||||
errorf: false
|
||||
# Optimizes `fmt.Sprintf` with only one argument.
|
||||
sprintf1: true
|
||||
# Optimizes into strings concatenation.
|
||||
strconcat: false
|
||||
testifylint:
|
||||
enable-all: true
|
||||
disable:
|
||||
|
||||
@@ -26,13 +26,6 @@ packages:
|
||||
github.com/argoproj/argo-cd/v2/applicationset/utils:
|
||||
interfaces:
|
||||
Renderer:
|
||||
github.com/argoproj/argo-cd/v2/commitserver/commit:
|
||||
interfaces:
|
||||
RepoClientFactory:
|
||||
github.com/argoproj/argo-cd/v2/commitserver/apiclient:
|
||||
interfaces:
|
||||
CommitServiceClient:
|
||||
Clientset:
|
||||
github.com/argoproj/argo-cd/v2/controller/cache:
|
||||
interfaces:
|
||||
LiveStateCache:
|
||||
|
||||
@@ -8,4 +8,4 @@ python:
|
||||
build:
|
||||
os: "ubuntu-22.04"
|
||||
tools:
|
||||
python: "3.12"
|
||||
python: "3.7"
|
||||
|
||||
@@ -4,7 +4,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:3f85b7caad41a95462cf5b787d8
|
||||
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
|
||||
# Also used as the image in CI jobs so needs all dependencies
|
||||
####################################################################################################
|
||||
FROM docker.io/library/golang:1.23.3@sha256:d56c3e08fe5b27729ee3834854ae8f7015af48fd651cd25d1e3bcf3c19830174 AS builder
|
||||
FROM docker.io/library/golang:1.23.1@sha256:2fe82a3f3e006b4f2a316c6a21f62b66e1330ae211d039bb8d1128e12ed57bf1 AS builder
|
||||
|
||||
RUN echo 'deb http://archive.debian.org/debian buster-backports main' >> /etc/apt/sources.list
|
||||
|
||||
@@ -83,7 +83,7 @@ WORKDIR /home/argocd
|
||||
####################################################################################################
|
||||
# Argo CD UI stage
|
||||
####################################################################################################
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/node:23.0.0@sha256:e643c0b70dca9704dff42e12b17f5b719dbe4f95e6392fc2dfa0c5f02ea8044d AS argocd-ui
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/node:22.8.0@sha256:bd00c03095f7586432805dbf7989be10361d27987f93de904b1fc003949a4794 AS argocd-ui
|
||||
|
||||
WORKDIR /src
|
||||
COPY ["ui/package.json", "ui/yarn.lock", "./"]
|
||||
@@ -101,7 +101,7 @@ RUN HOST_ARCH=$TARGETARCH NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OP
|
||||
####################################################################################################
|
||||
# Argo CD Build stage which performs the actual build of Argo CD binaries
|
||||
####################################################################################################
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.23.3@sha256:d56c3e08fe5b27729ee3834854ae8f7015af48fd651cd25d1e3bcf3c19830174 AS argocd-build
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.23.1@sha256:2fe82a3f3e006b4f2a316c6a21f62b66e1330ae211d039bb8d1128e12ed57bf1 AS argocd-build
|
||||
|
||||
WORKDIR /go/src/github.com/argoproj/argo-cd
|
||||
|
||||
@@ -140,8 +140,7 @@ RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \
|
||||
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-dex && \
|
||||
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-notifications && \
|
||||
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller && \
|
||||
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-k8s-auth && \
|
||||
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-commit-server
|
||||
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-k8s-auth
|
||||
|
||||
USER $ARGOCD_USER_ID
|
||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||
|
||||
2
Makefile
2
Makefile
@@ -472,7 +472,6 @@ start-e2e-local: mod-vendor-local dep-ui-local cli-local
|
||||
mkdir -p /tmp/coverage/repo-server
|
||||
mkdir -p /tmp/coverage/applicationset-controller
|
||||
mkdir -p /tmp/coverage/notification
|
||||
mkdir -p /tmp/coverage/commit-server
|
||||
# set paths for locally managed ssh known hosts and tls certs data
|
||||
ARGOCD_SSH_DATA_PATH=/tmp/argo-e2e/app/config/ssh \
|
||||
ARGOCD_TLS_DATA_PATH=/tmp/argo-e2e/app/config/tls \
|
||||
@@ -487,7 +486,6 @@ start-e2e-local: mod-vendor-local dep-ui-local cli-local
|
||||
BIN_MODE=$(ARGOCD_BIN_MODE) \
|
||||
ARGOCD_APPLICATION_NAMESPACES=argocd-e2e-external,argocd-e2e-external-2 \
|
||||
ARGOCD_APPLICATIONSET_CONTROLLER_NAMESPACES=argocd-e2e-external,argocd-e2e-external-2 \
|
||||
ARGOCD_APPLICATIONSET_CONTROLLER_TOKENREF_STRICT_MODE=true \
|
||||
ARGOCD_APPLICATIONSET_CONTROLLER_ALLOWED_SCM_PROVIDERS=http://127.0.0.1:8341,http://127.0.0.1:8342,http://127.0.0.1:8343,http://127.0.0.1:8344 \
|
||||
ARGOCD_E2E_TEST=true \
|
||||
goreman -f $(ARGOCD_PROCFILE) start ${ARGOCD_START}
|
||||
|
||||
3
Procfile
3
Procfile
@@ -1,10 +1,9 @@
|
||||
controller: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/app-controller} HOSTNAME=testappcontroller-1 FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-application-controller $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --otlp-address=${ARGOCD_OTLP_ADDRESS} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''} --server-side-diff-enabled=${ARGOCD_APPLICATION_CONTROLLER_SERVER_SIDE_DIFF:-'false'}"
|
||||
api-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/api-server} FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-server $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} --otlp-address=${ARGOCD_OTLP_ADDRESS} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''}"
|
||||
dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v2/cmd gendexcfg -o `pwd`/dist/dex.yaml && (test -f dist/dex.yaml || { echo 'Failed to generate dex configuration'; exit 1; }) && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml ghcr.io/dexidp/dex:$(grep "image: ghcr.io/dexidp/dex" manifests/base/dex/argocd-dex-server-deployment.yaml | cut -d':' -f3) dex serve /dex.yaml"
|
||||
redis: hack/start-redis-with-password.sh
|
||||
redis: bash -c "if [ \"$ARGOCD_REDIS_LOCAL\" = 'true' ]; then redis-server --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; else docker run --rm --name argocd-redis -i -p ${ARGOCD_E2E_REDIS_PORT:-6379}:${ARGOCD_E2E_REDIS_PORT:-6379} docker.io/library/redis:$(grep "image: redis" manifests/base/redis/argocd-redis-deployment.yaml | cut -d':' -f3) --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; fi"
|
||||
repo-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/repo-server} FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_GNUPGHOME=${ARGOCD_GNUPGHOME:-/tmp/argocd-local/gpg/keys} ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-repo-server ARGOCD_GPG_ENABLED=${ARGOCD_GPG_ENABLED:-false} $COMMAND --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --otlp-address=${ARGOCD_OTLP_ADDRESS}"
|
||||
cmp-server: [ "$ARGOCD_E2E_TEST" = 'true' ] && exit 0 || [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_BINARY_NAME=argocd-cmp-server ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} $COMMAND --config-dir-path ./test/cmp --loglevel debug --otlp-address=${ARGOCD_OTLP_ADDRESS}"
|
||||
commit-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/commit-server} FORCE_LOG_COLORS=1 ARGOCD_BINARY_NAME=argocd-commit-server $COMMAND --loglevel debug --port ${ARGOCD_E2E_COMMITSERVER_PORT:-8086}"
|
||||
ui: sh -c 'cd ui && ${ARGOCD_E2E_YARN_CMD:-yarn} start'
|
||||
git-server: test/fixture/testrepos/start-git.sh
|
||||
helm-registry: test/fixture/testrepos/start-helm-registry.sh
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
[](https://codecov.io/gh/argoproj/argo-cd)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/4486)
|
||||
[](https://scorecard.dev/viewer/?uri=github.com/argoproj/argo-cd)
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fargoproj%2Fargo-cd?ref=badge_shield)
|
||||
|
||||
**Social:**
|
||||
[](https://twitter.com/argoproj)
|
||||
@@ -56,7 +57,7 @@ Participation in the Argo CD project is governed by the [CNCF Code of Conduct](h
|
||||
### Blogs and Presentations
|
||||
|
||||
1. [Awesome-Argo: A Curated List of Awesome Projects and Resources Related to Argo](https://github.com/terrytangyuan/awesome-argo)
|
||||
1. [Unveil the Secret Ingredients of Continuous Delivery at Enterprise Scale with Argo CD](https://akuity.io/blog/secret-ingredients-of-continuous-delivery-at-enterprise-scale-with-argocd/)
|
||||
1. [Unveil the Secret Ingredients of Continuous Delivery at Enterprise Scale with Argo CD](https://akuity.io/blog/unveil-the-secret-ingredients-of-continuous-delivery-at-enterprise-scale-with-argocd-kubecon-china-2021/)
|
||||
1. [GitOps Without Pipelines With ArgoCD Image Updater](https://youtu.be/avPUQin9kzU)
|
||||
1. [Combining Argo CD (GitOps), Crossplane (Control Plane), And KubeVela (OAM)](https://youtu.be/eEcgn_gU3SM)
|
||||
1. [How to Apply GitOps to Everything - Combining Argo CD and Crossplane](https://youtu.be/yrj4lmScKHQ)
|
||||
|
||||
@@ -3,9 +3,9 @@ header:
|
||||
expiration-date: '2024-10-31T00:00:00.000Z' # One year from initial release.
|
||||
last-updated: '2023-10-27'
|
||||
last-reviewed: '2023-10-27'
|
||||
commit-hash: 74a367d10e7110209610ba3ec225539ebe5f7522
|
||||
commit-hash: fe606708859574b9b6102a505e260fac5d3fb14e
|
||||
project-url: https://github.com/argoproj/argo-cd
|
||||
project-release: v2.14.0
|
||||
project-release: v2.13.0
|
||||
changelog: https://github.com/argoproj/argo-cd/releases
|
||||
license: https://github.com/argoproj/argo-cd/blob/master/LICENSE
|
||||
project-lifecycle:
|
||||
|
||||
12
USERS.md
12
USERS.md
@@ -16,8 +16,6 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [Adyen](https://www.adyen.com)
|
||||
1. [AirQo](https://airqo.net/)
|
||||
1. [Akuity](https://akuity.io/)
|
||||
1. [Alarm.com](https://alarm.com/)
|
||||
1. [Alauda](https://alauda.io/)
|
||||
1. [Albert Heijn](https://ah.nl/)
|
||||
1. [Alibaba Group](https://www.alibabagroup.com/)
|
||||
1. [Allianz Direct](https://www.allianzdirect.de/)
|
||||
@@ -37,7 +35,6 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [Axians ACSP](https://www.axians.fr)
|
||||
1. [Axual B.V.](https://axual.com)
|
||||
1. [Back Market](https://www.backmarket.com)
|
||||
1. [Bajaj Finserv Health Ltd.](https://www.bajajfinservhealth.in)
|
||||
1. [Baloise](https://www.baloise.com)
|
||||
1. [BCDevExchange DevOps Platform](https://bcdevexchange.org/DevOpsPlatform)
|
||||
1. [Beat](https://thebeat.co/en/)
|
||||
@@ -79,7 +76,6 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [Codility](https://www.codility.com/)
|
||||
1. [Cognizant](https://www.cognizant.com/)
|
||||
1. [Commonbond](https://commonbond.co/)
|
||||
1. [Compatio.AI](https://compatio.ai/)
|
||||
1. [Contlo](https://contlo.com/)
|
||||
1. [Coralogix](https://coralogix.com/)
|
||||
1. [Crédit Agricole CIB](https://www.ca-cib.com)
|
||||
@@ -89,7 +85,6 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [D2iQ](https://www.d2iq.com)
|
||||
1. [DaoCloud](https://daocloud.io/)
|
||||
1. [Datarisk](https://www.datarisk.io/)
|
||||
1. [Daydream](https://daydream.ing)
|
||||
1. [Deloitte](https://www.deloitte.com/)
|
||||
1. [Deutsche Telekom AG](https://telekom.com)
|
||||
1. [Devopsi - Poland Software/DevOps Consulting](https://devopsi.pl/)
|
||||
@@ -120,7 +115,6 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [freee](https://corp.freee.co.jp/en/company/)
|
||||
1. [Freshop, Inc](https://www.freshop.com/)
|
||||
1. [Future PLC](https://www.futureplc.com/)
|
||||
1. [Flagler Health](https://www.flaglerhealth.io/)
|
||||
1. [G DATA CyberDefense AG](https://www.gdata-software.com/)
|
||||
1. [G-Research](https://www.gresearch.com/teams/open-source-software/)
|
||||
1. [Garner](https://www.garnercorp.com)
|
||||
@@ -249,7 +243,6 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [Optoro](https://www.optoro.com/)
|
||||
1. [Orbital Insight](https://orbitalinsight.com/)
|
||||
1. [Oscar Health Insurance](https://hioscar.com/)
|
||||
1. [Outpost24](https://outpost24.com/)
|
||||
1. [p3r](https://www.p3r.one/)
|
||||
1. [Packlink](https://www.packlink.com/)
|
||||
1. [PagerDuty](https://www.pagerduty.com/)
|
||||
@@ -278,7 +271,6 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [PT Boer Technology (Btech)](https://btech.id/)
|
||||
1. [PUBG](https://www.pubg.com)
|
||||
1. [Puzzle ITC](https://www.puzzle.ch/)
|
||||
1. [Pvotal Technologies](https://pvotal.tech/)
|
||||
1. [Qonto](https://qonto.com)
|
||||
1. [QuintoAndar](https://quintoandar.com.br)
|
||||
1. [Quipper](https://www.quipper.com/)
|
||||
@@ -315,7 +307,6 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [Skyscanner](https://www.skyscanner.net/)
|
||||
1. [Smart Pension](https://www.smartpension.co.uk/)
|
||||
1. [Smilee.io](https://smilee.io)
|
||||
1. [Smilegate Stove](https://www.onstove.com/)
|
||||
1. [Smood.ch](https://www.smood.ch/)
|
||||
1. [Snapp](https://snapp.ir/)
|
||||
1. [Snyk](https://snyk.io/)
|
||||
@@ -339,12 +330,10 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [TableCheck](https://tablecheck.com/)
|
||||
1. [Tailor Brands](https://www.tailorbrands.com)
|
||||
1. [Tamkeen Technologies](https://tamkeentech.sa/)
|
||||
1. [TBC Bank](https://tbcbank.ge/)
|
||||
1. [Techcombank](https://www.techcombank.com.vn/trang-chu)
|
||||
1. [Technacy](https://www.technacy.it/)
|
||||
1. [Telavita](https://www.telavita.com.br/)
|
||||
1. [Tesla](https://tesla.com/)
|
||||
1. [TextNow](https://www.textnow.com/)
|
||||
1. [The Scale Factory](https://www.scalefactory.com/)
|
||||
1. [ThousandEyes](https://www.thousandeyes.com/)
|
||||
1. [Ticketmaster](https://ticketmaster.com)
|
||||
@@ -392,5 +381,4 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [Yubo](https://www.yubo.live/)
|
||||
1. [ZDF](https://www.zdf.de/)
|
||||
1. [Zimpler](https://www.zimpler.com/)
|
||||
1. [ZipRecuiter](https://www.ziprecruiter.com/)
|
||||
1. [ZOZO](https://corp.zozo.com/)
|
||||
|
||||
@@ -18,9 +18,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -54,6 +52,7 @@ import (
|
||||
"github.com/argoproj/argo-cd/v2/util/db"
|
||||
|
||||
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned"
|
||||
argoutil "github.com/argoproj/argo-cd/v2/util/argo"
|
||||
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
|
||||
|
||||
@@ -80,6 +79,7 @@ type ApplicationSetReconciler struct {
|
||||
Recorder record.EventRecorder
|
||||
Generators map[string]generators.Generator
|
||||
ArgoDB db.ArgoDB
|
||||
ArgoAppClientset appclientset.Interface
|
||||
KubeClientset kubernetes.Interface
|
||||
Policy argov1alpha1.ApplicationsSyncPolicy
|
||||
EnablePolicyOverride bool
|
||||
@@ -96,22 +96,9 @@ type ApplicationSetReconciler struct {
|
||||
// +kubebuilder:rbac:groups=argoproj.io,resources=applicationsets,verbs=get;list;watch;create;update;patch;delete
|
||||
// +kubebuilder:rbac:groups=argoproj.io,resources=applicationsets/status,verbs=get;update;patch
|
||||
|
||||
func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, err error) {
|
||||
startReconcile := time.Now()
|
||||
func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
logCtx := log.WithField("applicationset", req.NamespacedName)
|
||||
|
||||
defer func() {
|
||||
if rec := recover(); rec != nil {
|
||||
logCtx.Errorf("Recovered from panic: %+v\n%s", rec, debug.Stack())
|
||||
result = ctrl.Result{}
|
||||
var ok bool
|
||||
err, ok = rec.(error)
|
||||
if !ok {
|
||||
err = fmt.Errorf("%v", r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
var applicationSetInfo argov1alpha1.ApplicationSet
|
||||
parametersGenerated := false
|
||||
startTime := time.Now()
|
||||
@@ -347,7 +334,7 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
|
||||
requeueAfter = ReconcileRequeueOnValidationError
|
||||
}
|
||||
|
||||
logCtx.WithField("requeueAfter", requeueAfter).Info("end reconcile in ", time.Since(startReconcile))
|
||||
logCtx.WithField("requeueAfter", requeueAfter).Info("end reconcile")
|
||||
|
||||
return ctrl.Result{
|
||||
RequeueAfter: requeueAfter,
|
||||
@@ -485,9 +472,7 @@ func (r *ApplicationSetReconciler) validateGeneratedApplications(ctx context.Con
|
||||
errorsByIndex[i] = fmt.Errorf("ApplicationSet %s contains applications with duplicate name: %s", applicationSetInfo.Name, app.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
appProject := &argov1alpha1.AppProject{}
|
||||
err := r.Client.Get(ctx, types.NamespacedName{Name: app.Spec.Project, Namespace: r.ArgoCDNamespace}, appProject)
|
||||
_, err := r.ArgoAppClientset.ArgoprojV1alpha1().AppProjects(r.ArgoCDNamespace).Get(ctx, app.Spec.GetProject(), metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if apierr.IsNotFound(err) {
|
||||
errorsByIndex[i] = fmt.Errorf("application references project %s which does not exist", app.Spec.Project)
|
||||
@@ -1061,7 +1046,7 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatus(ctx con
|
||||
LastTransitionTime: &now,
|
||||
Message: "No Application status found, defaulting status to Waiting.",
|
||||
Status: "Waiting",
|
||||
Step: strconv.Itoa(getAppStep(app.Name, appStepMap)),
|
||||
Step: fmt.Sprint(getAppStep(app.Name, appStepMap)),
|
||||
TargetRevisions: app.Status.GetRevisions(),
|
||||
}
|
||||
} else {
|
||||
@@ -1086,7 +1071,7 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatus(ctx con
|
||||
currentAppStatus.LastTransitionTime = &now
|
||||
currentAppStatus.Status = "Waiting"
|
||||
currentAppStatus.Message = "Application has pending changes, setting status to Waiting."
|
||||
currentAppStatus.Step = strconv.Itoa(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
currentAppStatus.Step = fmt.Sprint(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
currentAppStatus.TargetRevisions = app.Status.GetRevisions()
|
||||
}
|
||||
|
||||
@@ -1104,14 +1089,14 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatus(ctx con
|
||||
currentAppStatus.LastTransitionTime = &now
|
||||
currentAppStatus.Status = "Progressing"
|
||||
currentAppStatus.Message = "Application resource completed a sync successfully, updating status from Pending to Progressing."
|
||||
currentAppStatus.Step = strconv.Itoa(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
currentAppStatus.Step = fmt.Sprint(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
}
|
||||
} else if operationPhaseString == "Running" || healthStatusString == "Progressing" {
|
||||
logCtx.Infof("Application %v has entered Progressing status, updating its ApplicationSet status to Progressing", app.Name)
|
||||
currentAppStatus.LastTransitionTime = &now
|
||||
currentAppStatus.Status = "Progressing"
|
||||
currentAppStatus.Message = "Application resource became Progressing, updating status from Pending to Progressing."
|
||||
currentAppStatus.Step = strconv.Itoa(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
currentAppStatus.Step = fmt.Sprint(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,7 +1105,7 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatus(ctx con
|
||||
currentAppStatus.LastTransitionTime = &now
|
||||
currentAppStatus.Status = healthStatusString
|
||||
currentAppStatus.Message = "Application resource is already Healthy, updating status from Waiting to Healthy."
|
||||
currentAppStatus.Step = strconv.Itoa(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
currentAppStatus.Step = fmt.Sprint(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
}
|
||||
|
||||
if currentAppStatus.Status == "Progressing" && isApplicationHealthy(app) {
|
||||
@@ -1128,7 +1113,7 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatus(ctx con
|
||||
currentAppStatus.LastTransitionTime = &now
|
||||
currentAppStatus.Status = healthStatusString
|
||||
currentAppStatus.Message = "Application resource became Healthy, updating status from Progressing to Healthy."
|
||||
currentAppStatus.Step = strconv.Itoa(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
currentAppStatus.Step = fmt.Sprint(getAppStep(currentAppStatus.Application, appStepMap))
|
||||
}
|
||||
|
||||
appStatuses = append(appStatuses, currentAppStatus)
|
||||
@@ -1199,7 +1184,7 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatusProgress
|
||||
appStatus.LastTransitionTime = &now
|
||||
appStatus.Status = "Pending"
|
||||
appStatus.Message = "Application moved to Pending status, watching for the Application resource to start Progressing."
|
||||
appStatus.Step = strconv.Itoa(getAppStep(appStatus.Application, appStepMap))
|
||||
appStatus.Step = fmt.Sprint(getAppStep(appStatus.Application, appStepMap))
|
||||
|
||||
updateCountMap[appStepMap[appStatus.Application]] += 1
|
||||
}
|
||||
@@ -1505,7 +1490,7 @@ func getOwnsHandlerPredicates(enableProgressiveSyncs bool) predicate.Funcs {
|
||||
return false
|
||||
}
|
||||
requeue := shouldRequeueApplicationSet(appOld, appNew, enableProgressiveSyncs)
|
||||
logCtx.WithField("requeue", requeue).Debugf("requeue: %t caused by application %s", requeue, appNew.Name)
|
||||
logCtx.WithField("requeue", requeue).Debugf("requeue: %t caused by application %s\n", requeue, appNew.Name)
|
||||
return requeue
|
||||
},
|
||||
GenericFunc: func(e event.GenericEvent) bool {
|
||||
|
||||
@@ -38,6 +38,7 @@ import (
|
||||
appsetmetrics "github.com/argoproj/argo-cd/v2/applicationset/metrics"
|
||||
argocommon "github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake"
|
||||
dbmocks "github.com/argoproj/argo-cd/v2/util/db/mocks"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
|
||||
@@ -1151,7 +1152,7 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
|
||||
Name: "my-secret",
|
||||
Namespace: "namespace",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
@@ -1178,18 +1179,18 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
|
||||
// argoDB := db.NewDB("namespace", settingsMgr, r.KubeClientset)
|
||||
// clusterList, err := argoDB.ListClusters(context.Background())
|
||||
clusterList, err := utils.ListClusters(context.Background(), kubeclientset, "namespace")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "Unexpected error")
|
||||
|
||||
appLog := log.WithFields(log.Fields{"app": app.Name, "appSet": ""})
|
||||
|
||||
appInputParam := app.DeepCopy()
|
||||
|
||||
err = r.removeFinalizerOnInvalidDestination(context.Background(), appSet, appInputParam, clusterList, appLog)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "Unexpected error")
|
||||
|
||||
retrievedApp := v1alpha1.Application{}
|
||||
err = client.Get(context.Background(), crtclient.ObjectKeyFromObject(&app), &retrievedApp)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "Unexpected error")
|
||||
|
||||
// App on the cluster should have the expected finalizers
|
||||
assert.ElementsMatch(t, c.expectedFinalizers, retrievedApp.Finalizers)
|
||||
@@ -1307,7 +1308,7 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
|
||||
Name: "my-secret",
|
||||
Namespace: "namespace",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
@@ -1334,18 +1335,18 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
|
||||
// argoDB := db.NewDB("argocd", settingsMgr, r.KubeClientset)
|
||||
// clusterList, err := argoDB.ListClusters(context.Background())
|
||||
clusterList, err := utils.ListClusters(context.Background(), kubeclientset, "namespace")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "Unexpected error")
|
||||
|
||||
appLog := log.WithFields(log.Fields{"app": app.Name, "appSet": ""})
|
||||
|
||||
appInputParam := app.DeepCopy()
|
||||
|
||||
err = r.removeFinalizerOnInvalidDestination(context.Background(), appSet, appInputParam, clusterList, appLog)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "Unexpected error")
|
||||
|
||||
retrievedApp := v1alpha1.Application{}
|
||||
err = client.Get(context.Background(), crtclient.ObjectKeyFromObject(&app), &retrievedApp)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "Unexpected error")
|
||||
|
||||
finalizerRemoved := len(retrievedApp.Finalizers) == 0
|
||||
|
||||
@@ -1402,7 +1403,7 @@ func TestRemoveOwnerReferencesOnDeleteAppSet(t *testing.T) {
|
||||
}
|
||||
|
||||
err := controllerutil.SetControllerReference(&appSet, &app, scheme)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "Unexpected error")
|
||||
|
||||
initObjs := []crtclient.Object{&app, &appSet}
|
||||
|
||||
@@ -1418,11 +1419,11 @@ func TestRemoveOwnerReferencesOnDeleteAppSet(t *testing.T) {
|
||||
}
|
||||
|
||||
err = r.removeOwnerReferencesOnDeleteAppSet(context.Background(), appSet)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "Unexpected error")
|
||||
|
||||
retrievedApp := v1alpha1.Application{}
|
||||
err = client.Get(context.Background(), crtclient.ObjectKeyFromObject(&app), &retrievedApp)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "Unexpected error")
|
||||
|
||||
ownerReferencesRemoved := len(retrievedApp.OwnerReferences) == 0
|
||||
assert.True(t, ownerReferencesRemoved)
|
||||
@@ -1783,7 +1784,7 @@ func TestDeleteInCluster(t *testing.T) {
|
||||
Name: obj.Name,
|
||||
}, got)
|
||||
|
||||
assert.EqualError(t, err, fmt.Sprintf("applications.argoproj.io %q not found", obj.Name))
|
||||
assert.EqualError(t, err, fmt.Sprintf("applications.argoproj.io \"%s\" not found", obj.Name))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1839,8 +1840,6 @@ func TestRequeueGeneratorFails(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
err = v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
|
||||
appSet := v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -2047,7 +2046,7 @@ func TestValidateGeneratedApplications(t *testing.T) {
|
||||
Name: "my-secret",
|
||||
Namespace: "namespace",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
@@ -2060,15 +2059,21 @@ func TestValidateGeneratedApplications(t *testing.T) {
|
||||
objects := append([]runtime.Object{}, secret)
|
||||
kubeclientset := kubefake.NewSimpleClientset(objects...)
|
||||
|
||||
argoObjs := []runtime.Object{myProject}
|
||||
for _, app := range cc.apps {
|
||||
argoObjs = append(argoObjs, &app)
|
||||
}
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoCDNamespace: "namespace",
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoCDNamespace: "namespace",
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
appSetInfo := v1alpha1.ApplicationSet{}
|
||||
@@ -2147,8 +2152,9 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) {
|
||||
}
|
||||
|
||||
kubeclientset := kubefake.NewSimpleClientset()
|
||||
argoObjs := []runtime.Object{&project}
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &project).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
|
||||
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
@@ -2159,11 +2165,12 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) {
|
||||
Generators: map[string]generators.Generator{
|
||||
"List": generators.NewListGenerator(),
|
||||
},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Policy: v1alpha1.ApplicationsSyncPolicySync,
|
||||
ArgoCDNamespace: "argocd",
|
||||
Metrics: metrics,
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Policy: v1alpha1.ApplicationsSyncPolicySync,
|
||||
ArgoCDNamespace: "argocd",
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
req := ctrl.Request{
|
||||
@@ -2226,7 +2233,6 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
|
||||
},
|
||||
},
|
||||
testfunc: func(t *testing.T, appset v1alpha1.ApplicationSet) {
|
||||
t.Helper()
|
||||
assert.Len(t, appset.Status.Conditions, 3)
|
||||
},
|
||||
},
|
||||
@@ -2262,7 +2268,6 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
|
||||
},
|
||||
},
|
||||
testfunc: func(t *testing.T, appset v1alpha1.ApplicationSet) {
|
||||
t.Helper()
|
||||
assert.Len(t, appset.Status.Conditions, 3)
|
||||
|
||||
isProgressingCondition := false
|
||||
@@ -2325,7 +2330,6 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
|
||||
},
|
||||
},
|
||||
testfunc: func(t *testing.T, appset v1alpha1.ApplicationSet) {
|
||||
t.Helper()
|
||||
assert.Len(t, appset.Status.Conditions, 4)
|
||||
|
||||
isProgressingCondition := false
|
||||
@@ -2343,6 +2347,7 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
|
||||
}
|
||||
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoObjs := []runtime.Object{}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&testCase.appset).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).WithStatusSubresource(&testCase.appset).Build()
|
||||
@@ -2356,9 +2361,10 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
|
||||
Generators: map[string]generators.Generator{
|
||||
"List": generators.NewListGenerator(),
|
||||
},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
for _, condition := range testCase.conditions {
|
||||
@@ -2371,7 +2377,6 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
|
||||
}
|
||||
|
||||
func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alpha1.ApplicationsSyncPolicy, recordBuffer int, allowPolicyOverride bool) v1alpha1.Application {
|
||||
t.Helper()
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
@@ -2412,6 +2417,8 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
|
||||
},
|
||||
}
|
||||
|
||||
argoObjs := []runtime.Object{&defaultProject}
|
||||
|
||||
secret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-cluster",
|
||||
@@ -2432,7 +2439,7 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
|
||||
objects := append([]runtime.Object{}, secret)
|
||||
kubeclientset := kubefake.NewSimpleClientset(objects...)
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
|
||||
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
@@ -2445,6 +2452,7 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
|
||||
},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoCDNamespace: "argocd",
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Policy: v1alpha1.ApplicationsSyncPolicySync,
|
||||
EnablePolicyOverride: allowPolicyOverride,
|
||||
@@ -2545,7 +2553,6 @@ func TestUpdatePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *t
|
||||
}
|
||||
|
||||
func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alpha1.ApplicationsSyncPolicy, recordBuffer int, allowPolicyOverride bool) v1alpha1.ApplicationList {
|
||||
t.Helper()
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
@@ -2586,6 +2593,8 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
|
||||
},
|
||||
}
|
||||
|
||||
argoObjs := []runtime.Object{&defaultProject}
|
||||
|
||||
secret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-cluster",
|
||||
@@ -2606,7 +2615,7 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
|
||||
objects := append([]runtime.Object{}, secret)
|
||||
kubeclientset := kubefake.NewSimpleClientset(objects...)
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
|
||||
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
@@ -2619,6 +2628,7 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
|
||||
},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoCDNamespace: "argocd",
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Policy: v1alpha1.ApplicationsSyncPolicySync,
|
||||
EnablePolicyOverride: allowPolicyOverride,
|
||||
@@ -2722,6 +2732,7 @@ func TestPolicies(t *testing.T) {
|
||||
}
|
||||
|
||||
kubeclientset := kubefake.NewSimpleClientset()
|
||||
argoObjs := []runtime.Object{&defaultProject}
|
||||
|
||||
for _, c := range []struct {
|
||||
name string
|
||||
@@ -2793,7 +2804,7 @@ func TestPolicies(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
|
||||
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
@@ -2804,11 +2815,12 @@ func TestPolicies(t *testing.T) {
|
||||
Generators: map[string]generators.Generator{
|
||||
"List": generators.NewListGenerator(),
|
||||
},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoCDNamespace: "argocd",
|
||||
KubeClientset: kubeclientset,
|
||||
Policy: policy,
|
||||
Metrics: metrics,
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoCDNamespace: "argocd",
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Policy: policy,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
req := ctrl.Request{
|
||||
@@ -2878,6 +2890,7 @@ func TestSetApplicationSetApplicationStatus(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoObjs := []runtime.Object{}
|
||||
|
||||
for _, cc := range []struct {
|
||||
name string
|
||||
@@ -2961,9 +2974,10 @@ func TestSetApplicationSetApplicationStatus(t *testing.T) {
|
||||
Generators: map[string]generators.Generator{
|
||||
"List": generators.NewListGenerator(),
|
||||
},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
err = r.setAppSetApplicationStatus(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.appStatuses)
|
||||
@@ -3710,15 +3724,17 @@ func TestBuildAppDependencyList(t *testing.T) {
|
||||
} {
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoObjs := []runtime.Object{}
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
appDependencyList, appStepMap := r.buildAppDependencyList(log.NewEntry(log.StandardLogger()), cc.appSet, cc.apps)
|
||||
@@ -4376,15 +4392,17 @@ func TestBuildAppSyncMap(t *testing.T) {
|
||||
} {
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoObjs := []runtime.Object{}
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
appSyncMap := r.buildAppSyncMap(cc.appSet, cc.appDependencyList, cc.appMap)
|
||||
@@ -5320,18 +5338,20 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
|
||||
} {
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoObjs := []runtime.Object{}
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&cc.appSet).WithStatusSubresource(&cc.appSet).Build()
|
||||
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
appStatuses, err := r.updateApplicationSetApplicationStatus(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.apps, cc.appStepMap)
|
||||
@@ -6068,18 +6088,20 @@ func TestUpdateApplicationSetApplicationStatusProgress(t *testing.T) {
|
||||
} {
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoObjs := []runtime.Object{}
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&cc.appSet).WithStatusSubresource(&cc.appSet).Build()
|
||||
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
appStatuses, err := r.updateApplicationSetApplicationStatusProgress(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.appSyncMap, cc.appStepMap)
|
||||
@@ -6278,18 +6300,20 @@ func TestUpdateResourceStatus(t *testing.T) {
|
||||
} {
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoObjs := []runtime.Object{}
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithStatusSubresource(&cc.appSet).WithObjects(&cc.appSet).Build()
|
||||
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
err := r.updateResourcesStatus(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.apps)
|
||||
@@ -6342,8 +6366,6 @@ func TestResourceStatusAreOrdered(t *testing.T) {
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
for _, cc := range []struct {
|
||||
name string
|
||||
appSet v1alpha1.ApplicationSet
|
||||
@@ -6367,18 +6389,20 @@ func TestResourceStatusAreOrdered(t *testing.T) {
|
||||
} {
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoObjs := []runtime.Object{}
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithStatusSubresource(&cc.appSet).WithObjects(&cc.appSet).Build()
|
||||
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
}
|
||||
|
||||
err := r.updateResourcesStatus(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.apps)
|
||||
@@ -6592,9 +6616,6 @@ func TestMigrateStatus(t *testing.T) {
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
appset v1alpha1.ApplicationSet
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/argoproj/argo-cd/v2/applicationset/generators"
|
||||
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -50,7 +50,7 @@ type addRateLimitingInterface[T comparable] interface {
|
||||
|
||||
func (h *clusterSecretEventHandler) queueRelatedAppGenerators(ctx context.Context, q addRateLimitingInterface[reconcile.Request], object client.Object) {
|
||||
// Check for label, lookup all ApplicationSets that might match the cluster, queue them all
|
||||
if object.GetLabels()[common.LabelKeySecretType] != common.LabelValueSecretTypeCluster {
|
||||
if object.GetLabels()[generators.ArgoCDSecretTypeLabel] != generators.ArgoCDSecretTypeCluster {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
argocommon "github.com/argoproj/argo-cd/v2/common"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -18,6 +16,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/applicationset/generators"
|
||||
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -43,7 +42,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -71,7 +70,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -114,7 +113,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -158,7 +157,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -219,7 +218,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -255,7 +254,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -305,7 +304,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -356,7 +355,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -390,7 +389,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -426,7 +425,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -476,7 +475,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -527,7 +526,7 @@ func TestClusterEventHandler(t *testing.T) {
|
||||
Namespace: "argocd",
|
||||
Name: "my-secret",
|
||||
Labels: map[string]string{
|
||||
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
|
||||
generators.ArgoCDSecretTypeLabel: generators.ArgoCDSecretTypeCluster,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestRequeueAfter(t *testing.T) {
|
||||
},
|
||||
}
|
||||
fakeDynClient := dynfake.NewSimpleDynamicClientWithCustomListKinds(runtime.NewScheme(), gvrToListKind, duckType)
|
||||
scmConfig := generators.NewSCMConfig("", []string{""}, true, nil, true)
|
||||
scmConfig := generators.NewSCMConfig("", []string{""}, true, nil)
|
||||
terminalGenerators := map[string]generators.Generator{
|
||||
"List": generators.NewListGenerator(),
|
||||
"Clusters": generators.NewClusterGenerator(k8sClient, ctx, appClientset, "argocd"),
|
||||
@@ -100,8 +100,7 @@ func TestRequeueAfter(t *testing.T) {
|
||||
}
|
||||
|
||||
type args struct {
|
||||
appset *argov1alpha1.ApplicationSet
|
||||
requeueAfterOverride string
|
||||
appset *argov1alpha1.ApplicationSet
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -109,13 +108,11 @@ func TestRequeueAfter(t *testing.T) {
|
||||
want time.Duration
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{name: "Cluster", args: args{
|
||||
appset: &argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{{Clusters: &argov1alpha1.ClusterGenerator{}}},
|
||||
},
|
||||
}, requeueAfterOverride: "",
|
||||
}, want: generators.NoRequeueAfter, wantErr: assert.NoError},
|
||||
{name: "Cluster", args: args{appset: &argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{{Clusters: &argov1alpha1.ClusterGenerator{}}},
|
||||
},
|
||||
}}, want: generators.NoRequeueAfter, wantErr: assert.NoError},
|
||||
{name: "ClusterMergeNested", args: args{&argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{
|
||||
@@ -130,7 +127,7 @@ func TestRequeueAfter(t *testing.T) {
|
||||
}},
|
||||
},
|
||||
},
|
||||
}, ""}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
|
||||
}}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
|
||||
{name: "ClusterMatrixNested", args: args{&argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{
|
||||
@@ -145,65 +142,15 @@ func TestRequeueAfter(t *testing.T) {
|
||||
}},
|
||||
},
|
||||
},
|
||||
}, ""}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
|
||||
}}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
|
||||
{name: "ListGenerator", args: args{appset: &argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{{List: &argov1alpha1.ListGenerator{}}},
|
||||
},
|
||||
}}, want: generators.NoRequeueAfter, wantErr: assert.NoError},
|
||||
{name: "DuckGenerator", args: args{appset: &argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{{ClusterDecisionResource: &argov1alpha1.DuckTypeGenerator{}}},
|
||||
},
|
||||
}}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
|
||||
{name: "OverrideRequeueDuck", args: args{
|
||||
appset: &argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{{ClusterDecisionResource: &argov1alpha1.DuckTypeGenerator{}}},
|
||||
},
|
||||
}, requeueAfterOverride: "1h",
|
||||
}, want: 1 * time.Hour, wantErr: assert.NoError},
|
||||
{name: "OverrideRequeueGit", args: args{&argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{
|
||||
{Git: &argov1alpha1.GitGenerator{}},
|
||||
},
|
||||
},
|
||||
}, "1h"}, want: 1 * time.Hour, wantErr: assert.NoError},
|
||||
{name: "OverrideRequeueMatrix", args: args{&argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{
|
||||
{Clusters: &argov1alpha1.ClusterGenerator{}},
|
||||
{Merge: &argov1alpha1.MergeGenerator{
|
||||
Generators: []argov1alpha1.ApplicationSetNestedGenerator{
|
||||
{
|
||||
Clusters: &argov1alpha1.ClusterGenerator{},
|
||||
Git: &argov1alpha1.GitGenerator{},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}, "5m"}, want: 5 * time.Minute, wantErr: assert.NoError},
|
||||
{name: "OverrideRequeueMerge", args: args{&argov1alpha1.ApplicationSet{
|
||||
Spec: argov1alpha1.ApplicationSetSpec{
|
||||
Generators: []argov1alpha1.ApplicationSetGenerator{
|
||||
{Clusters: &argov1alpha1.ClusterGenerator{}},
|
||||
{Merge: &argov1alpha1.MergeGenerator{
|
||||
Generators: []argov1alpha1.ApplicationSetNestedGenerator{
|
||||
{
|
||||
Clusters: &argov1alpha1.ClusterGenerator{},
|
||||
Git: &argov1alpha1.GitGenerator{},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}, "12s"}, want: 12 * time.Second, wantErr: assert.NoError},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Setenv("ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER", tt.args.requeueAfterOverride)
|
||||
assert.Equalf(t, tt.want, r.getMinRequeueAfter(tt.args.appset), "getMinRequeueAfter(%v)", tt.args.appset)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -69,11 +69,9 @@ func GenerateApplications(logCtx *log.Entry, applicationSetInfo argov1alpha1.App
|
||||
res = append(res, *app)
|
||||
}
|
||||
}
|
||||
if log.IsLevelEnabled(log.DebugLevel) {
|
||||
logCtx.WithField("generator", requestedGenerator).Debugf("apps from generator: %+v", res)
|
||||
} else {
|
||||
logCtx.Infof("generated %d applications", len(res))
|
||||
}
|
||||
|
||||
logCtx.WithField("generator", requestedGenerator).Infof("generated %d applications", len(res))
|
||||
logCtx.WithField("generator", requestedGenerator).Debugf("apps from generator: %+v", res)
|
||||
}
|
||||
|
||||
return res, applicationSetReason, firstError
|
||||
|
||||
@@ -2,7 +2,6 @@ package template
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
@@ -19,6 +18,7 @@ import (
|
||||
rendmock "github.com/argoproj/argo-cd/v2/applicationset/utils/mocks"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/v2/util/collections"
|
||||
)
|
||||
|
||||
func TestGenerateApplications(t *testing.T) {
|
||||
@@ -344,7 +344,7 @@ func TestGenerateAppsUsingPullRequestGenerator(t *testing.T) {
|
||||
assert.EqualValues(t, cases.expectedApp[0].ObjectMeta.Name, gotApp[0].ObjectMeta.Name)
|
||||
assert.EqualValues(t, cases.expectedApp[0].Spec.Source.TargetRevision, gotApp[0].Spec.Source.TargetRevision)
|
||||
assert.EqualValues(t, cases.expectedApp[0].Spec.Destination.Namespace, gotApp[0].Spec.Destination.Namespace)
|
||||
assert.True(t, maps.Equal(cases.expectedApp[0].ObjectMeta.Labels, gotApp[0].ObjectMeta.Labels))
|
||||
assert.True(t, collections.StringMapsEqual(cases.expectedApp[0].ObjectMeta.Labels, gotApp[0].ObjectMeta.Labels))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,14 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/applicationset/utils"
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
argoappsetv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
ArgoCDSecretTypeLabel = "argocd.argoproj.io/secret-type"
|
||||
ArgoCDSecretTypeCluster = "cluster"
|
||||
)
|
||||
|
||||
var _ Generator = (*ClusterGenerator)(nil)
|
||||
|
||||
// ClusterGenerator generates Applications for some or all clusters registered with ArgoCD.
|
||||
@@ -48,7 +52,7 @@ func NewClusterGenerator(c client.Client, ctx context.Context, clientset kuberne
|
||||
|
||||
// GetRequeueAfter never requeue the cluster generator because the `clusterSecretEventHandler` will requeue the appsets
|
||||
// when the cluster secrets change
|
||||
func (g *ClusterGenerator) GetRequeueAfter(_ *argoappsetv1alpha1.ApplicationSetGenerator) time.Duration {
|
||||
func (g *ClusterGenerator) GetRequeueAfter(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator) time.Duration {
|
||||
return NoRequeueAfter
|
||||
}
|
||||
|
||||
@@ -57,7 +61,6 @@ func (g *ClusterGenerator) GetTemplate(appSetGenerator *argoappsetv1alpha1.Appli
|
||||
}
|
||||
|
||||
func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator, appSet *argoappsetv1alpha1.ApplicationSet, _ client.Client) ([]map[string]interface{}, error) {
|
||||
logCtx := log.WithField("applicationset", appSet.GetName()).WithField("namespace", appSet.GetNamespace())
|
||||
if appSetGenerator == nil {
|
||||
return nil, EmptyAppSetGeneratorError
|
||||
}
|
||||
@@ -80,7 +83,7 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
clusterSecrets, err := g.getSecretsByClusterName(logCtx, appSetGenerator)
|
||||
clusterSecrets, err := g.getSecretsByClusterName(appSetGenerator)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting cluster secrets: %w", err)
|
||||
}
|
||||
@@ -89,10 +92,6 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
|
||||
|
||||
secretsFound := []corev1.Secret{}
|
||||
|
||||
isFlatMode := appSetGenerator.Clusters.FlatList
|
||||
logCtx.Debugf("Using flat mode = %t for cluster generator", isFlatMode)
|
||||
clustersParams := make([]map[string]interface{}, 0)
|
||||
|
||||
for _, cluster := range clustersFromArgoCD.Items {
|
||||
// If there is a secret for this cluster, then it's a non-local cluster, so it will be
|
||||
// handled by the next step.
|
||||
@@ -104,20 +103,15 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
|
||||
params["name"] = cluster.Name
|
||||
params["nameNormalized"] = cluster.Name
|
||||
params["server"] = cluster.Server
|
||||
params["project"] = ""
|
||||
|
||||
err = appendTemplatedValues(appSetGenerator.Clusters.Values, params, appSet.Spec.GoTemplate, appSet.Spec.GoTemplateOptions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error appending templated values for local cluster: %w", err)
|
||||
}
|
||||
|
||||
if isFlatMode {
|
||||
clustersParams = append(clustersParams, params)
|
||||
} else {
|
||||
res = append(res, params)
|
||||
}
|
||||
res = append(res, params)
|
||||
|
||||
logCtx.WithField("cluster", "local cluster").Info("matched local cluster")
|
||||
log.WithField("cluster", "local cluster").Info("matched local cluster")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,13 +123,6 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
|
||||
params["nameNormalized"] = utils.SanitizeName(string(cluster.Data["name"]))
|
||||
params["server"] = string(cluster.Data["server"])
|
||||
|
||||
project, ok := cluster.Data["project"]
|
||||
if ok {
|
||||
params["project"] = string(project)
|
||||
} else {
|
||||
params["project"] = ""
|
||||
}
|
||||
|
||||
if appSet.Spec.GoTemplate {
|
||||
meta := map[string]interface{}{}
|
||||
|
||||
@@ -162,27 +149,19 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
|
||||
return nil, fmt.Errorf("error appending templated values for cluster: %w", err)
|
||||
}
|
||||
|
||||
if isFlatMode {
|
||||
clustersParams = append(clustersParams, params)
|
||||
} else {
|
||||
res = append(res, params)
|
||||
}
|
||||
res = append(res, params)
|
||||
|
||||
logCtx.WithField("cluster", cluster.Name).Debug("matched cluster secret")
|
||||
log.WithField("cluster", cluster.Name).Info("matched cluster secret")
|
||||
}
|
||||
|
||||
if isFlatMode {
|
||||
res = append(res, map[string]interface{}{
|
||||
"clusters": clustersParams,
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (g *ClusterGenerator) getSecretsByClusterName(log *log.Entry, appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator) (map[string]corev1.Secret, error) {
|
||||
func (g *ClusterGenerator) getSecretsByClusterName(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator) (map[string]corev1.Secret, error) {
|
||||
// List all Clusters:
|
||||
clusterSecretList := &corev1.SecretList{}
|
||||
|
||||
selector := metav1.AddLabelToSelector(&appSetGenerator.Clusters.Selector, common.LabelKeySecretType, common.LabelValueSecretTypeCluster)
|
||||
selector := metav1.AddLabelToSelector(&appSetGenerator.Clusters.Selector, ArgoCDSecretTypeLabel, ArgoCDSecretTypeCluster)
|
||||
secretSelector, err := metav1.LabelSelectorAsSelector(selector)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error converting label selector: %w", err)
|
||||
@@ -191,7 +170,7 @@ func (g *ClusterGenerator) getSecretsByClusterName(log *log.Entry, appSetGenerat
|
||||
if err := g.Client.List(context.Background(), clusterSecretList, client.MatchingLabelsSelector{Selector: secretSelector}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("clusters matching labels: %d", len(clusterSecretList.Items))
|
||||
log.Debug("clusters matching labels", "count", len(clusterSecretList.Items))
|
||||
|
||||
res := map[string]corev1.Secret{}
|
||||
|
||||
|
||||
@@ -76,20 +76,18 @@ func TestGenerateParams(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"config": []byte("{}"),
|
||||
"name": []byte("production_01/west"),
|
||||
"server": []byte("https://production-01.example.com"),
|
||||
"project": []byte("prod-project"),
|
||||
"config": []byte("{}"),
|
||||
"name": []byte("production_01/west"),
|
||||
"server": []byte("https://production-01.example.com"),
|
||||
},
|
||||
Type: corev1.SecretType("Opaque"),
|
||||
},
|
||||
}
|
||||
testCases := []struct {
|
||||
name string
|
||||
selector metav1.LabelSelector
|
||||
isFlatMode bool
|
||||
values map[string]string
|
||||
expected []map[string]interface{}
|
||||
name string
|
||||
selector metav1.LabelSelector
|
||||
values map[string]string
|
||||
expected []map[string]interface{}
|
||||
// clientError is true if a k8s client error should be simulated
|
||||
clientError bool
|
||||
expectedError error
|
||||
@@ -107,16 +105,17 @@ func TestGenerateParams(t *testing.T) {
|
||||
"aaa": "{{ server }}",
|
||||
"no-op": "{{ this-does-not-exist }}",
|
||||
}, expected: []map[string]interface{}{
|
||||
{"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "nameNormalized": "in-cluster", "name": "in-cluster", "server": "https://kubernetes.default.svc", "project": ""},
|
||||
{
|
||||
"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "production", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "production", "values.aaa": "https://production-01.example.com", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production", "project": "prod-project",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production",
|
||||
},
|
||||
|
||||
{
|
||||
"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "staging", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "staging", "values.aaa": "https://staging-01.example.com", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging", "project": "",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging",
|
||||
},
|
||||
|
||||
{"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "nameNormalized": "in-cluster", "name": "in-cluster", "server": "https://kubernetes.default.svc"},
|
||||
},
|
||||
clientError: false,
|
||||
expectedError: nil,
|
||||
@@ -132,12 +131,12 @@ func TestGenerateParams(t *testing.T) {
|
||||
expected: []map[string]interface{}{
|
||||
{
|
||||
"name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production", "project": "prod-project",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production",
|
||||
},
|
||||
|
||||
{
|
||||
"name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging", "project": "",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging",
|
||||
},
|
||||
},
|
||||
clientError: false,
|
||||
@@ -156,7 +155,7 @@ func TestGenerateParams(t *testing.T) {
|
||||
expected: []map[string]interface{}{
|
||||
{
|
||||
"values.foo": "bar", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production", "project": "prod-project",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production",
|
||||
},
|
||||
},
|
||||
clientError: false,
|
||||
@@ -182,11 +181,11 @@ func TestGenerateParams(t *testing.T) {
|
||||
expected: []map[string]interface{}{
|
||||
{
|
||||
"values.foo": "bar", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging", "project": "",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging",
|
||||
},
|
||||
{
|
||||
"values.foo": "bar", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production", "project": "prod-project",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production",
|
||||
},
|
||||
},
|
||||
clientError: false,
|
||||
@@ -215,7 +214,7 @@ func TestGenerateParams(t *testing.T) {
|
||||
expected: []map[string]interface{}{
|
||||
{
|
||||
"values.name": "baz", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging", "project": "",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging",
|
||||
},
|
||||
},
|
||||
clientError: false,
|
||||
@@ -229,74 +228,6 @@ func TestGenerateParams(t *testing.T) {
|
||||
clientError: true,
|
||||
expectedError: fmt.Errorf("error getting cluster secrets: could not list Secrets"),
|
||||
},
|
||||
{
|
||||
name: "flat mode without selectors",
|
||||
selector: metav1.LabelSelector{},
|
||||
values: map[string]string{
|
||||
"lol1": "lol",
|
||||
"lol2": "{{values.lol1}}{{values.lol1}}",
|
||||
"lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}",
|
||||
"foo": "bar",
|
||||
"bar": "{{ metadata.annotations.foo.argoproj.io }}",
|
||||
"bat": "{{ metadata.labels.environment }}",
|
||||
"aaa": "{{ server }}",
|
||||
"no-op": "{{ this-does-not-exist }}",
|
||||
},
|
||||
expected: []map[string]interface{}{
|
||||
{
|
||||
"clusters": []map[string]interface{}{
|
||||
{"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "nameNormalized": "in-cluster", "name": "in-cluster", "server": "https://kubernetes.default.svc", "project": ""},
|
||||
{
|
||||
"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "production", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "production", "values.aaa": "https://production-01.example.com", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production", "project": "prod-project",
|
||||
},
|
||||
|
||||
{
|
||||
"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "staging", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "staging", "values.aaa": "https://staging-01.example.com", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging", "project": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
isFlatMode: true,
|
||||
clientError: false,
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "production or staging with flat mode",
|
||||
selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "environment",
|
||||
Operator: "In",
|
||||
Values: []string{
|
||||
"production",
|
||||
"staging",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
isFlatMode: true,
|
||||
values: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
expected: []map[string]interface{}{
|
||||
{
|
||||
"clusters": []map[string]interface{}{
|
||||
{
|
||||
"values.foo": "bar", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production", "project": "prod-project",
|
||||
},
|
||||
{
|
||||
"values.foo": "bar", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
|
||||
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging", "project": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
clientError: false,
|
||||
expectedError: nil,
|
||||
},
|
||||
}
|
||||
|
||||
// convert []client.Object to []runtime.Object, for use by kubefake package
|
||||
@@ -328,7 +259,6 @@ func TestGenerateParams(t *testing.T) {
|
||||
Clusters: &argoprojiov1alpha1.ClusterGenerator{
|
||||
Selector: testCase.selector,
|
||||
Values: testCase.values,
|
||||
FlatList: testCase.isFlatMode,
|
||||
},
|
||||
}, &applicationSetInfo, nil)
|
||||
|
||||
@@ -394,11 +324,10 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
testCases := []struct {
|
||||
name string
|
||||
selector metav1.LabelSelector
|
||||
values map[string]string
|
||||
isFlatMode bool
|
||||
expected []map[string]interface{}
|
||||
name string
|
||||
selector metav1.LabelSelector
|
||||
values map[string]string
|
||||
expected []map[string]interface{}
|
||||
// clientError is true if a k8s client error should be simulated
|
||||
clientError bool
|
||||
expectedError error
|
||||
@@ -420,7 +349,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
"name": "production_01/west",
|
||||
"nameNormalized": "production-01-west",
|
||||
"server": "https://production-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
@@ -446,7 +374,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
"name": "staging-01",
|
||||
"nameNormalized": "staging-01",
|
||||
"server": "https://staging-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
@@ -472,7 +399,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
"nameNormalized": "in-cluster",
|
||||
"name": "in-cluster",
|
||||
"server": "https://kubernetes.default.svc",
|
||||
"project": "",
|
||||
"values": map[string]string{
|
||||
"lol1": "lol",
|
||||
"lol2": "<no value><no value>",
|
||||
@@ -501,7 +427,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
"name": "production_01/west",
|
||||
"nameNormalized": "production-01-west",
|
||||
"server": "https://production-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
@@ -517,7 +442,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
"name": "staging-01",
|
||||
"nameNormalized": "staging-01",
|
||||
"server": "https://staging-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
@@ -548,7 +472,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
"name": "production_01/west",
|
||||
"nameNormalized": "production-01-west",
|
||||
"server": "https://production-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
@@ -589,7 +512,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
"name": "production_01/west",
|
||||
"nameNormalized": "production-01-west",
|
||||
"server": "https://production-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
@@ -608,7 +530,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
"name": "staging-01",
|
||||
"nameNormalized": "staging-01",
|
||||
"server": "https://staging-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
@@ -652,7 +573,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
"name": "staging-01",
|
||||
"nameNormalized": "staging-01",
|
||||
"server": "https://staging-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
@@ -679,162 +599,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
clientError: true,
|
||||
expectedError: fmt.Errorf("error getting cluster secrets: could not list Secrets"),
|
||||
},
|
||||
{
|
||||
name: "Clusters with flat list mode and no selector",
|
||||
selector: metav1.LabelSelector{},
|
||||
isFlatMode: true,
|
||||
values: map[string]string{
|
||||
"lol1": "lol",
|
||||
"lol2": "{{ .values.lol1 }}{{ .values.lol1 }}",
|
||||
"lol3": "{{ .values.lol2 }}{{ .values.lol2 }}{{ .values.lol2 }}",
|
||||
"foo": "bar",
|
||||
"bar": "{{ if not (empty .metadata) }}{{index .metadata.annotations \"foo.argoproj.io\" }}{{ end }}",
|
||||
"bat": "{{ if not (empty .metadata) }}{{.metadata.labels.environment}}{{ end }}",
|
||||
"aaa": "{{ .server }}",
|
||||
"no-op": "{{ .thisDoesNotExist }}",
|
||||
},
|
||||
expected: []map[string]interface{}{
|
||||
{
|
||||
"clusters": []map[string]interface{}{
|
||||
{
|
||||
"nameNormalized": "in-cluster",
|
||||
"name": "in-cluster",
|
||||
"server": "https://kubernetes.default.svc",
|
||||
"project": "",
|
||||
"values": map[string]string{
|
||||
"lol1": "lol",
|
||||
"lol2": "<no value><no value>",
|
||||
"lol3": "<no value><no value><no value>",
|
||||
"foo": "bar",
|
||||
"bar": "",
|
||||
"bat": "",
|
||||
"aaa": "https://kubernetes.default.svc",
|
||||
"no-op": "<no value>",
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "production_01/west",
|
||||
"nameNormalized": "production-01-west",
|
||||
"server": "https://production-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
"environment": "production",
|
||||
"org": "bar",
|
||||
},
|
||||
"annotations": map[string]string{
|
||||
"foo.argoproj.io": "production",
|
||||
},
|
||||
},
|
||||
"values": map[string]string{
|
||||
"lol1": "lol",
|
||||
"lol2": "<no value><no value>",
|
||||
"lol3": "<no value><no value><no value>",
|
||||
"foo": "bar",
|
||||
"bar": "production",
|
||||
"bat": "production",
|
||||
"aaa": "https://production-01.example.com",
|
||||
"no-op": "<no value>",
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "staging-01",
|
||||
"nameNormalized": "staging-01",
|
||||
"server": "https://staging-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
"environment": "staging",
|
||||
"org": "foo",
|
||||
},
|
||||
"annotations": map[string]string{
|
||||
"foo.argoproj.io": "staging",
|
||||
},
|
||||
},
|
||||
"values": map[string]string{
|
||||
"lol1": "lol",
|
||||
"lol2": "<no value><no value>",
|
||||
"lol3": "<no value><no value><no value>",
|
||||
"foo": "bar",
|
||||
"bar": "staging",
|
||||
"bat": "staging",
|
||||
"aaa": "https://staging-01.example.com",
|
||||
"no-op": "<no value>",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
clientError: false,
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "production or staging with flat mode",
|
||||
selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "environment",
|
||||
Operator: "In",
|
||||
Values: []string{
|
||||
"production",
|
||||
"staging",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
isFlatMode: true,
|
||||
values: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
expected: []map[string]interface{}{
|
||||
{
|
||||
"clusters": []map[string]interface{}{
|
||||
{
|
||||
"name": "production_01/west",
|
||||
"nameNormalized": "production-01-west",
|
||||
"server": "https://production-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
"environment": "production",
|
||||
"org": "bar",
|
||||
},
|
||||
"annotations": map[string]string{
|
||||
"foo.argoproj.io": "production",
|
||||
},
|
||||
},
|
||||
"values": map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "staging-01",
|
||||
"nameNormalized": "staging-01",
|
||||
"server": "https://staging-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"argocd.argoproj.io/secret-type": "cluster",
|
||||
"environment": "staging",
|
||||
"org": "foo",
|
||||
},
|
||||
"annotations": map[string]string{
|
||||
"foo.argoproj.io": "staging",
|
||||
},
|
||||
},
|
||||
"values": map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
clientError: false,
|
||||
expectedError: nil,
|
||||
},
|
||||
}
|
||||
|
||||
// convert []client.Object to []runtime.Object, for use by kubefake package
|
||||
@@ -868,7 +632,6 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
|
||||
Clusters: &argoprojiov1alpha1.ClusterGenerator{
|
||||
Selector: testCase.selector,
|
||||
Values: testCase.values,
|
||||
FlatList: testCase.isFlatMode,
|
||||
},
|
||||
}, &applicationSetInfo, nil)
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ func (g *DuckTypeGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.
|
||||
return time.Duration(*appSetGenerator.ClusterDecisionResource.RequeueAfterSeconds) * time.Second
|
||||
}
|
||||
|
||||
return getDefaultRequeueAfter()
|
||||
return DefaultRequeueAfterSeconds
|
||||
}
|
||||
|
||||
func (g *DuckTypeGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) *argoprojiov1alpha1.ApplicationSetTemplate {
|
||||
|
||||
@@ -199,7 +199,6 @@ func TestTransForm(t *testing.T) {
|
||||
"name": "production_01/west",
|
||||
"nameNormalized": "production-01-west",
|
||||
"server": "https://production-01.example.com",
|
||||
"project": "",
|
||||
}},
|
||||
},
|
||||
{
|
||||
@@ -215,7 +214,6 @@ func TestTransForm(t *testing.T) {
|
||||
"name": "some-really-long-server-url",
|
||||
"nameNormalized": "some-really-long-server-url",
|
||||
"server": "https://some-really-long-url-that-will-exceed-63-characters.com",
|
||||
"project": "",
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func (g *GitGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.Appli
|
||||
return time.Duration(*appSetGenerator.Git.RequeueAfterSeconds) * time.Second
|
||||
}
|
||||
|
||||
return getDefaultRequeueAfter()
|
||||
return DefaultRequeueAfterSeconds
|
||||
}
|
||||
|
||||
func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet, client client.Client) ([]map[string]interface{}, error) {
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/v2/util/env"
|
||||
)
|
||||
|
||||
// Generator defines the interface implemented by all ApplicationSet generators.
|
||||
@@ -31,11 +30,7 @@ var (
|
||||
NoRequeueAfter time.Duration
|
||||
)
|
||||
|
||||
// DefaultRequeueAfterSeconds is used when GetRequeueAfter is not specified, it is the default time to wait before the next reconcile loop
|
||||
const (
|
||||
DefaultRequeueAfterSeconds = 3 * time.Minute
|
||||
)
|
||||
|
||||
func getDefaultRequeueAfter() time.Duration {
|
||||
// Default is 3 minutes, min is 1 second, max is 1 year
|
||||
return env.ParseDurationFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER", DefaultRequeueAfterSeconds, 1*time.Second, 8760*time.Hour)
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package generators
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_getDefaultRequeueAfter(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
requeueAfterEnv string
|
||||
want time.Duration
|
||||
}{
|
||||
{name: "Default", requeueAfterEnv: "", want: DefaultRequeueAfterSeconds},
|
||||
{name: "Min", requeueAfterEnv: "1s", want: 1 * time.Second},
|
||||
{name: "Max", requeueAfterEnv: "8760h", want: 8760 * time.Hour},
|
||||
{name: "Override", requeueAfterEnv: "10m", want: 10 * time.Minute},
|
||||
{name: "LessThanMin", requeueAfterEnv: "1ms", want: DefaultRequeueAfterSeconds},
|
||||
{name: "MoreThanMax", requeueAfterEnv: "8761h", want: DefaultRequeueAfterSeconds},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Setenv("ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER", tt.requeueAfterEnv)
|
||||
assert.Equalf(t, tt.want, getDefaultRequeueAfter(), "getDefaultRequeueAfter()")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -578,8 +578,8 @@ func TestInterpolatedMatrixGenerate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expected: []map[string]interface{}{
|
||||
{"path": "examples/git-generator-files-discovery/cluster-config/dev/config.json", "path.basename": "dev", "path.basenameNormalized": "dev", "name": "dev-01", "nameNormalized": "dev-01", "server": "https://dev-01.example.com", "metadata.labels.environment": "dev", "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "project": ""},
|
||||
{"path": "examples/git-generator-files-discovery/cluster-config/prod/config.json", "path.basename": "prod", "path.basenameNormalized": "prod", "name": "prod-01", "nameNormalized": "prod-01", "server": "https://prod-01.example.com", "metadata.labels.environment": "prod", "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "project": ""},
|
||||
{"path": "examples/git-generator-files-discovery/cluster-config/dev/config.json", "path.basename": "dev", "path.basenameNormalized": "dev", "name": "dev-01", "nameNormalized": "dev-01", "server": "https://dev-01.example.com", "metadata.labels.environment": "dev", "metadata.labels.argocd.argoproj.io/secret-type": "cluster"},
|
||||
{"path": "examples/git-generator-files-discovery/cluster-config/prod/config.json", "path.basename": "prod", "path.basenameNormalized": "prod", "name": "prod-01", "nameNormalized": "prod-01", "server": "https://prod-01.example.com", "metadata.labels.environment": "prod", "metadata.labels.argocd.argoproj.io/secret-type": "cluster"},
|
||||
},
|
||||
clientError: false,
|
||||
},
|
||||
@@ -734,7 +734,6 @@ func TestInterpolatedMatrixGenerateGoTemplate(t *testing.T) {
|
||||
"name": "dev-01",
|
||||
"nameNormalized": "dev-01",
|
||||
"server": "https://dev-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"environment": "dev",
|
||||
@@ -751,7 +750,6 @@ func TestInterpolatedMatrixGenerateGoTemplate(t *testing.T) {
|
||||
"name": "prod-01",
|
||||
"nameNormalized": "prod-01",
|
||||
"server": "https://prod-01.example.com",
|
||||
"project": "",
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]string{
|
||||
"environment": "prod",
|
||||
|
||||
@@ -197,7 +197,6 @@ func TestMergeGenerate(t *testing.T) {
|
||||
}
|
||||
|
||||
func toAPIExtensionsJSON(t *testing.T, g interface{}) *apiextensionsv1.JSON {
|
||||
t.Helper()
|
||||
resVal, err := json.Marshal(g)
|
||||
if err != nil {
|
||||
t.Error("unable to unmarshal json", g)
|
||||
|
||||
@@ -694,7 +694,7 @@ func TestPluginGenerateParams(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
gotJson, err := json.Marshal(got)
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, string(expectedJson), string(gotJson))
|
||||
assert.Equal(t, string(expectedJson), string(gotJson))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
|
||||
return nil, fmt.Errorf("error fetching CA certificates from ConfigMap: %w", prErr)
|
||||
}
|
||||
}
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
@@ -147,7 +147,7 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
|
||||
}
|
||||
if generatorConfig.Gitea != nil {
|
||||
providerConfig := generatorConfig.Gitea
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
@@ -164,13 +164,13 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
|
||||
}
|
||||
}
|
||||
if providerConfig.BearerToken != nil {
|
||||
appToken, err := utils.GetSecretRef(ctx, g.client, providerConfig.BearerToken.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
appToken, err := utils.GetSecretRef(ctx, g.client, providerConfig.BearerToken.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret Bearer token: %w", err)
|
||||
}
|
||||
return pullrequest.NewBitbucketServiceBearerToken(ctx, appToken, providerConfig.API, providerConfig.Project, providerConfig.Repo, g.scmRootCAPath, providerConfig.Insecure, caCerts)
|
||||
} else if providerConfig.BasicAuth != nil {
|
||||
password, err := utils.GetSecretRef(ctx, g.client, providerConfig.BasicAuth.PasswordRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
password, err := utils.GetSecretRef(ctx, g.client, providerConfig.BasicAuth.PasswordRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
@@ -182,13 +182,13 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
|
||||
if generatorConfig.Bitbucket != nil {
|
||||
providerConfig := generatorConfig.Bitbucket
|
||||
if providerConfig.BearerToken != nil {
|
||||
appToken, err := utils.GetSecretRef(ctx, g.client, providerConfig.BearerToken.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
appToken, err := utils.GetSecretRef(ctx, g.client, providerConfig.BearerToken.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret Bearer token: %w", err)
|
||||
}
|
||||
return pullrequest.NewBitbucketCloudServiceBearerToken(providerConfig.API, appToken, providerConfig.Owner, providerConfig.Repo)
|
||||
} else if providerConfig.BasicAuth != nil {
|
||||
password, err := utils.GetSecretRef(ctx, g.client, providerConfig.BasicAuth.PasswordRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
password, err := utils.GetSecretRef(ctx, g.client, providerConfig.BasicAuth.PasswordRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
@@ -199,7 +199,7 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
|
||||
}
|
||||
if generatorConfig.AzureDevOps != nil {
|
||||
providerConfig := generatorConfig.AzureDevOps
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
@@ -219,7 +219,7 @@ func (g *PullRequestGenerator) github(ctx context.Context, cfg *argoprojiov1alph
|
||||
}
|
||||
|
||||
// always default to token, even if not set (public access)
|
||||
token, err := utils.GetSecretRef(ctx, g.client, cfg.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
token, err := utils.GetSecretRef(ctx, g.client, cfg.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ func TestAllowedSCMProviderPullRequest(t *testing.T) {
|
||||
"gitea.myorg.com",
|
||||
"bitbucket.myorg.com",
|
||||
"azuredevops.myorg.com",
|
||||
}, true, nil, true))
|
||||
}, true, nil))
|
||||
|
||||
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -306,7 +306,7 @@ func TestAllowedSCMProviderPullRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSCMProviderDisabled_PRGenerator(t *testing.T) {
|
||||
generator := NewPullRequestGenerator(nil, NewSCMConfig("", []string{}, false, nil, true))
|
||||
generator := NewPullRequestGenerator(nil, NewSCMConfig("", []string{}, false, nil))
|
||||
|
||||
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
||||
@@ -35,16 +35,14 @@ type SCMConfig struct {
|
||||
allowedSCMProviders []string
|
||||
enableSCMProviders bool
|
||||
GitHubApps github_app_auth.Credentials
|
||||
tokenRefStrictMode bool
|
||||
}
|
||||
|
||||
func NewSCMConfig(scmRootCAPath string, allowedSCMProviders []string, enableSCMProviders bool, gitHubApps github_app_auth.Credentials, tokenRefStrictMode bool) SCMConfig {
|
||||
func NewSCMConfig(scmRootCAPath string, allowedSCMProviders []string, enableSCMProviders bool, gitHubApps github_app_auth.Credentials) SCMConfig {
|
||||
return SCMConfig{
|
||||
scmRootCAPath: scmRootCAPath,
|
||||
allowedSCMProviders: allowedSCMProviders,
|
||||
enableSCMProviders: enableSCMProviders,
|
||||
GitHubApps: gitHubApps,
|
||||
tokenRefStrictMode: tokenRefStrictMode,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +154,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
return nil, fmt.Errorf("error fetching CA certificates from ConfigMap: %w", scmError)
|
||||
}
|
||||
}
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Gitlab token: %w", err)
|
||||
}
|
||||
@@ -165,7 +163,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
return nil, fmt.Errorf("error initializing Gitlab service: %w", err)
|
||||
}
|
||||
} else if providerConfig.Gitea != nil {
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.Gitea.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.Gitea.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Gitea token: %w", err)
|
||||
}
|
||||
@@ -184,13 +182,13 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
}
|
||||
}
|
||||
if providerConfig.BearerToken != nil {
|
||||
appToken, err := utils.GetSecretRef(ctx, g.client, providerConfig.BearerToken.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
appToken, err := utils.GetSecretRef(ctx, g.client, providerConfig.BearerToken.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret Bearer token: %w", err)
|
||||
}
|
||||
provider, scmError = scm_provider.NewBitbucketServerProviderBearerToken(ctx, appToken, providerConfig.API, providerConfig.Project, providerConfig.AllBranches, g.scmRootCAPath, providerConfig.Insecure, caCerts)
|
||||
} else if providerConfig.BasicAuth != nil {
|
||||
password, err := utils.GetSecretRef(ctx, g.client, providerConfig.BasicAuth.PasswordRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
password, err := utils.GetSecretRef(ctx, g.client, providerConfig.BasicAuth.PasswordRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
@@ -202,7 +200,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
return nil, fmt.Errorf("error initializing Bitbucket Server service: %w", scmError)
|
||||
}
|
||||
} else if providerConfig.AzureDevOps != nil {
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.AzureDevOps.AccessTokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
token, err := utils.GetSecretRef(ctx, g.client, providerConfig.AzureDevOps.AccessTokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Azure Devops access token: %w", err)
|
||||
}
|
||||
@@ -211,7 +209,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
return nil, fmt.Errorf("error initializing Azure Devops service: %w", err)
|
||||
}
|
||||
} else if providerConfig.Bitbucket != nil {
|
||||
appPassword, err := utils.GetSecretRef(ctx, g.client, providerConfig.Bitbucket.AppPasswordRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
appPassword, err := utils.GetSecretRef(ctx, g.client, providerConfig.Bitbucket.AppPasswordRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Bitbucket cloud appPassword: %w", err)
|
||||
}
|
||||
@@ -285,7 +283,7 @@ func (g *SCMProviderGenerator) githubProvider(ctx context.Context, github *argop
|
||||
)
|
||||
}
|
||||
|
||||
token, err := utils.GetSecretRef(ctx, g.client, github.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
token, err := utils.GetSecretRef(ctx, g.client, github.TokenRef, applicationSetInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Github token: %w", err)
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ func TestApplicationsetCollector(t *testing.T) {
|
||||
appsetCollector := newAppsetCollector(utils.NewAppsetLister(client), collectedLabels, filter)
|
||||
|
||||
metrics.Registry.MustRegister(appsetCollector)
|
||||
req, err := http.NewRequest(http.MethodGet, "/metrics", nil)
|
||||
req, err := http.NewRequest("GET", "/metrics", nil)
|
||||
require.NoError(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
handler := promhttp.HandlerFor(metrics.Registry, promhttp.HandlerOpts{})
|
||||
@@ -220,7 +220,7 @@ func TestObserveReconcile(t *testing.T) {
|
||||
|
||||
appsetMetrics := NewApplicationsetMetrics(utils.NewAppsetLister(client), collectedLabels, filter)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "/metrics", nil)
|
||||
req, err := http.NewRequest("GET", "/metrics", nil)
|
||||
require.NoError(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
handler := promhttp.HandlerFor(metrics.Registry, promhttp.HandlerOpts{})
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/bradleyfalzon/ghinstallation/v2"
|
||||
"github.com/google/go-github/v66/github"
|
||||
"github.com/google/go-github/v63/github"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/applicationset/services/github_app_auth"
|
||||
)
|
||||
|
||||
@@ -134,7 +134,7 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*htt
|
||||
|
||||
// CheckResponse checks the API response for errors, and returns them if present.
|
||||
func CheckResponse(resp *http.Response) error {
|
||||
if c := resp.StatusCode; http.StatusOK <= c && c < http.StatusMultipleChoices {
|
||||
if c := resp.StatusCode; 200 <= c && c <= 299 {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
@@ -25,7 +24,9 @@ func TestClient(t *testing.T) {
|
||||
|
||||
var clientOptionFns []ClientOptionFunc
|
||||
_, err := NewClient(server.URL, clientOptionFns...)
|
||||
require.NoError(t, err, "Failed to create client")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create client: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientDo(t *testing.T) {
|
||||
@@ -76,7 +77,7 @@ func TestClientDo(t *testing.T) {
|
||||
"key3": float64(123),
|
||||
},
|
||||
},
|
||||
expectedCode: http.StatusOK,
|
||||
expectedCode: 200,
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
@@ -108,7 +109,7 @@ func TestClientDo(t *testing.T) {
|
||||
})),
|
||||
clientOptionFns: nil,
|
||||
expected: []map[string]interface{}(nil),
|
||||
expectedCode: http.StatusUnauthorized,
|
||||
expectedCode: 401,
|
||||
expectedError: fmt.Errorf("API error with status code 401: "),
|
||||
},
|
||||
} {
|
||||
@@ -117,10 +118,14 @@ func TestClientDo(t *testing.T) {
|
||||
defer cc.fakeServer.Close()
|
||||
|
||||
client, err := NewClient(cc.fakeServer.URL, cc.clientOptionFns...)
|
||||
require.NoError(t, err, "NewClient returned unexpected error")
|
||||
if err != nil {
|
||||
t.Fatalf("NewClient returned unexpected error: %v", err)
|
||||
}
|
||||
|
||||
req, err := client.NewRequest("POST", "", cc.params, nil)
|
||||
require.NoError(t, err, "NewRequest returned unexpected error")
|
||||
if err != nil {
|
||||
t.Fatalf("NewRequest returned unexpected error: %v", err)
|
||||
}
|
||||
|
||||
var data []map[string]interface{}
|
||||
|
||||
@@ -144,5 +149,12 @@ func TestCheckResponse(t *testing.T) {
|
||||
}
|
||||
|
||||
err := CheckResponse(resp)
|
||||
require.EqualError(t, err, "API error with status code 400: invalid_request")
|
||||
if err == nil {
|
||||
t.Error("Expected an error, got nil")
|
||||
}
|
||||
|
||||
expected := "API error with status code 400: invalid_request"
|
||||
if err.Error() != expected {
|
||||
t.Errorf("Expected error '%s', got '%s'", expected, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPlugin(t *testing.T) {
|
||||
@@ -32,13 +31,19 @@ func TestPlugin(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
client, err := NewPluginService(context.Background(), "plugin-test", ts.URL, token, 0)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
data, err := client.List(context.Background(), nil)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
var expectedData ServiceResponse
|
||||
err = json.Unmarshal([]byte(expectedJSON), &expectedData)
|
||||
require.NoError(t, err)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, &expectedData, data)
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ func (a *AzureDevOpsService) List(ctx context.Context) ([]*PullRequest, error) {
|
||||
pr.Repository.Name == nil ||
|
||||
pr.PullRequestId == nil ||
|
||||
pr.SourceRefName == nil ||
|
||||
pr.TargetRefName == nil ||
|
||||
pr.LastMergeSourceCommit == nil ||
|
||||
pr.LastMergeSourceCommit.CommitId == nil {
|
||||
continue
|
||||
@@ -95,13 +94,12 @@ func (a *AzureDevOpsService) List(ctx context.Context) ([]*PullRequest, error) {
|
||||
|
||||
if *pr.Repository.Name == a.repo {
|
||||
pullRequests = append(pullRequests, &PullRequest{
|
||||
Number: *pr.PullRequestId,
|
||||
Title: *pr.Title,
|
||||
Branch: strings.Replace(*pr.SourceRefName, "refs/heads/", "", 1),
|
||||
TargetBranch: strings.Replace(*pr.TargetRefName, "refs/heads/", "", 1),
|
||||
HeadSHA: *pr.LastMergeSourceCommit.CommitId,
|
||||
Labels: azureDevOpsLabels,
|
||||
Author: strings.Split(*pr.CreatedBy.UniqueName, "@")[0], // Get the part before the @ in the email-address
|
||||
Number: *pr.PullRequestId,
|
||||
Title: *pr.Title,
|
||||
Branch: strings.Replace(*pr.SourceRefName, "refs/heads/", "", 1),
|
||||
HeadSHA: *pr.LastMergeSourceCommit.CommitId,
|
||||
Labels: azureDevOpsLabels,
|
||||
Author: strings.Split(*pr.CreatedBy.UniqueName, "@")[0], // Get the part before the @ in the email-address
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,6 @@ func TestListPullRequest(t *testing.T) {
|
||||
PullRequestId: createIntPtr(pr_id),
|
||||
Title: createStringPtr(pr_title),
|
||||
SourceRefName: createStringPtr("refs/heads/feature-branch"),
|
||||
TargetRefName: createStringPtr("refs/heads/main"),
|
||||
LastMergeSourceCommit: &git.GitCommitRef{
|
||||
CommitId: createStringPtr(pr_head_sha),
|
||||
},
|
||||
@@ -107,7 +106,6 @@ func TestListPullRequest(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, list, 1)
|
||||
assert.Equal(t, "feature-branch", list[0].Branch)
|
||||
assert.Equal(t, "main", list[0].TargetBranch)
|
||||
assert.Equal(t, pr_head_sha, list[0].HeadSHA)
|
||||
assert.Equal(t, "feat(123)", list[0].Title)
|
||||
assert.Equal(t, pr_id, list[0].Number)
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
)
|
||||
|
||||
func defaultHandlerCloud(t *testing.T) func(http.ResponseWriter, *http.Request) {
|
||||
t.Helper()
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var err error
|
||||
@@ -242,7 +241,7 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
|
||||
|
||||
func TestListResponseErrorCloud(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.WriteHeader(500)
|
||||
}))
|
||||
defer ts.Close()
|
||||
svc, _ := NewBitbucketCloudServiceNoAuth(ts.URL, "OWNER", "REPO")
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
)
|
||||
|
||||
func defaultHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
|
||||
t.Helper()
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var err error
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
)
|
||||
|
||||
func giteaMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
|
||||
t.Helper()
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
fmt.Println(r.RequestURI)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/google/go-github/v66/github"
|
||||
"github.com/google/go-github/v63/github"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ package pull_request
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-github/v66/github"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/google/go-github/v63/github"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func toPtr(s string) *string {
|
||||
@@ -52,8 +52,9 @@ func TestContainLabels(t *testing.T) {
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.Name, func(t *testing.T) {
|
||||
got := containLabels(c.Labels, c.PullLabels)
|
||||
require.Equal(t, got, c.Expect)
|
||||
if got := containLabels(c.Labels, c.PullLabels); got != c.Expect {
|
||||
t.Errorf("expect: %v, got: %v", c.Expect, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -82,7 +83,7 @@ func TestGetGitHubPRLabelNames(t *testing.T) {
|
||||
for _, test := range Tests {
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
labels := getGithubPRLabelNames(test.PullLabels)
|
||||
require.Equal(t, test.ExpectedResult, labels)
|
||||
assert.Equal(t, test.ExpectedResult, labels)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,14 @@ import (
|
||||
)
|
||||
|
||||
func writeMRListResponse(t *testing.T, w io.Writer) {
|
||||
t.Helper()
|
||||
f, err := os.Open("fixtures/gitlab_mr_list_response.json")
|
||||
require.NoErrorf(t, err, "error opening fixture file: %v", err)
|
||||
if err != nil {
|
||||
t.Fatalf("error opening fixture file: %v", err)
|
||||
}
|
||||
|
||||
_, err = io.Copy(w, f)
|
||||
require.NoErrorf(t, err, "error writing response: %v", err)
|
||||
if _, err = io.Copy(w, f); err != nil {
|
||||
t.Fatalf("error writing response: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitLabServiceCustomBaseURL(t *testing.T) {
|
||||
|
||||
@@ -129,7 +129,7 @@ func (b *BitbucketServerProvider) RepoHasPath(_ context.Context, repo *Repositor
|
||||
}
|
||||
// No need to query for all pages here
|
||||
response, err := b.client.DefaultApi.GetContent_0(repo.Organization, repo.Repository, path, opts)
|
||||
if response != nil && response.StatusCode == http.StatusNotFound {
|
||||
if response != nil && response.StatusCode == 404 {
|
||||
// File/directory not found
|
||||
return false, nil
|
||||
}
|
||||
@@ -203,7 +203,7 @@ func (b *BitbucketServerProvider) getDefaultBranch(org string, repo string) (*bi
|
||||
response, err := b.client.DefaultApi.GetDefaultBranch(org, repo)
|
||||
// The API will return 404 if a default branch is set but doesn't exist. In case the repo is empty and default branch is unset,
|
||||
// we will get an EOF and a nil response.
|
||||
if (response != nil && response.StatusCode == http.StatusNotFound) || (response == nil && err != nil && errors.Is(err, io.EOF)) {
|
||||
if (response != nil && response.StatusCode == 404) || (response == nil && err != nil && errors.Is(err, io.EOF)) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
)
|
||||
|
||||
func defaultHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
|
||||
t.Helper()
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var err error
|
||||
@@ -83,7 +82,6 @@ func defaultHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
|
||||
}
|
||||
|
||||
func verifyDefaultRepo(t *testing.T, err error, repos []*Repository) {
|
||||
t.Helper()
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, repos, 1)
|
||||
assert.Equal(t, Repository{
|
||||
|
||||
@@ -128,7 +128,7 @@ func (g *GiteaProvider) ListRepos(ctx context.Context, cloneProtocol string) ([]
|
||||
|
||||
func (g *GiteaProvider) RepoHasPath(ctx context.Context, repo *Repository, path string) (bool, error) {
|
||||
_, resp, err := g.client.GetContents(repo.Organization, repo.Repository, repo.Branch, path)
|
||||
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
||||
if resp != nil && resp.StatusCode == 404 {
|
||||
return false, nil
|
||||
}
|
||||
if fmt.Sprint(err) == "expect file, got directory" {
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
)
|
||||
|
||||
func giteaMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
|
||||
t.Helper()
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
switch r.RequestURI {
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/google/go-github/v66/github"
|
||||
"github.com/google/go-github/v63/github"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
@@ -107,7 +107,7 @@ func (g *GithubProvider) RepoHasPath(ctx context.Context, repo *Repository, path
|
||||
Ref: repo.Branch,
|
||||
})
|
||||
// 404s are not an error here, just a normal false.
|
||||
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
||||
if resp != nil && resp.StatusCode == 404 {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
)
|
||||
|
||||
func githubMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
|
||||
t.Helper()
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
switch r.RequestURI {
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
)
|
||||
|
||||
func gitlabMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
|
||||
t.Helper()
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
switch r.RequestURI {
|
||||
|
||||
@@ -30,7 +30,7 @@ func Test_secretToCluster(t *testing.T) {
|
||||
Data: map[string][]byte{
|
||||
"name": []byte("test"),
|
||||
"server": []byte("http://mycluster"),
|
||||
"config": []byte("{\"username\":\"foo\", \"disableCompression\":true}"),
|
||||
"config": []byte("{\"username\":\"foo\"}"),
|
||||
},
|
||||
}
|
||||
cluster, err := secretToCluster(secret)
|
||||
@@ -39,8 +39,7 @@ func Test_secretToCluster(t *testing.T) {
|
||||
Name: "test",
|
||||
Server: "http://mycluster",
|
||||
Config: argoappv1.ClusterConfig{
|
||||
Username: "foo",
|
||||
DisableCompression: true,
|
||||
Username: "foo",
|
||||
},
|
||||
}, *cluster)
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ spec:
|
||||
require.NoError(t, err)
|
||||
yamlExpected, err := yaml.Marshal(tc.expectedApp)
|
||||
require.NoError(t, err)
|
||||
assert.YAMLEq(t, string(yamlExpected), string(yamlFound))
|
||||
assert.Equal(t, string(yamlExpected), string(yamlFound))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
)
|
||||
|
||||
var ErrDisallowedSecretAccess = fmt.Errorf("secret must have label %q=%q", common.LabelKeySecretType, common.LabelValueSecretTypeSCMCreds)
|
||||
|
||||
// getSecretRef gets the value of the key for the specified Secret resource.
|
||||
func GetSecretRef(ctx context.Context, k8sClient client.Client, ref *argoprojiov1alpha1.SecretRef, namespace string, tokenRefStrictMode bool) (string, error) {
|
||||
func GetSecretRef(ctx context.Context, k8sClient client.Client, ref *argoprojiov1alpha1.SecretRef, namespace string) (string, error) {
|
||||
if ref == nil {
|
||||
return "", nil
|
||||
}
|
||||
@@ -31,11 +27,6 @@ func GetSecretRef(ctx context.Context, k8sClient client.Client, ref *argoprojiov
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error fetching secret %s/%s: %w", namespace, ref.SecretName, err)
|
||||
}
|
||||
|
||||
if tokenRefStrictMode && secret.GetLabels()[common.LabelKeySecretType] != common.LabelValueSecretTypeSCMCreds {
|
||||
return "", fmt.Errorf("secret %s/%s is not a valid SCM creds secret: %w", namespace, ref.SecretName, ErrDisallowedSecretAccess)
|
||||
}
|
||||
|
||||
tokenBytes, ok := secret.Data[ref.Key]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("key %q in secret %s/%s not found", ref.Key, namespace, ref.SecretName)
|
||||
|
||||
@@ -67,7 +67,7 @@ func TestGetSecretRef(t *testing.T) {
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
token, err := GetSecretRef(ctx, client, c.ref, c.namespace, false)
|
||||
token, err := GetSecretRef(ctx, client, c.ref, c.namespace)
|
||||
if c.hasError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
|
||||
@@ -8,7 +8,10 @@ func ConvertToMapStringString(mapStringInterface map[string]interface{}) map[str
|
||||
mapStringString := make(map[string]string, len(mapStringInterface))
|
||||
|
||||
for key, value := range mapStringInterface {
|
||||
mapStringString[key] = fmt.Sprintf("%v", value)
|
||||
strKey := fmt.Sprintf("%v", key)
|
||||
strValue := fmt.Sprintf("%v", value)
|
||||
|
||||
mapStringString[strKey] = strValue
|
||||
}
|
||||
return mapStringString
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ func getGitGeneratorInfo(payload interface{}) *gitGeneratorInfo {
|
||||
log.Errorf("Failed to parse repoURL '%s'", webURL)
|
||||
return nil
|
||||
}
|
||||
regexpStr := `(?i)(http://|https://|\w+@|ssh://(\w+@)?)` + urlObj.Hostname() + "(:[0-9]+|)[:/]" + urlObj.Path[1:] + "(\\.git)?$"
|
||||
regexpStr := `(?i)(http://|https://|\w+@|ssh://(\w+@)?)` + urlObj.Hostname() + "(:[0-9]+|)[:/]" + urlObj.Path[1:] + "(\\.git)?"
|
||||
repoRegexp, err := regexp.Compile(regexpStr)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to compile regexp for repoURL '%s'", webURL)
|
||||
|
||||
@@ -199,7 +199,6 @@ func TestWebhookHandler(t *testing.T) {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
fc := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
|
||||
fakeAppWithGitGenerator("git-github", namespace, "https://github.com/org/repo"),
|
||||
fakeAppWithGitGenerator("git-github-copy", namespace, "https://github.com/org/repo-copy"),
|
||||
fakeAppWithGitGenerator("git-gitlab", namespace, "https://gitlab/group/name"),
|
||||
fakeAppWithGitGenerator("git-azure-devops", namespace, "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git"),
|
||||
fakeAppWithGitGeneratorWithRevision("github-shorthand", namespace, "https://github.com/org/repo", "env/dev"),
|
||||
@@ -243,8 +242,9 @@ func TestWebhookHandler(t *testing.T) {
|
||||
for i := range list.Items {
|
||||
gotAppSet := &list.Items[i]
|
||||
if _, isEffected := effectedAppSetsAsExpected[gotAppSet.Name]; isEffected {
|
||||
expected, got := test.expectedRefresh, gotAppSet.RefreshRequired()
|
||||
require.Equalf(t, expected, got, "unexpected RefreshRequired() for appset '%s' expect: %v got: %v", gotAppSet.Name, expected, got)
|
||||
if expected, got := test.expectedRefresh, gotAppSet.RefreshRequired(); expected != got {
|
||||
t.Errorf("unexpected RefreshRequired() for appset '%s' expect: %v got: %v", gotAppSet.Name, expected, got)
|
||||
}
|
||||
effectedAppSetsAsExpected[gotAppSet.Name] = true
|
||||
} else {
|
||||
assert.False(t, gotAppSet.RefreshRequired())
|
||||
|
||||
159
assets/swagger.json
generated
159
assets/swagger.json
generated
@@ -4557,9 +4557,6 @@
|
||||
"namespace": {
|
||||
"type": "string"
|
||||
},
|
||||
"requiresDeletionConfirmation": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"requiresPruning": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -4691,12 +4688,6 @@
|
||||
"clusterSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"additionalUrls": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"appLabelKey": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -6535,10 +6526,6 @@
|
||||
"kustomize": {
|
||||
"$ref": "#/definitions/v1alpha1ApplicationSourceKustomize"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name is used to refer to a source and is displayed in the UI. It is used in multi-source Applications.",
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"description": "Path is a directory path within the Git repository, and is only valid for applications sourced from Git.",
|
||||
"type": "string"
|
||||
@@ -6630,14 +6617,6 @@
|
||||
"type": "boolean",
|
||||
"title": "SkipCrds skips custom resource definition installation step (Helm's --skip-crds)"
|
||||
},
|
||||
"skipSchemaValidation": {
|
||||
"type": "boolean",
|
||||
"title": "SkipSchemaValidation skips JSON schema validation (Helm's --skip-schema-validation)"
|
||||
},
|
||||
"skipTests": {
|
||||
"description": "SkipTests skips test manifest installation step (Helm's --skip-tests).",
|
||||
"type": "boolean"
|
||||
},
|
||||
"valueFiles": {
|
||||
"type": "array",
|
||||
"title": "ValuesFiles is a list of Helm value files to use when generating a template",
|
||||
@@ -6857,9 +6836,6 @@
|
||||
"source": {
|
||||
"$ref": "#/definitions/v1alpha1ApplicationSource"
|
||||
},
|
||||
"sourceHydrator": {
|
||||
"$ref": "#/definitions/v1alpha1SourceHydrator"
|
||||
},
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"title": "Sources is a reference to the location of the application's manifests or chart",
|
||||
@@ -6917,9 +6893,6 @@
|
||||
"$ref": "#/definitions/applicationv1alpha1ResourceStatus"
|
||||
}
|
||||
},
|
||||
"sourceHydrator": {
|
||||
"$ref": "#/definitions/v1alpha1SourceHydratorStatus"
|
||||
},
|
||||
"sourceType": {
|
||||
"type": "string",
|
||||
"title": "SourceType specifies the type of this application"
|
||||
@@ -7167,20 +7140,12 @@
|
||||
"description": "Server requires Bearer authentication. This client will not attempt to use\nrefresh tokens for an OAuth2 flow.\nTODO: demonstrate an OAuth2 compatible client.",
|
||||
"type": "string"
|
||||
},
|
||||
"disableCompression": {
|
||||
"description": "DisableCompression bypasses automatic GZip compression requests to the server.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"execProviderConfig": {
|
||||
"$ref": "#/definitions/v1alpha1ExecProviderConfig"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"proxyUrl": {
|
||||
"type": "string",
|
||||
"title": "ProxyURL is the URL to the proxy to be used for all requests send to the server"
|
||||
},
|
||||
"tlsClientConfig": {
|
||||
"$ref": "#/definitions/v1alpha1TLSClientConfig"
|
||||
},
|
||||
@@ -7194,10 +7159,6 @@
|
||||
"description": "ClusterGenerator defines a generator to match against clusters registered with ArgoCD.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"flatList": {
|
||||
"type": "boolean",
|
||||
"title": "returns the clusters a single 'clusters' value in the template"
|
||||
},
|
||||
"selector": {
|
||||
"$ref": "#/definitions/v1LabelSelector"
|
||||
},
|
||||
@@ -7347,24 +7308,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1DrySource": {
|
||||
"description": "DrySource specifies a location for dry \"don't repeat yourself\" manifest source information.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string",
|
||||
"title": "Path is a directory path within the Git repository where the manifests are located"
|
||||
},
|
||||
"repoURL": {
|
||||
"type": "string",
|
||||
"title": "RepoURL is the URL to the git repository that contains the application manifests"
|
||||
},
|
||||
"targetRevision": {
|
||||
"type": "string",
|
||||
"title": "TargetRevision defines the revision of the source to hydrate"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1DuckTypeGenerator": {
|
||||
"description": "DuckType defines a generator to match against clusters registered with ArgoCD.",
|
||||
"type": "object",
|
||||
@@ -7535,9 +7478,6 @@
|
||||
"type": "object",
|
||||
"title": "HealthStatus contains information about the currently observed health state of an application or resource",
|
||||
"properties": {
|
||||
"lastTransitionTime": {
|
||||
"$ref": "#/definitions/v1Time"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"title": "Message is a human-readable informational message describing the health status"
|
||||
@@ -7619,47 +7559,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1HydrateOperation": {
|
||||
"type": "object",
|
||||
"title": "HydrateOperation contains information about the most recent hydrate operation",
|
||||
"properties": {
|
||||
"drySHA": {
|
||||
"type": "string",
|
||||
"title": "DrySHA holds the resolved revision (sha) of the dry source as of the most recent reconciliation"
|
||||
},
|
||||
"finishedAt": {
|
||||
"$ref": "#/definitions/v1Time"
|
||||
},
|
||||
"hydratedSHA": {
|
||||
"type": "string",
|
||||
"title": "HydratedSHA holds the resolved revision (sha) of the hydrated source as of the most recent reconciliation"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"title": "Message contains a message describing the current status of the hydrate operation"
|
||||
},
|
||||
"phase": {
|
||||
"type": "string",
|
||||
"title": "Phase indicates the status of the hydrate operation"
|
||||
},
|
||||
"sourceHydrator": {
|
||||
"$ref": "#/definitions/v1alpha1SourceHydrator"
|
||||
},
|
||||
"startedAt": {
|
||||
"$ref": "#/definitions/v1Time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1HydrateTo": {
|
||||
"description": "HydrateTo specifies a location to which hydrated manifests should be pushed as a \"staging area\" before being moved to\nthe SyncSource. The RepoURL and Path are assumed based on the associated SyncSource config in the SourceHydrator.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"targetBranch": {
|
||||
"type": "string",
|
||||
"title": "TargetBranch is the branch to which hydrated manifests should be committed"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1Info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -9267,50 +9166,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1SourceHydrator": {
|
||||
"description": "SourceHydrator specifies a dry \"don't repeat yourself\" source for manifests, a sync source from which to sync\nhydrated manifests, and an optional hydrateTo location to act as a \"staging\" aread for hydrated manifests.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"drySource": {
|
||||
"$ref": "#/definitions/v1alpha1DrySource"
|
||||
},
|
||||
"hydrateTo": {
|
||||
"$ref": "#/definitions/v1alpha1HydrateTo"
|
||||
},
|
||||
"syncSource": {
|
||||
"$ref": "#/definitions/v1alpha1SyncSource"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1SourceHydratorStatus": {
|
||||
"type": "object",
|
||||
"title": "SourceHydratorStatus contains information about the current state of source hydration",
|
||||
"properties": {
|
||||
"currentOperation": {
|
||||
"$ref": "#/definitions/v1alpha1HydrateOperation"
|
||||
},
|
||||
"lastSuccessfulOperation": {
|
||||
"$ref": "#/definitions/v1alpha1SuccessfulHydrateOperation"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1SuccessfulHydrateOperation": {
|
||||
"type": "object",
|
||||
"title": "SuccessfulHydrateOperation contains information about the most recent successful hydrate operation",
|
||||
"properties": {
|
||||
"drySHA": {
|
||||
"type": "string",
|
||||
"title": "DrySHA holds the resolved revision (sha) of the dry source as of the most recent reconciliation"
|
||||
},
|
||||
"hydratedSHA": {
|
||||
"type": "string",
|
||||
"title": "HydratedSHA holds the resolved revision (sha) of the hydrated source as of the most recent reconciliation"
|
||||
},
|
||||
"sourceHydrator": {
|
||||
"$ref": "#/definitions/v1alpha1SourceHydrator"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1SyncOperation": {
|
||||
"description": "SyncOperation contains details about a sync operation.",
|
||||
"type": "object",
|
||||
@@ -9470,20 +9325,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1SyncSource": {
|
||||
"description": "SyncSource specifies a location from which hydrated manifests may be synced. RepoURL is assumed based on the\nassociated DrySource config in the SourceHydrator.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"description": "Path is a directory path within the git repository where hydrated manifests should be committed to and synced\nfrom. If hydrateTo is set, this is just the path from which hydrated manifests will be synced.",
|
||||
"type": "string"
|
||||
},
|
||||
"targetBranch": {
|
||||
"type": "string",
|
||||
"title": "TargetBranch is the branch to which hydrated manifests should be committed"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1alpha1SyncStatus": {
|
||||
"type": "object",
|
||||
"title": "SyncStatus contains information about the currently observed live and desired states of an application",
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"math"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime/debug"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -62,7 +61,6 @@ func NewCommand() *cobra.Command {
|
||||
selfHealBackoffTimeoutSeconds int
|
||||
selfHealBackoffFactor int
|
||||
selfHealBackoffCapSeconds int
|
||||
syncTimeout int
|
||||
statusProcessors int
|
||||
operationProcessors int
|
||||
glogLevel int
|
||||
@@ -112,13 +110,6 @@ func NewCommand() *cobra.Command {
|
||||
cli.SetLogLevel(cmdutil.LogLevel)
|
||||
cli.SetGLogLevel(glogLevel)
|
||||
|
||||
// Recover from panic and log the error using the configured logger instead of the default.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.WithField("trace", string(debug.Stack())).Fatal("Recovered from panic: ", r)
|
||||
}
|
||||
}()
|
||||
|
||||
config, err := clientConfig.ClientConfig()
|
||||
errors.CheckError(err)
|
||||
errors.CheckError(v1alpha1.SetK8SConfigDefaults(config))
|
||||
@@ -190,7 +181,6 @@ func NewCommand() *cobra.Command {
|
||||
time.Duration(appResyncJitter)*time.Second,
|
||||
time.Duration(selfHealTimeoutSeconds)*time.Second,
|
||||
selfHealBackoff,
|
||||
time.Duration(syncTimeout)*time.Second,
|
||||
time.Duration(repoErrorGracePeriod)*time.Second,
|
||||
metricsPort,
|
||||
metricsCacheExpiration,
|
||||
@@ -207,7 +197,7 @@ func NewCommand() *cobra.Command {
|
||||
enableK8sEvent,
|
||||
)
|
||||
errors.CheckError(err)
|
||||
cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer(), nil)
|
||||
cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer())
|
||||
|
||||
stats.RegisterStackDumper()
|
||||
stats.StartStatsTicker(10 * time.Minute)
|
||||
@@ -258,7 +248,6 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().IntVar(&selfHealBackoffTimeoutSeconds, "self-heal-backoff-timeout-seconds", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_TIMEOUT_SECONDS", 2, 0, math.MaxInt32), "Specifies initial timeout of exponential backoff between self heal attempts")
|
||||
command.Flags().IntVar(&selfHealBackoffFactor, "self-heal-backoff-factor", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_FACTOR", 3, 0, math.MaxInt32), "Specifies factor of exponential timeout between application self heal attempts")
|
||||
command.Flags().IntVar(&selfHealBackoffCapSeconds, "self-heal-backoff-cap-seconds", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_CAP_SECONDS", 300, 0, math.MaxInt32), "Specifies max timeout of exponential backoff between application self heal attempts")
|
||||
command.Flags().IntVar(&syncTimeout, "sync-timeout", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_SYNC_TIMEOUT", 0, 0, math.MaxInt32), "Specifies the timeout after which a sync would be terminated. 0 means no timeout (default 0).")
|
||||
command.Flags().Int64Var(&kubectlParallelismLimit, "kubectl-parallelism-limit", env.ParseInt64FromEnv("ARGOCD_APPLICATION_CONTROLLER_KUBECTL_PARALLELISM_LIMIT", 20, 0, math.MaxInt64), "Number of allowed concurrent kubectl fork/execs. Any value less than 1 means no limit.")
|
||||
command.Flags().BoolVar(&repoServerPlaintext, "repo-server-plaintext", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_PLAINTEXT", false), "Disable TLS on connections to repo server")
|
||||
command.Flags().BoolVar(&repoServerStrictTLS, "repo-server-strict-tls", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_STRICT_TLS", false), "Whether to use strict validation of the TLS cert presented by the repo server")
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/argoproj/pkg/stats"
|
||||
@@ -39,6 +38,7 @@ import (
|
||||
appsetmetrics "github.com/argoproj/argo-cd/v2/applicationset/metrics"
|
||||
"github.com/argoproj/argo-cd/v2/applicationset/services"
|
||||
appv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned"
|
||||
"github.com/argoproj/argo-cd/v2/util/cli"
|
||||
"github.com/argoproj/argo-cd/v2/util/db"
|
||||
"github.com/argoproj/argo-cd/v2/util/errors"
|
||||
@@ -73,7 +73,6 @@ func NewCommand() *cobra.Command {
|
||||
metricsAplicationsetLabels []string
|
||||
enableScmProviders bool
|
||||
webhookParallelism int
|
||||
tokenRefStrictMode bool
|
||||
)
|
||||
scheme := runtime.NewScheme()
|
||||
_ = clientgoscheme.AddToScheme(scheme)
|
||||
@@ -101,13 +100,6 @@ func NewCommand() *cobra.Command {
|
||||
|
||||
ctrl.SetLogger(logutils.NewLogrusLogger(logutils.NewWithCurrentConfig()))
|
||||
|
||||
// Recover from panic and log the error using the configured logger instead of the default.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.WithField("trace", string(debug.Stack())).Fatal("Recovered from panic: ", r)
|
||||
}
|
||||
}()
|
||||
|
||||
restConfig, err := clientConfig.ClientConfig()
|
||||
errors.CheckError(err)
|
||||
|
||||
@@ -170,9 +162,10 @@ func NewCommand() *cobra.Command {
|
||||
errors.CheckError(err)
|
||||
|
||||
argoSettingsMgr := argosettings.NewSettingsManager(ctx, k8sClient, namespace)
|
||||
appSetConfig := appclientset.NewForConfigOrDie(mgr.GetConfig())
|
||||
argoCDDB := db.NewDB(namespace, argoSettingsMgr, k8sClient)
|
||||
|
||||
scmConfig := generators.NewSCMConfig(scmRootCAPath, allowedScmProviders, enableScmProviders, github_app.NewAuthCredentials(argoCDDB.(db.RepoCredsDB)), tokenRefStrictMode)
|
||||
scmConfig := generators.NewSCMConfig(scmRootCAPath, allowedScmProviders, enableScmProviders, github_app.NewAuthCredentials(argoCDDB.(db.RepoCredsDB)))
|
||||
|
||||
tlsConfig := apiclient.TLSConfiguration{
|
||||
DisableTLS: repoServerPlaintext,
|
||||
@@ -218,6 +211,7 @@ func NewCommand() *cobra.Command {
|
||||
Renderer: &utils.Render{},
|
||||
Policy: policyObj,
|
||||
EnablePolicyOverride: enablePolicyOverride,
|
||||
ArgoAppClientset: appSetConfig,
|
||||
KubeClientset: k8sClient,
|
||||
ArgoDB: argoCDDB,
|
||||
ArgoCDNamespace: namespace,
|
||||
@@ -258,7 +252,6 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().StringSliceVar(&allowedScmProviders, "allowed-scm-providers", env.StringsFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_ALLOWED_SCM_PROVIDERS", []string{}, ","), "The list of allowed custom SCM provider API URLs. This restriction does not apply to SCM or PR generators which do not accept a custom API URL. (Default: Empty = all)")
|
||||
command.Flags().BoolVar(&enableScmProviders, "enable-scm-providers", env.ParseBoolFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_SCM_PROVIDERS", true), "Enable retrieving information from SCM providers, used by the SCM and PR generators (Default: true)")
|
||||
command.Flags().BoolVar(&dryRun, "dry-run", env.ParseBoolFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_DRY_RUN", false), "Enable dry run mode")
|
||||
command.Flags().BoolVar(&tokenRefStrictMode, "token-ref-strict-mode", env.ParseBoolFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_TOKENREF_STRICT_MODE", false), fmt.Sprintf("Set to true to require secrets referenced by SCM providers to have the %s=%s label set (Default: false)", common.LabelKeySecretType, common.LabelValueSecretTypeSCMCreds))
|
||||
command.Flags().BoolVar(&enableProgressiveSyncs, "enable-progressive-syncs", env.ParseBoolFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_PROGRESSIVE_SYNCS", false), "Enable use of the experimental progressive syncs feature.")
|
||||
command.Flags().BoolVar(&enableNewGitFileGlobbing, "enable-new-git-file-globbing", env.ParseBoolFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_NEW_GIT_FILE_GLOBBING", false), "Enable new globbing in Git files generator.")
|
||||
command.Flags().BoolVar(&repoServerPlaintext, "repo-server-plaintext", env.ParseBoolFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_PLAINTEXT", false), "Disable TLS on connections to repo server")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/argoproj/pkg/stats"
|
||||
@@ -45,13 +44,6 @@ func NewCommand() *cobra.Command {
|
||||
cli.SetLogFormat(cmdutil.LogFormat)
|
||||
cli.SetLogLevel(cmdutil.LogLevel)
|
||||
|
||||
// Recover from panic and log the error using the configured logger instead of the default.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.WithField("trace", string(debug.Stack())).Fatal("Recovered from panic: ", r)
|
||||
}
|
||||
}()
|
||||
|
||||
config, err := plugin.ReadPluginConfig(configFilePath)
|
||||
errors.CheckError(err)
|
||||
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc/health/grpc_health_v1"
|
||||
|
||||
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
|
||||
"github.com/argoproj/argo-cd/v2/commitserver"
|
||||
"github.com/argoproj/argo-cd/v2/commitserver/apiclient"
|
||||
"github.com/argoproj/argo-cd/v2/commitserver/metrics"
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/argoproj/argo-cd/v2/util/askpass"
|
||||
"github.com/argoproj/argo-cd/v2/util/cli"
|
||||
"github.com/argoproj/argo-cd/v2/util/env"
|
||||
"github.com/argoproj/argo-cd/v2/util/errors"
|
||||
"github.com/argoproj/argo-cd/v2/util/healthz"
|
||||
ioutil "github.com/argoproj/argo-cd/v2/util/io"
|
||||
)
|
||||
|
||||
// NewCommand returns a new instance of an argocd-commit-server command
|
||||
func NewCommand() *cobra.Command {
|
||||
var (
|
||||
listenHost string
|
||||
listenPort int
|
||||
metricsPort int
|
||||
metricsHost string
|
||||
)
|
||||
command := &cobra.Command{
|
||||
Use: "argocd-commit-server",
|
||||
Short: "Run Argo CD Commit Server",
|
||||
Long: "Argo CD Commit Server is an internal service which commits and pushes hydrated manifests to git. This command runs Commit Server in the foreground.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
vers := common.GetVersion()
|
||||
vers.LogStartupInfo(
|
||||
"Argo CD Commit Server",
|
||||
map[string]any{
|
||||
"port": listenPort,
|
||||
},
|
||||
)
|
||||
|
||||
cli.SetLogFormat(cmdutil.LogFormat)
|
||||
cli.SetLogLevel(cmdutil.LogLevel)
|
||||
|
||||
metricsServer := metrics.NewMetricsServer()
|
||||
http.Handle("/metrics", metricsServer.GetHandler())
|
||||
go func() { errors.CheckError(http.ListenAndServe(fmt.Sprintf("%s:%d", metricsHost, metricsPort), nil)) }()
|
||||
|
||||
askPassServer := askpass.NewServer(askpass.CommitServerSocketPath)
|
||||
go func() { errors.CheckError(askPassServer.Run()) }()
|
||||
|
||||
server := commitserver.NewServer(askPassServer, metricsServer)
|
||||
grpc := server.CreateGRPC()
|
||||
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", listenHost, listenPort))
|
||||
errors.CheckError(err)
|
||||
|
||||
healthz.ServeHealthCheck(http.DefaultServeMux, func(r *http.Request) error {
|
||||
if val, ok := r.URL.Query()["full"]; ok && len(val) > 0 && val[0] == "true" {
|
||||
// connect to itself to make sure commit server is able to serve connection
|
||||
// used by liveness probe to auto restart commit server
|
||||
conn, err := apiclient.NewConnection(fmt.Sprintf("localhost:%d", listenPort))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ioutil.Close(conn)
|
||||
client := grpc_health_v1.NewHealthClient(conn)
|
||||
res, err := client.Check(r.Context(), &grpc_health_v1.HealthCheckRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.Status != grpc_health_v1.HealthCheckResponse_SERVING {
|
||||
return fmt.Errorf("grpc health check status is '%v'", res.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// Graceful shutdown code adapted from here: https://gist.github.com/embano1/e0bf49d24f1cdd07cffad93097c04f0a
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
s := <-sigCh
|
||||
log.Printf("got signal %v, attempting graceful shutdown", s)
|
||||
grpc.GracefulStop()
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
log.Println("starting grpc server")
|
||||
err = grpc.Serve(listener)
|
||||
errors.CheckError(err)
|
||||
wg.Wait()
|
||||
log.Println("clean shutdown")
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
command.Flags().StringVar(&cmdutil.LogFormat, "logformat", env.StringFromEnv("ARGOCD_COMMIT_SERVER_LOGFORMAT", "text"), "Set the logging format. One of: text|json")
|
||||
command.Flags().StringVar(&cmdutil.LogLevel, "loglevel", env.StringFromEnv("ARGOCD_COMMIT_SERVER_LOGLEVEL", "info"), "Set the logging level. One of: debug|info|warn|error")
|
||||
command.Flags().StringVar(&listenHost, "address", env.StringFromEnv("ARGOCD_COMMIT_SERVER_LISTEN_ADDRESS", common.DefaultAddressCommitServer), "Listen on given address for incoming connections")
|
||||
command.Flags().IntVar(&listenPort, "port", common.DefaultPortCommitServer, "Listen on given port for incoming connections")
|
||||
command.Flags().StringVar(&metricsHost, "metrics-address", env.StringFromEnv("ARGOCD_COMMIT_SERVER_METRICS_LISTEN_ADDRESS", common.DefaultAddressCommitServerMetrics), "Listen on given address for metrics")
|
||||
command.Flags().IntVar(&metricsPort, "metrics-port", common.DefaultPortCommitServerMetrics, "Start metrics server on given port")
|
||||
|
||||
return command
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime/debug"
|
||||
"syscall"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
@@ -67,14 +66,6 @@ func NewRunDexCommand() *cobra.Command {
|
||||
|
||||
cli.SetLogFormat(cmdutil.LogFormat)
|
||||
cli.SetLogLevel(cmdutil.LogLevel)
|
||||
|
||||
// Recover from panic and log the error using the configured logger instead of the default.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.WithField("trace", string(debug.Stack())).Fatal("Recovered from panic: ", r)
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = exec.LookPath("dex")
|
||||
errors.CheckError(err)
|
||||
config, err := clientConfig.ClientConfig()
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/askpass"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver/askpass"
|
||||
"github.com/argoproj/argo-cd/v2/util/errors"
|
||||
grpc_util "github.com/argoproj/argo-cd/v2/util/grpc"
|
||||
"github.com/argoproj/argo-cd/v2/util/io"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/Azure/kubelogin/pkg/token"
|
||||
@@ -20,26 +19,24 @@ const (
|
||||
)
|
||||
|
||||
func newAzureCommand() *cobra.Command {
|
||||
o := token.NewOptions()
|
||||
// we'll use default of WorkloadIdentityLogin for the login flow
|
||||
o.LoginMethod = token.WorkloadIdentityLogin
|
||||
o.ServerID = DEFAULT_AAD_SERVER_APPLICATION_ID
|
||||
command := &cobra.Command{
|
||||
Use: "azure",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
o := token.OptionsWithEnv()
|
||||
if o.LoginMethod == "" { // no environment variable overrides
|
||||
// we'll use default of WorkloadIdentityLogin for the login flow
|
||||
o.LoginMethod = token.WorkloadIdentityLogin
|
||||
}
|
||||
o.ServerID = DEFAULT_AAD_SERVER_APPLICATION_ID
|
||||
o.UpdateFromEnv()
|
||||
if v, ok := os.LookupEnv(envServerApplicationID); ok {
|
||||
o.ServerID = v
|
||||
}
|
||||
if v, ok := os.LookupEnv(envEnvironmentName); ok {
|
||||
o.Environment = v
|
||||
}
|
||||
tp, err := token.GetTokenProvider(o)
|
||||
plugin, err := token.New(&o)
|
||||
errors.CheckError(err)
|
||||
tok, err := tp.GetAccessToken(c.Context())
|
||||
err = plugin.Do()
|
||||
errors.CheckError(err)
|
||||
_, _ = fmt.Fprint(os.Stdout, formatJSON(tok.Token, tok.ExpiresOn))
|
||||
},
|
||||
}
|
||||
return command
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@@ -116,13 +115,6 @@ func NewCommand() *cobra.Command {
|
||||
return fmt.Errorf("unknown log format '%s'", logFormat)
|
||||
}
|
||||
|
||||
// Recover from panic and log the error using the configured logger instead of the default.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.WithField("trace", string(debug.Stack())).Fatal("Recovered from panic: ", r)
|
||||
}
|
||||
}()
|
||||
|
||||
tlsConfig := apiclient.TLSConfiguration{
|
||||
DisableTLS: argocdRepoServerPlaintext,
|
||||
StrictValidation: argocdRepoServerStrictTLS,
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
@@ -23,10 +22,10 @@ import (
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver/askpass"
|
||||
reposervercache "github.com/argoproj/argo-cd/v2/reposerver/cache"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver/metrics"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver/repository"
|
||||
"github.com/argoproj/argo-cd/v2/util/askpass"
|
||||
cacheutil "github.com/argoproj/argo-cd/v2/util/cache"
|
||||
"github.com/argoproj/argo-cd/v2/util/cli"
|
||||
"github.com/argoproj/argo-cd/v2/util/env"
|
||||
@@ -76,7 +75,6 @@ func NewCommand() *cobra.Command {
|
||||
helmRegistryMaxIndexSize string
|
||||
disableManifestMaxExtractedSize bool
|
||||
includeHiddenDirectories bool
|
||||
cmpUseManifestGeneratePaths bool
|
||||
)
|
||||
command := cobra.Command{
|
||||
Use: cliName,
|
||||
@@ -97,13 +95,6 @@ func NewCommand() *cobra.Command {
|
||||
cli.SetLogFormat(cmdutil.LogFormat)
|
||||
cli.SetLogLevel(cmdutil.LogLevel)
|
||||
|
||||
// Recover from panic and log the error using the configured logger instead of the default.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.WithField("trace", string(debug.Stack())).Fatal("Recovered from panic: ", r)
|
||||
}
|
||||
}()
|
||||
|
||||
if !disableTLS {
|
||||
var err error
|
||||
tlsConfigCustomizer, err = tlsConfigCustomizerSrc()
|
||||
@@ -130,7 +121,7 @@ func NewCommand() *cobra.Command {
|
||||
|
||||
askPassServer := askpass.NewServer(askpass.SocketPath)
|
||||
metricsServer := metrics.NewMetricsServer()
|
||||
cacheutil.CollectMetrics(redisClient, metricsServer, nil)
|
||||
cacheutil.CollectMetrics(redisClient, metricsServer)
|
||||
server, err := reposerver.NewServer(metricsServer, cache, tlsConfigCustomizer, repository.RepoServerInitConstants{
|
||||
ParallelismLimit: parallelismLimit,
|
||||
PauseGenerationAfterFailedGenerationAttempts: pauseGenerationAfterFailedGenerationAttempts,
|
||||
@@ -145,7 +136,6 @@ func NewCommand() *cobra.Command {
|
||||
HelmManifestMaxExtractedSize: helmManifestMaxExtractedSizeQuantity.ToDec().Value(),
|
||||
HelmRegistryMaxIndexSize: helmRegistryMaxIndexSizeQuantity.ToDec().Value(),
|
||||
IncludeHiddenDirectories: includeHiddenDirectories,
|
||||
CMPUseManifestGeneratePaths: cmpUseManifestGeneratePaths,
|
||||
}, askPassServer)
|
||||
errors.CheckError(err)
|
||||
|
||||
@@ -251,7 +241,6 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().StringVar(&helmRegistryMaxIndexSize, "helm-registry-max-index-size", env.StringFromEnv("ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_INDEX_SIZE", "1G"), "Maximum size of registry index file")
|
||||
command.Flags().BoolVar(&disableManifestMaxExtractedSize, "disable-helm-manifest-max-extracted-size", env.ParseBoolFromEnv("ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE", false), "Disable maximum size of helm manifest archives when extracted")
|
||||
command.Flags().BoolVar(&includeHiddenDirectories, "include-hidden-directories", env.ParseBoolFromEnv("ARGOCD_REPO_SERVER_INCLUDE_HIDDEN_DIRECTORIES", false), "Include hidden directories from Git")
|
||||
command.Flags().BoolVar(&cmpUseManifestGeneratePaths, "plugin-use-manifest-generate-paths", env.ParseBoolFromEnv("ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS", false), "Pass the resources described in argocd.argoproj.io/manifest-generate-paths value to the cmpserver to generate the application manifests.")
|
||||
tlsConfigCustomizerSrc = tls.AddTLSFlagsToCmd(&command)
|
||||
cacheSrc = reposervercache.AddCacheFlagsToCmd(&command, cacheutil.Options{
|
||||
OnClientCreated: func(client *redis.Client) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -120,13 +119,6 @@ func NewCommand() *cobra.Command {
|
||||
cli.SetLogLevel(cmdutil.LogLevel)
|
||||
cli.SetGLogLevel(glogLevel)
|
||||
|
||||
// Recover from panic and log the error using the configured logger instead of the default.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.WithField("trace", string(debug.Stack())).Fatal("Recovered from panic: ", r)
|
||||
}
|
||||
}()
|
||||
|
||||
config, err := clientConfig.ClientConfig()
|
||||
errors.CheckError(err)
|
||||
errors.CheckError(v1alpha1.SetK8SConfigDefaults(config))
|
||||
@@ -258,25 +250,22 @@ func NewCommand() *cobra.Command {
|
||||
stats.RegisterHeapDumper("memprofile")
|
||||
argocd := server.NewServer(ctx, argoCDOpts, appsetOpts)
|
||||
argocd.Init(ctx)
|
||||
lns, err := argocd.Listen()
|
||||
errors.CheckError(err)
|
||||
for {
|
||||
var closer func()
|
||||
serverCtx, cancel := context.WithCancel(ctx)
|
||||
lns, err := argocd.Listen()
|
||||
errors.CheckError(err)
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
if otlpAddress != "" {
|
||||
closer, err = traceutil.InitTracer(serverCtx, "argocd-server", otlpAddress, otlpInsecure, otlpHeaders, otlpAttrs)
|
||||
closer, err = traceutil.InitTracer(ctx, "argocd-server", otlpAddress, otlpInsecure, otlpHeaders, otlpAttrs)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to initialize tracing: %v", err)
|
||||
}
|
||||
}
|
||||
argocd.Run(serverCtx, lns)
|
||||
argocd.Run(ctx, lns)
|
||||
cancel()
|
||||
if closer != nil {
|
||||
closer()
|
||||
}
|
||||
cancel()
|
||||
if argocd.TerminateRequested() {
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
Example: templates.Examples(`
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/utils"
|
||||
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
|
||||
accountpkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/account"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apiclient/session"
|
||||
@@ -433,14 +432,8 @@ argocd account delete-token --account <account-name> ID`,
|
||||
if account == "" {
|
||||
account = getCurrentAccount(ctx, clientset).Username
|
||||
}
|
||||
promptUtil := utils.NewPrompt(clientOpts.PromptsEnabled)
|
||||
canDelete := promptUtil.Confirm(fmt.Sprintf("Are you sure you want to delete '%s' token? [y/n]", id))
|
||||
if canDelete {
|
||||
_, err := client.DeleteToken(ctx, &accountpkg.DeleteTokenRequest{Name: account, Id: id})
|
||||
errors.CheckError(err)
|
||||
} else {
|
||||
fmt.Printf("The command to delete '%s' was cancelled.\n", id)
|
||||
}
|
||||
_, err := client.DeleteToken(ctx, &accountpkg.DeleteTokenRequest{Name: account, Id: id})
|
||||
errors.CheckError(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVarP(&account, "account", "a", "", "Account name. Defaults to the current account.")
|
||||
|
||||
@@ -188,12 +188,12 @@ func NewDiffReconcileResults() *cobra.Command {
|
||||
func toUnstructured(val interface{}) (*unstructured.Unstructured, error) {
|
||||
data, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while marhsalling value: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
res := make(map[string]interface{})
|
||||
err = json.Unmarshal(data, &res)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while unmarhsalling data: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
return &unstructured.Unstructured{Object: res}, nil
|
||||
}
|
||||
@@ -227,7 +227,7 @@ func diffReconcileResults(res1 reconcileResults, res2 reconcileResults) error {
|
||||
for k, v := range resMap2 {
|
||||
secondUn, err := toUnstructured(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error converting second resource of second map to unstructure: %w", err)
|
||||
return err
|
||||
}
|
||||
pairs = append(pairs, diffPair{name: k, first: nil, second: secondUn})
|
||||
}
|
||||
@@ -338,7 +338,7 @@ func saveToFile(err error, outputFormat string, result reconcileResults, outputP
|
||||
func getReconcileResults(ctx context.Context, appClientset appclientset.Interface, namespace string, selector string) ([]appReconcileResult, error) {
|
||||
appsList, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(ctx, v1.ListOptions{LabelSelector: selector})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error listing namespaced apps: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var items []appReconcileResult
|
||||
@@ -389,11 +389,11 @@ func reconcileApplications(
|
||||
return nil
|
||||
}, []string{}, []string{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error starting new metrics server: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
stateCache := createLiveStateCache(argoDB, appInformer, settingsMgr, server)
|
||||
if err := stateCache.Init(); err != nil {
|
||||
return nil, fmt.Errorf("error initializing state cache: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cache := appstatecache.NewCache(
|
||||
@@ -406,7 +406,7 @@ func reconcileApplications(
|
||||
|
||||
appsList, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(ctx, v1.ListOptions{LabelSelector: selector})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error listing namespaced apps: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Slice(appsList.Items, func(i, j int) bool {
|
||||
@@ -429,7 +429,7 @@ func reconcileApplications(
|
||||
|
||||
proj, err := projLister.AppProjects(namespace).Get(app.Spec.Project)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting namespaced project: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sources := make([]v1alpha1.ApplicationSource, 0)
|
||||
@@ -439,7 +439,7 @@ func reconcileApplications(
|
||||
|
||||
res, err := appStateManager.CompareAppState(&app, proj, revisions, sources, false, false, nil, false, false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error comparing app states: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, appReconcileResult{
|
||||
Name: app.Name,
|
||||
|
||||
@@ -16,12 +16,10 @@ import (
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/utils"
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
|
||||
"github.com/argoproj/argo-cd/v2/util/cli"
|
||||
"github.com/argoproj/argo-cd/v2/util/errors"
|
||||
"github.com/argoproj/argo-cd/v2/util/localconfig"
|
||||
secutil "github.com/argoproj/argo-cd/v2/util/security"
|
||||
)
|
||||
|
||||
@@ -139,7 +137,6 @@ func NewImportCommand() *cobra.Command {
|
||||
verbose bool
|
||||
stopOperation bool
|
||||
ignoreTracking bool
|
||||
promptsEnabled bool
|
||||
applicationNamespaces []string
|
||||
applicationsetNamespaces []string
|
||||
)
|
||||
@@ -311,8 +308,6 @@ func NewImportCommand() *cobra.Command {
|
||||
}
|
||||
}
|
||||
|
||||
promptUtil := utils.NewPrompt(promptsEnabled)
|
||||
|
||||
// Delete objects not in backup
|
||||
for key, liveObj := range pruneObjects {
|
||||
if prune {
|
||||
@@ -340,19 +335,13 @@ func NewImportCommand() *cobra.Command {
|
||||
log.Fatalf("Unexpected kind '%s' in prune list", key.Kind)
|
||||
}
|
||||
isForbidden := false
|
||||
|
||||
if !dryRun {
|
||||
canPrune := promptUtil.Confirm(fmt.Sprintf("Are you sure you want to prune %s/%s %s ? [y/n]", key.Group, key.Kind, key.Name))
|
||||
if canPrune {
|
||||
err = dynClient.Delete(ctx, key.Name, v1.DeleteOptions{})
|
||||
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
|
||||
isForbidden = true
|
||||
log.Warnf("%s/%s %s: %v\n", key.Group, key.Kind, key.Name, err)
|
||||
} else {
|
||||
errors.CheckError(err)
|
||||
}
|
||||
err = dynClient.Delete(ctx, key.Name, v1.DeleteOptions{})
|
||||
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
|
||||
isForbidden = true
|
||||
log.Warnf("%s/%s %s: %v\n", key.Group, key.Kind, key.Name, err)
|
||||
} else {
|
||||
fmt.Printf("The command to prune %s/%s %s was cancelled.\n", key.Group, key.Kind, key.Name)
|
||||
errors.CheckError(err)
|
||||
}
|
||||
}
|
||||
if !isForbidden {
|
||||
@@ -373,7 +362,6 @@ func NewImportCommand() *cobra.Command {
|
||||
command.Flags().BoolVar(&stopOperation, "stop-operation", false, "Stop any existing operations")
|
||||
command.Flags().StringSliceVarP(&applicationNamespaces, "application-namespaces", "", []string{}, fmt.Sprintf("Comma separated list of namespace globs to which import of applications is allowed. If not provided value from '%s' in %s will be used,if it's not defined only applications without an explicit namespace will be imported to the Argo CD namespace", applicationNamespacesCmdParamsKey, common.ArgoCDCmdParamsConfigMapName))
|
||||
command.Flags().StringSliceVarP(&applicationsetNamespaces, "applicationset-namespaces", "", []string{}, fmt.Sprintf("Comma separated list of namespace globs which import of applicationsets is allowed. If not provided value from '%s' in %s will be used,if it's not defined only applicationsets without an explicit namespace will be imported to the Argo CD namespace", applicationsetNamespacesCmdParamsKey, common.ArgoCDCmdParamsConfigMapName))
|
||||
command.PersistentFlags().BoolVar(&promptsEnabled, "prompts-enabled", localconfig.GetPromptsEnabled(true), "Force optional interactive prompts to be enabled or disabled, overriding local configuration. If not specified, the local configuration value will be used, which is false by default.")
|
||||
|
||||
return &command
|
||||
}
|
||||
|
||||
@@ -565,9 +565,7 @@ argocd admin cluster kubeconfig https://cluster-api-url:6443 /path/to/output/kub
|
||||
|
||||
cluster, err := db.NewDB(namespace, settings.NewSettingsManager(ctx, kubeclientset, namespace), kubeclientset).GetCluster(ctx, serverUrl)
|
||||
errors.CheckError(err)
|
||||
rawConfig, err := cluster.RawRestConfig()
|
||||
errors.CheckError(err)
|
||||
err = kube.WriteKubeConfig(rawConfig, namespace, output)
|
||||
err = kube.WriteKubeConfig(cluster.RawRestConfig(), namespace, output)
|
||||
errors.CheckError(err)
|
||||
},
|
||||
}
|
||||
@@ -680,7 +678,7 @@ func NewGenClusterConfigCommand(pathOpts *clientcmd.PathOptions) *cobra.Command
|
||||
command.PersistentFlags().StringVar(&pathOpts.LoadingRules.ExplicitPath, pathOpts.ExplicitFileFlag, pathOpts.LoadingRules.ExplicitPath, "use a particular kubeconfig file")
|
||||
command.Flags().StringVar(&bearerToken, "bearer-token", "", "Authentication token that should be used to access K8S API server")
|
||||
command.Flags().BoolVar(&generateToken, "generate-bearer-token", false, "Generate authentication token that should be used to access K8S API server")
|
||||
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "argocd-manager", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default %q SA will be used", clusterauth.ArgoCDManagerServiceAccount))
|
||||
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "argocd-manager", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default \"%s\" SA will be used", clusterauth.ArgoCDManagerServiceAccount))
|
||||
command.Flags().StringVar(&clusterOpts.SystemNamespace, "system-namespace", common.DefaultSystemNamespace, "Use different system namespace")
|
||||
command.Flags().StringVarP(&outputFormat, "output", "o", "yaml", "Output format. One of: json|yaml")
|
||||
command.Flags().StringArrayVar(&labels, "label", nil, "Set metadata labels (e.g. --label key=value)")
|
||||
|
||||
@@ -50,13 +50,13 @@ func NewGenProjectSpecCommand() *cobra.Command {
|
||||
Short: "Generate declarative config for a project",
|
||||
Example: templates.Examples(`
|
||||
# Generate a YAML configuration for a project named "myproject"
|
||||
argocd admin proj generate-spec myproject
|
||||
argocd admin projects generate-spec myproject
|
||||
|
||||
# Generate a JSON configuration for a project named "anotherproject" and specify an output file
|
||||
argocd admin proj generate-spec anotherproject --output json --file config.json
|
||||
argocd admin projects generate-spec anotherproject --output json --file config.json
|
||||
|
||||
# Generate a YAML configuration for a project named "someproject" and write it back to the input file
|
||||
argocd admin proj generate-spec someproject --inline
|
||||
argocd admin projects generate-spec someproject --inline
|
||||
`),
|
||||
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
@@ -155,10 +155,10 @@ func NewUpdatePolicyRuleCommand() *cobra.Command {
|
||||
Use: "update-role-policy PROJECT_GLOB MODIFICATION ACTION",
|
||||
Short: "Implement bulk project role update. Useful to back-fill existing project policies or remove obsolete actions.",
|
||||
Example: ` # Add policy that allows executing any action (action/*) to roles which name matches to *deployer* in all projects
|
||||
argocd admin proj update-role-policy '*' set 'action/*' --role '*deployer*' --resource applications --scope '*' --permission allow
|
||||
argocd admin projects update-role-policy '*' set 'action/*' --role '*deployer*' --resource applications --scope '*' --permission allow
|
||||
|
||||
# Remove policy that which manages running (action/*) from all roles which name matches *deployer* in all projects
|
||||
argocd admin proj update-role-policy '*' remove override --role '*deployer*'
|
||||
argocd admin projects update-role-policy '*' remove override --role '*deployer*'
|
||||
`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
ctx := c.Context()
|
||||
|
||||
@@ -45,14 +45,9 @@ func NewRedisInitialPasswordCommand() *cobra.Command {
|
||||
namespace, _, err := clientConfig.Namespace()
|
||||
errors.CheckError(err)
|
||||
|
||||
// redisInitialCredentials is the kubernetes secret containing
|
||||
// the redis password
|
||||
redisInitialCredentials := common.RedisInitialCredentials
|
||||
|
||||
// redisInitialCredentialsKey is the key in the redisInitialCredentials
|
||||
// secret which maps to the redis password
|
||||
redisInitialCredentialsKey := common.RedisInitialCredentialsKey
|
||||
fmt.Printf("Checking for initial Redis password in secret %s/%s at key %s. \n", namespace, redisInitialCredentials, redisInitialCredentialsKey)
|
||||
redisInitialPasswordSecretName := common.DefaultRedisInitialPasswordSecretName
|
||||
redisInitialPasswordKey := common.DefaultRedisInitialPasswordKey
|
||||
fmt.Printf("Checking for initial Redis password in secret %s/%s at key %s. \n", namespace, redisInitialPasswordSecretName, redisInitialPasswordKey)
|
||||
|
||||
config, err := clientConfig.ClientConfig()
|
||||
errors.CheckError(err)
|
||||
@@ -64,11 +59,11 @@ func NewRedisInitialPasswordCommand() *cobra.Command {
|
||||
errors.CheckError(err)
|
||||
|
||||
data := map[string][]byte{
|
||||
redisInitialCredentialsKey: []byte(randomPassword),
|
||||
redisInitialPasswordKey: []byte(randomPassword),
|
||||
}
|
||||
secret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: redisInitialCredentials,
|
||||
Name: redisInitialPasswordSecretName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: data,
|
||||
@@ -79,14 +74,14 @@ func NewRedisInitialPasswordCommand() *cobra.Command {
|
||||
errors.CheckError(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Argo CD Redis secret state confirmed: secret name %s.\n", redisInitialCredentials)
|
||||
secret, err = kubeClientset.CoreV1().Secrets(namespace).Get(context.Background(), redisInitialCredentials, v1.GetOptions{})
|
||||
fmt.Println("Argo CD Redis secret state confirmed: secret name argocd-redis.")
|
||||
secret, err = kubeClientset.CoreV1().Secrets(namespace).Get(context.Background(), redisInitialPasswordSecretName, v1.GetOptions{})
|
||||
errors.CheckError(err)
|
||||
|
||||
if _, ok := secret.Data[redisInitialCredentialsKey]; ok {
|
||||
if _, ok := secret.Data[redisInitialPasswordKey]; ok {
|
||||
fmt.Println("Password secret is configured properly.")
|
||||
} else {
|
||||
err := fmt.Errorf("key %s doesn't exist in secret %s. \n", redisInitialCredentialsKey, redisInitialCredentials)
|
||||
err := fmt.Errorf("key %s doesn't exist in secret %s. \n", redisInitialPasswordKey, redisInitialPasswordSecretName)
|
||||
errors.CheckError(err)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -579,7 +579,7 @@ func NewResourceActionRunCommand(cmdCtx commandContext) *cobra.Command {
|
||||
Short: "Executes resource action",
|
||||
Long: "Executes resource action using the lua script configured in the 'resource.customizations' field of 'argocd-cm' ConfigMap and outputs updated fields",
|
||||
Example: `
|
||||
argocd admin settings resource-overrides action /tmp/deploy.yaml restart --argocd-cm-path ./argocd-cm.yaml`,
|
||||
argocd admin settings resource-overrides action run /tmp/deploy.yaml restart --argocd-cm-path ./argocd-cm.yaml`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
ctx := c.Context()
|
||||
|
||||
|
||||
@@ -200,7 +200,8 @@ admissionregistration.k8s.io/MutatingWebhookConfiguration:
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, summary, tc.containsSummary)
|
||||
} else if tc.containsError != "" {
|
||||
assert.ErrorContains(t, err, tc.containsError)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tc.containsError)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -28,7 +27,6 @@ import (
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
k8swatch "k8s.io/apimachinery/pkg/watch"
|
||||
@@ -36,7 +34,6 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/utils"
|
||||
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
|
||||
"github.com/argoproj/argo-cd/v2/controller"
|
||||
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
|
||||
@@ -101,7 +98,6 @@ func NewApplicationCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman
|
||||
command.AddCommand(NewApplicationLogsCommand(clientOpts))
|
||||
command.AddCommand(NewApplicationAddSourceCommand(clientOpts))
|
||||
command.AddCommand(NewApplicationRemoveSourceCommand(clientOpts))
|
||||
command.AddCommand(NewApplicationConfirmDeletionCommand(clientOpts))
|
||||
return command
|
||||
}
|
||||
|
||||
@@ -318,17 +314,6 @@ func printHeader(acdClient argocdclient.Client, app *argoappv1.Application, ctx
|
||||
}
|
||||
}
|
||||
|
||||
// getSourceNameToPositionMap returns a map of source name to position
|
||||
func getSourceNameToPositionMap(app *argoappv1.Application) map[string]int64 {
|
||||
sourceNameToPosition := make(map[string]int64)
|
||||
for i, s := range app.Spec.Sources {
|
||||
if s.Name != "" {
|
||||
sourceNameToPosition[s.Name] = int64(i + 1)
|
||||
}
|
||||
}
|
||||
return sourceNameToPosition
|
||||
}
|
||||
|
||||
// NewApplicationGetCommand returns a new instance of an `argocd app get` command
|
||||
func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
@@ -339,7 +324,6 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
|
||||
showOperation bool
|
||||
appNamespace string
|
||||
sourcePosition int
|
||||
sourceName string
|
||||
)
|
||||
command := &cobra.Command{
|
||||
Use: "get APPNAME",
|
||||
@@ -363,9 +347,6 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
|
||||
# Show application parameters and overrides for a source at position 1 under spec.sources of app my-app
|
||||
argocd app get my-app --show-params --source-position 1
|
||||
|
||||
# Show application parameters and overrides for a source named "test"
|
||||
argocd app get my-app --show-params --source-name test
|
||||
|
||||
# Refresh application data when retrieving
|
||||
argocd app get my-app --refresh
|
||||
|
||||
@@ -398,19 +379,6 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
|
||||
})
|
||||
errors.CheckError(err)
|
||||
|
||||
if sourceName != "" && sourcePosition != -1 {
|
||||
errors.CheckError(fmt.Errorf("Only one of source-position and source-name can be specified."))
|
||||
}
|
||||
|
||||
if sourceName != "" {
|
||||
sourceNameToPosition := getSourceNameToPositionMap(app)
|
||||
if pos, ok := sourceNameToPosition[sourceName]; !ok {
|
||||
log.Fatalf("Unknown source name '%s'", sourceName)
|
||||
} else {
|
||||
sourcePosition = int(pos)
|
||||
}
|
||||
}
|
||||
|
||||
// check for source position if --show-params is set
|
||||
if app.Spec.HasMultipleSources() && showParams {
|
||||
if sourcePosition <= 0 {
|
||||
@@ -466,7 +434,6 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
|
||||
command.Flags().BoolVar(&hardRefresh, "hard-refresh", false, "Refresh application data as well as target manifests cache")
|
||||
command.Flags().StringVarP(&appNamespace, "app-namespace", "N", "", "Only get application from namespace")
|
||||
command.Flags().IntVar(&sourcePosition, "source-position", -1, "Position of the source from the list of sources of the app. Counting starts at 1.")
|
||||
command.Flags().StringVar(&sourceName, "source-name", "", "Name of the source from the list of sources of the app.")
|
||||
return command
|
||||
}
|
||||
|
||||
@@ -796,7 +763,6 @@ func NewApplicationSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
|
||||
appOpts cmdutil.AppOptions
|
||||
appNamespace string
|
||||
sourcePosition int
|
||||
sourceName string
|
||||
)
|
||||
command := &cobra.Command{
|
||||
Use: "set APPNAME",
|
||||
@@ -811,9 +777,6 @@ func NewApplicationSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
|
||||
# Set and override application parameters for a source at position 1 under spec.sources of app my-app. source-position starts at 1.
|
||||
argocd app set my-app --source-position 1 --repo https://github.com/argoproj/argocd-example-apps.git
|
||||
|
||||
# Set and override application parameters for a source named "test" under spec.sources of app my-app.
|
||||
argocd app set my-app --source-name test --repo https://github.com/argoproj/argocd-example-apps.git
|
||||
|
||||
# Set application parameters and specify the namespace
|
||||
argocd app set my-app --parameter key1=value1 --parameter key2=value2 --namespace my-namespace
|
||||
`),
|
||||
@@ -832,20 +795,6 @@ func NewApplicationSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
|
||||
app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName, AppNamespace: &appNs})
|
||||
errors.CheckError(err)
|
||||
|
||||
sourceName = appOpts.SourceName
|
||||
if sourceName != "" && sourcePosition != -1 {
|
||||
errors.CheckError(fmt.Errorf("Only one of source-position and source-name can be specified."))
|
||||
}
|
||||
|
||||
if sourceName != "" {
|
||||
sourceNameToPosition := getSourceNameToPositionMap(app)
|
||||
if pos, ok := sourceNameToPosition[sourceName]; !ok {
|
||||
log.Fatalf("Unknown source name '%s'", sourceName)
|
||||
} else {
|
||||
sourcePosition = int(pos)
|
||||
}
|
||||
}
|
||||
|
||||
if app.Spec.HasMultipleSources() {
|
||||
if sourcePosition <= 0 {
|
||||
errors.CheckError(fmt.Errorf("Source position should be specified and must be greater than 0 for applications with multiple sources"))
|
||||
@@ -909,7 +858,6 @@ func (o *unsetOpts) KustomizeIsZero() bool {
|
||||
// NewApplicationUnsetCommand returns a new instance of an `argocd app unset` command
|
||||
func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var sourcePosition int
|
||||
var sourceName string
|
||||
appOpts := cmdutil.AppOptions{}
|
||||
opts := unsetOpts{}
|
||||
var appNamespace string
|
||||
@@ -925,9 +873,6 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
|
||||
# Unset kustomize override suffix for source at position 1 under spec.sources of app my-app. source-position starts at 1.
|
||||
argocd app unset my-app --source-position 1 --namesuffix
|
||||
|
||||
# Unset kustomize override suffix for source named "test" under spec.sources of app my-app.
|
||||
argocd app unset my-app --source-name test --namesuffix
|
||||
|
||||
# Unset parameter override
|
||||
argocd app unset my-app -p COMPONENT=PARAM`,
|
||||
|
||||
@@ -945,20 +890,6 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
|
||||
app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName, AppNamespace: &appNs})
|
||||
errors.CheckError(err)
|
||||
|
||||
sourceName = appOpts.SourceName
|
||||
if sourceName != "" && sourcePosition != -1 {
|
||||
errors.CheckError(fmt.Errorf("Only one of source-position and source-name can be specified."))
|
||||
}
|
||||
|
||||
if sourceName != "" {
|
||||
sourceNameToPosition := getSourceNameToPositionMap(app)
|
||||
if pos, ok := sourceNameToPosition[sourceName]; !ok {
|
||||
log.Fatalf("Unknown source name '%s'", sourceName)
|
||||
} else {
|
||||
sourcePosition = int(pos)
|
||||
}
|
||||
}
|
||||
|
||||
if app.Spec.HasMultipleSources() {
|
||||
if sourcePosition <= 0 {
|
||||
errors.CheckError(fmt.Errorf("Source position should be specified and must be greater than 0 for applications with multiple sources"))
|
||||
@@ -980,20 +911,13 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
|
||||
}
|
||||
|
||||
cmdutil.SetAppSpecOptions(c.Flags(), &app.Spec, &appOpts, sourcePosition)
|
||||
|
||||
promptUtil := utils.NewPrompt(clientOpts.PromptsEnabled)
|
||||
canUnset := promptUtil.Confirm("Are you sure you want to unset the parameters? [y/n]")
|
||||
if canUnset {
|
||||
_, err = appIf.UpdateSpec(ctx, &application.ApplicationUpdateSpecRequest{
|
||||
Name: &app.Name,
|
||||
Spec: &app.Spec,
|
||||
Validate: &appOpts.Validate,
|
||||
AppNamespace: &appNs,
|
||||
})
|
||||
errors.CheckError(err)
|
||||
} else {
|
||||
fmt.Println("The command to unset the parameters has been cancelled.")
|
||||
}
|
||||
_, err = appIf.UpdateSpec(ctx, &application.ApplicationUpdateSpecRequest{
|
||||
Name: &app.Name,
|
||||
Spec: &app.Spec,
|
||||
Validate: &appOpts.Validate,
|
||||
AppNamespace: &appNs,
|
||||
})
|
||||
errors.CheckError(err)
|
||||
},
|
||||
}
|
||||
command.Flags().StringVarP(&appNamespace, "app-namespace", "N", "", "Unset application parameters in namespace")
|
||||
@@ -1158,18 +1082,17 @@ func getLocalObjectsString(ctx context.Context, app *argoappv1.Application, proj
|
||||
) []string {
|
||||
source := app.Spec.GetSource()
|
||||
res, err := repository.GenerateManifests(ctx, local, localRepoRoot, source.TargetRevision, &repoapiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{Repo: source.RepoURL},
|
||||
AppLabelKey: appLabelKey,
|
||||
AppName: app.Name,
|
||||
Namespace: app.Spec.Destination.Namespace,
|
||||
ApplicationSource: &source,
|
||||
KustomizeOptions: kustomizeOptions,
|
||||
KubeVersion: kubeVersion,
|
||||
ApiVersions: apiVersions,
|
||||
TrackingMethod: trackingMethod,
|
||||
ProjectName: proj.Name,
|
||||
ProjectSourceRepos: proj.Spec.SourceRepos,
|
||||
AnnotationManifestGeneratePaths: app.GetAnnotation(argoappv1.AnnotationKeyManifestGeneratePaths),
|
||||
Repo: &argoappv1.Repository{Repo: source.RepoURL},
|
||||
AppLabelKey: appLabelKey,
|
||||
AppName: app.Name,
|
||||
Namespace: app.Spec.Destination.Namespace,
|
||||
ApplicationSource: &source,
|
||||
KustomizeOptions: kustomizeOptions,
|
||||
KubeVersion: kubeVersion,
|
||||
ApiVersions: apiVersions,
|
||||
TrackingMethod: trackingMethod,
|
||||
ProjectName: proj.Name,
|
||||
ProjectSourceRepos: proj.Spec.SourceRepos,
|
||||
}, true, &git.NoopCredsStore{}, resource.MustParse("0"), nil)
|
||||
errors.CheckError(err)
|
||||
|
||||
@@ -1218,7 +1141,6 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
refresh bool
|
||||
hardRefresh bool
|
||||
exitCode bool
|
||||
diffExitCode int
|
||||
local string
|
||||
revision string
|
||||
localRepoRoot string
|
||||
@@ -1227,7 +1149,6 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
appNamespace string
|
||||
revisions []string
|
||||
sourcePositions []int64
|
||||
sourceNames []string
|
||||
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
|
||||
)
|
||||
shortDesc := "Perform a diff against the target and live state."
|
||||
@@ -1243,16 +1164,8 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if len(sourceNames) > 0 && len(sourcePositions) > 0 {
|
||||
errors.CheckError(fmt.Errorf("Only one of source-positions and source-names can be specified."))
|
||||
}
|
||||
|
||||
if len(sourcePositions) > 0 && len(revisions) != len(sourcePositions) {
|
||||
errors.CheckError(fmt.Errorf("While using --revisions and --source-positions, length of values for both flags should be same."))
|
||||
}
|
||||
|
||||
if len(sourceNames) > 0 && len(revisions) != len(sourceNames) {
|
||||
errors.CheckError(fmt.Errorf("While using --revisions and --source-names, length of values for both flags should be same."))
|
||||
if len(revisions) != len(sourcePositions) {
|
||||
errors.CheckError(fmt.Errorf("While using revisions and source-positions, length of values for both flags should be same."))
|
||||
}
|
||||
|
||||
clientset := headless.NewClientOrDie(clientOpts, c)
|
||||
@@ -1266,18 +1179,6 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
})
|
||||
errors.CheckError(err)
|
||||
|
||||
if len(sourceNames) > 0 {
|
||||
sourceNameToPosition := getSourceNameToPositionMap(app)
|
||||
|
||||
for _, name := range sourceNames {
|
||||
if pos, ok := sourceNameToPosition[name]; !ok {
|
||||
log.Fatalf("Unknown source name '%s'", name)
|
||||
} else {
|
||||
sourcePositions = append(sourcePositions, pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resources, err := appIf.ManagedResources(ctx, &application.ResourcesQuery{ApplicationName: &appName, AppNamespace: &appNs})
|
||||
errors.CheckError(err)
|
||||
conn, settingsIf := clientset.NewSettingsClientOrDie()
|
||||
@@ -1342,14 +1243,13 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
proj := getProject(c, clientOpts, ctx, app.Spec.Project)
|
||||
foundDiffs := findandPrintDiff(ctx, app, proj.Project, resources, argoSettings, diffOption, ignoreNormalizerOpts)
|
||||
if foundDiffs && exitCode {
|
||||
os.Exit(diffExitCode)
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
command.Flags().BoolVar(&refresh, "refresh", false, "Refresh application data when retrieving")
|
||||
command.Flags().BoolVar(&hardRefresh, "hard-refresh", false, "Refresh application data as well as target manifests cache")
|
||||
command.Flags().BoolVar(&exitCode, "exit-code", true, "Return non-zero exit code when there is a diff. May also return non-zero exit code if there is an error.")
|
||||
command.Flags().IntVar(&diffExitCode, "diff-exit-code", 1, "Return specified exit code when there is a diff. Typical error code is 20.")
|
||||
command.Flags().BoolVar(&exitCode, "exit-code", true, "Return non-zero exit code when there is a diff")
|
||||
command.Flags().StringVar(&local, "local", "", "Compare live app to a local manifests")
|
||||
command.Flags().StringVar(&revision, "revision", "", "Compare live app to a particular revision")
|
||||
command.Flags().StringVar(&localRepoRoot, "local-repo-root", "/", "Path to the repository root. Used together with --local allows setting the repository root")
|
||||
@@ -1358,7 +1258,6 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
command.Flags().StringVarP(&appNamespace, "app-namespace", "N", "", "Only render the difference in namespace")
|
||||
command.Flags().StringArrayVar(&revisions, "revisions", []string{}, "Show manifests at specific revisions for source position in source-positions")
|
||||
command.Flags().Int64SliceVar(&sourcePositions, "source-positions", []int64{}, "List of source positions. Default is empty array. Counting start at 1.")
|
||||
command.Flags().StringArrayVar(&sourceNames, "source-names", []string{}, "List of source names. Default is an empty array.")
|
||||
command.Flags().DurationVar(&ignoreNormalizerOpts.JQExecutionTimeout, "ignore-normalizer-jq-execution-timeout", normalizers.DefaultJQExecutionTimeout, "Set ignore normalizer JQ execution timeout")
|
||||
return command
|
||||
}
|
||||
@@ -1532,6 +1431,8 @@ func NewApplicationDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.
|
||||
conn, appIf := acdClient.NewApplicationClientOrDie()
|
||||
defer argoio.Close(conn)
|
||||
var isTerminal bool = isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
|
||||
var isConfirmAll bool = false
|
||||
numOfApps := len(args)
|
||||
promptFlag := c.Flag("yes")
|
||||
if promptFlag.Changed && promptFlag.Value.String() == "true" {
|
||||
noPrompt = true
|
||||
@@ -1544,16 +1445,6 @@ func NewApplicationDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.
|
||||
appNames = args
|
||||
}
|
||||
|
||||
numOfApps := len(appNames)
|
||||
|
||||
// This is for backward compatibility,
|
||||
// before we showed the prompts only when condition cascade && isTerminal && !noPrompt is true
|
||||
promptUtil := utils.NewPrompt(cascade && isTerminal && !noPrompt)
|
||||
var (
|
||||
confirmAll = false
|
||||
confirm = false
|
||||
)
|
||||
|
||||
for _, appFullName := range appNames {
|
||||
appName, appNs := argo.ParseFromQualifiedName(appFullName, appNamespace)
|
||||
appDeleteReq := application.ApplicationDeleteRequest{
|
||||
@@ -1566,21 +1457,38 @@ func NewApplicationDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.
|
||||
if c.Flag("propagation-policy").Changed {
|
||||
appDeleteReq.PropagationPolicy = &propagationPolicy
|
||||
}
|
||||
messageForSingle := "Are you sure you want to delete '" + appFullName + "' and all its resources? [y/n] "
|
||||
messageForAll := "Are you sure you want to delete '" + appFullName + "' and all its resources? [y/n/a] where 'a' is to delete all specified apps and their resources without prompting "
|
||||
|
||||
if !confirmAll {
|
||||
confirm, confirmAll = promptUtil.ConfirmBaseOnCount(messageForSingle, messageForAll, numOfApps)
|
||||
}
|
||||
if confirm || confirmAll {
|
||||
if cascade && isTerminal && !noPrompt {
|
||||
var lowercaseAnswer string
|
||||
if numOfApps == 1 {
|
||||
lowercaseAnswer = cli.AskToProceedS("Are you sure you want to delete '" + appFullName + "' and all its resources? [y/n] ")
|
||||
} else {
|
||||
if !isConfirmAll {
|
||||
lowercaseAnswer = cli.AskToProceedS("Are you sure you want to delete '" + appFullName + "' and all its resources? [y/n/A] where 'A' is to delete all specified apps and their resources without prompting ")
|
||||
if lowercaseAnswer == "a" {
|
||||
lowercaseAnswer = "y"
|
||||
isConfirmAll = true
|
||||
}
|
||||
} else {
|
||||
lowercaseAnswer = "y"
|
||||
}
|
||||
}
|
||||
if lowercaseAnswer == "y" {
|
||||
_, err := appIf.Delete(ctx, &appDeleteReq)
|
||||
errors.CheckError(err)
|
||||
if wait {
|
||||
checkForDeleteEvent(ctx, acdClient, appFullName)
|
||||
}
|
||||
fmt.Printf("application '%s' deleted\n", appFullName)
|
||||
} else {
|
||||
fmt.Println("The command to delete '" + appFullName + "' was cancelled.")
|
||||
}
|
||||
} else {
|
||||
_, err := appIf.Delete(ctx, &appDeleteReq)
|
||||
errors.CheckError(err)
|
||||
|
||||
if wait {
|
||||
checkForDeleteEvent(ctx, acdClient, appFullName)
|
||||
}
|
||||
fmt.Printf("application '%s' deleted\n", appFullName)
|
||||
} else {
|
||||
fmt.Println("The command to delete '" + appFullName + "' was cancelled.")
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1739,7 +1647,6 @@ func formatConditionsSummary(app argoappv1.Application) string {
|
||||
}
|
||||
summary := "<none>"
|
||||
if len(items) > 0 {
|
||||
slices.Sort(items)
|
||||
summary = strings.Join(items, ",")
|
||||
}
|
||||
return summary
|
||||
@@ -1924,7 +1831,6 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
revision string
|
||||
revisions []string
|
||||
sourcePositions []int64
|
||||
sourceNames []string
|
||||
resources []string
|
||||
labels []string
|
||||
selector string
|
||||
@@ -1968,8 +1874,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
argocd app sync -l 'app.kubernetes.io/instance notin (my-app,other-app)'
|
||||
|
||||
# Sync a multi-source application for specific revision of specific sources
|
||||
argocd app sync my-app --revisions 0.0.1 --source-positions 1 --revisions 0.0.2 --source-positions 2
|
||||
argocd app sync my-app --revisions 0.0.1 --source-names my-chart --revisions 0.0.2 --source-names my-values
|
||||
argocd app manifests my-app --revisions 0.0.1 --source-positions 1 --revisions 0.0.2 --source-positions 2
|
||||
|
||||
# Sync a specific resource
|
||||
# Resource should be formatted as GROUP:KIND:NAME. If no GROUP is specified then :KIND:NAME
|
||||
@@ -1994,22 +1899,10 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
log.Fatal("Cannot use --revisions and --source-positions options when 0 or more than 1 application names are passed as argument(s)")
|
||||
}
|
||||
|
||||
if len(args) != 1 && (len(revisions) > 0 || len(sourceNames) > 0) {
|
||||
log.Fatal("Cannot use --revisions and --source-names options when 0 or more than 1 application names are passed as argument(s)")
|
||||
}
|
||||
|
||||
if len(sourceNames) > 0 && len(sourcePositions) > 0 {
|
||||
log.Fatal("Only one of source-positions and source-names can be specified.")
|
||||
}
|
||||
|
||||
if len(sourcePositions) > 0 && len(revisions) != len(sourcePositions) {
|
||||
if len(revisions) != len(sourcePositions) {
|
||||
log.Fatal("While using --revisions and --source-positions, length of values for both flags should be same.")
|
||||
}
|
||||
|
||||
if len(sourceNames) > 0 && len(revisions) != len(sourceNames) {
|
||||
log.Fatal("While using --revisions and --source-names, length of values for both flags should be same.")
|
||||
}
|
||||
|
||||
for _, pos := range sourcePositions {
|
||||
if pos <= 0 {
|
||||
log.Fatal("source-position cannot be less than or equal to 0, Counting starts at 1")
|
||||
@@ -2023,22 +1916,6 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
selectedLabels, err := label.Parse(labels)
|
||||
errors.CheckError(err)
|
||||
|
||||
if len(args) == 1 && len(sourceNames) > 0 {
|
||||
appName, _ := argo.ParseFromQualifiedName(args[0], appNamespace)
|
||||
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName})
|
||||
errors.CheckError(err)
|
||||
|
||||
sourceNameToPosition := getSourceNameToPositionMap(app)
|
||||
|
||||
for _, name := range sourceNames {
|
||||
if pos, ok := sourceNameToPosition[name]; !ok {
|
||||
log.Fatalf("Unknown source name '%s'", name)
|
||||
} else {
|
||||
sourcePositions = append(sourcePositions, pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appNames := args
|
||||
if selector != "" || len(projects) > 0 {
|
||||
list, err := appIf.List(ctx, &application.ApplicationQuery{
|
||||
@@ -2297,7 +2174,6 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
|
||||
command.Flags().DurationVar(&ignoreNormalizerOpts.JQExecutionTimeout, "ignore-normalizer-jq-execution-timeout", normalizers.DefaultJQExecutionTimeout, "Set ignore normalizer JQ execution timeout")
|
||||
command.Flags().StringArrayVar(&revisions, "revisions", []string{}, "Show manifests at specific revisions for source position in source-positions")
|
||||
command.Flags().Int64SliceVar(&sourcePositions, "source-positions", []int64{}, "List of source positions. Default is empty array. Counting start at 1.")
|
||||
command.Flags().StringArrayVar(&sourceNames, "source-names", []string{}, "List of source names. Default is an empty array.")
|
||||
return command
|
||||
}
|
||||
|
||||
@@ -2938,7 +2814,6 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
revision string
|
||||
revisions []string
|
||||
sourcePositions []int64
|
||||
sourceNames []string
|
||||
local string
|
||||
localRepoRoot string
|
||||
)
|
||||
@@ -2952,9 +2827,6 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
# Get manifests for an application at a specific revision
|
||||
argocd app manifests my-app --revision 0.0.1
|
||||
|
||||
# Get manifests for a multi-source application at specific revisions for specific sources
|
||||
argocd app manifests my-app --revisions 0.0.1 --source-names src-base --revisions 0.0.2 --source-names src-values
|
||||
|
||||
# Get manifests for a multi-source application at specific revisions for specific sources
|
||||
argocd app manifests my-app --revisions 0.0.1 --source-positions 1 --revisions 0.0.2 --source-positions 2
|
||||
`),
|
||||
@@ -2966,16 +2838,8 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if len(sourceNames) > 0 && len(sourcePositions) > 0 {
|
||||
errors.CheckError(fmt.Errorf("Only one of source-positions and source-names can be specified."))
|
||||
}
|
||||
|
||||
if len(sourcePositions) > 0 && len(revisions) != len(sourcePositions) {
|
||||
errors.CheckError(fmt.Errorf("While using --revisions and --source-positions, length of values for both flags should be same."))
|
||||
}
|
||||
|
||||
if len(sourceNames) > 0 && len(revisions) != len(sourceNames) {
|
||||
errors.CheckError(fmt.Errorf("While using --revisions and --source-names, length of values for both flags should be same."))
|
||||
if len(revisions) != len(sourcePositions) {
|
||||
errors.CheckError(fmt.Errorf("While using revisions and source-positions, length of values for both flags should be same."))
|
||||
}
|
||||
|
||||
for _, pos := range sourcePositions {
|
||||
@@ -2989,24 +2853,6 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
conn, appIf := clientset.NewApplicationClientOrDie()
|
||||
defer argoio.Close(conn)
|
||||
|
||||
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{
|
||||
Name: &appName,
|
||||
AppNamespace: &appNs,
|
||||
})
|
||||
errors.CheckError(err)
|
||||
|
||||
if len(sourceNames) > 0 {
|
||||
sourceNameToPosition := getSourceNameToPositionMap(app)
|
||||
|
||||
for _, name := range sourceNames {
|
||||
if pos, ok := sourceNameToPosition[name]; !ok {
|
||||
log.Fatalf("Unknown source name '%s'", name)
|
||||
} else {
|
||||
sourcePositions = append(sourcePositions, pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resources, err := appIf.ManagedResources(ctx, &application.ResourcesQuery{
|
||||
ApplicationName: &appName,
|
||||
AppNamespace: &appNs,
|
||||
@@ -3017,6 +2863,9 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
switch source {
|
||||
case "git":
|
||||
if local != "" {
|
||||
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName})
|
||||
errors.CheckError(err)
|
||||
|
||||
settingsConn, settingsIf := clientset.NewSettingsClientOrDie()
|
||||
defer argoio.Close(settingsConn)
|
||||
argoSettings, err := settingsIf.Get(context.Background(), &settings.SettingsQuery{})
|
||||
@@ -3085,7 +2934,6 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
command.Flags().StringVar(&revision, "revision", "", "Show manifests at a specific revision")
|
||||
command.Flags().StringArrayVar(&revisions, "revisions", []string{}, "Show manifests at specific revisions for the source at position in source-positions")
|
||||
command.Flags().Int64SliceVar(&sourcePositions, "source-positions", []int64{}, "List of source positions. Default is empty array. Counting start at 1.")
|
||||
command.Flags().StringArrayVar(&sourceNames, "source-names", []string{}, "List of source names. Default is an empty array.")
|
||||
command.Flags().StringVar(&local, "local", "", "If set, show locally-generated manifests. Value is the absolute path to app manifests within the manifest repo. Example: '/home/username/apps/env/app-1'.")
|
||||
command.Flags().StringVar(&localRepoRoot, "local-repo-root", ".", "Path to the local repository root. Used together with --local allows setting the repository root. Example: '/home/username/apps'.")
|
||||
return command
|
||||
@@ -3234,7 +3082,7 @@ func NewApplicationAddSourceCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
Use: "add-source APPNAME",
|
||||
Short: "Adds a source to the list of sources in the application",
|
||||
Example: ` # Append a source to the list of sources in the application
|
||||
argocd app add-source guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --source-name guestbook`,
|
||||
argocd app add-source guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
ctx := c.Context()
|
||||
if len(args) != 1 {
|
||||
@@ -3292,17 +3140,13 @@ func NewApplicationAddSourceCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
func NewApplicationRemoveSourceCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
sourcePosition int
|
||||
sourceName string
|
||||
appNamespace string
|
||||
)
|
||||
command := &cobra.Command{
|
||||
Use: "remove-source APPNAME",
|
||||
Short: "Remove a source from multiple sources application.",
|
||||
Short: "Remove a source from multiple sources application. Counting starts with 1. Default value is -1.",
|
||||
Example: ` # Remove the source at position 1 from application's sources. Counting starts at 1.
|
||||
argocd app remove-source myapplication --source-position 1
|
||||
|
||||
# Remove the source named "test" from application's sources.
|
||||
argocd app remove-source myapplication --source-name test`,
|
||||
argocd app remove-source myapplication --source-position 1`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
ctx := c.Context()
|
||||
|
||||
@@ -3311,7 +3155,7 @@ func NewApplicationRemoveSourceCommand(clientOpts *argocdclient.ClientOptions) *
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if sourceName == "" && sourcePosition <= 0 {
|
||||
if sourcePosition <= 0 {
|
||||
errors.CheckError(fmt.Errorf("Value of source-position must be greater than 0"))
|
||||
}
|
||||
|
||||
@@ -3328,19 +3172,6 @@ func NewApplicationRemoveSourceCommand(clientOpts *argocdclient.ClientOptions) *
|
||||
})
|
||||
errors.CheckError(err)
|
||||
|
||||
if sourceName != "" && sourcePosition != -1 {
|
||||
errors.CheckError(fmt.Errorf("Only one of source-position and source-name can be specified."))
|
||||
}
|
||||
|
||||
if sourceName != "" {
|
||||
sourceNameToPosition := getSourceNameToPositionMap(app)
|
||||
if pos, ok := sourceNameToPosition[sourceName]; !ok {
|
||||
log.Fatalf("Unknown source name '%s'", sourceName)
|
||||
} else {
|
||||
sourcePosition = int(pos)
|
||||
}
|
||||
}
|
||||
|
||||
if !app.Spec.HasMultipleSources() {
|
||||
errors.CheckError(fmt.Errorf("Application does not have multiple sources configured"))
|
||||
}
|
||||
@@ -3355,71 +3186,17 @@ func NewApplicationRemoveSourceCommand(clientOpts *argocdclient.ClientOptions) *
|
||||
|
||||
app.Spec.Sources = append(app.Spec.Sources[:sourcePosition-1], app.Spec.Sources[sourcePosition:]...)
|
||||
|
||||
promptUtil := utils.NewPrompt(clientOpts.PromptsEnabled)
|
||||
canDelete := promptUtil.Confirm("Are you sure you want to delete the source? [y/n]")
|
||||
if canDelete {
|
||||
_, err = appIf.UpdateSpec(ctx, &application.ApplicationUpdateSpecRequest{
|
||||
Name: &app.Name,
|
||||
Spec: &app.Spec,
|
||||
AppNamespace: &appNs,
|
||||
})
|
||||
errors.CheckError(err)
|
||||
|
||||
fmt.Printf("Application '%s' updated successfully\n", app.ObjectMeta.Name)
|
||||
} else {
|
||||
fmt.Println("The command to delete the source was cancelled")
|
||||
}
|
||||
},
|
||||
}
|
||||
command.Flags().StringVarP(&appNamespace, "app-namespace", "N", "", "Namespace of the target application where the source will be appended")
|
||||
command.Flags().IntVar(&sourcePosition, "source-position", -1, "Position of the source from the list of sources of the app. Counting starts at 1.")
|
||||
command.Flags().StringVar(&sourceName, "source-name", "", "Name of the source from the list of sources of the app.")
|
||||
return command
|
||||
}
|
||||
|
||||
func NewApplicationConfirmDeletionCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var appNamespace string
|
||||
command := &cobra.Command{
|
||||
Use: "confirm-deletion APPNAME",
|
||||
Short: "Confirms deletion/pruning of an application resources",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
ctx := c.Context()
|
||||
|
||||
if len(args) != 1 {
|
||||
c.HelpFunc()(c, args)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
argocdClient := headless.NewClientOrDie(clientOpts, c)
|
||||
conn, appIf := argocdClient.NewApplicationClientOrDie()
|
||||
defer argoio.Close(conn)
|
||||
|
||||
appName, appNs := argo.ParseFromQualifiedName(args[0], appNamespace)
|
||||
|
||||
app, err := appIf.Get(ctx, &application.ApplicationQuery{
|
||||
Name: &appName,
|
||||
Refresh: getRefreshType(false, false),
|
||||
_, err = appIf.UpdateSpec(ctx, &application.ApplicationUpdateSpecRequest{
|
||||
Name: &app.Name,
|
||||
Spec: &app.Spec,
|
||||
AppNamespace: &appNs,
|
||||
})
|
||||
errors.CheckError(err)
|
||||
|
||||
annotations := app.Annotations
|
||||
if annotations == nil {
|
||||
annotations = map[string]string{}
|
||||
app.Annotations = annotations
|
||||
}
|
||||
annotations[common.AnnotationDeletionApproved] = metav1.Now().Format(time.RFC3339)
|
||||
|
||||
_, err = appIf.Update(ctx, &application.ApplicationUpdateRequest{
|
||||
Application: app,
|
||||
Validate: ptr.To(false),
|
||||
Project: &app.Spec.Project,
|
||||
})
|
||||
errors.CheckError(err)
|
||||
|
||||
fmt.Printf("Application '%s' updated successfully\n", app.ObjectMeta.Name)
|
||||
},
|
||||
}
|
||||
command.Flags().StringVarP(&appNamespace, "app-namespace", "N", "", "Namespace of the target application where the source will be appended")
|
||||
command.Flags().IntVar(&sourcePosition, "source-position", -1, "Position of the source from the list of sources of the app. Counting starts at 1.")
|
||||
return command
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
)
|
||||
@@ -38,7 +37,9 @@ func TestPrintTreeViewAppResources(t *testing.T) {
|
||||
w := tabwriter.NewWriter(buf, 0, 0, 2, ' ', 0)
|
||||
|
||||
printTreeViewAppResourcesNotOrphaned(nodeMapping, mapParentToChild, parentNode, w)
|
||||
require.NoError(t, w.Flush())
|
||||
if err := w.Flush(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
output := buf.String()
|
||||
|
||||
assert.Contains(t, output, "Rollout")
|
||||
@@ -77,7 +78,9 @@ func TestPrintTreeViewDetailedAppResources(t *testing.T) {
|
||||
w := tabwriter.NewWriter(buf, 0, 0, 2, ' ', 0)
|
||||
|
||||
printDetailedTreeViewAppResourcesNotOrphaned(nodeMapping, mapParentToChild, parentNode, w)
|
||||
require.NoError(t, w.Flush())
|
||||
if err := w.Flush(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
output := buf.String()
|
||||
|
||||
assert.Contains(t, output, "Rollout")
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/utils"
|
||||
"github.com/argoproj/argo-cd/v2/cmd/util"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
|
||||
@@ -131,32 +130,23 @@ func NewApplicationDeleteResourceCommand(clientOpts *argocdclient.ClientOptions)
|
||||
errors.CheckError(err)
|
||||
objectsToDelete, err := util.FilterResources(command.Flags().Changed("group"), resources.Items, group, kind, namespace, resourceName, all)
|
||||
errors.CheckError(err)
|
||||
|
||||
promptUtil := utils.NewPrompt(clientOpts.PromptsEnabled)
|
||||
|
||||
for i := range objectsToDelete {
|
||||
obj := objectsToDelete[i]
|
||||
gvk := obj.GroupVersionKind()
|
||||
|
||||
canDelete := promptUtil.Confirm(fmt.Sprintf("Are you sure you want to delete %s/%s %s/%s ? [y/n]", gvk.Group, gvk.Kind, obj.GetNamespace(), obj.GetName()))
|
||||
if canDelete {
|
||||
_, err = appIf.DeleteResource(ctx, &applicationpkg.ApplicationResourceDeleteRequest{
|
||||
Name: &appName,
|
||||
AppNamespace: &appNs,
|
||||
Namespace: ptr.To(obj.GetNamespace()),
|
||||
ResourceName: ptr.To(obj.GetName()),
|
||||
Version: ptr.To(gvk.Version),
|
||||
Group: ptr.To(gvk.Group),
|
||||
Kind: ptr.To(gvk.Kind),
|
||||
Force: &force,
|
||||
Orphan: &orphan,
|
||||
Project: ptr.To(project),
|
||||
})
|
||||
errors.CheckError(err)
|
||||
log.Infof("Resource '%s' deleted", obj.GetName())
|
||||
} else {
|
||||
fmt.Printf("The command to delete %s/%s %s/%s was cancelled.\n", gvk.Group, gvk.Kind, obj.GetNamespace(), obj.GetName())
|
||||
}
|
||||
_, err = appIf.DeleteResource(ctx, &applicationpkg.ApplicationResourceDeleteRequest{
|
||||
Name: &appName,
|
||||
AppNamespace: &appNs,
|
||||
Namespace: ptr.To(obj.GetNamespace()),
|
||||
ResourceName: ptr.To(obj.GetName()),
|
||||
Version: ptr.To(gvk.Version),
|
||||
Group: ptr.To(gvk.Group),
|
||||
Kind: ptr.To(gvk.Kind),
|
||||
Force: &force,
|
||||
Orphan: &orphan,
|
||||
Project: ptr.To(project),
|
||||
})
|
||||
errors.CheckError(err)
|
||||
log.Infof("Resource '%s' deleted", obj.GetName())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,8 +136,13 @@ func TestFindRevisionHistoryWithoutPassedId(t *testing.T) {
|
||||
}
|
||||
|
||||
history, err := findRevisionHistory(&application, -1)
|
||||
require.NoError(t, err, "Find revision history should fail without errors")
|
||||
require.NotNil(t, history, "History should be found")
|
||||
if err != nil {
|
||||
t.Fatal("Find revision history should fail without errors")
|
||||
}
|
||||
|
||||
if history == nil {
|
||||
t.Fatal("History should be found")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintTreeViewAppGet(t *testing.T) {
|
||||
@@ -244,8 +249,13 @@ func TestFindRevisionHistoryWithoutPassedIdWithMultipleSources(t *testing.T) {
|
||||
}
|
||||
|
||||
history, err := findRevisionHistory(&application, -1)
|
||||
require.NoError(t, err, "Find revision history should fail without errors")
|
||||
require.NotNil(t, history, "History should be found")
|
||||
if err != nil {
|
||||
t.Fatal("Find revision history should fail without errors")
|
||||
}
|
||||
|
||||
if history == nil {
|
||||
t.Fatal("History should be found")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultWaitOptions(t *testing.T) {
|
||||
@@ -298,9 +308,17 @@ func TestFindRevisionHistoryWithoutPassedIdAndEmptyHistoryList(t *testing.T) {
|
||||
|
||||
history, err := findRevisionHistory(&application, -1)
|
||||
|
||||
require.Error(t, err, "Find revision history should fail with errors")
|
||||
require.Nil(t, history, "History should be empty")
|
||||
require.EqualError(t, err, "Application '' should have at least two successful deployments", "Find revision history should fail with correct error message")
|
||||
if err == nil {
|
||||
t.Fatal("Find revision history should fail with errors")
|
||||
}
|
||||
|
||||
if history != nil {
|
||||
t.Fatal("History should be empty")
|
||||
}
|
||||
|
||||
if err.Error() != "Application '' should have at least two successful deployments" {
|
||||
t.Fatal("Find revision history should fail with correct error message")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindRevisionHistoryWithPassedId(t *testing.T) {
|
||||
@@ -328,9 +346,17 @@ func TestFindRevisionHistoryWithPassedId(t *testing.T) {
|
||||
}
|
||||
|
||||
history, err := findRevisionHistory(&application, 3)
|
||||
require.NoError(t, err, "Find revision history should fail without errors")
|
||||
require.NotNil(t, history, "History should be found")
|
||||
require.Equal(t, "123", history.Revision, "Failed to find correct history with correct revision")
|
||||
if err != nil {
|
||||
t.Fatal("Find revision history should fail without errors")
|
||||
}
|
||||
|
||||
if history == nil {
|
||||
t.Fatal("History should be found")
|
||||
}
|
||||
|
||||
if history.Revision != "123" {
|
||||
t.Fatal("Failed to find correct history with correct revision")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindRevisionHistoryWithPassedIdThatNotExist(t *testing.T) {
|
||||
@@ -359,9 +385,17 @@ func TestFindRevisionHistoryWithPassedIdThatNotExist(t *testing.T) {
|
||||
|
||||
history, err := findRevisionHistory(&application, 4)
|
||||
|
||||
require.Error(t, err, "Find revision history should fail with errors")
|
||||
require.Nil(t, history, "History should be not found")
|
||||
require.EqualError(t, err, "Application '' does not have deployment id '4' in history\n", "Find revision history should fail with correct error message")
|
||||
if err == nil {
|
||||
t.Fatal("Find revision history should fail with errors")
|
||||
}
|
||||
|
||||
if history != nil {
|
||||
t.Fatal("History should be not found")
|
||||
}
|
||||
|
||||
if err.Error() != "Application '' does not have deployment id '4' in history\n" {
|
||||
t.Fatal("Find revision history should fail with correct error message")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_groupObjsByKey(t *testing.T) {
|
||||
@@ -423,7 +457,9 @@ func TestFormatSyncPolicy(t *testing.T) {
|
||||
|
||||
policy := formatSyncPolicy(app)
|
||||
|
||||
require.Equalf(t, "Manual", policy, "Incorrect policy %q, should be Manual", policy)
|
||||
if policy != "Manual" {
|
||||
t.Fatalf("Incorrect policy %q, should be Manual", policy)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Auto policy", func(t *testing.T) {
|
||||
@@ -437,7 +473,9 @@ func TestFormatSyncPolicy(t *testing.T) {
|
||||
|
||||
policy := formatSyncPolicy(app)
|
||||
|
||||
require.Equalf(t, "Auto", policy, "Incorrect policy %q, should be Auto", policy)
|
||||
if policy != "Auto" {
|
||||
t.Fatalf("Incorrect policy %q, should be Auto", policy)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Auto policy with prune", func(t *testing.T) {
|
||||
@@ -453,7 +491,9 @@ func TestFormatSyncPolicy(t *testing.T) {
|
||||
|
||||
policy := formatSyncPolicy(app)
|
||||
|
||||
require.Equalf(t, "Auto-Prune", policy, "Incorrect policy %q, should be Auto-Prune", policy)
|
||||
if policy != "Auto-Prune" {
|
||||
t.Fatalf("Incorrect policy %q, should be Auto-Prune", policy)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -470,7 +510,9 @@ func TestFormatConditionSummary(t *testing.T) {
|
||||
}
|
||||
|
||||
summary := formatConditionsSummary(app)
|
||||
require.Equalf(t, "<none>", summary, "Incorrect summary %q, should be <none>", summary)
|
||||
if summary != "<none>" {
|
||||
t.Fatalf("Incorrect summary %q, should be <none>", summary)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Few conditions are defined", func(t *testing.T) {
|
||||
@@ -491,28 +533,9 @@ func TestFormatConditionSummary(t *testing.T) {
|
||||
}
|
||||
|
||||
summary := formatConditionsSummary(app)
|
||||
require.Equalf(t, "type1(2),type2", summary, "Incorrect summary %q, should be type1(2),type2", summary)
|
||||
})
|
||||
|
||||
t.Run("Conditions are sorted for idempotent summary", func(t *testing.T) {
|
||||
app := v1alpha1.Application{
|
||||
Status: v1alpha1.ApplicationStatus{
|
||||
Conditions: []v1alpha1.ApplicationCondition{
|
||||
{
|
||||
Type: "type2",
|
||||
},
|
||||
{
|
||||
Type: "type1",
|
||||
},
|
||||
{
|
||||
Type: "type1",
|
||||
},
|
||||
},
|
||||
},
|
||||
if summary != "type1(2),type2" && summary != "type2,type1(2)" {
|
||||
t.Fatalf("Incorrect summary %q, should be type1(2),type2", summary)
|
||||
}
|
||||
|
||||
summary := formatConditionsSummary(app)
|
||||
require.Equalf(t, "type1(2),type2", summary, "Incorrect summary %q, should be type1(2),type2", summary)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -523,7 +546,9 @@ func TestPrintOperationResult(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
require.Emptyf(t, output, "Incorrect print operation output %q, should be ''", output)
|
||||
if output != "" {
|
||||
t.Fatalf("Incorrect print operation output %q, should be ''", output)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Operation state sync result is not empty", func(t *testing.T) {
|
||||
@@ -537,7 +562,9 @@ func TestPrintOperationResult(t *testing.T) {
|
||||
})
|
||||
|
||||
expectation := "Operation: Sync\nSync Revision: revision\nPhase: \nStart: 0001-01-01 00:00:00 +0000 UTC\nFinished: 2020-11-10 23:00:00 +0000 UTC\nDuration: 2333448h16m18.871345152s\n"
|
||||
require.Equalf(t, output, expectation, "Incorrect print operation output %q, should be %q", output, expectation)
|
||||
if output != expectation {
|
||||
t.Fatalf("Incorrect print operation output %q, should be %q", output, expectation)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Operation state sync result with message is not empty", func(t *testing.T) {
|
||||
@@ -552,7 +579,9 @@ func TestPrintOperationResult(t *testing.T) {
|
||||
})
|
||||
|
||||
expectation := "Operation: Sync\nSync Revision: revision\nPhase: \nStart: 0001-01-01 00:00:00 +0000 UTC\nFinished: 2020-11-10 23:00:00 +0000 UTC\nDuration: 2333448h16m18.871345152s\nMessage: test\n"
|
||||
require.Equalf(t, output, expectation, "Incorrect print operation output %q, should be %q", output, expectation)
|
||||
if output != expectation {
|
||||
t.Fatalf("Incorrect print operation output %q, should be %q", output, expectation)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -588,7 +617,9 @@ func TestPrintApplicationHistoryTable(t *testing.T) {
|
||||
|
||||
expectation := "SOURCE test\nID DATE REVISION\n1 0001-01-01 00:00:00 +0000 UTC 1\n2 0001-01-01 00:00:00 +0000 UTC 2\n3 0001-01-01 00:00:00 +0000 UTC 3\n"
|
||||
|
||||
require.Equalf(t, output, expectation, "Incorrect print operation output %q, should be %q", output, expectation)
|
||||
if output != expectation {
|
||||
t.Fatalf("Incorrect print operation output %q, should be %q", output, expectation)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintApplicationHistoryTableWithMultipleSources(t *testing.T) {
|
||||
@@ -665,7 +696,9 @@ func TestPrintApplicationHistoryTableWithMultipleSources(t *testing.T) {
|
||||
|
||||
expectation := "SOURCE test\nID DATE REVISION\n0 0001-01-01 00:00:00 +0000 UTC 0\n\nSOURCE test-1\nID DATE REVISION\n1 0001-01-01 00:00:00 +0000 UTC 1a\n2 0001-01-01 00:00:00 +0000 UTC 2a\n3 0001-01-01 00:00:00 +0000 UTC 3a\n\nSOURCE test-2\nID DATE REVISION\n1 0001-01-01 00:00:00 +0000 UTC 1b\n2 0001-01-01 00:00:00 +0000 UTC 2b\n3 0001-01-01 00:00:00 +0000 UTC 3b\n"
|
||||
|
||||
require.Equalf(t, output, expectation, "Incorrect print operation output %q, should be %q", output, expectation)
|
||||
if output != expectation {
|
||||
t.Fatalf("Incorrect print operation output %q, should be %q", output, expectation)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintAppSummaryTable(t *testing.T) {
|
||||
@@ -879,7 +912,9 @@ func TestPrintAppConditions(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
expectation := "CONDITION\tMESSAGE\tLAST TRANSITION\nDeletionError\ttest\t<nil>\nExcludedResourceWarning\ttest2\t<nil>\nRepeatedResourceWarning\ttest3\t<nil>\n"
|
||||
require.Equalf(t, output, expectation, "Incorrect print app conditions output %q, should be %q", output, expectation)
|
||||
if output != expectation {
|
||||
t.Fatalf("Incorrect print app conditions output %q, should be %q", output, expectation)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintParams(t *testing.T) {
|
||||
@@ -956,7 +991,9 @@ func TestPrintParams(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
require.Equalf(t, tc.expectedOutput, output, "Incorrect print params output %q, should be %q\n", output, tc.expectedOutput)
|
||||
if output != tc.expectedOutput {
|
||||
t.Fatalf("Incorrect print params output %q, should be %q\n", output, tc.expectedOutput)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -968,7 +1005,9 @@ func TestAppUrlDefault(t *testing.T) {
|
||||
PlainText: true,
|
||||
}), "test")
|
||||
expectation := "http://localhost:80/applications/test"
|
||||
require.Equalf(t, result, expectation, "Incorrect url %q, should be %q", result, expectation)
|
||||
if result != expectation {
|
||||
t.Fatalf("Incorrect url %q, should be %q", result, expectation)
|
||||
}
|
||||
})
|
||||
t.Run("https", func(t *testing.T) {
|
||||
result := appURLDefault(argocdclient.NewClientOrDie(&argocdclient.ClientOptions{
|
||||
@@ -976,14 +1015,18 @@ func TestAppUrlDefault(t *testing.T) {
|
||||
PlainText: false,
|
||||
}), "test")
|
||||
expectation := "https://localhost/applications/test"
|
||||
require.Equalf(t, result, expectation, "Incorrect url %q, should be %q", result, expectation)
|
||||
if result != expectation {
|
||||
t.Fatalf("Incorrect url %q, should be %q", result, expectation)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestTruncateString(t *testing.T) {
|
||||
result := truncateString("argocdtool", 2)
|
||||
expectation := "ar..."
|
||||
require.Equalf(t, result, expectation, "Incorrect truncate string %q, should be %q", result, expectation)
|
||||
if result != expectation {
|
||||
t.Fatalf("Incorrect truncate string %q, should be %q", result, expectation)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetService(t *testing.T) {
|
||||
@@ -997,7 +1040,9 @@ func TestGetService(t *testing.T) {
|
||||
}
|
||||
result := getServer(app)
|
||||
expectation := "test-server"
|
||||
require.Equal(t, result, expectation, "Incorrect server %q, should be %q", result, expectation)
|
||||
if result != expectation {
|
||||
t.Fatalf("Incorrect server %q, should be %q", result, expectation)
|
||||
}
|
||||
})
|
||||
t.Run("Name", func(t *testing.T) {
|
||||
app := &v1alpha1.Application{
|
||||
@@ -1009,7 +1054,9 @@ func TestGetService(t *testing.T) {
|
||||
}
|
||||
result := getServer(app)
|
||||
expectation := "test-name"
|
||||
require.Equal(t, result, expectation, "Incorrect server name %q, should be %q", result, expectation)
|
||||
if result != expectation {
|
||||
t.Fatalf("Incorrect server name %q, should be %q", result, expectation)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1023,9 +1070,17 @@ func TestTargetObjects(t *testing.T) {
|
||||
},
|
||||
}
|
||||
objects, err := targetObjects(resources)
|
||||
require.NoError(t, err, "operation should finish without error")
|
||||
require.Lenf(t, objects, 2, "incorrect number of objects %v, should be 2", len(objects))
|
||||
require.Equalf(t, "test-helm-guestbook", objects[0].GetName(), "incorrect name %q, should be %q", objects[0].GetName(), "test-helm-guestbook")
|
||||
if err != nil {
|
||||
t.Fatal("operation should finish without error")
|
||||
}
|
||||
|
||||
if len(objects) != 2 {
|
||||
t.Fatalf("incorrect number of objects %v, should be 2", len(objects))
|
||||
}
|
||||
|
||||
if objects[0].GetName() != "test-helm-guestbook" {
|
||||
t.Fatalf("incorrect name %q, should be %q", objects[0].GetName(), "test-helm-guestbook")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTargetObjects_invalid(t *testing.T) {
|
||||
@@ -1052,7 +1107,9 @@ func TestPrintApplicationNames(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
expectation := "test\ntest\n"
|
||||
require.Equalf(t, output, expectation, "Incorrect print params output %q, should be %q", output, expectation)
|
||||
if output != expectation {
|
||||
t.Fatalf("Incorrect print params output %q, should be %q", output, expectation)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_unset(t *testing.T) {
|
||||
@@ -1842,8 +1899,9 @@ func Test_hasAppChanged(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := hasAppChanged(tt.args.appReq, tt.args.appRes, tt.args.upsert)
|
||||
assert.Equalf(t, tt.want, got, "hasAppChanged() = %v, want %v", got, tt.want)
|
||||
if got := hasAppChanged(tt.args.appReq, tt.args.appRes, tt.args.upsert); got != tt.want {
|
||||
t.Errorf("hasAppChanged() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@ import (
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/admin"
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/utils"
|
||||
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
|
||||
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apiclient/applicationset"
|
||||
arogappsetv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/v2/util/argo"
|
||||
"github.com/argoproj/argo-cd/v2/util/cli"
|
||||
"github.com/argoproj/argo-cd/v2/util/errors"
|
||||
"github.com/argoproj/argo-cd/v2/util/grpc"
|
||||
argoio "github.com/argoproj/argo-cd/v2/util/io"
|
||||
@@ -93,6 +93,7 @@ func NewApplicationSetGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.
|
||||
errors.CheckError(err)
|
||||
case "wide", "":
|
||||
printAppSetSummaryTable(appSet)
|
||||
|
||||
if len(appSet.Status.Conditions) > 0 {
|
||||
fmt.Println()
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
@@ -344,21 +345,12 @@ func NewApplicationSetDeleteCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationSetClientOrDie()
|
||||
defer argoio.Close(conn)
|
||||
var isTerminal bool = isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
|
||||
var isConfirmAll bool = false
|
||||
numOfApps := len(args)
|
||||
promptFlag := c.Flag("yes")
|
||||
if promptFlag.Changed && promptFlag.Value.String() == "true" {
|
||||
noPrompt = true
|
||||
}
|
||||
|
||||
var (
|
||||
confirmAll = false
|
||||
confirm = false
|
||||
)
|
||||
|
||||
// This is for backward compatibility,
|
||||
// before we showed the prompts only when condition isTerminal && !noPrompt is true
|
||||
promptUtil := utils.NewPrompt(isTerminal && !noPrompt)
|
||||
|
||||
for _, appSetQualifiedName := range args {
|
||||
appSetName, appSetNs := argo.ParseFromQualifiedName(appSetQualifiedName, "")
|
||||
|
||||
@@ -366,17 +358,32 @@ func NewApplicationSetDeleteCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
Name: appSetName,
|
||||
AppsetNamespace: appSetNs,
|
||||
}
|
||||
messageForSingle := "Are you sure you want to delete '" + appSetQualifiedName + "' and all its Applications? [y/n] "
|
||||
messageForAll := "Are you sure you want to delete '" + appSetQualifiedName + "' and all its Applications? [y/n/a] where 'a' is to delete all specified ApplicationSets and their Applications without prompting"
|
||||
if !confirmAll {
|
||||
confirm, confirmAll = promptUtil.ConfirmBaseOnCount(messageForSingle, messageForAll, numOfApps)
|
||||
}
|
||||
if confirm || confirmAll {
|
||||
|
||||
if isTerminal && !noPrompt {
|
||||
var lowercaseAnswer string
|
||||
if numOfApps == 1 {
|
||||
lowercaseAnswer = cli.AskToProceedS("Are you sure you want to delete '" + appSetQualifiedName + "' and all its Applications? [y/n] ")
|
||||
} else {
|
||||
if !isConfirmAll {
|
||||
lowercaseAnswer = cli.AskToProceedS("Are you sure you want to delete '" + appSetQualifiedName + "' and all its Applications? [y/n/A] where 'A' is to delete all specified ApplicationSets and their Applications without prompting")
|
||||
if lowercaseAnswer == "a" || lowercaseAnswer == "all" {
|
||||
lowercaseAnswer = "y"
|
||||
isConfirmAll = true
|
||||
}
|
||||
} else {
|
||||
lowercaseAnswer = "y"
|
||||
}
|
||||
}
|
||||
if lowercaseAnswer == "y" || lowercaseAnswer == "yes" {
|
||||
_, err := appIf.Delete(ctx, &appsetDeleteReq)
|
||||
errors.CheckError(err)
|
||||
fmt.Printf("applicationset '%s' deleted\n", appSetQualifiedName)
|
||||
} else {
|
||||
fmt.Println("The command to delete '" + appSetQualifiedName + "' was cancelled.")
|
||||
}
|
||||
} else {
|
||||
_, err := appIf.Delete(ctx, &appsetDeleteReq)
|
||||
errors.CheckError(err)
|
||||
fmt.Printf("applicationset '%s' deleted\n", appSetQualifiedName)
|
||||
} else {
|
||||
fmt.Println("The command to delete '" + appSetQualifiedName + "' was cancelled.")
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -434,6 +441,7 @@ func getServerForAppSet(appSet *arogappsetv1.ApplicationSet) string {
|
||||
}
|
||||
|
||||
func printAppSetSummaryTable(appSet *arogappsetv1.ApplicationSet) {
|
||||
source := appSet.Spec.Template.Spec.GetSource()
|
||||
fmt.Printf(printOpFmtStr, "Name:", appSet.QualifiedName())
|
||||
fmt.Printf(printOpFmtStr, "Project:", appSet.Spec.Template.Spec.GetProject())
|
||||
fmt.Printf(printOpFmtStr, "Server:", getServerForAppSet(appSet))
|
||||
@@ -443,17 +451,7 @@ func printAppSetSummaryTable(appSet *arogappsetv1.ApplicationSet) {
|
||||
} else {
|
||||
fmt.Println("Sources:")
|
||||
}
|
||||
|
||||
// if no source has been defined, print the default value for a source
|
||||
if len(appSet.Spec.Template.Spec.GetSources()) == 0 {
|
||||
src := appSet.Spec.Template.Spec.GetSource()
|
||||
printAppSourceDetails(&src)
|
||||
} else {
|
||||
// otherwise range over the sources and print each source details
|
||||
for _, source := range appSet.Spec.Template.Spec.GetSources() {
|
||||
printAppSourceDetails(&source)
|
||||
}
|
||||
}
|
||||
printAppSourceDetails(&source)
|
||||
|
||||
var (
|
||||
syncPolicyStr string
|
||||
|
||||
@@ -29,7 +29,9 @@ func TestPrintApplicationSetNames(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
expectation := "test\nteam-one/test\n"
|
||||
require.Equalf(t, output, expectation, "Incorrect print params output %q, should be %q", output, expectation)
|
||||
if output != expectation {
|
||||
t.Fatalf("Incorrect print params output %q, should be %q", output, expectation)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintApplicationSetTable(t *testing.T) {
|
||||
@@ -145,26 +147,6 @@ func TestPrintAppSetSummaryTable(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
appsetSpecSource := baseAppSet.DeepCopy()
|
||||
appsetSpecSource.Spec.Template.Spec.Source = &v1alpha1.ApplicationSource{
|
||||
RepoURL: "test1",
|
||||
TargetRevision: "master1",
|
||||
Path: "/test1",
|
||||
}
|
||||
|
||||
appsetSpecSources := baseAppSet.DeepCopy()
|
||||
appsetSpecSources.Spec.Template.Spec.Sources = v1alpha1.ApplicationSources{
|
||||
{
|
||||
RepoURL: "test1",
|
||||
TargetRevision: "master1",
|
||||
Path: "/test1",
|
||||
},
|
||||
{
|
||||
RepoURL: "test2",
|
||||
TargetRevision: "master2",
|
||||
Path: "/test2",
|
||||
},
|
||||
}
|
||||
|
||||
appsetSpecSyncPolicy := baseAppSet.DeepCopy()
|
||||
appsetSpecSyncPolicy.Spec.SyncPolicy = &v1alpha1.ApplicationSetSyncPolicy{
|
||||
@@ -230,37 +212,6 @@ Source:
|
||||
- Repo:
|
||||
Target:
|
||||
SyncPolicy: Automated
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "appset with a single source",
|
||||
appSet: appsetSpecSource,
|
||||
expectedOutput: `Name: app-name
|
||||
Project: default
|
||||
Server:
|
||||
Namespace:
|
||||
Source:
|
||||
- Repo: test1
|
||||
Target: master1
|
||||
Path: /test1
|
||||
SyncPolicy: <none>
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "appset with a multiple sources",
|
||||
appSet: appsetSpecSources,
|
||||
expectedOutput: `Name: app-name
|
||||
Project: default
|
||||
Server:
|
||||
Namespace:
|
||||
Sources:
|
||||
- Repo: test1
|
||||
Target: master1
|
||||
Path: /test1
|
||||
- Repo: test2
|
||||
Target: master2
|
||||
Path: /test2
|
||||
SyncPolicy: <none>
|
||||
`,
|
||||
},
|
||||
} {
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/utils"
|
||||
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
|
||||
certificatepkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/certificate"
|
||||
appsv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
@@ -237,26 +236,19 @@ func NewCertRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
|
||||
err := fmt.Errorf("A single wildcard is not allowed as REPOSERVER name.")
|
||||
errors.CheckError(err)
|
||||
}
|
||||
|
||||
promptUtil := utils.NewPrompt(clientOpts.PromptsEnabled)
|
||||
canDelete := promptUtil.Confirm(fmt.Sprintf("Are you sure you want to remove all certificates for '%s'? [y/n]", hostNamePattern))
|
||||
if canDelete {
|
||||
certQuery = certificatepkg.RepositoryCertificateQuery{
|
||||
HostNamePattern: hostNamePattern,
|
||||
CertType: certType,
|
||||
CertSubType: certSubType,
|
||||
}
|
||||
removed, err := certIf.DeleteCertificate(ctx, &certQuery)
|
||||
errors.CheckError(err)
|
||||
if len(removed.Items) > 0 {
|
||||
for _, cert := range removed.Items {
|
||||
fmt.Printf("Removed cert for '%s' of type '%s' (subtype '%s')\n", cert.ServerName, cert.CertType, cert.CertSubType)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("No certificates were removed (none matched the given pattern)")
|
||||
certQuery = certificatepkg.RepositoryCertificateQuery{
|
||||
HostNamePattern: hostNamePattern,
|
||||
CertType: certType,
|
||||
CertSubType: certSubType,
|
||||
}
|
||||
removed, err := certIf.DeleteCertificate(ctx, &certQuery)
|
||||
errors.CheckError(err)
|
||||
if len(removed.Items) > 0 {
|
||||
for _, cert := range removed.Items {
|
||||
fmt.Printf("Removed cert for '%s' of type '%s' (subtype '%s')\n", cert.ServerName, cert.CertType, cert.CertSubType)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("The command to remove all certificates for '%s' was cancelled.\n", hostNamePattern)
|
||||
fmt.Println("No certificates were removed (none matched the given patterns)")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -107,11 +106,6 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
|
||||
contextName := args[0]
|
||||
conf, err := getRestConfig(pathOpts, contextName)
|
||||
errors.CheckError(err)
|
||||
if clusterOpts.ProxyUrl != "" {
|
||||
u, err := argoappv1.ParseProxyUrl(clusterOpts.ProxyUrl)
|
||||
errors.CheckError(err)
|
||||
conf.Proxy = http.ProxyURL(u)
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(conf)
|
||||
errors.CheckError(err)
|
||||
managerBearerToken := ""
|
||||
@@ -192,12 +186,11 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
|
||||
}
|
||||
command.PersistentFlags().StringVar(&pathOpts.LoadingRules.ExplicitPath, pathOpts.ExplicitFileFlag, pathOpts.LoadingRules.ExplicitPath, "use a particular kubeconfig file")
|
||||
command.Flags().BoolVar(&clusterOpts.Upsert, "upsert", false, "Override an existing cluster with the same name even if the spec differs")
|
||||
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default %q SA will be created", clusterauth.ArgoCDManagerServiceAccount))
|
||||
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default \"%s\" SA will be created", clusterauth.ArgoCDManagerServiceAccount))
|
||||
command.Flags().StringVar(&clusterOpts.SystemNamespace, "system-namespace", common.DefaultSystemNamespace, "Use different system namespace")
|
||||
command.Flags().BoolVarP(&skipConfirmation, "yes", "y", false, "Skip explicit confirmation")
|
||||
command.Flags().StringArrayVar(&labels, "label", nil, "Set metadata labels (e.g. --label key=value)")
|
||||
command.Flags().StringArrayVar(&annotations, "annotation", nil, "Set metadata annotations (e.g. --annotation key=value)")
|
||||
command.Flags().StringVar(&clusterOpts.ProxyUrl, "proxy-url", "", "use proxy to connect cluster")
|
||||
cmdutil.AddClusterFlags(command, &clusterOpts)
|
||||
return command
|
||||
}
|
||||
@@ -380,8 +373,6 @@ func printClusterDetails(clusters []argoappv1.Cluster) {
|
||||
fmt.Printf(" Basic authentication: %v\n", cluster.Config.Username != "")
|
||||
fmt.Printf(" oAuth authentication: %v\n", cluster.Config.BearerToken != "")
|
||||
fmt.Printf(" AWS authentication: %v\n", cluster.Config.AWSAuthConfig != nil)
|
||||
fmt.Printf("\nDisable compression: %v\n", cluster.Config.DisableCompression)
|
||||
fmt.Printf("\nUse proxy: %v\n", cluster.Config.ProxyUrl != "")
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,11 @@ func Test_printClusterTable(t *testing.T) {
|
||||
Server: "my-server",
|
||||
Name: "my-name",
|
||||
Config: v1alpha1.ClusterConfig{
|
||||
Username: "my-username",
|
||||
Password: "my-password",
|
||||
BearerToken: "my-bearer-token",
|
||||
TLSClientConfig: v1alpha1.TLSClientConfig{},
|
||||
AWSAuthConfig: nil,
|
||||
DisableCompression: false,
|
||||
Username: "my-username",
|
||||
Password: "my-password",
|
||||
BearerToken: "my-bearer-token",
|
||||
TLSClientConfig: v1alpha1.TLSClientConfig{},
|
||||
AWSAuthConfig: nil,
|
||||
},
|
||||
ConnectionState: v1alpha1.ConnectionState{
|
||||
Status: "my-status",
|
||||
@@ -98,12 +97,12 @@ func Test_getRestConfig(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := getRestConfig(tt.args.pathOpts, tt.args.ctxName)
|
||||
if tt.wantErr {
|
||||
require.EqualError(t, err, tt.expectedErr)
|
||||
} else {
|
||||
require.NoErrorf(t, err, "An unexpected error occurred during test %s", tt.name)
|
||||
if got, err := getRestConfig(tt.args.pathOpts, tt.args.ctxName); err == nil {
|
||||
require.Equal(t, tt.expected, got)
|
||||
} else if tt.wantErr {
|
||||
require.Equal(t, tt.expectedErr, err.Error())
|
||||
} else {
|
||||
t.Errorf("An unexpected error occurred during test %s:\n%s", tt.name, err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -81,14 +81,14 @@ func Test_PrintResource(t *testing.T) {
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.YAMLEq(t, expectYamlSingle, str)
|
||||
assert.Equal(t, expectYamlSingle, str)
|
||||
|
||||
str, err = captureOutput(func() error {
|
||||
err := PrintResource(testResource, "json")
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, expectJsonSingle, str)
|
||||
assert.Equal(t, expectJsonSingle, str)
|
||||
|
||||
err = PrintResource(testResource, "unknown")
|
||||
require.Error(t, err)
|
||||
@@ -116,28 +116,28 @@ func Test_PrintResourceList(t *testing.T) {
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.YAMLEq(t, expectYamlList, str)
|
||||
assert.Equal(t, expectYamlList, str)
|
||||
|
||||
str, err = captureOutput(func() error {
|
||||
err := PrintResourceList(testResource, "json", false)
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, expectJsonList, str)
|
||||
assert.Equal(t, expectJsonList, str)
|
||||
|
||||
str, err = captureOutput(func() error {
|
||||
err := PrintResourceList(testResource2, "yaml", true)
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.YAMLEq(t, expectYamlSingle, str)
|
||||
assert.Equal(t, expectYamlSingle, str)
|
||||
|
||||
str, err = captureOutput(func() error {
|
||||
err := PrintResourceList(testResource2, "json", true)
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, expectJsonSingle, str)
|
||||
assert.Equal(t, expectJsonSingle, str)
|
||||
|
||||
err = PrintResourceList(testResource, "unknown", false)
|
||||
require.Error(t, err)
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
|
||||
"github.com/argoproj/argo-cd/v2/util/errors"
|
||||
"github.com/argoproj/argo-cd/v2/util/localconfig"
|
||||
)
|
||||
|
||||
// NewConfigureCommand returns a new instance of an `argocd configure` command
|
||||
func NewConfigureCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var promptsEnabled bool
|
||||
|
||||
command := &cobra.Command{
|
||||
Use: "configure",
|
||||
Short: "Manage local configuration",
|
||||
Example: `# Enable optional interactive prompts
|
||||
argocd configure --prompts-enabled
|
||||
argocd configure --prompts-enabled=true
|
||||
|
||||
# Disable optional interactive prompts
|
||||
argocd configure --prompts-enabled=false`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
localCfg, err := localconfig.ReadLocalConfig(globalClientOpts.ConfigPath)
|
||||
errors.CheckError(err)
|
||||
|
||||
localCfg.PromptsEnabled = promptsEnabled
|
||||
|
||||
err = localconfig.WriteLocalConfig(*localCfg, globalClientOpts.ConfigPath)
|
||||
errors.CheckError(err)
|
||||
|
||||
fmt.Println("Successfully updated the following configuration settings:")
|
||||
fmt.Printf("prompts-enabled: %v\n", strconv.FormatBool(localCfg.PromptsEnabled))
|
||||
},
|
||||
}
|
||||
|
||||
command.Flags().BoolVar(&promptsEnabled, "prompts-enabled", localconfig.GetPromptsEnabled(false), "Enable (or disable) optional interactive prompts")
|
||||
|
||||
return command
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/localconfig"
|
||||
)
|
||||
|
||||
func TestNewConfigureCommand_PromptsEnabled_DefaultTrue(t *testing.T) {
|
||||
// Write the test config file
|
||||
err := os.WriteFile(testConfigFilePath, []byte(testConfig), os.ModePerm)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer os.Remove(testConfigFilePath)
|
||||
|
||||
err = os.Chmod(testConfigFilePath, 0o600)
|
||||
require.NoError(t, err, "Could not change the file permission to 0600 %v", err)
|
||||
|
||||
localConfig, err := localconfig.ReadLocalConfig(testConfigFilePath)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, localConfig.PromptsEnabled)
|
||||
|
||||
// Set `PromptsEnabled` to `true` using `argocd configure --prompts-enabled`
|
||||
cmd := NewConfigureCommand(&argocdclient.ClientOptions{ConfigPath: testConfigFilePath})
|
||||
cmd.SetArgs([]string{"--prompts-enabled"})
|
||||
|
||||
err = cmd.Execute()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Read the test config file
|
||||
localConfig, err = localconfig.ReadLocalConfig(testConfigFilePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.True(t, localConfig.PromptsEnabled)
|
||||
}
|
||||
|
||||
func TestNewConfigureCommand_PromptsEnabled_True(t *testing.T) {
|
||||
// Write the test config file
|
||||
err := os.WriteFile(testConfigFilePath, []byte(testConfig), os.ModePerm)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer os.Remove(testConfigFilePath)
|
||||
|
||||
err = os.Chmod(testConfigFilePath, 0o600)
|
||||
require.NoError(t, err, "Could not change the file permission to 0600 %v", err)
|
||||
|
||||
localConfig, err := localconfig.ReadLocalConfig(testConfigFilePath)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, localConfig.PromptsEnabled)
|
||||
|
||||
// Set `PromptsEnabled` to `true` using `argocd configure --prompts-enabled=true`
|
||||
cmd := NewConfigureCommand(&argocdclient.ClientOptions{ConfigPath: testConfigFilePath})
|
||||
cmd.SetArgs([]string{"--prompts-enabled=true"})
|
||||
|
||||
err = cmd.Execute()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Read the test config file
|
||||
localConfig, err = localconfig.ReadLocalConfig(testConfigFilePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.True(t, localConfig.PromptsEnabled)
|
||||
}
|
||||
|
||||
func TestNewConfigureCommand_PromptsEnabled_False(t *testing.T) {
|
||||
// Write the test config file
|
||||
err := os.WriteFile(testConfigFilePath, []byte(testConfig), os.ModePerm)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer os.Remove(testConfigFilePath)
|
||||
|
||||
err = os.Chmod(testConfigFilePath, 0o600)
|
||||
require.NoError(t, err, "Could not change the file permission to 0600 %v", err)
|
||||
|
||||
localConfig, err := localconfig.ReadLocalConfig(testConfigFilePath)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, localConfig.PromptsEnabled)
|
||||
|
||||
// Set `PromptsEnabled` to `false` using `argocd configure --prompts-enabled=false`
|
||||
cmd := NewConfigureCommand(&argocdclient.ClientOptions{ConfigPath: testConfigFilePath})
|
||||
cmd.SetArgs([]string{"--prompts-enabled=false"})
|
||||
|
||||
err = cmd.Execute()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Read the test config file
|
||||
localConfig, err = localconfig.ReadLocalConfig(testConfigFilePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.False(t, localConfig.PromptsEnabled)
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
|
||||
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/utils"
|
||||
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
|
||||
gpgkeypkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/gpgkey"
|
||||
appsv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
@@ -168,21 +167,11 @@ func NewGPGDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
|
||||
if len(args) != 1 {
|
||||
errors.CheckError(fmt.Errorf("Missing KEYID argument"))
|
||||
}
|
||||
|
||||
keyId := args[0]
|
||||
|
||||
conn, gpgIf := headless.NewClientOrDie(clientOpts, c).NewGPGKeyClientOrDie()
|
||||
defer argoio.Close(conn)
|
||||
|
||||
promptUtil := utils.NewPrompt(clientOpts.PromptsEnabled)
|
||||
canDelete := promptUtil.Confirm(fmt.Sprintf("Are you sure you want to remove '%s'? [y/n] ", keyId))
|
||||
if canDelete {
|
||||
_, err := gpgIf.Delete(ctx, &gpgkeypkg.GnuPGPublicKeyQuery{KeyID: keyId})
|
||||
errors.CheckError(err)
|
||||
fmt.Printf("Deleted key with key ID %s\n", keyId)
|
||||
} else {
|
||||
fmt.Printf("The command to delete key with key ID '%s' was cancelled.\n", keyId)
|
||||
}
|
||||
_, err := gpgIf.Delete(ctx, &gpgkeypkg.GnuPGPublicKeyQuery{KeyID: args[0]})
|
||||
errors.CheckError(err)
|
||||
fmt.Printf("Deleted key with key ID %s\n", args[0])
|
||||
},
|
||||
}
|
||||
return command
|
||||
|
||||
@@ -14,7 +14,8 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
runtimeUtil "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/dynamic"
|
||||
@@ -128,7 +129,7 @@ func (c *forwardRepoClientset) NewRepoServerClient() (io.Closer, repoapiclient.R
|
||||
}
|
||||
repoServerName := c.repoServerName
|
||||
repoServererviceLabelSelector := common.LabelKeyComponentRepoServer + "=" + common.LabelValueComponentRepoServer
|
||||
repoServerServices, err := c.kubeClientset.CoreV1().Services(c.namespace).List(context.Background(), v1.ListOptions{LabelSelector: repoServererviceLabelSelector})
|
||||
repoServerServices, err := c.kubeClientset.CoreV1().Services(c.namespace).List(context.Background(), metaV1.ListOptions{LabelSelector: repoServererviceLabelSelector})
|
||||
if err != nil {
|
||||
c.err = err
|
||||
return
|
||||
@@ -243,6 +244,10 @@ func MaybeStartLocalServer(ctx context.Context, clientOpts *apiclient.ClientOpti
|
||||
if err != nil {
|
||||
return fmt.Errorf("error adding argo resources to scheme: %w", err)
|
||||
}
|
||||
err = corev1.AddToScheme(scheme)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error adding corev1 resources to scheme: %w", err)
|
||||
}
|
||||
controllerClientset, err := client.New(restConfig, client.Options{
|
||||
Scheme: scheme,
|
||||
})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user