Compare commits

...

1 Commits

Author SHA1 Message Date
Justin Marquis
b17068c1c1 sibling of 020881af84 2024-06-10 19:06:27 +00:00
643 changed files with 43148 additions and 55712 deletions

View File

@@ -17,11 +17,6 @@ updates:
schedule:
interval: "daily"
- package-ecosystem: "npm"
directory: "/ui-test/"
schedule:
interval: "daily"
- package-ecosystem: "docker"
directory: "/"
schedule:

View File

@@ -6,10 +6,9 @@
| codeql.yaml | CodeQL analysis |
| image-reuse.yaml | Build, push, and Sign container images |
| image.yaml | Build container image for PR's & publish for push events |
| init-release.yaml | Build manifests and version then create a PR for release branch|
| pr-title-check.yaml| Lint PR for semantic information |
| init-release.yaml | Build manifests and version then create a PR for release branch|
| release.yaml | Build images, cli-binaries, provenances, and post actions |
| scorecard.yaml | Generate scorecard for supply-chain security |
| update-snyk.yaml | Scheduled snyk reports |
# Reusable workflows

View File

@@ -13,7 +13,7 @@ on:
env:
# Golang version to use across CI steps
GOLANG_VERSION: '1.22'
GOLANG_VERSION: '1.21'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -28,7 +28,6 @@ jobs:
outputs:
backend: ${{ steps.filter.outputs.backend_any_changed }}
frontend: ${{ steps.filter.outputs.frontend_any_changed }}
docs: ${{ steps.filter.outputs.docs_any_changed }}
steps:
- uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- uses: tj-actions/changed-files@90a06d6ba9543371ab4df8eeca0be07ca6054959 # v42.0.2
@@ -44,8 +43,6 @@ jobs:
frontend:
- 'ui/**'
- Dockerfile
docs:
- 'docs/**'
check-go:
name: Ensure Go modules synchronicity
if: ${{ needs.changes.outputs.backend == 'true' }}
@@ -56,7 +53,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.0.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Download all Go modules
@@ -77,11 +74,11 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.0.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Restore go build cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -104,14 +101,14 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.0.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Run golangci-lint
uses: golangci/golangci-lint-action@a4f60bb28d35aeee14e6880718e0c85ff1882e64 # v6.0.1
uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0
with:
version: v1.58.2
args: --verbose
version: v1.54.0
args: --enable gofmt --timeout 10m --exclude SA5011 --verbose --max-issues-per-linter 0 --max-same-issues 0
test-go:
name: Run unit tests for Go packages
@@ -131,7 +128,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@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.0.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -151,7 +148,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -172,12 +169,12 @@ jobs:
- name: Run all unit tests
run: make test-local
- name: Generate code coverage artifacts
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: code-coverage
path: coverage.out
- name: Generate test results artifacts
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: test-results
path: test-results/
@@ -200,7 +197,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@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.0.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -220,7 +217,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -241,14 +238,14 @@ jobs:
- name: Run all unit tests
run: make test-race-local
- name: Generate test results artifacts
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: race-results
path: test-results/
codegen:
name: Check changes to generated code
if: ${{ needs.changes.outputs.backend == 'true' || needs.changes.outputs.docs == 'true'}}
if: ${{ needs.changes.outputs.backend == 'true' }}
runs-on: ubuntu-22.04
needs:
- changes
@@ -256,7 +253,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.0.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Create symlink in GOPATH
@@ -299,8 +296,7 @@ jobs:
build-ui:
name: Build, test & lint UI code
# We run UI logic for backend changes so that we have a complete set of coverage documents to send to codecov.
if: ${{ needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' }}
if: ${{ needs.changes.outputs.frontend == 'true' }}
runs-on: ubuntu-22.04
needs:
- changes
@@ -308,12 +304,12 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup NodeJS
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
with:
node-version: '21.6.1'
- name: Restore node dependency cache
id: cache-dependencies
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
@@ -350,7 +346,7 @@ jobs:
fetch-depth: 0
- name: Restore node dependency cache
id: cache-dependencies
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
@@ -361,27 +357,46 @@ jobs:
run: |
mkdir -p test-results
- name: Get code coverage artifact
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
name: code-coverage
- name: Get test result artifact
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
name: test-results
path: test-results
- name: Upload code coverage information to codecov.io
uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1
uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
with:
file: coverage.out
fail_ci_if_error: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Perform static code analysis using SonarCloud
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
uses: SonarSource/sonarqube-scan-action@86fe81775628f1c6349c28baab87881a2170f495 # v2.1.0
SCANNER_VERSION: 4.2.0.1873
SCANNER_PATH: /tmp/cache/scanner
OS: linux
run: |
# We do not use the provided action, because it does contain an old
# version of the scanner, and also takes time to build.
set -e
mkdir -p ${SCANNER_PATH}
export SONAR_USER_HOME=${SCANNER_PATH}/.sonar
if [[ ! -x "${SCANNER_PATH}/sonar-scanner-${SCANNER_VERSION}-${OS}/bin/sonar-scanner" ]]; then
curl -Ol https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SCANNER_VERSION}-${OS}.zip
unzip -qq -o sonar-scanner-cli-${SCANNER_VERSION}-${OS}.zip -d ${SCANNER_PATH}
fi
chmod +x ${SCANNER_PATH}/sonar-scanner-${SCANNER_VERSION}-${OS}/bin/sonar-scanner
chmod +x ${SCANNER_PATH}/sonar-scanner-${SCANNER_VERSION}-${OS}/jre/bin/java
# Explicitly set NODE_MODULES
export NODE_MODULES=${PWD}/ui/node_modules
export NODE_PATH=${PWD}/ui/node_modules
${SCANNER_PATH}/sonar-scanner-${SCANNER_VERSION}-${OS}/bin/sonar-scanner
if: env.sonar_secret != ''
test-e2e:
name: Run end-to-end tests
if: ${{ needs.changes.outputs.backend == 'true' }}
@@ -410,7 +425,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.0.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: GH actions workaround - Kill XSP4 process
@@ -429,7 +444,7 @@ jobs:
sudo chmod go-r $HOME/.kube/config
kubectl version
- name: Restore go build cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -457,7 +472,7 @@ jobs:
run: |
docker pull ghcr.io/dexidp/dex:v2.38.0
docker pull argoproj/argo-cd-ci-builder:v1.0.0
docker pull redis:7.0.15-alpine
docker pull redis:7.0.14-alpine
- name: Create target directory for binaries in the build-process
run: |
mkdir -p dist
@@ -485,7 +500,7 @@ jobs:
set -x
make test-e2e-local
- name: Upload e2e-server logs
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: e2e-server-k8s${{ matrix.k3s-version }}.log
path: /tmp/e2e-server.log
@@ -512,4 +527,4 @@ jobs:
exit 0
else
exit 1
fi
fi

View File

@@ -33,13 +33,13 @@ jobs:
# Use correct go version. https://github.com/github/codeql-action/issues/1842#issuecomment-1704398087
- name: Setup Golang
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.0.0
with:
go-version-file: go.mod
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@8fcfedf57053e09257688fce7a0beeb18b1b9ae3 # v2.17.2
uses: github/codeql-action/init@8aff97f12c99086bdb92ff62ae06dbbcdf07941b # v2.1.33
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
@@ -47,7 +47,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@8fcfedf57053e09257688fce7a0beeb18b1b9ae3 # v2.17.2
uses: github/codeql-action/autobuild@8aff97f12c99086bdb92ff62ae06dbbcdf07941b # v2.1.33
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -61,4 +61,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@8fcfedf57053e09257688fce7a0beeb18b1b9ae3 # v2.17.2
uses: github/codeql-action/analyze@8aff97f12c99086bdb92ff62ae06dbbcdf07941b # v2.1.33

View File

@@ -69,14 +69,14 @@ jobs:
if: ${{ github.ref_type != 'tag'}}
- name: Setup Golang
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
go-version: ${{ inputs.go-version }}
- name: Install cosign
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4 # v3.4.0
- uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
- uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
- uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Setup tags for container image as a CSV type
@@ -104,7 +104,7 @@ jobs:
echo 'EOF' >> $GITHUB_ENV
- name: Login to Quay.io
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
registry: quay.io
username: ${{ secrets.quay_username }}
@@ -112,7 +112,7 @@ jobs:
if: ${{ inputs.quay_image_name && inputs.push }}
- name: Login to GitHub Container Registry
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
registry: ghcr.io
username: ${{ secrets.ghcr_username }}
@@ -120,7 +120,7 @@ jobs:
if: ${{ inputs.ghcr_image_name && inputs.push }}
- name: Login to dockerhub Container Registry
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
username: ${{ secrets.docker_username }}
password: ${{ secrets.docker_password }}
@@ -134,7 +134,7 @@ jobs:
echo "GIT_TREE_STATE=$(if [ -z "`git status --porcelain`" ]; then echo "clean" ; else echo "dirty"; fi)" >> $GITHUB_ENV
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
uses: jlumbroso/free-disk-space@4d9e71b726748f254fe64fa44d273194bd18ec91
with:
large-packages: false
docker-images: false

View File

@@ -52,7 +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)
go-version: 1.22
go-version: 1.21
platforms: ${{ needs.set-vars.outputs.platforms }}
push: false
@@ -68,7 +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)
go-version: 1.22
go-version: 1.21
platforms: ${{ needs.set-vars.outputs.platforms }}
push: true
secrets:
@@ -86,7 +86,7 @@ jobs:
packages: write # for uploading attestations. (https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#known-issues)
if: ${{ github.repository == 'argoproj/argo-cd' && github.event_name == 'push' }}
# 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_container_slsa3.yml@v2.0.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.10.0
with:
image: ghcr.io/argoproj/argo-cd/argocd
digest: ${{ needs.build-and-publish.outputs.image-digest }}

View File

@@ -64,7 +64,7 @@ jobs:
git stash pop
- name: Create pull request
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5
uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5.0.2
with:
commit-message: "Bump version to ${{ inputs.TARGET_VERSION }}"
title: "Bump version to ${{ inputs.TARGET_VERSION }} on ${{ inputs.TARGET_BRANCH }} branch"

View File

@@ -23,7 +23,7 @@ jobs:
name: Validate PR Title
runs-on: ubuntu-latest
steps:
- uses: thehanimo/pr-title-checker@1d8cd483a2b73118406a187f54dca8a9415f1375 # v1.4.2
- uses: thehanimo/pr-title-checker@0cf5902181e78341bb97bb06646396e5bd354b3f # v1.4.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
configuration_path: ".github/pr-title-checker-config.json"

View File

@@ -10,7 +10,7 @@ on:
permissions: {}
env:
GOLANG_VERSION: '1.22' # Note: go-version must also be set in job argocd-image.with.go-version
GOLANG_VERSION: '1.21' # Note: go-version must also be set in job argocd-image.with.go-version
jobs:
argocd-image:
@@ -23,7 +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)
go-version: 1.22
go-version: 1.21
platforms: linux/amd64,linux/arm64,linux/s390x,linux/ppc64le
push: true
secrets:
@@ -38,7 +38,7 @@ jobs:
packages: write # for uploading attestations. (https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#known-issues)
# 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
if: github.repository == 'argoproj/argo-cd'
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.10.0
with:
image: quay.io/argoproj/argocd
digest: ${{ needs.argocd-image.outputs.image-digest }}
@@ -77,7 +77,7 @@ jobs:
fi
- name: Setup Golang
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.0.0
with:
go-version: ${{ env.GOLANG_VERSION }}
@@ -88,7 +88,7 @@ jobs:
echo "GIT_TREE_STATE=$(if [ -z "`git status --porcelain`" ]; then echo "clean" ; else echo "dirty"; fi)" >> $GITHUB_ENV
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
uses: jlumbroso/free-disk-space@4d9e71b726748f254fe64fa44d273194bd18ec91
with:
large-packages: false
docker-images: false
@@ -96,7 +96,7 @@ jobs:
tool-cache: false
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0
id: run-goreleaser
with:
version: latest
@@ -128,7 +128,7 @@ jobs:
contents: write # Needed for release uploads
if: github.repository == 'argoproj/argo-cd'
# 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
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.10.0
with:
base64-subjects: "${{ needs.goreleaser.outputs.hashes }}"
provenance-name: "argocd-cli.intoto.jsonl"
@@ -153,7 +153,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Golang
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
go-version: ${{ env.GOLANG_VERSION }}
@@ -197,7 +197,7 @@ jobs:
echo "hashes=$(sha256sum /tmp/sbom.tar.gz | base64 -w0)" >> "$GITHUB_OUTPUT"
- name: Upload SBOM
uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # v2.0.5
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
@@ -212,7 +212,7 @@ jobs:
contents: write # Needed for release uploads
if: github.repository == 'argoproj/argo-cd'
# 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
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.10.0
with:
base64-subjects: "${{ needs.generate-sbom.outputs.hashes }}"
provenance-name: "argocd-sbom.intoto.jsonl"
@@ -295,7 +295,7 @@ jobs:
if: ${{ env.UPDATE_VERSION == 'true' }}
- name: Create PR to update VERSION on master branch
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5
uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5.0.2
with:
commit-message: Bump version in master
title: "chore: Bump version in master"

View File

@@ -35,7 +35,7 @@ jobs:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with:
results_file: results.sarif
results_format: sarif
@@ -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@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: SARIF file
path: results.sarif
@@ -62,6 +62,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@8fcfedf57053e09257688fce7a0beeb18b1b9ae3 # v2.17.2
uses: github/codeql-action/upload-sarif@83a02f7883b12e0e4e1a146174f5e2292a01e601 # v2.16.4
with:
sarif_file: results.sarif

1
.gitignore vendored
View File

@@ -19,7 +19,6 @@ node_modules/
./test/cmp/*.sock
.envrc.remote
.*.swp
rerunreport.txt
# ignore built binaries
cmd/argocd/argocd

2
.gitpod.Dockerfile vendored
View File

@@ -1,4 +1,4 @@
FROM gitpod/workspace-full@sha256:8dd34e72ae5b9e6f60d267dd6287befc2cf5ad1a11c64e9d93daa60c952a2154
FROM gitpod/workspace-full@sha256:511cecde4dc129ca9eb4cc4c479d61f95e5485ebe320a07f5b902f11899956a3
USER root

View File

@@ -1,37 +0,0 @@
issues:
exclude:
- SA5011
exclude-rules:
- path: "(applicationset|cmd|cmpserver|controller|reposerver|server|util)/"
linters:
- errorlint
max-issues-per-linter: 0
max-same-issues: 0
linters:
enable:
- errcheck
- errorlint
- gofmt
- goimports
- gosimple
- govet
- ineffassign
- misspell
- staticcheck
- testifylint
- unused
linters-settings:
goimports:
local-prefixes: github.com/argoproj/argo-cd/v2
testifylint:
enable-all: true
disable:
- compares
- error-is-as
- expected-actual
- float-compare
- go-require
- nil-compare
- require-error
run:
timeout: 50m

View File

@@ -1,5 +1,3 @@
version: 2
project_name: argocd
before:

View File

@@ -1,10 +1,10 @@
ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:3f85b7caad41a95462cf5b787d8a04604c8262cdcdf9a472b8c52ef83375fe15
ARG BASE_IMAGE=docker.io/library/ubuntu:22.04@sha256:0bced47fffa3361afa981854fcabcd4577cd43cebbb808cea2b1f33a3dd7f508
####################################################################################################
# Builder image
# 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.22.4@sha256:969349b8121a56d51c74f4c273ab974c15b3a8ae246a5cffc1df7d28b66cf978 AS builder
FROM docker.io/library/golang:1.21.10@sha256:16438a8e66c0c984f732e815ee5b7d715b8e33e81bac6d6a3750b1067744e7ca 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:22.2.0@sha256:a8ba58f54e770a0f910ec36d25f8a4f1670e741a58c2e6358b2c30b575c84263 AS argocd-ui
FROM --platform=$BUILDPLATFORM docker.io/library/node:21.6.2@sha256:65998e325b06014d4f1417a8a6afb1540d1ac66521cca76f2221a6953947f9ee 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.22.4@sha256:969349b8121a56d51c74f4c273ab974c15b3a8ae246a5cffc1df7d28b66cf978 AS argocd-build
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21.10@sha256:16438a8e66c0c984f732e815ee5b7d715b8e33e81bac6d6a3750b1067744e7ca AS argocd-build
WORKDIR /go/src/github.com/argoproj/argo-cd

View File

@@ -188,7 +188,7 @@ all: cli image
.PHONY: gogen
gogen:
export GO111MODULE=off
go generate ./...
go generate ./util/argo/...
.PHONY: protogen
protogen: mod-vendor-local protogen-fast
@@ -357,7 +357,7 @@ lint-local:
golangci-lint --version
# NOTE: If you get a "Killed" OOM message, try reducing the value of GOGC
# See https://github.com/golangci/golangci-lint#memory-usage-of-golangci-lint
GOGC=$(ARGOCD_LINT_GOGC) GOMAXPROCS=2 golangci-lint run --fix --verbose
GOGC=$(ARGOCD_LINT_GOGC) GOMAXPROCS=2 golangci-lint run --enable gofmt --fix --verbose --timeout 3000s --max-issues-per-linter 0 --max-same-issues 0
.PHONY: lint-ui
lint-ui: test-tools-image
@@ -494,7 +494,6 @@ start-local: mod-vendor-local dep-ui-local cli-local
mkdir -p /tmp/argocd-local
mkdir -p /tmp/argocd-local/gpg/keys && chmod 0700 /tmp/argocd-local/gpg/keys
mkdir -p /tmp/argocd-local/gpg/source
REDIS_PASSWORD=$(shell kubectl get secret argocd-redis -o jsonpath='{.data.auth}' | base64 -d) \
ARGOCD_ZJWT_FEATURE_FLAG=always \
ARGOCD_IN_CI=false \
ARGOCD_GPG_ENABLED=$(ARGOCD_GPG_ENABLED) \

View File

@@ -18,11 +18,9 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Albert Heijn](https://ah.nl/)
1. [Alibaba Group](https://www.alibabagroup.com/)
1. [Allianz Direct](https://www.allianzdirect.de/)
1. [AlphaSense](https://www.alpha-sense.com/)
1. [Amadeus IT Group](https://amadeus.com/)
1. [Ambassador Labs](https://www.getambassador.io/)
1. [Ancestry](https://www.ancestry.com/)
1. [Andgo Systems](https://www.andgosystems.com/)
1. [ANSTO - Australian Synchrotron](https://www.synchrotron.org.au/)
1. [Ant Group](https://www.antgroup.com/)
1. [AppDirect](https://www.appdirect.com)
@@ -37,14 +35,12 @@ Currently, the following organizations are **officially** using Argo CD:
1. [BCDevExchange DevOps Platform](https://bcdevexchange.org/DevOpsPlatform)
1. [Beat](https://thebeat.co/en/)
1. [Beez Innovation Labs](https://www.beezlabs.com/)
1. [Bedag Informatik AG](https://www.bedag.ch/)
1. [Beleza Na Web](https://www.belezanaweb.com.br/)
1. [BigPanda](https://bigpanda.io)
1. [BioBox Analytics](https://biobox.io)
1. [BMW Group](https://www.bmwgroup.com/)
1. [Boozt](https://www.booztgroup.com/)
1. [Boticario](https://www.boticario.com.br/)
1. [Broker Consulting, a.s.](https://www.bcas.cz/en/)
1. [Bulder Bank](https://bulderbank.no)
1. [CAM](https://cam-inc.co.jp)
1. [Camptocamp](https://camptocamp.com)
@@ -62,14 +58,12 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Cisco ET&I](https://eti.cisco.com/)
1. [Cloud Posse](https://www.cloudposse.com/)
1. [Cloud Scale](https://cloudscaleinc.com/)
1. [CloudGeometry](https://www.cloudgeometry.io/)
1. [Cloudmate](https://cloudmt.co.kr/)
1. [Cloudogu](https://cloudogu.com/)
1. [Cobalt](https://www.cobalt.io/)
1. [Codefresh](https://www.codefresh.io/)
1. [Codility](https://www.codility.com/)
1. [Commonbond](https://commonbond.co/)
1. [Contlo](https://contlo.com/)
1. [Coralogix](https://coralogix.com/)
1. [Crédit Agricole CIB](https://www.ca-cib.com)
1. [CROZ d.o.o.](https://croz.net/)
@@ -138,7 +132,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [IABAI](https://www.iab.ai)
1. [IBM](https://www.ibm.com/)
1. [Ibotta](https://home.ibotta.com)
1. [IFS](https://www.ifs.com)
1. [IITS-Consulting](https://iits-consulting.de)
1. [IllumiDesk](https://www.illumidesk.com)
1. [imaware](https://imaware.health)
@@ -166,7 +159,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [KubeSphere](https://github.com/kubesphere)
1. [Kurly](https://www.kurly.com/)
1. [Kvist](https://kvistsolutions.com)
1. [Kyriba](https://www.kyriba.com/)
1. [LexisNexis](https://www.lexisnexis.com/)
1. [Lian Chu Securities](https://lczq.com)
1. [Liatrio](https://www.liatrio.com)
@@ -187,7 +179,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Meilleurs Agents](https://www.meilleursagents.com/)
1. [Mercedes-Benz Tech Innovation](https://www.mercedes-benz-techinnovation.com/)
1. [Mercedes-Benz.io](https://www.mercedes-benz.io/)
1. [Metacore Games](https://metacoregames.com/)
1. [Metanet](http://www.metanet.co.kr/en/)
1. [MindSpore](https://mindspore.cn)
1. [Mirantis](https://mirantis.com/)
@@ -208,7 +199,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Objective](https://www.objective.com.br/)
1. [OCCMundial](https://occ.com.mx)
1. [Octadesk](https://octadesk.com)
1. [Octopus Deploy](https://octopus.com)
1. [Olfeo](https://www.olfeo.com/)
1. [omegaUp](https://omegaUp.com)
1. [Omni](https://omni.se/)
@@ -235,9 +225,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Percona](https://percona.com/)
1. [PGS](https://www.pgs.com)
1. [Pigment](https://www.gopigment.com/)
1. [Pipedrive](https://www.pipedrive.com/)
1. [Pipefy](https://www.pipefy.com/)
1. [Pipekit](https://pipekit.io/)
1. [Pismo](https://pismo.io/)
1. [PITS Globale Datenrettungsdienste](https://www.pitsdatenrettung.de/)
1. [Platform9 Systems](https://platform9.com/)
@@ -256,6 +244,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Quipper](https://www.quipper.com/)
1. [RapidAPI](https://www.rapidapi.com/)
1. [rebuy](https://www.rebuy.de/)
1. [Recreation.gov](https://www.recreation.gov/)
1. [Red Hat](https://www.redhat.com/)
1. [Redpill Linpro](https://www.redpill-linpro.com/)
1. [Reenigne Cloud](https://reenigne.ca)
@@ -266,7 +255,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Riskified](https://www.riskified.com/)
1. [Robotinfra](https://www.robotinfra.com)
1. [Rocket.Chat](https://rocket.chat)
1. [Rogo](https://rogodata.com)
1. [Rubin Observatory](https://www.lsst.org)
1. [Saildrone](https://www.saildrone.com/)
1. [Salad Technologies](https://salad.com/)
@@ -331,7 +319,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Urbantz](https://urbantz.com/)
1. [Vectra](https://www.vectra.ai)
1. [Veepee](https://www.veepee.com)
1. [Verkada](https://www.verkada.com)
1. [Viaduct](https://www.viaduct.ai/)
1. [VietMoney](https://vietmoney.vn/)
1. [Vinted](https://vinted.com/)

View File

@@ -1 +1 @@
2.11.0
2.11.3

View File

@@ -17,7 +17,6 @@ package controllers
import (
"context"
"fmt"
"reflect"
"strings"
"time"
@@ -42,6 +41,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/source"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
@@ -111,19 +111,15 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
// Do not attempt to further reconcile the ApplicationSet if it is being deleted.
if applicationSetInfo.ObjectMeta.DeletionTimestamp != nil {
appsetName := applicationSetInfo.ObjectMeta.Name
logCtx.Debugf("DeletionTimestamp is set on %s", appsetName)
deleteAllowed := utils.DefaultPolicy(applicationSetInfo.Spec.SyncPolicy, r.Policy, r.EnablePolicyOverride).AllowDelete()
if !deleteAllowed {
logCtx.Debugf("ApplicationSet policy does not allow to delete")
if err := r.removeOwnerReferencesOnDeleteAppSet(ctx, applicationSetInfo); err != nil {
return ctrl.Result{}, err
}
logCtx.Debugf("ownerReferences referring %s is deleted from generated applications", appsetName)
}
controllerutil.RemoveFinalizer(&applicationSetInfo, argov1alpha1.ResourcesFinalizerName)
if err := r.Update(ctx, &applicationSetInfo); err != nil {
return ctrl.Result{}, err
controllerutil.RemoveFinalizer(&applicationSetInfo, argov1alpha1.ResourcesFinalizerName)
if err := r.Update(ctx, &applicationSetInfo); err != nil {
return ctrl.Result{}, err
}
}
return ctrl.Result{}, nil
}
@@ -172,16 +168,6 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
return ctrl.Result{RequeueAfter: ReconcileRequeueOnValidationError}, nil
}
currentApplications, err := r.getCurrentApplications(ctx, applicationSetInfo)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get current applications for application set: %w", err)
}
err = r.updateResourcesStatus(ctx, logCtx, &applicationSetInfo, currentApplications)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get update resources status for application set: %w", err)
}
// appMap is a name->app collection of Applications in this ApplicationSet.
appMap := map[string]argov1alpha1.Application{}
// appSyncMap tracks which apps will be synced during this reconciliation.
@@ -198,11 +184,16 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
} else if applicationSetInfo.Spec.Strategy != nil {
// appset uses progressive sync
for _, app := range currentApplications {
applications, err := r.getCurrentApplications(ctx, applicationSetInfo)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get current applications for application set: %w", err)
}
for _, app := range applications {
appMap[app.Name] = app
}
appSyncMap, err = r.performProgressiveSyncs(ctx, logCtx, applicationSetInfo, currentApplications, desiredApplications, appMap)
appSyncMap, err = r.performProgressiveSyncs(ctx, logCtx, applicationSetInfo, applications, desiredApplications, appMap)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to perform progressive sync reconciliation for application set: %w", err)
}
@@ -623,7 +614,7 @@ func (r *ApplicationSetReconciler) SetupWithManager(mgr ctrl.Manager, enableProg
Owns(&argov1alpha1.Application{}, builder.WithPredicates(ownsHandler)).
WithEventFilter(ignoreNotAllowedNamespaces(r.ApplicationSetNamespaces)).
Watches(
&corev1.Secret{},
&source.Kind{Type: &corev1.Secret{}},
&clusterSecretEventHandler{
Client: mgr.GetClient(),
Log: log.WithField("type", "createSecretEventHandler"),
@@ -1175,7 +1166,6 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatus(ctx con
Message: "No Application status found, defaulting status to Waiting.",
Status: "Waiting",
Step: fmt.Sprint(appStepMap[app.Name] + 1),
TargetRevisions: app.Status.GetRevisions(),
}
} else {
// we have an existing AppStatus
@@ -1193,25 +1183,20 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatus(ctx con
currentAppStatus.Status = "Waiting"
currentAppStatus.Message = "Application has pending changes, setting status to Waiting."
currentAppStatus.Step = fmt.Sprint(appStepMap[currentAppStatus.Application] + 1)
currentAppStatus.TargetRevisions = app.Status.GetRevisions()
}
if currentAppStatus.Status == "Pending" {
if operationPhaseString == "Succeeded" {
revisions := []string{}
if len(app.Status.OperationState.SyncResult.Revisions) > 0 {
revisions = app.Status.OperationState.SyncResult.Revisions
} else if app.Status.OperationState.SyncResult.Revision != "" {
revisions = append(revisions, app.Status.OperationState.SyncResult.Revision)
}
if reflect.DeepEqual(currentAppStatus.TargetRevisions, revisions) {
logCtx.Infof("Application %v has completed a sync successfully, updating its ApplicationSet status to Progressing", app.Name)
currentAppStatus.LastTransitionTime = &now
currentAppStatus.Status = "Progressing"
currentAppStatus.Message = "Application resource completed a sync successfully, updating status from Pending to Progressing."
currentAppStatus.Step = fmt.Sprint(appStepMap[currentAppStatus.Application] + 1)
// check for successful syncs started less than 10s before the Application transitioned to Pending
// this covers race conditions where syncs initiated by RollingSync miraculously have a sync time before the transition to Pending state occurred (could be a few seconds)
if operationPhaseString == "Succeeded" && app.Status.OperationState.StartedAt.Add(time.Duration(10)*time.Second).After(currentAppStatus.LastTransitionTime.Time) {
if !app.Status.OperationState.StartedAt.After(currentAppStatus.LastTransitionTime.Time) {
logCtx.Warnf("Application %v was synced less than 10s prior to entering Pending status, we'll assume the AppSet controller triggered this sync and update its status to Progressing", app.Name)
}
logCtx.Infof("Application %v has completed a sync successfully, updating its ApplicationSet status to Progressing", app.Name)
currentAppStatus.LastTransitionTime = &now
currentAppStatus.Status = "Progressing"
currentAppStatus.Message = "Application resource completed a sync successfully, updating status from Pending to Progressing."
currentAppStatus.Step = fmt.Sprint(appStepMap[currentAppStatus.Application] + 1)
} 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
@@ -1380,87 +1365,7 @@ func findApplicationStatusIndex(appStatuses []argov1alpha1.ApplicationSetApplica
return -1
}
func (r *ApplicationSetReconciler) updateResourcesStatus(ctx context.Context, logCtx *log.Entry, appset *argov1alpha1.ApplicationSet, apps []argov1alpha1.Application) error {
statusMap := getResourceStatusMap(appset)
statusMap = buildResourceStatus(statusMap, apps)
statuses := []argov1alpha1.ResourceStatus{}
for _, status := range statusMap {
statuses = append(statuses, status)
}
appset.Status.Resources = statuses
namespacedName := types.NamespacedName{Namespace: appset.Namespace, Name: appset.Name}
err := r.Client.Status().Update(ctx, appset)
if err != nil {
logCtx.Errorf("unable to set application set status: %v", err)
return fmt.Errorf("unable to set application set status: %v", err)
}
if err := r.Get(ctx, namespacedName, appset); err != nil {
if client.IgnoreNotFound(err) != nil {
return nil
}
return fmt.Errorf("error fetching updated application set: %v", err)
}
return nil
}
func buildResourceStatus(statusMap map[string]argov1alpha1.ResourceStatus, apps []argov1alpha1.Application) map[string]argov1alpha1.ResourceStatus {
appMap := map[string]argov1alpha1.Application{}
for _, app := range apps {
appCopy := app
appMap[app.Name] = app
gvk := app.GroupVersionKind()
// Create status if it does not exist
status, ok := statusMap[app.Name]
if !ok {
status = argov1alpha1.ResourceStatus{
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind,
Name: app.Name,
Namespace: app.Namespace,
Status: app.Status.Sync.Status,
Health: &appCopy.Status.Health,
}
}
status.Group = gvk.Group
status.Version = gvk.Version
status.Kind = gvk.Kind
status.Name = app.Name
status.Namespace = app.Namespace
status.Status = app.Status.Sync.Status
status.Health = &appCopy.Status.Health
statusMap[app.Name] = status
}
cleanupDeletedApplicationStatuses(statusMap, appMap)
return statusMap
}
func getResourceStatusMap(appset *argov1alpha1.ApplicationSet) map[string]argov1alpha1.ResourceStatus {
statusMap := map[string]argov1alpha1.ResourceStatus{}
for _, status := range appset.Status.Resources {
statusMap[status.Name] = status
}
return statusMap
}
func cleanupDeletedApplicationStatuses(statusMap map[string]argov1alpha1.ResourceStatus, apps map[string]argov1alpha1.Application) {
for name := range statusMap {
if _, ok := apps[name]; !ok {
delete(statusMap, name)
}
}
}
// setApplicationSetApplicationStatus updates the ApplicationSet's status field
// setApplicationSetApplicationStatus updates the ApplicatonSet's status field
// with any new/changed Application statuses.
func (r *ApplicationSetReconciler) setAppSetApplicationStatus(ctx context.Context, logCtx *log.Entry, applicationSet *argov1alpha1.ApplicationSet, applicationStatuses []argov1alpha1.ApplicationSetApplicationStatus) error {
needToUpdateStatus := false
@@ -1639,7 +1544,7 @@ func shouldRequeueApplicationSet(appOld *argov1alpha1.Application, appNew *argov
// the applicationset controller owns the application spec, labels, annotations, and finalizers on the applications
// reflect.DeepEqual considers nil slices/maps not equal to empty slices/maps
// https://pkg.go.dev/reflect#DeepEqual
// ApplicationDestination has an unexported field so we can just use the == for comparison
// ApplicationDestination has an unexported field so we can just use the == for comparsion
if !cmp.Equal(appOld.Spec, appNew.Spec, cmpopts.EquateEmpty(), cmpopts.EquateComparable(argov1alpha1.ApplicationDestination{})) ||
!cmp.Equal(appOld.ObjectMeta.GetAnnotations(), appNew.ObjectMeta.GetAnnotations(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appOld.ObjectMeta.GetLabels(), appNew.ObjectMeta.GetLabels(), cmpopts.EquateEmpty()) ||

File diff suppressed because it is too large Load Diff

View File

@@ -24,20 +24,20 @@ type clusterSecretEventHandler struct {
Client client.Client
}
func (h *clusterSecretEventHandler) Create(ctx context.Context, e event.CreateEvent, q workqueue.RateLimitingInterface) {
h.queueRelatedAppGenerators(ctx, q, e.Object)
func (h *clusterSecretEventHandler) Create(e event.CreateEvent, q workqueue.RateLimitingInterface) {
h.queueRelatedAppGenerators(q, e.Object)
}
func (h *clusterSecretEventHandler) Update(ctx context.Context, e event.UpdateEvent, q workqueue.RateLimitingInterface) {
h.queueRelatedAppGenerators(ctx, q, e.ObjectNew)
func (h *clusterSecretEventHandler) Update(e event.UpdateEvent, q workqueue.RateLimitingInterface) {
h.queueRelatedAppGenerators(q, e.ObjectNew)
}
func (h *clusterSecretEventHandler) Delete(ctx context.Context, e event.DeleteEvent, q workqueue.RateLimitingInterface) {
h.queueRelatedAppGenerators(ctx, q, e.Object)
func (h *clusterSecretEventHandler) Delete(e event.DeleteEvent, q workqueue.RateLimitingInterface) {
h.queueRelatedAppGenerators(q, e.Object)
}
func (h *clusterSecretEventHandler) Generic(ctx context.Context, e event.GenericEvent, q workqueue.RateLimitingInterface) {
h.queueRelatedAppGenerators(ctx, q, e.Object)
func (h *clusterSecretEventHandler) Generic(e event.GenericEvent, q workqueue.RateLimitingInterface) {
h.queueRelatedAppGenerators(q, e.Object)
}
// addRateLimitingInterface defines the Add method of workqueue.RateLimitingInterface, allow us to easily mock
@@ -46,7 +46,7 @@ type addRateLimitingInterface interface {
Add(item interface{})
}
func (h *clusterSecretEventHandler) queueRelatedAppGenerators(ctx context.Context, q addRateLimitingInterface, object client.Object) {
func (h *clusterSecretEventHandler) queueRelatedAppGenerators(q addRateLimitingInterface, object client.Object) {
// Check for label, lookup all ApplicationSets that might match the cluster, queue them all
if object.GetLabels()[generators.ArgoCDSecretTypeLabel] != generators.ArgoCDSecretTypeCluster {
return
@@ -58,7 +58,7 @@ func (h *clusterSecretEventHandler) queueRelatedAppGenerators(ctx context.Contex
}).Info("processing event for cluster secret")
appSetList := &argoprojiov1alpha1.ApplicationSetList{}
err := h.Client.List(ctx, appSetList)
err := h.Client.List(context.Background(), appSetList)
if err != nil {
h.Log.WithError(err).Error("unable to list ApplicationSets")
return

View File

@@ -1,7 +1,6 @@
package controllers
import (
"context"
"testing"
log "github.com/sirupsen/logrus"
@@ -23,10 +22,10 @@ func TestClusterEventHandler(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
assert.NoError(t, err)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
assert.NoError(t, err)
assert.Nil(t, err)
tests := []struct {
name string
@@ -551,7 +550,7 @@ func TestClusterEventHandler(t *testing.T) {
mockAddRateLimitingInterface := mockAddRateLimitingInterface{}
handler.queueRelatedAppGenerators(context.Background(), &mockAddRateLimitingInterface, &test.secret)
handler.queueRelatedAppGenerators(&mockAddRateLimitingInterface, &test.secret)
assert.False(t, mockAddRateLimitingInterface.errorOccurred)
assert.ElementsMatch(t, mockAddRateLimitingInterface.addedItems, test.expectedRequests)
@@ -582,7 +581,7 @@ func TestNestedGeneratorHasClusterGenerator_NestedClusterGenerator(t *testing.T)
hasClusterGenerator, err := nestedGeneratorHasClusterGenerator(nested)
assert.NoError(t, err)
assert.Nil(t, err)
assert.True(t, hasClusterGenerator)
}
@@ -609,7 +608,7 @@ func TestNestedGeneratorHasClusterGenerator_NestedMergeGenerator(t *testing.T) {
hasClusterGenerator, err := nestedGeneratorHasClusterGenerator(nested)
assert.NoError(t, err)
assert.Nil(t, err)
assert.True(t, hasClusterGenerator)
}
@@ -636,6 +635,6 @@ func TestNestedGeneratorHasClusterGenerator_NestedMergeGeneratorWithInvalidJSON(
hasClusterGenerator, err := nestedGeneratorHasClusterGenerator(nested)
assert.Error(t, err)
assert.NotNil(t, err)
assert.False(t, hasClusterGenerator)
}

View File

@@ -25,7 +25,7 @@ func TestRequeueAfter(t *testing.T) {
ctx := context.Background()
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
assert.NoError(t, err)
assert.Nil(t, err)
gvrToListKind := map[schema.GroupVersionResource]string{{
Group: "mallard.io",
Version: "v1",

View File

@@ -4,12 +4,11 @@ import (
"fmt"
"testing"
"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
func Test_generateParamsFromGitFile(t *testing.T) {

View File

@@ -265,9 +265,9 @@ func TestPullRequestGetSecretRef(t *testing.T) {
t.Run(c.name, func(t *testing.T) {
token, err := gen.getSecretRef(ctx, c.ref, c.namespace)
if c.hasError {
assert.Error(t, err)
assert.NotNil(t, err)
} else {
assert.NoError(t, err)
assert.Nil(t, err)
}
assert.Equal(t, c.token, token)
})

View File

@@ -69,9 +69,9 @@ func TestSCMProviderGetSecretRef(t *testing.T) {
t.Run(c.name, func(t *testing.T) {
token, err := gen.getSecretRef(ctx, c.ref, c.namespace)
if c.hasError {
assert.Error(t, err)
assert.NotNil(t, err)
} else {
assert.NoError(t, err)
assert.Nil(t, err)
}
assert.Equal(t, c.token, token)

View File

@@ -1,4 +1,4 @@
// Code generated by mockery v2.40.2. DO NOT EDIT.
// Code generated by mockery v2.25.1. DO NOT EDIT.
package mocks
@@ -17,10 +17,6 @@ type Repos struct {
func (_m *Repos) GetDirectories(ctx context.Context, repoURL string, revision string, noRevisionCache bool) ([]string, error) {
ret := _m.Called(ctx, repoURL, revision, noRevisionCache)
if len(ret) == 0 {
panic("no return value specified for GetDirectories")
}
var r0 []string
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, string, bool) ([]string, error)); ok {
@@ -47,10 +43,6 @@ func (_m *Repos) GetDirectories(ctx context.Context, repoURL string, revision st
func (_m *Repos) GetFiles(ctx context.Context, repoURL string, revision string, pattern string, noRevisionCache bool) (map[string][]byte, error) {
ret := _m.Called(ctx, repoURL, revision, pattern, noRevisionCache)
if len(ret) == 0 {
panic("no return value specified for GetFiles")
}
var r0 map[string][]byte
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, bool) (map[string][]byte, error)); ok {
@@ -73,12 +65,13 @@ func (_m *Repos) GetFiles(ctx context.Context, repoURL string, revision string,
return r0, r1
}
// NewRepos creates a new instance of Repos. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewRepos(t interface {
type mockConstructorTestingTNewRepos interface {
mock.TestingT
Cleanup(func())
}) *Repos {
}
// NewRepos creates a new instance of Repos. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewRepos(t mockConstructorTestingTNewRepos) *Repos {
mock := &Repos{}
mock.Mock.Test(t)

View File

@@ -0,0 +1,57 @@
// Code generated by mockery v2.21.1. DO NOT EDIT.
package mocks
import (
context "context"
mock "github.com/stretchr/testify/mock"
v1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
// RepositoryDB is an autogenerated mock type for the RepositoryDB type
type RepositoryDB struct {
mock.Mock
}
// GetRepository provides a mock function with given fields: ctx, url
func (_m *RepositoryDB) GetRepository(ctx context.Context, url string) (*v1alpha1.Repository, error) {
ret := _m.Called(ctx, url)
var r0 *v1alpha1.Repository
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string) (*v1alpha1.Repository, error)); ok {
return rf(ctx, url)
}
if rf, ok := ret.Get(0).(func(context.Context, string) *v1alpha1.Repository); ok {
r0 = rf(ctx, url)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1alpha1.Repository)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
r1 = rf(ctx, url)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
type mockConstructorTestingTNewRepositoryDB interface {
mock.TestingT
Cleanup(func())
}
// NewRepositoryDB creates a new instance of RepositoryDB. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewRepositoryDB(t mockConstructorTestingTNewRepositoryDB) *RepositoryDB {
mock := &RepositoryDB{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -91,7 +91,7 @@ func TestListPullRequest(t *testing.T) {
list, err := provider.List(ctx)
assert.NoError(t, err)
assert.Len(t, list, 1)
assert.Equal(t, 1, len(list))
assert.Equal(t, "feature-branch", list[0].Branch)
assert.Equal(t, pr_head_sha, list[0].HeadSHA)
assert.Equal(t, pr_id, list[0].Number)

View File

@@ -83,7 +83,7 @@ func TestListPullRequestBearerTokenCloud(t *testing.T) {
assert.NoError(t, err)
pullRequests, err := ListPullRequests(context.Background(), svc, []v1alpha1.PullRequestGeneratorFilter{})
assert.NoError(t, err)
assert.Len(t, pullRequests, 1)
assert.Equal(t, 1, len(pullRequests))
assert.Equal(t, 101, pullRequests[0].Number)
assert.Equal(t, "feature/foo-bar", pullRequests[0].Branch)
assert.Equal(t, "1a8dd249c04a", pullRequests[0].HeadSHA)
@@ -99,7 +99,7 @@ func TestListPullRequestNoAuthCloud(t *testing.T) {
assert.NoError(t, err)
pullRequests, err := ListPullRequests(context.Background(), svc, []v1alpha1.PullRequestGeneratorFilter{})
assert.NoError(t, err)
assert.Len(t, pullRequests, 1)
assert.Equal(t, 1, len(pullRequests))
assert.Equal(t, 101, pullRequests[0].Number)
assert.Equal(t, "feature/foo-bar", pullRequests[0].Branch)
assert.Equal(t, "1a8dd249c04a", pullRequests[0].HeadSHA)
@@ -115,7 +115,7 @@ func TestListPullRequestBasicAuthCloud(t *testing.T) {
assert.NoError(t, err)
pullRequests, err := ListPullRequests(context.Background(), svc, []v1alpha1.PullRequestGeneratorFilter{})
assert.NoError(t, err)
assert.Len(t, pullRequests, 1)
assert.Equal(t, 1, len(pullRequests))
assert.Equal(t, 101, pullRequests[0].Number)
assert.Equal(t, "feature/foo-bar", pullRequests[0].Branch)
assert.Equal(t, "1a8dd249c04a", pullRequests[0].HeadSHA)
@@ -192,7 +192,7 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
assert.NoError(t, err)
pullRequests, err := ListPullRequests(context.Background(), svc, []v1alpha1.PullRequestGeneratorFilter{})
assert.NoError(t, err)
assert.Len(t, pullRequests, 3)
assert.Equal(t, 3, len(pullRequests))
assert.Equal(t, PullRequest{
Number: 101,
Branch: "feature-101",
@@ -370,7 +370,7 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
},
})
assert.NoError(t, err)
assert.Len(t, pullRequests, 2)
assert.Equal(t, 2, len(pullRequests))
assert.Equal(t, PullRequest{
Number: 101,
Branch: "feature-101",
@@ -391,7 +391,7 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
},
})
assert.NoError(t, err)
assert.Len(t, pullRequests, 1)
assert.Equal(t, 1, len(pullRequests))
assert.Equal(t, PullRequest{
Number: 102,
Branch: "feature-102",

View File

@@ -4,10 +4,9 @@ import (
"context"
"fmt"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
bitbucketv1 "github.com/gfleury/go-bitbucket-v1"
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
)
type BitbucketService struct {

View File

@@ -7,9 +7,8 @@ import (
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
)
func defaultHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
@@ -58,7 +57,7 @@ func TestListPullRequestNoAuth(t *testing.T) {
assert.NoError(t, err)
pullRequests, err := ListPullRequests(context.Background(), svc, []v1alpha1.PullRequestGeneratorFilter{})
assert.NoError(t, err)
assert.Len(t, pullRequests, 1)
assert.Equal(t, 1, len(pullRequests))
assert.Equal(t, 101, pullRequests[0].Number)
assert.Equal(t, "feature-ABC-123", pullRequests[0].Branch)
assert.Equal(t, "master", pullRequests[0].TargetBranch)
@@ -139,7 +138,7 @@ func TestListPullRequestPagination(t *testing.T) {
assert.NoError(t, err)
pullRequests, err := ListPullRequests(context.Background(), svc, []v1alpha1.PullRequestGeneratorFilter{})
assert.NoError(t, err)
assert.Len(t, pullRequests, 3)
assert.Equal(t, 3, len(pullRequests))
assert.Equal(t, PullRequest{
Number: 101,
Branch: "feature-101",
@@ -175,7 +174,7 @@ func TestListPullRequestBasicAuth(t *testing.T) {
assert.NoError(t, err)
pullRequests, err := ListPullRequests(context.Background(), svc, []v1alpha1.PullRequestGeneratorFilter{})
assert.NoError(t, err)
assert.Len(t, pullRequests, 1)
assert.Equal(t, 1, len(pullRequests))
assert.Equal(t, 101, pullRequests[0].Number)
assert.Equal(t, "feature-ABC-123", pullRequests[0].Branch)
assert.Equal(t, "cb3cf2e4d1517c83e720d2585b9402dbef71f992", pullRequests[0].HeadSHA)
@@ -322,7 +321,7 @@ func TestListPullRequestBranchMatch(t *testing.T) {
},
})
assert.NoError(t, err)
assert.Len(t, pullRequests, 2)
assert.Equal(t, 2, len(pullRequests))
assert.Equal(t, PullRequest{
Number: 101,
Branch: "feature-101",
@@ -347,7 +346,7 @@ func TestListPullRequestBranchMatch(t *testing.T) {
},
})
assert.NoError(t, err)
assert.Len(t, pullRequests, 1)
assert.Equal(t, 1, len(pullRequests))
assert.Equal(t, PullRequest{
Number: 102,
Branch: "feature-102",

View File

@@ -250,10 +250,10 @@ func TestGiteaList(t *testing.T) {
giteaMockHandler(t)(w, r)
}))
host, err := NewGiteaService(context.Background(), "", ts.URL, "test-argocd", "pr-test", false)
assert.NoError(t, err)
assert.Nil(t, err)
prs, err := host.List(context.Background())
assert.NoError(t, err)
assert.Len(t, prs, 1)
assert.Nil(t, err)
assert.Equal(t, len(prs), 1)
assert.Equal(t, prs[0].Number, 1)
assert.Equal(t, prs[0].Branch, "test")
assert.Equal(t, prs[0].TargetBranch, "main")

View File

@@ -6,10 +6,9 @@ import (
"net/http"
"os"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/hashicorp/go-retryablehttp"
gitlab "github.com/xanzy/go-gitlab"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
)
type GitLabService struct {

View File

@@ -4,9 +4,8 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
)
func strp(s string) *string {

View File

@@ -6,19 +6,28 @@ import (
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/git"
"github.com/argoproj/argo-cd/v2/util/io"
)
//go:generate go run github.com/vektra/mockery/v2@v2.25.1 --name=RepositoryDB
// RepositoryDB Is a lean facade for ArgoDB,
// Using a lean interface makes it easier to test the functionality of the git generator
type RepositoryDB interface {
GetRepository(ctx context.Context, url string) (*v1alpha1.Repository, error)
}
type argoCDService struct {
getRepository func(ctx context.Context, url, project string) (*v1alpha1.Repository, error)
repositoriesDB RepositoryDB
storecreds git.CredsStore
submoduleEnabled bool
repoServerClientSet apiclient.Clientset
newFileGlobbingEnabled bool
}
//go:generate go run github.com/vektra/mockery/v2@v2.40.2 --name=Repos
//go:generate go run github.com/vektra/mockery/v2@v2.25.1 --name=Repos
type Repos interface {
@@ -29,9 +38,9 @@ type Repos interface {
GetDirectories(ctx context.Context, repoURL string, revision string, noRevisionCache bool) ([]string, error)
}
func NewArgoCDService(getRepository func(ctx context.Context, url, project string) (*v1alpha1.Repository, error), submoduleEnabled bool, repoClientset apiclient.Clientset, newFileGlobbingEnabled bool) (Repos, error) {
func NewArgoCDService(db db.ArgoDB, submoduleEnabled bool, repoClientset apiclient.Clientset, newFileGlobbingEnabled bool) (Repos, error) {
return &argoCDService{
getRepository: getRepository,
repositoriesDB: db.(RepositoryDB),
submoduleEnabled: submoduleEnabled,
repoServerClientSet: repoClientset,
newFileGlobbingEnabled: newFileGlobbingEnabled,
@@ -39,7 +48,7 @@ func NewArgoCDService(getRepository func(ctx context.Context, url, project strin
}
func (a *argoCDService) GetFiles(ctx context.Context, repoURL string, revision string, pattern string, noRevisionCache bool) (map[string][]byte, error) {
repo, err := a.getRepository(ctx, repoURL, "")
repo, err := a.repositoriesDB.GetRepository(ctx, repoURL)
if err != nil {
return nil, fmt.Errorf("error in GetRepository: %w", err)
}
@@ -66,7 +75,7 @@ func (a *argoCDService) GetFiles(ctx context.Context, repoURL string, revision s
}
func (a *argoCDService) GetDirectories(ctx context.Context, repoURL string, revision string, noRevisionCache bool) ([]string, error) {
repo, err := a.getRepository(ctx, repoURL, "")
repo, err := a.repositoriesDB.GetRepository(ctx, repoURL)
if err != nil {
return nil, fmt.Errorf("error in GetRepository: %w", err)
}

View File

@@ -5,12 +5,13 @@ import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
repo_mocks "github.com/argoproj/argo-cd/v2/reposerver/apiclient/mocks"
db_mocks "github.com/argoproj/argo-cd/v2/util/db/mocks"
"github.com/argoproj/argo-cd/v2/util/git"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
@@ -18,9 +19,9 @@ import (
func TestGetDirectories(t *testing.T) {
type fields struct {
repositoriesDBFuncs []func(*mocks.RepositoryDB)
storecreds git.CredsStore
submoduleEnabled bool
getRepository func(ctx context.Context, url, project string) (*v1alpha1.Repository, error)
repoServerClientFuncs []func(*repo_mocks.RepoServerServiceClient)
}
type args struct {
@@ -37,13 +38,17 @@ func TestGetDirectories(t *testing.T) {
wantErr assert.ErrorAssertionFunc
}{
{name: "ErrorGettingRepos", fields: fields{
getRepository: func(ctx context.Context, url, project string) (*v1alpha1.Repository, error) {
return nil, fmt.Errorf("unable to get repos")
repositoriesDBFuncs: []func(*mocks.RepositoryDB){
func(db *mocks.RepositoryDB) {
db.On("GetRepository", mock.Anything, mock.Anything).Return(nil, fmt.Errorf("unable to get repos"))
},
},
}, args: args{}, want: nil, wantErr: assert.Error},
{name: "ErrorGettingDirs", fields: fields{
getRepository: func(ctx context.Context, url, project string) (*v1alpha1.Repository, error) {
return &v1alpha1.Repository{}, nil
repositoriesDBFuncs: []func(*mocks.RepositoryDB){
func(db *mocks.RepositoryDB) {
db.On("GetRepository", mock.Anything, mock.Anything).Return(&v1alpha1.Repository{}, nil)
},
},
repoServerClientFuncs: []func(*repo_mocks.RepoServerServiceClient){
func(client *repo_mocks.RepoServerServiceClient) {
@@ -52,8 +57,10 @@ func TestGetDirectories(t *testing.T) {
},
}, args: args{}, want: nil, wantErr: assert.Error},
{name: "HappyCase", fields: fields{
getRepository: func(ctx context.Context, url, project string) (*v1alpha1.Repository, error) {
return &v1alpha1.Repository{}, nil
repositoriesDBFuncs: []func(*mocks.RepositoryDB){
func(db *mocks.RepositoryDB) {
db.On("GetRepository", mock.Anything, mock.Anything).Return(&v1alpha1.Repository{}, nil)
},
},
repoServerClientFuncs: []func(*repo_mocks.RepoServerServiceClient){
func(client *repo_mocks.RepoServerServiceClient) {
@@ -66,14 +73,18 @@ func TestGetDirectories(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockDb := &mocks.RepositoryDB{}
mockRepoClient := &repo_mocks.RepoServerServiceClient{}
// decorate the mocks
for i := range tt.fields.repositoriesDBFuncs {
tt.fields.repositoriesDBFuncs[i](mockDb)
}
for i := range tt.fields.repoServerClientFuncs {
tt.fields.repoServerClientFuncs[i](mockRepoClient)
}
a := &argoCDService{
getRepository: tt.fields.getRepository,
repositoriesDB: mockDb,
storecreds: tt.fields.storecreds,
submoduleEnabled: tt.fields.submoduleEnabled,
repoServerClientSet: &repo_mocks.Clientset{RepoServerServiceClient: mockRepoClient},
@@ -89,10 +100,10 @@ func TestGetDirectories(t *testing.T) {
func TestGetFiles(t *testing.T) {
type fields struct {
repositoriesDBFuncs []func(*mocks.RepositoryDB)
storecreds git.CredsStore
submoduleEnabled bool
repoServerClientFuncs []func(*repo_mocks.RepoServerServiceClient)
getRepository func(ctx context.Context, url, project string) (*v1alpha1.Repository, error)
}
type args struct {
ctx context.Context
@@ -109,13 +120,17 @@ func TestGetFiles(t *testing.T) {
wantErr assert.ErrorAssertionFunc
}{
{name: "ErrorGettingRepos", fields: fields{
getRepository: func(ctx context.Context, url, project string) (*v1alpha1.Repository, error) {
return nil, fmt.Errorf("unable to get repos")
repositoriesDBFuncs: []func(*mocks.RepositoryDB){
func(db *mocks.RepositoryDB) {
db.On("GetRepository", mock.Anything, mock.Anything).Return(nil, fmt.Errorf("unable to get repos"))
},
},
}, args: args{}, want: nil, wantErr: assert.Error},
{name: "ErrorGettingFiles", fields: fields{
getRepository: func(ctx context.Context, url, project string) (*v1alpha1.Repository, error) {
return &v1alpha1.Repository{}, nil
repositoriesDBFuncs: []func(*mocks.RepositoryDB){
func(db *mocks.RepositoryDB) {
db.On("GetRepository", mock.Anything, mock.Anything).Return(&v1alpha1.Repository{}, nil)
},
},
repoServerClientFuncs: []func(*repo_mocks.RepoServerServiceClient){
func(client *repo_mocks.RepoServerServiceClient) {
@@ -124,8 +139,10 @@ func TestGetFiles(t *testing.T) {
},
}, args: args{}, want: nil, wantErr: assert.Error},
{name: "HappyCase", fields: fields{
getRepository: func(ctx context.Context, url, project string) (*v1alpha1.Repository, error) {
return &v1alpha1.Repository{}, nil
repositoriesDBFuncs: []func(*mocks.RepositoryDB){
func(db *mocks.RepositoryDB) {
db.On("GetRepository", mock.Anything, mock.Anything).Return(&v1alpha1.Repository{}, nil)
},
},
repoServerClientFuncs: []func(*repo_mocks.RepoServerServiceClient){
func(client *repo_mocks.RepoServerServiceClient) {
@@ -144,14 +161,18 @@ func TestGetFiles(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockDb := &mocks.RepositoryDB{}
mockRepoClient := &repo_mocks.RepoServerServiceClient{}
// decorate the mocks
for i := range tt.fields.repositoriesDBFuncs {
tt.fields.repositoriesDBFuncs[i](mockDb)
}
for i := range tt.fields.repoServerClientFuncs {
tt.fields.repoServerClientFuncs[i](mockRepoClient)
}
a := &argoCDService{
getRepository: tt.fields.getRepository,
repositoriesDB: mockDb,
storecreds: tt.fields.storecreds,
submoduleEnabled: tt.fields.submoduleEnabled,
repoServerClientSet: &repo_mocks.Clientset{RepoServerServiceClient: mockRepoClient},
@@ -166,9 +187,7 @@ func TestGetFiles(t *testing.T) {
}
func TestNewArgoCDService(t *testing.T) {
service, err := NewArgoCDService(func(ctx context.Context, url, project string) (*v1alpha1.Repository, error) {
return &v1alpha1.Repository{}, nil
}, false, &repo_mocks.Clientset{}, false)
service, err := NewArgoCDService(&db_mocks.ArgoDB{}, false, &repo_mocks.Clientset{}, false)
assert.NoError(t, err, err)
assert.NotNil(t, service)
}

View File

@@ -3,12 +3,12 @@ package scm_provider
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go/aws/request"
pathpkg "path"
"path/filepath"
"strings"
"github.com/aws/aws-sdk-go/aws/request"
application "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/aws/awserr"
@@ -19,8 +19,6 @@ import (
log "github.com/sirupsen/logrus"
"golang.org/x/exp/maps"
"k8s.io/utils/strings/slices"
application "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
const (

View File

@@ -6,15 +6,14 @@ import (
"sort"
"testing"
"github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider/aws_codecommit/mocks"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/codecommit"
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider/aws_codecommit/mocks"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
type awsCodeCommitTestRepository struct {

View File

@@ -8,18 +8,15 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"k8s.io/utils/ptr"
"github.com/microsoft/azure-devops-go-api/azuredevops"
azureGit "github.com/microsoft/azure-devops-go-api/azuredevops/git"
"k8s.io/utils/pointer"
azureMock "github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider/azure_devops/git/mocks"
"github.com/microsoft/azure-devops-go-api/azuredevops"
azureGit "github.com/microsoft/azure-devops-go-api/azuredevops/git"
)
//go:generate go run github.com/vektra/mockery/v2@v2.40.2 --srcpkg=github.com/microsoft/azure-devops-go-api/azuredevops/git --name=Client --output=azure_devops/git/mocks --outpkg=mocks
func s(input string) *string {
return ptr.To(input)
return pointer.String(input)
}
func TestAzureDevopsRepoHasPath(t *testing.T) {

View File

@@ -5,10 +5,9 @@ import (
"fmt"
"io"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
bitbucketv1 "github.com/gfleury/go-bitbucket-v1"
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
)
type BitbucketServerProvider struct {

View File

@@ -80,7 +80,7 @@ func defaultHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
func verifyDefaultRepo(t *testing.T, err error, repos []*Repository) {
assert.NoError(t, err)
assert.Len(t, repos, 1)
assert.Equal(t, 1, len(repos))
assert.Equal(t, Repository{
Organization: "PROJECT",
Repository: "REPO",
@@ -194,7 +194,7 @@ func TestListReposPagination(t *testing.T) {
assert.NoError(t, err)
repos, err := provider.ListRepos(context.Background(), "ssh")
assert.NoError(t, err)
assert.Len(t, repos, 2)
assert.Equal(t, 2, len(repos))
assert.Equal(t, Repository{
Organization: "PROJECT",
Repository: "REPO",
@@ -277,7 +277,7 @@ func TestGetBranchesBranchPagination(t *testing.T) {
RepositoryId: 1,
})
assert.NoError(t, err)
assert.Len(t, repos, 2)
assert.Equal(t, 2, len(repos))
assert.Equal(t, Repository{
Organization: "PROJECT",
Repository: "REPO",
@@ -330,7 +330,7 @@ func TestGetBranchesDefaultOnly(t *testing.T) {
RepositoryId: 1,
})
assert.NoError(t, err)
assert.Len(t, repos, 1)
assert.Equal(t, 1, len(repos))
assert.Equal(t, Repository{
Organization: "PROJECT",
Repository: "REPO",
@@ -447,7 +447,7 @@ func TestListReposDefaultBranch(t *testing.T) {
assert.NoError(t, err)
repos, err := provider.ListRepos(context.Background(), "ssh")
assert.NoError(t, err)
assert.Len(t, repos, 1)
assert.Equal(t, 1, len(repos))
assert.Equal(t, Repository{
Organization: "PROJECT",
Repository: "REPO",
@@ -502,7 +502,7 @@ func TestListReposCloneProtocol(t *testing.T) {
assert.NoError(t, err)
repos, err := provider.ListRepos(context.Background(), "https")
assert.NoError(t, err)
assert.Len(t, repos, 1)
assert.Equal(t, 1, len(repos))
assert.Equal(t, Repository{
Organization: "PROJECT",
Repository: "REPO",
@@ -523,7 +523,7 @@ func TestListReposUnknownProtocol(t *testing.T) {
provider, err := NewBitbucketServerProviderNoAuth(context.Background(), ts.URL, "PROJECT", true)
assert.NoError(t, err)
_, errProtocol := provider.ListRepos(context.Background(), "http")
assert.Error(t, errProtocol)
assert.NotNil(t, errProtocol)
}
func TestBitbucketServerHasPath(t *testing.T) {

View File

@@ -305,9 +305,9 @@ func TestGiteaListRepos(t *testing.T) {
provider, _ := NewGiteaProvider(context.Background(), "test-argocd", "", ts.URL, c.allBranches, false)
rawRepos, err := ListRepos(context.Background(), provider, c.filters, c.proto)
if c.hasError {
assert.Error(t, err)
assert.NotNil(t, err)
} else {
assert.NoError(t, err)
assert.Nil(t, err)
// Just check that this one project shows up. Not a great test but better thing nothing?
repos := []*Repository{}
branches := []string{}
@@ -341,19 +341,19 @@ func TestGiteaHasPath(t *testing.T) {
t.Run("file exists", func(t *testing.T) {
ok, err := host.RepoHasPath(context.Background(), repo, "README.md")
assert.NoError(t, err)
assert.Nil(t, err)
assert.True(t, ok)
})
t.Run("directory exists", func(t *testing.T) {
ok, err := host.RepoHasPath(context.Background(), repo, "gitea")
assert.NoError(t, err)
assert.Nil(t, err)
assert.True(t, ok)
})
t.Run("does not exists", func(t *testing.T) {
ok, err := host.RepoHasPath(context.Background(), repo, "notathing")
assert.NoError(t, err)
assert.Nil(t, err)
assert.False(t, ok)
})
}

View File

@@ -278,11 +278,11 @@ func TestGithubHasPath(t *testing.T) {
Branch: "master",
}
ok, err := host.RepoHasPath(context.Background(), repo, "pkg/")
assert.NoError(t, err)
assert.Nil(t, err)
assert.True(t, ok)
ok, err = host.RepoHasPath(context.Background(), repo, "notathing/")
assert.NoError(t, err)
assert.Nil(t, err)
assert.False(t, ok)
}
@@ -319,6 +319,6 @@ func TestGithubGetBranches(t *testing.T) {
assert.NoError(t, err)
} else {
// considering master branch to exist.
assert.Len(t, repos, 1)
assert.Equal(t, len(repos), 1)
}
}

View File

@@ -7,10 +7,9 @@ import (
"os"
pathpkg "path"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/hashicorp/go-retryablehttp"
"github.com/xanzy/go-gitlab"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
)
type GitlabProvider struct {

View File

@@ -1122,9 +1122,9 @@ func TestGitlabListRepos(t *testing.T) {
provider, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, c.allBranches, c.includeSubgroups, c.includeSharedProjects, c.insecure, "", c.topic)
rawRepos, err := ListRepos(context.Background(), provider, c.filters, c.proto)
if c.hasError {
assert.Error(t, err)
assert.NotNil(t, err)
} else {
assert.NoError(t, err)
assert.Nil(t, err)
// Just check that this one project shows up. Not a great test but better than nothing?
repos := []*Repository{}
uniqueRepos := map[string]int{}
@@ -1143,11 +1143,11 @@ func TestGitlabListRepos(t *testing.T) {
}
// In case of listing subgroups, validate the number of returned projects
if c.includeSubgroups || c.includeSharedProjects {
assert.Len(t, uniqueRepos, 2)
assert.Equal(t, 2, len(uniqueRepos))
}
// In case we filter on the topic, ensure we got only one repo returned
if c.topic != "" {
assert.Len(t, uniqueRepos, 1)
assert.Equal(t, 1, len(uniqueRepos))
}
}
})
@@ -1194,7 +1194,7 @@ func TestGitlabHasPath(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
ok, err := host.RepoHasPath(context.Background(), repo, c.path)
assert.NoError(t, err)
assert.Nil(t, err)
assert.Equal(t, c.exists, ok)
})
}
@@ -1212,7 +1212,7 @@ func TestGitlabGetBranches(t *testing.T) {
}
t.Run("branch exists", func(t *testing.T) {
repos, err := host.GetBranches(context.Background(), repo)
assert.NoError(t, err)
assert.Nil(t, err)
assert.Equal(t, repos[0].Branch, "master")
})

View File

@@ -37,7 +37,7 @@ func TestFilterRepoMatch(t *testing.T) {
},
}
repos, err := ListRepos(context.Background(), provider, filters, "")
assert.NoError(t, err)
assert.Nil(t, err)
assert.Len(t, repos, 2)
assert.Equal(t, "one", repos[0].Repository)
assert.Equal(t, "three", repos[1].Repository)
@@ -66,7 +66,7 @@ func TestFilterLabelMatch(t *testing.T) {
},
}
repos, err := ListRepos(context.Background(), provider, filters, "")
assert.NoError(t, err)
assert.Nil(t, err)
assert.Len(t, repos, 2)
assert.Equal(t, "one", repos[0].Repository)
assert.Equal(t, "two", repos[1].Repository)
@@ -92,7 +92,7 @@ func TestFilterPathExists(t *testing.T) {
},
}
repos, err := ListRepos(context.Background(), provider, filters, "")
assert.NoError(t, err)
assert.Nil(t, err)
assert.Len(t, repos, 1)
assert.Equal(t, "two", repos[0].Repository)
}
@@ -117,7 +117,7 @@ func TestFilterPathDoesntExists(t *testing.T) {
},
}
repos, err := ListRepos(context.Background(), provider, filters, "")
assert.NoError(t, err)
assert.Nil(t, err)
assert.Len(t, repos, 2)
}
func TestFilterRepoMatchBadRegexp(t *testing.T) {
@@ -134,7 +134,7 @@ func TestFilterRepoMatchBadRegexp(t *testing.T) {
},
}
_, err := ListRepos(context.Background(), provider, filters, "")
assert.Error(t, err)
assert.NotNil(t, err)
}
func TestFilterLabelMatchBadRegexp(t *testing.T) {
@@ -151,7 +151,7 @@ func TestFilterLabelMatchBadRegexp(t *testing.T) {
},
}
_, err := ListRepos(context.Background(), provider, filters, "")
assert.Error(t, err)
assert.NotNil(t, err)
}
func TestFilterBranchMatch(t *testing.T) {
@@ -185,7 +185,7 @@ func TestFilterBranchMatch(t *testing.T) {
},
}
repos, err := ListRepos(context.Background(), provider, filters, "")
assert.NoError(t, err)
assert.Nil(t, err)
assert.Len(t, repos, 2)
assert.Equal(t, "one", repos[0].Repository)
assert.Equal(t, "two", repos[0].Branch)
@@ -217,7 +217,7 @@ func TestMultiFilterAnd(t *testing.T) {
},
}
repos, err := ListRepos(context.Background(), provider, filters, "")
assert.NoError(t, err)
assert.Nil(t, err)
assert.Len(t, repos, 1)
assert.Equal(t, "two", repos[0].Repository)
}
@@ -248,7 +248,7 @@ func TestMultiFilterOr(t *testing.T) {
},
}
repos, err := ListRepos(context.Background(), provider, filters, "")
assert.NoError(t, err)
assert.Nil(t, err)
assert.Len(t, repos, 3)
assert.Equal(t, "one", repos[0].Repository)
assert.Equal(t, "two", repos[1].Repository)
@@ -274,7 +274,7 @@ func TestNoFilters(t *testing.T) {
}
filters := []argoprojiov1alpha1.SCMProviderGeneratorFilter{}
repos, err := ListRepos(context.Background(), provider, filters, "")
assert.NoError(t, err)
assert.Nil(t, err)
assert.Len(t, repos, 3)
assert.Equal(t, "one", repos[0].Repository)
assert.Equal(t, "two", repos[1].Repository)

View File

@@ -17,7 +17,7 @@ import (
appv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"k8s.io/client-go/kubernetes"
"k8s.io/utils/ptr"
"k8s.io/utils/pointer"
)
// The contents of this file are from
@@ -180,7 +180,7 @@ func secretToCluster(s *corev1.Secret) (*appv1.Cluster, error) {
if val, err := strconv.Atoi(string(shardStr)); err != nil {
log.Warnf("Error while parsing shard in cluster secret '%s': %v", s.Name, err)
} else {
shard = ptr.To(int64(val))
shard = pointer.Int64(int64(val))
}
}
cluster := appv1.Cluster{

View File

@@ -33,7 +33,7 @@ func Test_secretToCluster(t *testing.T) {
},
}
cluster, err := secretToCluster(secret)
assert.NoError(t, err)
assert.Nil(t, err)
assert.Equal(t, *cluster, argoappv1.Cluster{
Name: "test",
Server: "http://mycluster",
@@ -56,7 +56,7 @@ func Test_secretToCluster_NoConfig(t *testing.T) {
},
}
cluster, err := secretToCluster(secret)
assert.NoError(t, err)
assert.Nil(t, err)
assert.Equal(t, *cluster, argoappv1.Cluster{
Name: "test",
Server: "http://mycluster",
@@ -96,7 +96,7 @@ func TestValidateDestination(t *testing.T) {
}
appCond := ValidateDestination(context.Background(), &dest, nil, fakeNamespace)
assert.NoError(t, appCond)
assert.Nil(t, appCond)
assert.False(t, dest.IsServerInferred())
})
@@ -111,7 +111,7 @@ func TestValidateDestination(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(objects...)
appCond := ValidateDestination(context.Background(), &dest, kubeclientset, fakeNamespace)
assert.NoError(t, appCond)
assert.Nil(t, appCond)
assert.Equal(t, "https://127.0.0.1:6443", dest.Server)
assert.True(t, dest.IsServerInferred())
})

View File

@@ -2,16 +2,15 @@ package utils
import (
"fmt"
"sort"
"strconv"
"strings"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/klog/v2"
"sort"
"strconv"
"strings"
)
var (

View File

@@ -828,7 +828,7 @@ func TestRenderTemplateParamsFinalizers(t *testing.T) {
render := Render{}
res, err := render.RenderTemplateParams(application, c.syncPolicy, params, true, nil)
assert.NoError(t, err)
assert.Nil(t, err)
assert.ElementsMatch(t, res.Finalizers, c.expectedFinalizers)
@@ -842,9 +842,9 @@ func TestCheckInvalidGenerators(t *testing.T) {
scheme := runtime.NewScheme()
err := argoappsv1.AddToScheme(scheme)
assert.NoError(t, err)
assert.Nil(t, err)
err = argoappsv1.AddToScheme(scheme)
assert.NoError(t, err)
assert.Nil(t, err)
for _, c := range []struct {
testName string
@@ -946,9 +946,9 @@ func TestInvalidGenerators(t *testing.T) {
scheme := runtime.NewScheme()
err := argoappsv1.AddToScheme(scheme)
assert.NoError(t, err)
assert.Nil(t, err)
err = argoappsv1.AddToScheme(scheme)
assert.NoError(t, err)
assert.Nil(t, err)
for _, c := range []struct {
testName string

View File

@@ -179,9 +179,9 @@ func TestWebhookHandler(t *testing.T) {
fakeClient := newFakeClient(namespace)
scheme := runtime.NewScheme()
err := v1alpha1.AddToScheme(scheme)
assert.NoError(t, err)
assert.Nil(t, err)
err = v1alpha1.AddToScheme(scheme)
assert.NoError(t, err)
assert.Nil(t, err)
for _, test := range tt {
t.Run(test.desc, func(t *testing.T) {
@@ -205,7 +205,7 @@ func TestWebhookHandler(t *testing.T) {
).Build()
set := argosettings.NewSettingsManager(context.TODO(), fakeClient, namespace)
h, err := NewWebhookHandler(namespace, set, fc, mockGenerators())
assert.NoError(t, err)
assert.Nil(t, err)
req := httptest.NewRequest(http.MethodPost, "/api/webhook", nil)
req.Header.Set(test.headerKey, test.headerValue)
@@ -219,7 +219,7 @@ func TestWebhookHandler(t *testing.T) {
list := &v1alpha1.ApplicationSetList{}
err = fc.List(context.TODO(), list)
assert.NoError(t, err)
assert.Nil(t, err)
effectedAppSetsAsExpected := make(map[string]bool)
for _, appSetName := range test.effectedAppSets {
effectedAppSetsAsExpected[appSetName] = false

View File

@@ -384,7 +384,7 @@
"parameters": [
{
"type": "string",
"description": "Name must be unique within a namespace. Is required when creating resources, although\nsome resources may allow a client to request the generation of an appropriate name\nautomatically. Name is primarily intended for creation idempotence and configuration\ndefinition.\nCannot be updated.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names\n+optional",
"description": "Name must be unique within a namespace. Is required when creating resources, although\nsome resources may allow a client to request the generation of an appropriate name\nautomatically. Name is primarily intended for creation idempotence and configuration\ndefinition.\nCannot be updated.\nMore info: http://kubernetes.io/docs/user-guide/identifiers#names\n+optional",
"name": "application.metadata.name",
"in": "path",
"required": true
@@ -2030,43 +2030,6 @@
}
}
},
"/api/v1/applicationsets/{name}/resource-tree": {
"get": {
"tags": [
"ApplicationSetService"
],
"summary": "ResourceTree returns resource tree",
"operationId": "ApplicationSetService_ResourceTree",
"parameters": [
{
"type": "string",
"name": "name",
"in": "path",
"required": true
},
{
"type": "string",
"description": "The application set namespace. Default empty is argocd control plane namespace.",
"name": "appsetNamespace",
"in": "query"
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1alpha1ApplicationSetTree"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
}
}
},
"/api/v1/certificates": {
"get": {
"tags": [
@@ -2968,7 +2931,7 @@
"parameters": [
{
"type": "string",
"description": "Name must be unique within a namespace. Is required when creating resources, although\nsome resources may allow a client to request the generation of an appropriate name\nautomatically. Name is primarily intended for creation idempotence and configuration\ndefinition.\nCannot be updated.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names\n+optional",
"description": "Name must be unique within a namespace. Is required when creating resources, although\nsome resources may allow a client to request the generation of an appropriate name\nautomatically. Name is primarily intended for creation idempotence and configuration\ndefinition.\nCannot be updated.\nMore info: http://kubernetes.io/docs/user-guide/identifiers#names\n+optional",
"name": "project.metadata.name",
"in": "path",
"required": true
@@ -3171,7 +3134,7 @@
"parameters": [
{
"type": "string",
"description": "URL is the URL to which these credentials match",
"description": "URL is the URL that this credentials matches to",
"name": "creds.url",
"in": "path",
"required": true
@@ -3251,12 +3214,6 @@
"description": "Whether to force a cache refresh on repo's connection state.",
"name": "forceRefresh",
"in": "query"
},
{
"type": "string",
"description": "App project for query.",
"name": "appProject",
"in": "query"
}
],
"responses": {
@@ -3379,12 +3336,6 @@
"description": "Whether to force a cache refresh on repo's connection state.",
"name": "forceRefresh",
"in": "query"
},
{
"type": "string",
"description": "App project for query.",
"name": "appProject",
"in": "query"
}
],
"responses": {
@@ -3421,12 +3372,6 @@
"description": "Whether to force a cache refresh on repo's connection state.",
"name": "forceRefresh",
"in": "query"
},
{
"type": "string",
"description": "App project for query.",
"name": "appProject",
"in": "query"
}
],
"responses": {
@@ -3511,12 +3456,6 @@
"description": "Whether to force a cache refresh on repo's connection state.",
"name": "forceRefresh",
"in": "query"
},
{
"type": "string",
"description": "App project for query.",
"name": "appProject",
"in": "query"
}
],
"responses": {
@@ -3554,12 +3493,6 @@
"description": "Whether to force a cache refresh on repo's connection state.",
"name": "forceRefresh",
"in": "query"
},
{
"type": "string",
"description": "App project for query.",
"name": "appProject",
"in": "query"
}
],
"responses": {
@@ -5433,8 +5366,8 @@
"type": "object",
"properties": {
"key": {
"description": "key is the label key that the selector applies to.",
"type": "string"
"type": "string",
"title": "key is the label key that the selector applies to.\n+patchMergeKey=key\n+patchStrategy=merge"
},
"operator": {
"description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.",
@@ -5484,10 +5417,6 @@
"type": "string",
"title": "IP is set for load-balancer ingress points that are IP based\n(typically GCE or OpenStack load-balancers)\n+optional"
},
"ipMode": {
"type": "string",
"title": "IPMode specifies how the load-balancer IP behaves, and may only be specified when the ip field is specified.\nSetting this to \"VIP\" indicates that traffic is delivered to the node with\nthe destination set to the load-balancer's IP and port.\nSetting this to \"Proxy\" indicates that traffic is delivered to the node or pod with\nthe destination set to the node's IP and node port or the pod's IP and port.\nService implementations may use this information to adjust traffic routing.\n+optional"
},
"ports": {
"type": "array",
"title": "Ports is a list of records of service ports\nIf used, every port defined in the service should have an entry in it\n+listType=atomic\n+optional",
@@ -5597,7 +5526,7 @@
"properties": {
"annotations": {
"type": "object",
"title": "Annotations is an unstructured key value map stored with a resource that may be\nset by external tools to store and retrieve arbitrary metadata. They are not\nqueryable and should be preserved when modifying objects.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations\n+optional",
"title": "Annotations is an unstructured key value map stored with a resource that may be\nset by external tools to store and retrieve arbitrary metadata. They are not\nqueryable and should be preserved when modifying objects.\nMore info: http://kubernetes.io/docs/user-guide/annotations\n+optional",
"additionalProperties": {
"type": "string"
}
@@ -5631,7 +5560,7 @@
},
"labels": {
"type": "object",
"title": "Map of string keys and values that can be used to organize and categorize\n(scope and select) objects. May match selectors of replication controllers\nand services.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels\n+optional",
"title": "Map of string keys and values that can be used to organize and categorize\n(scope and select) objects. May match selectors of replication controllers\nand services.\nMore info: http://kubernetes.io/docs/user-guide/labels\n+optional",
"additionalProperties": {
"type": "string"
}
@@ -5645,10 +5574,10 @@
},
"name": {
"type": "string",
"title": "Name must be unique within a namespace. Is required when creating resources, although\nsome resources may allow a client to request the generation of an appropriate name\nautomatically. Name is primarily intended for creation idempotence and configuration\ndefinition.\nCannot be updated.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names\n+optional"
"title": "Name must be unique within a namespace. Is required when creating resources, although\nsome resources may allow a client to request the generation of an appropriate name\nautomatically. Name is primarily intended for creation idempotence and configuration\ndefinition.\nCannot be updated.\nMore info: http://kubernetes.io/docs/user-guide/identifiers#names\n+optional"
},
"namespace": {
"description": "Namespace defines the space within which each name must be unique. An empty namespace is\nequivalent to the \"default\" namespace, but \"default\" is the canonical representation.\nNot all objects are required to be scoped to a namespace - the value of this field for\nthose objects will be empty.\n\nMust be a DNS_LABEL.\nCannot be updated.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces\n+optional",
"description": "Namespace defines the space within which each name must be unique. An empty namespace is\nequivalent to the \"default\" namespace, but \"default\" is the canonical representation.\nNot all objects are required to be scoped to a namespace - the value of this field for\nthose objects will be empty.\n\nMust be a DNS_LABEL.\nCannot be updated.\nMore info: http://kubernetes.io/docs/user-guide/namespaces\n+optional",
"type": "string"
},
"ownerReferences": {
@@ -5667,7 +5596,7 @@
"title": "Deprecated: selfLink is a legacy read-only field that is no longer populated by the system.\n+optional"
},
"uid": {
"description": "UID is the unique in time and space value for this object. It is typically generated by\nthe server on successful creation of a resource and is not allowed to change on PUT\noperations.\n\nPopulated by the system.\nRead-only.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids\n+optional",
"description": "UID is the unique in time and space value for this object. It is typically generated by\nthe server on successful creation of a resource and is not allowed to change on PUT\noperations.\n\nPopulated by the system.\nRead-only.\nMore info: http://kubernetes.io/docs/user-guide/identifiers#uids\n+optional",
"type": "string"
}
}
@@ -5728,11 +5657,11 @@
},
"name": {
"type": "string",
"title": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names"
"title": "Name of the referent.\nMore info: http://kubernetes.io/docs/user-guide/identifiers#names"
},
"uid": {
"type": "string",
"title": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids"
"title": "UID of the referent.\nMore info: http://kubernetes.io/docs/user-guide/identifiers#uids"
}
}
},
@@ -5909,7 +5838,7 @@
},
"v1alpha1Application": {
"type": "object",
"title": "Application is a definition of Application resource.\n+genclient\n+genclient:noStatus\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+kubebuilder:resource:path=applications,shortName=app;apps\n+kubebuilder:printcolumn:name=\"Sync Status\",type=string,JSONPath=`.status.sync.status`\n+kubebuilder:printcolumn:name=\"Health Status\",type=string,JSONPath=`.status.health.status`\n+kubebuilder:printcolumn:name=\"Revision\",type=string,JSONPath=`.status.sync.revision`,priority=10\n+kubebuilder:printcolumn:name=\"Project\",type=string,JSONPath=`.spec.project`,priority=10",
"title": "Application is a definition of Application resource.\n+genclient\n+genclient:noStatus\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+kubebuilder:resource:path=applications,shortName=app;apps\n+kubebuilder:printcolumn:name=\"Sync Status\",type=string,JSONPath=`.status.sync.status`\n+kubebuilder:printcolumn:name=\"Health Status\",type=string,JSONPath=`.status.health.status`\n+kubebuilder:printcolumn:name=\"Revision\",type=string,JSONPath=`.status.sync.revision`,priority=10",
"properties": {
"metadata": {
"$ref": "#/definitions/v1ObjectMeta"
@@ -6046,19 +5975,12 @@
"step": {
"type": "string",
"title": "Step tracks which step this Application should be updated in"
},
"targetrevisions": {
"description": "TargetRevision tracks the desired revisions the Application should be synced to.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
"v1alpha1ApplicationSetCondition": {
"type": "object",
"title": "ApplicationSetCondition contains details about an applicationset condition, which is usually an error or warning",
"title": "ApplicationSetCondition contains details about an applicationset condition, which is usally an error or warning",
"properties": {
"lastTransitionTime": {
"$ref": "#/definitions/v1Time"
@@ -6279,13 +6201,6 @@
"items": {
"$ref": "#/definitions/v1alpha1ApplicationSetCondition"
}
},
"resources": {
"description": "Resources is a list of Applications resources managed by this application set.",
"type": "array",
"items": {
"$ref": "#/definitions/v1alpha1ResourceStatus"
}
}
}
},
@@ -6357,19 +6272,6 @@
}
}
},
"v1alpha1ApplicationSetTree": {
"type": "object",
"title": "ApplicationSetTree holds nodes which belongs to the application\nUsed to build a tree of an ApplicationSet and its children",
"properties": {
"nodes": {
"type": "array",
"title": "Nodes contains list of nodes which are directly managed by the applicationset",
"items": {
"$ref": "#/definitions/v1alpha1ResourceNode"
}
}
}
},
"v1alpha1ApplicationSource": {
"type": "object",
"title": "ApplicationSource contains all required information about the source of an application",
@@ -8095,7 +7997,7 @@
},
"url": {
"type": "string",
"title": "URL is the URL to which these credentials match"
"title": "URL is the URL that this credentials matches to"
},
"username": {
"type": "string",
@@ -8181,7 +8083,7 @@
},
"project": {
"type": "string",
"title": "Reference between project and repository that allows it to be automatically added as an item inside SourceRepos project entity"
"title": "Reference between project and repository that allow you automatically to be added as item inside SourceRepos project entity"
},
"proxy": {
"type": "string",

View File

@@ -220,7 +220,7 @@ func NewCommand() *cobra.Command {
command.Flags().StringSliceVar(&otlpAttrs, "otlp-attrs", env.StringsFromEnv("ARGOCD_APPLICATION_CONTROLLER_OTLP_ATTRS", []string{}, ","), "List of OpenTelemetry collector extra attrs when send traces, each attribute is separated by a colon(e.g. key:value)")
command.Flags().StringSliceVar(&applicationNamespaces, "application-namespaces", env.StringsFromEnv("ARGOCD_APPLICATION_NAMESPACES", []string{}, ","), "List of additional namespaces that applications are allowed to be reconciled from")
command.Flags().BoolVar(&persistResourceHealth, "persist-resource-health", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_PERSIST_RESOURCE_HEALTH", true), "Enables storing the managed resources health in the Application CRD")
command.Flags().StringVar(&shardingAlgorithm, "sharding-method", env.StringFromEnv(common.EnvControllerShardingAlgorithm, common.DefaultShardingAlgorithm), "Enables choice of sharding method. Supported sharding methods are : [legacy, round-robin, consistent-hashing] ")
command.Flags().StringVar(&shardingAlgorithm, "sharding-method", env.StringFromEnv(common.EnvControllerShardingAlgorithm, common.DefaultShardingAlgorithm), "Enables choice of sharding method. Supported sharding methods are : [legacy, round-robin] ")
// global queue rate limit config
command.Flags().Int64Var(&workqueueRateLimit.BucketSize, "wq-bucket-size", env.ParseInt64FromEnv("WORKQUEUE_BUCKET_SIZE", 500, 1, math.MaxInt64), "Set Workqueue Rate Limiter Bucket Size, default 500")
command.Flags().Float64Var(&workqueueRateLimit.BucketQPS, "wq-bucket-qps", env.ParseFloat64FromEnv("WORKQUEUE_BUCKET_QPS", math.MaxFloat64, 1, math.MaxFloat64), "Set Workqueue Rate Limiter Bucket QPS, default set to MaxFloat64 which disables the bucket limiter")

View File

@@ -30,9 +30,6 @@ import (
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/tools/clientcmd"
ctrlcache "sigs.k8s.io/controller-runtime/pkg/cache"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"github.com/argoproj/argo-cd/v2/applicationset/services"
appv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
@@ -105,7 +102,7 @@ func NewCommand() *cobra.Command {
os.Exit(1)
}
// By default, watch all namespaces
// By default watch all namespace
var watchedNamespace string = ""
// If the applicationset-namespaces contains only one namespace it corresponds to the current namespace
@@ -116,28 +113,15 @@ func NewCommand() *cobra.Command {
os.Exit(1)
}
var cacheOpt ctrlcache.Options
if watchedNamespace != "" {
cacheOpt = ctrlcache.Options{
DefaultNamespaces: map[string]ctrlcache.Config{
watchedNamespace: {},
},
}
}
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: metricsserver.Options{
BindAddress: metricsAddr,
},
Cache: cacheOpt,
Scheme: scheme,
MetricsBindAddress: metricsAddr,
Namespace: watchedNamespace,
HealthProbeBindAddress: probeBindAddr,
Port: 9443,
LeaderElection: enableLeaderElection,
LeaderElectionID: "58ac56fa.applicationsets.argoproj.io",
Client: ctrlclient.Options{
DryRun: &dryRun,
},
DryRunClient: dryRun,
})
if err != nil {
@@ -172,7 +156,7 @@ func NewCommand() *cobra.Command {
}
repoClientset := apiclient.NewRepoServerClientset(argocdRepoServer, repoServerTimeoutSeconds, tlsConfig)
argoCDService, err := services.NewArgoCDService(argoCDDB.GetRepository, gitSubmoduleEnabled, repoClientset, enableNewGitFileGlobbing)
argoCDService, err := services.NewArgoCDService(argoCDDB, gitSubmoduleEnabled, repoClientset, enableNewGitFileGlobbing)
errors.CheckError(err)
terminalGenerators := map[string]generators.Generator{

View File

@@ -70,7 +70,6 @@ func NewCommand() *cobra.Command {
helmManifestMaxExtractedSize string
helmRegistryMaxIndexSize string
disableManifestMaxExtractedSize bool
includeHiddenDirectories bool
)
var command = cobra.Command{
Use: cliName,
@@ -131,7 +130,6 @@ func NewCommand() *cobra.Command {
StreamedManifestMaxTarSize: streamedManifestMaxTarSizeQuantity.ToDec().Value(),
HelmManifestMaxExtractedSize: helmManifestMaxExtractedSizeQuantity.ToDec().Value(),
HelmRegistryMaxIndexSize: helmRegistryMaxIndexSizeQuantity.ToDec().Value(),
IncludeHiddenDirectories: includeHiddenDirectories,
}, askPassServer)
errors.CheckError(err)
@@ -217,7 +215,6 @@ func NewCommand() *cobra.Command {
command.Flags().StringVar(&helmManifestMaxExtractedSize, "helm-manifest-max-extracted-size", env.StringFromEnv("ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE", "1G"), "Maximum size of helm manifest archives when extracted")
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")
tlsConfigCustomizerSrc = tls.AddTLSFlagsToCmd(&command)
cacheSrc = reposervercache.AddCacheFlagsToCmd(&command, cacheutil.Options{
OnClientCreated: func(client *redis.Client) {

View File

@@ -19,7 +19,7 @@ import (
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/utils/ptr"
"k8s.io/utils/pointer"
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
"github.com/argoproj/argo-cd/v2/common"
@@ -141,7 +141,7 @@ func loadClusters(ctx context.Context, kubeClient *kubernetes.Clientset, appClie
cluster := batch[i]
if replicas > 0 {
clusterShard = clusterShards[cluster.Server]
cluster.Shard = ptr.To(int64(clusterShard))
cluster.Shard = pointer.Int64(int64(clusterShard))
log.Infof("Cluster with uid: %s will be processed by shard %d", cluster.ID, clusterShard)
}
if shard != -1 && clusterShard != shard {
@@ -219,7 +219,7 @@ func NewClusterShardsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comm
clientConfig = cli.AddKubectlFlagsToCmd(&command)
command.Flags().IntVar(&shard, "shard", -1, "Cluster shard filter")
command.Flags().IntVar(&replicas, "replicas", 0, "Application controller replicas count. Inferred from number of running controller pods if not specified")
command.Flags().StringVar(&shardingAlgorithm, "sharding-method", common.DefaultShardingAlgorithm, "Sharding method. Defaults: legacy. Supported sharding methods are : [legacy, round-robin, consistent-hashing] ")
command.Flags().StringVar(&shardingAlgorithm, "sharding-method", common.DefaultShardingAlgorithm, "Sharding method. Defaults: legacy. Supported sharding methods are : [legacy, round-robin] ")
command.Flags().BoolVar(&portForwardRedis, "port-forward-redis", true, "Automatically port-forward ha proxy redis from current namespace?")
cacheSrc = appstatecache.AddCacheFlagsToCmd(&command)
@@ -514,7 +514,7 @@ argocd admin cluster stats target-cluster`,
clientConfig = cli.AddKubectlFlagsToCmd(&command)
command.Flags().IntVar(&shard, "shard", -1, "Cluster shard filter")
command.Flags().IntVar(&replicas, "replicas", 0, "Application controller replicas count. Inferred from number of running controller pods if not specified")
command.Flags().StringVar(&shardingAlgorithm, "sharding-method", common.DefaultShardingAlgorithm, "Sharding method. Defaults: legacy. Supported sharding methods are : [legacy, round-robin, consistent-hashing] ")
command.Flags().StringVar(&shardingAlgorithm, "sharding-method", common.DefaultShardingAlgorithm, "Sharding method. Defaults: legacy. Supported sharding methods are : [legacy, round-robin] ")
command.Flags().BoolVar(&portForwardRedis, "port-forward-redis", true, "Automatically port-forward ha proxy redis from current namespace?")
cacheSrc = appstatecache.AddCacheFlagsToCmd(&command)

View File

@@ -3,11 +3,10 @@ package admin
import (
"fmt"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/spf13/cobra"
"k8s.io/client-go/tools/clientcmd"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/initialize"
"github.com/argoproj/argo-cd/v2/common"

View File

@@ -15,10 +15,9 @@ import (
settings "github.com/argoproj/argo-cd/v2/util/notification/settings"
"github.com/argoproj/argo-cd/v2/util/tls"
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
"github.com/argoproj/notifications-engine/pkg/cmd"
"github.com/spf13/cobra"
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
)
var (

View File

@@ -40,7 +40,7 @@ func TestUpdateProjects_FindMatchingProject(t *testing.T) {
fooProj, err := clientset.ArgoprojV1alpha1().AppProjects(namespace).Get(ctx, "foo", v1.GetOptions{})
assert.NoError(t, err)
assert.Empty(t, fooProj.Spec.Roles[0].Policies)
assert.Len(t, fooProj.Spec.Roles[0].Policies, 0)
barProj, err := clientset.ArgoprojV1alpha1().AppProjects(namespace).Get(ctx, "bar", v1.GetOptions{})
assert.NoError(t, err)
@@ -60,7 +60,7 @@ func TestUpdateProjects_FindMatchingRole(t *testing.T) {
proj, err := clientset.ArgoprojV1alpha1().AppProjects(namespace).Get(ctx, "proj", v1.GetOptions{})
assert.NoError(t, err)
assert.EqualValues(t, proj.Spec.Roles[0].Policies, []string{"p, proj:proj:foo, *, set, proj/*, allow"})
assert.Empty(t, proj.Spec.Roles[1].Policies)
assert.Len(t, proj.Spec.Roles[1].Policies, 0)
}
func TestGetModification_SetPolicy(t *testing.T) {

View File

@@ -6,18 +6,16 @@ import (
"fmt"
"math/big"
apierr "k8s.io/apimachinery/pkg/api/errors"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/cli"
apierr "k8s.io/apimachinery/pkg/api/errors"
"github.com/argoproj/argo-cd/v2/util/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"github.com/argoproj/argo-cd/v2/util/errors"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
)

View File

@@ -157,7 +157,7 @@ func NewGenRepoSpecCommand() *cobra.Command {
_, err := argoDB.CreateRepository(ctx, &repoOpts.Repo)
errors.CheckError(err)
secret, err := kubeClientset.CoreV1().Secrets(ArgoCDNamespace).Get(ctx, db.RepoURLToSecretName(repoSecretPrefix, repoOpts.Repo.Repo, repoOpts.Repo.Project), v1.GetOptions{})
secret, err := kubeClientset.CoreV1().Secrets(ArgoCDNamespace).Get(ctx, db.RepoURLToSecretName(repoSecretPrefix, repoOpts.Repo.Repo), v1.GetOptions{})
errors.CheckError(err)
errors.CheckError(PrintResources(outputFormat, os.Stdout, secret))

View File

@@ -21,12 +21,6 @@ import (
"github.com/argoproj/argo-cd/v2/util/rbac"
)
type actionTraitMap map[string]rbacTrait
type rbacTrait struct {
allowPath bool
}
// Provide a mapping of short-hand resource names to their RBAC counterparts
var resourceMap map[string]string = map[string]string{
"account": rbacpolicy.ResourceAccounts,
@@ -38,7 +32,6 @@ var resourceMap map[string]string = map[string]string{
"certs": rbacpolicy.ResourceCertificates,
"certificate": rbacpolicy.ResourceCertificates,
"cluster": rbacpolicy.ResourceClusters,
"extension": rbacpolicy.ResourceExtensions,
"gpgkey": rbacpolicy.ResourceGPGKeys,
"key": rbacpolicy.ResourceGPGKeys,
"log": rbacpolicy.ResourceLogs,
@@ -53,53 +46,28 @@ var resourceMap map[string]string = map[string]string{
}
// List of allowed RBAC resources
var validRBACResourcesActions map[string]actionTraitMap = map[string]actionTraitMap{
rbacpolicy.ResourceAccounts: accountsActions,
rbacpolicy.ResourceApplications: applicationsActions,
rbacpolicy.ResourceApplicationSets: defaultCRUDActions,
rbacpolicy.ResourceCertificates: defaultCRDActions,
rbacpolicy.ResourceClusters: defaultCRUDActions,
rbacpolicy.ResourceExtensions: extensionActions,
rbacpolicy.ResourceGPGKeys: defaultCRDActions,
rbacpolicy.ResourceLogs: logsActions,
rbacpolicy.ResourceExec: execActions,
rbacpolicy.ResourceProjects: defaultCRUDActions,
rbacpolicy.ResourceRepositories: defaultCRUDActions,
var validRBACResources map[string]bool = map[string]bool{
rbacpolicy.ResourceAccounts: true,
rbacpolicy.ResourceApplications: true,
rbacpolicy.ResourceApplicationSets: true,
rbacpolicy.ResourceCertificates: true,
rbacpolicy.ResourceClusters: true,
rbacpolicy.ResourceGPGKeys: true,
rbacpolicy.ResourceLogs: true,
rbacpolicy.ResourceExec: true,
rbacpolicy.ResourceProjects: true,
rbacpolicy.ResourceRepositories: true,
}
// List of allowed RBAC actions
var defaultCRUDActions = actionTraitMap{
rbacpolicy.ActionCreate: rbacTrait{},
rbacpolicy.ActionGet: rbacTrait{},
rbacpolicy.ActionUpdate: rbacTrait{},
rbacpolicy.ActionDelete: rbacTrait{},
}
var defaultCRDActions = actionTraitMap{
rbacpolicy.ActionCreate: rbacTrait{},
rbacpolicy.ActionGet: rbacTrait{},
rbacpolicy.ActionDelete: rbacTrait{},
}
var applicationsActions = actionTraitMap{
rbacpolicy.ActionCreate: rbacTrait{},
rbacpolicy.ActionGet: rbacTrait{},
rbacpolicy.ActionUpdate: rbacTrait{allowPath: true},
rbacpolicy.ActionDelete: rbacTrait{allowPath: true},
rbacpolicy.ActionAction: rbacTrait{allowPath: true},
rbacpolicy.ActionOverride: rbacTrait{},
rbacpolicy.ActionSync: rbacTrait{},
}
var accountsActions = actionTraitMap{
rbacpolicy.ActionCreate: rbacTrait{},
rbacpolicy.ActionUpdate: rbacTrait{},
}
var execActions = actionTraitMap{
rbacpolicy.ActionCreate: rbacTrait{},
}
var logsActions = actionTraitMap{
rbacpolicy.ActionGet: rbacTrait{},
}
var extensionActions = actionTraitMap{
rbacpolicy.ActionInvoke: rbacTrait{},
var validRBACActions map[string]bool = map[string]bool{
rbacpolicy.ActionAction: true,
rbacpolicy.ActionCreate: true,
rbacpolicy.ActionDelete: true,
rbacpolicy.ActionGet: true,
rbacpolicy.ActionOverride: true,
rbacpolicy.ActionSync: true,
rbacpolicy.ActionUpdate: true,
}
// NewRBACCommand is the command for 'rbac'
@@ -253,8 +221,8 @@ argocd admin settings rbac validate --policy-file policy.csv
# i.e. 'policy.csv' and (optionally) 'policy.default'
argocd admin settings rbac validate --policy-file argocd-rbac-cm.yaml
# If --policy-file is not given, and instead --namespace is giventhe ConfigMap 'argocd-rbac-cm'
# from K8s is used.
# If --policy-file is not given, and instead --namespace is giventhe ConfigMap 'argocd-rbac-cm'
# from K8s is used.
argocd admin settings rbac validate --namespace argocd
# Either --policy-file or --namespace must be given.
@@ -408,9 +376,11 @@ func checkPolicy(subject, action, resource, subResource, builtinPolicy, userPoli
// If in strict mode, validate that given RBAC resource and action are
// actually valid tokens.
if strict {
if err := validateRBACResourceAction(realResource, action); err != nil {
log.Fatalf("error in RBAC request: %v", err)
return false
if !isValidRBACResource(realResource) {
log.Fatalf("error in RBAC request: '%s' is not a valid resource name", realResource)
}
if !isValidRBACAction(action) {
log.Fatalf("error in RBAC request: '%s' is not a valid action name", action)
}
}
@@ -436,18 +406,17 @@ func resolveRBACResourceName(name string) string {
}
}
// validateRBACResourceAction checks whether a given resource is a valid RBAC resource.
// If it is, it validates that the action is a valid RBAC action for this resource.
func validateRBACResourceAction(resource, action string) error {
validActions, ok := validRBACResourcesActions[resource]
if !ok {
return fmt.Errorf("'%s' is not a valid resource name", resource)
// isValidRBACAction checks whether a given action is a valid RBAC action
func isValidRBACAction(action string) bool {
if strings.HasPrefix(action, rbacpolicy.ActionAction+"/") {
return true
}
realAction, _, hasPath := strings.Cut(action, "/")
actionTrait, ok := validActions[realAction]
if !ok || hasPath && !actionTrait.allowPath {
return fmt.Errorf("'%s' is not a valid action for %s", action, resource)
}
return nil
_, ok := validRBACActions[action]
return ok
}
// isValidRBACResource checks whether a given resource is a valid RBAC resource
func isValidRBACResource(resource string) bool {
_, ok := validRBACResources[resource]
return ok
}

View File

@@ -5,6 +5,7 @@ import (
"os"
"testing"
"github.com/argoproj/argo-cd/v2/util/assets"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
@@ -13,9 +14,6 @@ import (
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"github.com/argoproj/argo-cd/v2/server/rbacpolicy"
"github.com/argoproj/argo-cd/v2/util/assets"
)
type FakeClientConfig struct {
@@ -43,75 +41,35 @@ func (f *FakeClientConfig) ConfigAccess() clientcmd.ConfigAccess {
return nil
}
func Test_validateRBACResourceAction(t *testing.T) {
type args struct {
resource string
action string
}
tests := []struct {
name string
args args
valid bool
}{
{
name: "Test valid resource and action",
args: args{
resource: rbacpolicy.ResourceApplications,
action: rbacpolicy.ActionCreate,
},
valid: true,
},
{
name: "Test invalid resource",
args: args{
resource: "invalid",
},
valid: false,
},
{
name: "Test invalid action",
args: args{
resource: rbacpolicy.ResourceApplications,
action: "invalid",
},
valid: false,
},
{
name: "Test invalid action for resource",
args: args{
resource: rbacpolicy.ResourceLogs,
action: rbacpolicy.ActionCreate,
},
valid: false,
},
{
name: "Test valid action with path",
args: args{
resource: rbacpolicy.ResourceApplications,
action: rbacpolicy.ActionAction + "/apps/Deployment/restart",
},
valid: true,
},
{
name: "Test invalid action with path",
args: args{
resource: rbacpolicy.ResourceApplications,
action: rbacpolicy.ActionGet + "/apps/Deployment/restart",
},
valid: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := validateRBACResourceAction(tt.args.resource, tt.args.action)
if tt.valid {
assert.NoError(t, result)
} else {
assert.Error(t, result)
}
func Test_isValidRBACAction(t *testing.T) {
for k := range validRBACActions {
t.Run(k, func(t *testing.T) {
ok := isValidRBACAction(k)
assert.True(t, ok)
})
}
t.Run("invalid", func(t *testing.T) {
ok := isValidRBACAction("invalid")
assert.False(t, ok)
})
}
func Test_isValidRBACAction_ActionAction(t *testing.T) {
ok := isValidRBACAction("action/apps/Deployment/restart")
assert.True(t, ok)
}
func Test_isValidRBACResource(t *testing.T) {
for k := range validRBACResources {
t.Run(k, func(t *testing.T) {
ok := isValidRBACResource(k)
assert.True(t, ok)
})
}
t.Run("invalid", func(t *testing.T) {
ok := isValidRBACResource("invalid")
assert.False(t, ok)
})
}
func Test_PolicyFromCSV(t *testing.T) {

View File

@@ -29,7 +29,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
k8swatch "k8s.io/apimachinery/pkg/watch"
"k8s.io/utils/ptr"
"k8s.io/utils/pointer"
"sigs.k8s.io/yaml"
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
@@ -51,7 +51,6 @@ import (
"github.com/argoproj/argo-cd/v2/util/git"
"github.com/argoproj/argo-cd/v2/util/grpc"
argoio "github.com/argoproj/argo-cd/v2/util/io"
logutils "github.com/argoproj/argo-cd/v2/util/log"
"github.com/argoproj/argo-cd/v2/util/manifeststream"
"github.com/argoproj/argo-cd/v2/util/templates"
"github.com/argoproj/argo-cd/v2/util/text/label"
@@ -497,16 +496,16 @@ func NewApplicationLogsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
stream, err := appIf.PodLogs(ctx, &application.ApplicationPodLogsQuery{
Name: &appName,
Group: &group,
Namespace: ptr.To(namespace),
Namespace: pointer.String(namespace),
Kind: &kind,
ResourceName: &resourceName,
Follow: ptr.To(follow),
TailLines: ptr.To(tail),
SinceSeconds: ptr.To(sinceSeconds),
Follow: pointer.Bool(follow),
TailLines: pointer.Int64(tail),
SinceSeconds: pointer.Int64(sinceSeconds),
UntilTime: &untilTime,
Filter: &filter,
Container: ptr.To(container),
Previous: ptr.To(previous),
Container: pointer.String(container),
Previous: pointer.Bool(previous),
AppNamespace: &appNs,
})
if err != nil {
@@ -1313,7 +1312,6 @@ func findandPrintDiff(ctx context.Context, app *argoappv1.Application, proj *arg
WithDiffSettings(app.Spec.IgnoreDifferences, overrides, ignoreAggregatedRoles, ignoreNormalizerOpts).
WithTracking(argoSettings.AppLabelKey, argoSettings.TrackingMethod).
WithNoCache().
WithLogger(logutils.NewLogrusLogger(logutils.NewWithCurrentConfig())).
Build()
errors.CheckError(err)
diffRes, err := argodiff.StateDiff(item.live, item.target, diffConfig)
@@ -1557,7 +1555,7 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie()
defer argoio.Close(conn)
apps, err := appIf.List(ctx, &application.ApplicationQuery{
Selector: ptr.To(selector),
Selector: pointer.String(selector),
AppNamespace: &appNamespace,
})
@@ -1749,7 +1747,7 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
closer, appIf := acdClient.NewApplicationClientOrDie()
defer argoio.Close(closer)
if selector != "" {
list, err := appIf.List(ctx, &application.ApplicationQuery{Selector: ptr.To(selector)})
list, err := appIf.List(ctx, &application.ApplicationQuery{Selector: pointer.String(selector)})
errors.CheckError(err)
for _, i := range list.Items {
appNames = append(appNames, i.QualifiedName())
@@ -1899,7 +1897,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
appNames := args
if selector != "" || len(projects) > 0 {
list, err := appIf.List(ctx, &application.ApplicationQuery{
Selector: ptr.To(selector),
Selector: pointer.String(selector),
AppNamespace: &appNamespace,
Projects: projects})
errors.CheckError(err)
@@ -2071,7 +2069,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
Backoff: &argoappv1.Backoff{
Duration: retryBackoffDuration.String(),
MaxDuration: retryBackoffMaxDuration.String(),
Factor: ptr.To(retryBackoffFactor),
Factor: pointer.Int64(retryBackoffFactor),
},
}
}
@@ -2099,8 +2097,6 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
}
} else {
fmt.Printf("====== No Differences found ======\n")
// if no differences found, then no need to sync
return
}
}
_, err = appIf.Sync(ctx, &syncReq)
@@ -2159,7 +2155,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
func getAppNamesBySelector(ctx context.Context, appIf application.ApplicationServiceClient, selector string) ([]string, error) {
appNames := []string{}
if selector != "" {
list, err := appIf.List(ctx, &application.ApplicationQuery{Selector: ptr.To(selector)})
list, err := appIf.List(ctx, &application.ApplicationQuery{Selector: pointer.String(selector)})
if err != nil {
return []string{}, err
}
@@ -2341,7 +2337,7 @@ func checkResourceStatus(watch watchOpts, healthStatus string, syncStatus string
func resourceParentChild(ctx context.Context, acdClient argocdclient.Client, appName string, appNs string) (map[string]argoappv1.ResourceNode, map[string][]string, map[string]struct{}, map[string]*resourceState) {
_, appIf := acdClient.NewApplicationClientOrDie()
mapUidToNode, mapParentToChild, parentNode := parentChildDetails(appIf, ctx, appName, appNs)
app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: ptr.To(appName), AppNamespace: ptr.To(appNs)})
app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: pointer.String(appName), AppNamespace: pointer.String(appNs)})
errors.CheckError(err)
mapNodeNameToResourceState := make(map[string]*resourceState)
for _, res := range getResourceStates(app, nil) {
@@ -2721,8 +2717,8 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr
_, err = appIf.Rollback(ctx, &application.ApplicationRollbackRequest{
Name: &appName,
AppNamespace: &appNs,
Id: ptr.To(depInfo.ID),
Prune: ptr.To(prune),
Id: pointer.Int64(depInfo.ID),
Prune: pointer.Bool(prune),
})
errors.CheckError(err)
@@ -2845,7 +2841,7 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
q := application.ApplicationManifestQuery{
Name: &appName,
AppNamespace: &appNs,
Revision: ptr.To(revision),
Revision: pointer.String(revision),
Revisions: revisions,
SourcePositions: sourcePositions,
}
@@ -2861,7 +2857,7 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob
q := application.ApplicationManifestQuery{
Name: &appName,
AppNamespace: &appNs,
Revision: ptr.To(revision),
Revision: pointer.String(revision),
}
res, err := appIf.GetManifests(ctx, &q)
errors.CheckError(err)

View File

@@ -4,17 +4,16 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/argoproj/argo-cd/v2/util/templates"
"os"
"strconv"
"text/tabwriter"
"github.com/argoproj/argo-cd/v2/util/templates"
"github.com/argoproj/argo-cd/v2/cmd/util"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"k8s.io/utils/ptr"
"k8s.io/utils/pointer"
"sigs.k8s.io/yaml"
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
@@ -97,11 +96,11 @@ func NewApplicationResourceActionsListCommand(clientOpts *argocdclient.ClientOpt
availActionsForResource, err := appIf.ListResourceActions(ctx, &applicationpkg.ApplicationResourceRequest{
Name: &appName,
AppNamespace: &appNs,
Namespace: ptr.To(obj.GetNamespace()),
ResourceName: ptr.To(obj.GetName()),
Group: ptr.To(gvk.Group),
Kind: ptr.To(gvk.Kind),
Version: ptr.To(gvk.Version),
Namespace: pointer.String(obj.GetNamespace()),
ResourceName: pointer.String(obj.GetName()),
Group: pointer.String(gvk.Group),
Kind: pointer.String(gvk.Kind),
Version: pointer.String(gvk.Version),
})
errors.CheckError(err)
for _, action := range availActionsForResource.Actions {
@@ -196,12 +195,12 @@ func NewApplicationResourceActionsRunCommand(clientOpts *argocdclient.ClientOpti
_, err := appIf.RunResourceAction(ctx, &applicationpkg.ResourceActionRunRequest{
Name: &appName,
AppNamespace: &appNs,
Namespace: ptr.To(obj.GetNamespace()),
ResourceName: ptr.To(objResourceName),
Group: ptr.To(gvk.Group),
Kind: ptr.To(gvk.Kind),
Version: ptr.To(gvk.GroupVersion().Version),
Action: ptr.To(actionName),
Namespace: pointer.String(obj.GetNamespace()),
ResourceName: pointer.String(objResourceName),
Group: pointer.String(gvk.Group),
Kind: pointer.String(gvk.Kind),
Version: pointer.String(gvk.GroupVersion().Version),
Action: pointer.String(actionName),
})
errors.CheckError(err)
}

View File

@@ -11,7 +11,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
"k8s.io/utils/pointer"
"github.com/argoproj/argo-cd/v2/cmd/argocd/commands/headless"
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
@@ -71,14 +71,14 @@ func NewApplicationPatchResourceCommand(clientOpts *argocdclient.ClientOptions)
_, err = appIf.PatchResource(ctx, &applicationpkg.ApplicationResourcePatchRequest{
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),
Patch: ptr.To(patch),
PatchType: ptr.To(patchType),
Project: ptr.To(project),
Namespace: pointer.String(obj.GetNamespace()),
ResourceName: pointer.String(obj.GetName()),
Version: pointer.String(gvk.Version),
Group: pointer.String(gvk.Group),
Kind: pointer.String(gvk.Kind),
Patch: pointer.String(patch),
PatchType: pointer.String(patchType),
Project: pointer.String(project),
})
errors.CheckError(err)
log.Infof("Resource '%s' patched", obj.GetName())
@@ -108,8 +108,8 @@ func NewApplicationDeleteResourceCommand(clientOpts *argocdclient.ClientOptions)
errors.CheckError(err)
command.Flags().StringVar(&group, "group", "", "Group")
command.Flags().StringVar(&namespace, "namespace", "", "Namespace")
command.Flags().BoolVar(&force, "force", false, "Indicates whether to force delete the resource")
command.Flags().BoolVar(&orphan, "orphan", false, "Indicates whether to orphan the dependents of the deleted resource")
command.Flags().BoolVar(&force, "force", false, "Indicates whether to orphan the dependents of the deleted resource")
command.Flags().BoolVar(&orphan, "orphan", false, "Indicates whether to force delete the resource")
command.Flags().BoolVar(&all, "all", false, "Indicates whether to patch multiple matching of resources")
command.Flags().StringVar(&project, "project", "", `The name of the application's project - specifying this allows the command to report "not found" instead of "permission denied" if the app does not exist`)
command.Run = func(c *cobra.Command, args []string) {
@@ -136,14 +136,14 @@ func NewApplicationDeleteResourceCommand(clientOpts *argocdclient.ClientOptions)
_, 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),
Namespace: pointer.String(obj.GetNamespace()),
ResourceName: pointer.String(obj.GetName()),
Version: pointer.String(gvk.Version),
Group: pointer.String(gvk.Group),
Kind: pointer.String(gvk.Kind),
Force: &force,
Orphan: &orphan,
Project: ptr.To(project),
Project: pointer.String(project),
})
errors.CheckError(err)
log.Infof("Resource '%s' deleted", obj.GetName())

View File

@@ -223,10 +223,10 @@ func TestDefaultWaitOptions(t *testing.T) {
suspended: false,
}
opts := getWatchOpts(watch)
assert.True(t, opts.sync)
assert.True(t, opts.health)
assert.True(t, opts.operation)
assert.False(t, opts.suspended)
assert.Equal(t, true, opts.sync)
assert.Equal(t, true, opts.health)
assert.Equal(t, true, opts.operation)
assert.Equal(t, false, opts.suspended)
}
func TestOverrideWaitOptions(t *testing.T) {
@@ -237,10 +237,10 @@ func TestOverrideWaitOptions(t *testing.T) {
suspended: false,
}
opts := getWatchOpts(watch)
assert.True(t, opts.sync)
assert.False(t, opts.health)
assert.False(t, opts.operation)
assert.False(t, opts.suspended)
assert.Equal(t, true, opts.sync)
assert.Equal(t, false, opts.health)
assert.Equal(t, false, opts.operation)
assert.Equal(t, false, opts.suspended)
}
func TestFindRevisionHistoryWithoutPassedIdAndEmptyHistoryList(t *testing.T) {
@@ -1118,36 +1118,36 @@ func Test_unset(t *testing.T) {
assert.False(t, updated)
assert.False(t, nothingToUnset)
assert.Len(t, kustomizeSource.Kustomize.Images, 2)
assert.Equal(t, 2, len(kustomizeSource.Kustomize.Images))
updated, nothingToUnset = unset(kustomizeSource, unsetOpts{kustomizeImages: []string{"old1=new:tag"}})
assert.Len(t, kustomizeSource.Kustomize.Images, 1)
assert.Equal(t, 1, len(kustomizeSource.Kustomize.Images))
assert.True(t, updated)
assert.False(t, nothingToUnset)
updated, nothingToUnset = unset(kustomizeSource, unsetOpts{kustomizeImages: []string{"old1=new:tag"}})
assert.False(t, updated)
assert.False(t, nothingToUnset)
assert.Len(t, kustomizeSource.Kustomize.Replicas, 2)
assert.Equal(t, 2, len(kustomizeSource.Kustomize.Replicas))
updated, nothingToUnset = unset(kustomizeSource, unsetOpts{kustomizeReplicas: []string{"my-deployment"}})
assert.Len(t, kustomizeSource.Kustomize.Replicas, 1)
assert.Equal(t, 1, len(kustomizeSource.Kustomize.Replicas))
assert.True(t, updated)
assert.False(t, nothingToUnset)
updated, nothingToUnset = unset(kustomizeSource, unsetOpts{kustomizeReplicas: []string{"my-deployment"}})
assert.False(t, updated)
assert.False(t, nothingToUnset)
assert.Len(t, helmSource.Helm.Parameters, 2)
assert.Equal(t, 2, len(helmSource.Helm.Parameters))
updated, nothingToUnset = unset(helmSource, unsetOpts{parameters: []string{"name-1"}})
assert.Len(t, helmSource.Helm.Parameters, 1)
assert.Equal(t, 1, len(helmSource.Helm.Parameters))
assert.True(t, updated)
assert.False(t, nothingToUnset)
updated, nothingToUnset = unset(helmSource, unsetOpts{parameters: []string{"name-1"}})
assert.False(t, updated)
assert.False(t, nothingToUnset)
assert.Len(t, helmSource.Helm.ValueFiles, 2)
assert.Equal(t, 2, len(helmSource.Helm.ValueFiles))
updated, nothingToUnset = unset(helmSource, unsetOpts{valuesFiles: []string{"values-1.yaml"}})
assert.Len(t, helmSource.Helm.ValueFiles, 1)
assert.Equal(t, 1, len(helmSource.Helm.ValueFiles))
assert.True(t, updated)
assert.False(t, nothingToUnset)
updated, nothingToUnset = unset(helmSource, unsetOpts{valuesFiles: []string{"values-1.yaml"}})
@@ -1163,27 +1163,27 @@ func Test_unset(t *testing.T) {
assert.False(t, updated)
assert.False(t, nothingToUnset)
assert.True(t, helmSource.Helm.IgnoreMissingValueFiles)
assert.Equal(t, true, helmSource.Helm.IgnoreMissingValueFiles)
updated, nothingToUnset = unset(helmSource, unsetOpts{ignoreMissingValueFiles: true})
assert.False(t, helmSource.Helm.IgnoreMissingValueFiles)
assert.Equal(t, false, helmSource.Helm.IgnoreMissingValueFiles)
assert.True(t, updated)
assert.False(t, nothingToUnset)
updated, nothingToUnset = unset(helmSource, unsetOpts{ignoreMissingValueFiles: true})
assert.False(t, updated)
assert.False(t, nothingToUnset)
assert.True(t, helmSource.Helm.PassCredentials)
assert.Equal(t, true, helmSource.Helm.PassCredentials)
updated, nothingToUnset = unset(helmSource, unsetOpts{passCredentials: true})
assert.False(t, helmSource.Helm.PassCredentials)
assert.Equal(t, false, helmSource.Helm.PassCredentials)
assert.True(t, updated)
assert.False(t, nothingToUnset)
updated, nothingToUnset = unset(helmSource, unsetOpts{passCredentials: true})
assert.False(t, updated)
assert.False(t, nothingToUnset)
assert.Len(t, pluginSource.Plugin.Env, 2)
assert.Equal(t, 2, len(pluginSource.Plugin.Env))
updated, nothingToUnset = unset(pluginSource, unsetOpts{pluginEnvs: []string{"env-1"}})
assert.Len(t, pluginSource.Plugin.Env, 1)
assert.Equal(t, 1, len(pluginSource.Plugin.Env))
assert.True(t, updated)
assert.False(t, nothingToUnset)
updated, nothingToUnset = unset(pluginSource, unsetOpts{pluginEnvs: []string{"env-1"}})
@@ -1357,47 +1357,47 @@ func TestFilterAppResources(t *testing.T) {
expectedResult []*v1alpha1.SyncOperationResource
}{
// --resource apps:ReplicaSet:replicaSet-name1 --resource *:Service:*
{testName: "Include ReplicaSet replicaSet-name1 resource and all service resources",
{testName: "Include ReplicaSet replicaSet-name1 resouce and all service resources",
selectedResources: []*v1alpha1.SyncOperationResource{&includeAllServiceResources, &includeReplicaSet1Resource},
expectedResult: []*v1alpha1.SyncOperationResource{&replicaSet1, &service1, &service2},
},
// --resource apps:ReplicaSet:replicaSet-name1 --resource !*:Service:*
{testName: "Include ReplicaSet replicaSet-name1 resource and exclude all service resources",
{testName: "Include ReplicaSet replicaSet-name1 resouce and exclude all service resources",
selectedResources: []*v1alpha1.SyncOperationResource{&excludeAllServiceResources, &includeReplicaSet1Resource},
expectedResult: []*v1alpha1.SyncOperationResource{&replicaSet1, &replicaSet2, &job, &deployment},
},
// --resource !apps:ReplicaSet:replicaSet-name2 --resource !*:Service:*
{testName: "Exclude ReplicaSet replicaSet-name2 resource and all service resources",
{testName: "Exclude ReplicaSet replicaSet-name2 resouce and all service resources",
selectedResources: []*v1alpha1.SyncOperationResource{&excludeReplicaSet2Resource, &excludeAllServiceResources},
expectedResult: []*v1alpha1.SyncOperationResource{&replicaSet1, &replicaSet2, &job, &service1, &service2, &deployment},
},
// --resource !apps:ReplicaSet:replicaSet-name2
{testName: "Exclude ReplicaSet replicaSet-name2 resource",
{testName: "Exclude ReplicaSet replicaSet-name2 resouce",
selectedResources: []*v1alpha1.SyncOperationResource{&excludeReplicaSet2Resource},
expectedResult: []*v1alpha1.SyncOperationResource{&replicaSet1, &job, &service1, &service2, &deployment},
},
// --resource apps:ReplicaSet:replicaSet-name1
{testName: "Include ReplicaSet replicaSet-name1 resource",
{testName: "Include ReplicaSet replicaSet-name1 resouce",
selectedResources: []*v1alpha1.SyncOperationResource{&includeReplicaSet1Resource},
expectedResult: []*v1alpha1.SyncOperationResource{&replicaSet1},
},
// --resource !*:Service:*
{testName: "Exclude Service resources",
{testName: "Exclude Service resouces",
selectedResources: []*v1alpha1.SyncOperationResource{&excludeAllServiceResources},
expectedResult: []*v1alpha1.SyncOperationResource{&replicaSet1, &replicaSet2, &job, &deployment},
},
// --resource *:Service:*
{testName: "Include Service resources",
{testName: "Include Service resouces",
selectedResources: []*v1alpha1.SyncOperationResource{&includeAllServiceResources},
expectedResult: []*v1alpha1.SyncOperationResource{&service1, &service2},
},
// --resource !*:*:*
{testName: "Exclude all resources",
{testName: "Exclude all resouces",
selectedResources: []*v1alpha1.SyncOperationResource{&excludeAllResources},
expectedResult: nil,
},
// --resource *:*:*
{testName: "Include all resources",
{testName: "Include all resouces",
selectedResources: []*v1alpha1.SyncOperationResource{&includeAllResources},
expectedResult: []*v1alpha1.SyncOperationResource{&replicaSet1, &replicaSet2, &job, &service1, &service2, &deployment},
},
@@ -1480,7 +1480,7 @@ func TestParseSelectedResourcesEmptyList(t *testing.T) {
var resources []string
operationResources, err := parseSelectedResources(resources)
assert.NoError(t, err)
assert.Empty(t, operationResources)
assert.Len(t, operationResources, 0)
}
func TestPrintApplicationTableNotWide(t *testing.T) {

View File

@@ -5,10 +5,9 @@ import (
"os"
"testing"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
func TestPrintApplicationSetNames(t *testing.T) {

View File

@@ -490,7 +490,7 @@ func NewClusterListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman
# List Clusters in Default "Wide" Format
argocd cluster list
# List Cluster via specifying the server
# List Cluster via specifing the server
argocd cluster list --server <ARGOCD_SERVER_ADDRESS>
# List Clusters in JSON Format

View File

@@ -3,13 +3,12 @@ package commands
import (
"testing"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
func Test_getQueryBySelector(t *testing.T) {

View File

@@ -196,8 +196,8 @@ __argocd_custom_func() {
func NewCompletionCommand() *cobra.Command {
var command = &cobra.Command{
Use: "completion SHELL",
Short: "output shell completion code for the specified shell (bash, zsh or fish)",
Long: `Write bash, zsh or fish shell completion code to standard output.
Short: "output shell completion code for the specified shell (bash or zsh)",
Long: `Write bash or zsh shell completion code to standard output.
For bash, ensure you have bash completions installed and enabled.
To access completions in your current shell, run
@@ -218,11 +218,6 @@ $ source <(argocd completion bash)
# For zsh
$ argocd completion zsh > _argocd
$ source _argocd
# For fish
$ argocd completion fish > ~/.config/fish/completions/argocd.fish
$ source ~/.config/fish/completions/argocd.fish
`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 {
@@ -232,17 +227,16 @@ $ source ~/.config/fish/completions/argocd.fish
shell := args[0]
rootCommand := NewCommand()
rootCommand.BashCompletionFunction = bashCompletionFunc
availableCompletions := map[string]func(out io.Writer, cmd *cobra.Command) error{
"bash": runCompletionBash,
"zsh": runCompletionZsh,
"fish": runCompletionFish,
availableCompletions := map[string]func(io.Writer) error{
"bash": rootCommand.GenBashCompletion,
"zsh": rootCommand.GenZshCompletion,
}
completion, ok := availableCompletions[shell]
if !ok {
fmt.Printf("Invalid shell '%s'. The supported shells are bash, zsh and fish.\n", shell)
fmt.Printf("Invalid shell '%s'. The supported shells are bash and zsh.\n", shell)
os.Exit(1)
}
if err := completion(os.Stdout, rootCommand); err != nil {
if err := completion(os.Stdout); err != nil {
log.Fatal(err)
}
},
@@ -250,15 +244,3 @@ $ source ~/.config/fish/completions/argocd.fish
return command
}
func runCompletionBash(out io.Writer, cmd *cobra.Command) error {
return cmd.GenBashCompletion(out)
}
func runCompletionZsh(out io.Writer, cmd *cobra.Command) error {
return cmd.GenZshCompletion(out)
}
func runCompletionFish(out io.Writer, cmd *cobra.Command) error {
return cmd.GenFishCompletion(out, true)
}

View File

@@ -4,10 +4,9 @@ import (
"os"
"testing"
"github.com/argoproj/argo-cd/v2/util/localconfig"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/argoproj/argo-cd/v2/util/localconfig"
)
const testConfig = `contexts:

View File

@@ -23,7 +23,7 @@ import (
"k8s.io/client-go/kubernetes"
cache2 "k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/utils/ptr"
"k8s.io/utils/pointer"
"github.com/argoproj/argo-cd/v2/pkg/apiclient"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
@@ -205,7 +205,7 @@ func MaybeStartLocalServer(ctx context.Context, clientOpts *apiclient.ClientOpti
log.SetLevel(log.ErrorLevel)
os.Setenv(v1alpha1.EnvVarFakeInClusterConfig, "true")
if address == nil {
address = ptr.To("localhost")
address = pointer.String("localhost")
}
if port == nil || *port == 0 {
addr := fmt.Sprintf("%s:0", *address)

View File

@@ -31,7 +31,6 @@ import (
"github.com/argoproj/argo-cd/v2/util/localconfig"
oidcutil "github.com/argoproj/argo-cd/v2/util/oidc"
"github.com/argoproj/argo-cd/v2/util/rand"
oidcconfig "github.com/argoproj/argo-cd/v2/util/settings"
)
// NewLoginCommand returns a new instance of `argocd login` command
@@ -307,7 +306,6 @@ func oauth2Login(
fmt.Printf("Opening browser for authentication\n")
var url string
var oidcconfig oidcconfig.OIDCConfig
grantType := oidcutil.InferGrantType(oidcConf)
opts := []oauth2.AuthCodeOption{oauth2.AccessTypeOffline}
if claimsRequested := oidcSettings.GetIDTokenClaims(); claimsRequested != nil {
@@ -318,9 +316,6 @@ func oauth2Login(
case oidcutil.GrantTypeAuthorizationCode:
opts = append(opts, oauth2.SetAuthURLParam("code_challenge", codeChallenge))
opts = append(opts, oauth2.SetAuthURLParam("code_challenge_method", "S256"))
if oidcconfig.DomainHint != "" {
opts = append(opts, oauth2.SetAuthURLParam("domain_hint", oidcconfig.DomainHint))
}
url = oauth2conf.AuthCodeURL(stateNonce, opts...)
case oidcutil.GrantTypeImplicit:
url, err = oidcutil.ImplicitFlowURL(oauth2conf, stateNonce, opts...)

View File

@@ -58,7 +58,7 @@ func NewProjectWindowsDisableManualSyncCommand(clientOpts *argocdclient.ClientOp
#Disable manual sync for a sync window for the Project
argocd proj windows disable-manual-sync PROJECT ID
#Disabling manual sync for a windows set on the default project with Id 0
#Disbaling manual sync for a windows set on the default project with Id 0
argocd proj windows disable-manual-sync default 0`,
Run: func(c *cobra.Command, args []string) {
ctx := c.Context()

View File

@@ -242,9 +242,6 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
// NewRepoRemoveCommand returns a new instance of an `argocd repo remove` command
func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
project string
)
var command = &cobra.Command{
Use: "rm REPO",
Short: "Remove repository credentials",
@@ -258,13 +255,12 @@ func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
conn, repoIf := headless.NewClientOrDie(clientOpts, c).NewRepoClientOrDie()
defer io.Close(conn)
for _, repoURL := range args {
_, err := repoIf.DeleteRepository(ctx, &repositorypkg.RepoQuery{Repo: repoURL, AppProject: project})
_, err := repoIf.DeleteRepository(ctx, &repositorypkg.RepoQuery{Repo: repoURL})
errors.CheckError(err)
fmt.Printf("Repository '%s' removed\n", repoURL)
}
},
}
command.Flags().StringVar(&project, "project", "", "project of the repository")
return command
}
@@ -341,7 +337,6 @@ func NewRepoGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
output string
refresh string
project string
)
var command = &cobra.Command{
Use: "get",
@@ -367,7 +362,7 @@ func NewRepoGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
err := fmt.Errorf("--refresh must be one of: 'hard'")
errors.CheckError(err)
}
repo, err := repoIf.Get(ctx, &repositorypkg.RepoQuery{Repo: repoURL, ForceRefresh: forceRefresh, AppProject: project})
repo, err := repoIf.Get(ctx, &repositorypkg.RepoQuery{Repo: repoURL, ForceRefresh: forceRefresh})
errors.CheckError(err)
switch output {
case "yaml", "json":
@@ -383,8 +378,6 @@ func NewRepoGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
}
},
}
command.Flags().StringVar(&project, "project", "", "project of the repository")
command.Flags().StringVarP(&output, "output", "o", "wide", "Output format. One of: json|yaml|wide|url")
command.Flags().StringVar(&refresh, "refresh", "", "Force a cache refresh on connection status , must be one of: 'hard'")
return command

View File

@@ -75,11 +75,11 @@ func NewCommand() *cobra.Command {
command.PersistentFlags().StringVar(&clientOpts.GRPCWebRootPath, "grpc-web-root-path", config.GetFlag("grpc-web-root-path", ""), "Enables gRPC-web protocol. Useful if Argo CD server is behind proxy which does not support HTTP2. Set web root.")
command.PersistentFlags().StringVar(&cmdutil.LogFormat, "logformat", config.GetFlag("logformat", "text"), "Set the logging format. One of: text|json")
command.PersistentFlags().StringVar(&cmdutil.LogLevel, "loglevel", config.GetFlag("loglevel", "info"), "Set the logging level. One of: debug|info|warn|error")
command.PersistentFlags().StringSliceVarP(&clientOpts.Headers, "header", "H", config.GetStringSliceFlag("header", []string{}), "Sets additional header to all requests made by Argo CD CLI. (Can be repeated multiple times to add multiple headers, also supports comma separated headers)")
command.PersistentFlags().StringSliceVarP(&clientOpts.Headers, "header", "H", []string{}, "Sets additional header to all requests made by Argo CD CLI. (Can be repeated multiple times to add multiple headers, also supports comma separated headers)")
command.PersistentFlags().BoolVar(&clientOpts.PortForward, "port-forward", config.GetBoolFlag("port-forward"), "Connect to a random argocd-server port using port forwarding")
command.PersistentFlags().StringVar(&clientOpts.PortForwardNamespace, "port-forward-namespace", config.GetFlag("port-forward-namespace", ""), "Namespace name which should be used for port forwarding")
command.PersistentFlags().IntVar(&clientOpts.HttpRetryMax, "http-retry-max", config.GetIntFlag("http-retry-max", 0), "Maximum number of retries to establish http connection to Argo CD server")
command.PersistentFlags().BoolVar(&clientOpts.Core, "core", config.GetBoolFlag("core"), "If set to true then CLI talks directly to Kubernetes instead of talking to Argo CD API server")
command.PersistentFlags().IntVar(&clientOpts.HttpRetryMax, "http-retry-max", 0, "Maximum number of retries to establish http connection to Argo CD server")
command.PersistentFlags().BoolVar(&clientOpts.Core, "core", false, "If set to true then CLI talks directly to Kubernetes instead of talking to Argo CD API server")
command.PersistentFlags().StringVar(&clientOpts.ServerName, "server-name", env.StringFromEnv(common.EnvServerName, common.DefaultServerName), fmt.Sprintf("Name of the Argo CD API server; set this or the %s environment variable when the server's name label differs from the default, for example when installing via the Helm chart", common.EnvServerName))
command.PersistentFlags().StringVar(&clientOpts.AppControllerName, "controller-name", env.StringFromEnv(common.EnvAppControllerName, common.DefaultApplicationControllerName), fmt.Sprintf("Name of the Argo CD Application controller; set this or the %s environment variable when the controller's name label differs from the default, for example when installing via the Helm chart", common.EnvAppControllerName))
command.PersistentFlags().StringVar(&clientOpts.RedisHaProxyName, "redis-haproxy-name", env.StringFromEnv(common.EnvRedisHaProxyName, common.DefaultRedisHaProxyName), fmt.Sprintf("Name of the Redis HA Proxy; set this or the %s environment variable when the HA Proxy's name label differs from the default, for example when installing via the Helm chart", common.EnvRedisHaProxyName))

View File

@@ -6,10 +6,9 @@ import (
"text/tabwriter"
"time"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/gitops-engine/pkg/health"
"k8s.io/apimachinery/pkg/util/duration"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
const (

View File

@@ -5,9 +5,8 @@ import (
"testing"
"text/tabwriter"
"github.com/stretchr/testify/assert"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
)
func TestTreeViewAppGet(t *testing.T) {

View File

@@ -4,10 +4,9 @@ import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
"github.com/argoproj/argo-cd/v2/pkg/apiclient/version"
"github.com/stretchr/testify/assert"
)
func TestShortVersionClient(t *testing.T) {

View File

@@ -17,7 +17,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"k8s.io/utils/pointer"
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
@@ -218,7 +218,7 @@ func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, ap
Backoff: &argoappv1.Backoff{
Duration: appOpts.retryBackoffDuration.String(),
MaxDuration: appOpts.retryBackoffMaxDuration.String(),
Factor: ptr.To(appOpts.retryBackoffFactor),
Factor: pointer.Int64(appOpts.retryBackoffFactor),
},
}
} else if appOpts.retryLimit == 0 {

View File

@@ -27,7 +27,7 @@ func Test_setHelmOpt(t *testing.T) {
t.Run("IgnoreMissingValueFiles", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setHelmOpt(&src, helmOpts{ignoreMissingValueFiles: true})
assert.True(t, src.Helm.IgnoreMissingValueFiles)
assert.Equal(t, true, src.Helm.IgnoreMissingValueFiles)
})
t.Run("ReleaseName", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
@@ -57,12 +57,12 @@ func Test_setHelmOpt(t *testing.T) {
t.Run("HelmPassCredentials", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setHelmOpt(&src, helmOpts{passCredentials: true})
assert.True(t, src.Helm.PassCredentials)
assert.Equal(t, true, src.Helm.PassCredentials)
})
t.Run("HelmSkipCrds", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setHelmOpt(&src, helmOpts{skipCrds: true})
assert.True(t, src.Helm.SkipCrds)
assert.Equal(t, true, src.Helm.SkipCrds)
})
}
@@ -264,7 +264,7 @@ func Test_setAppSpecOptionsMultiSourceApp(t *testing.T) {
})
t.Run("Helm - SourcePosition 0", func(t *testing.T) {
assert.NoError(t, f.SetFlagWithSourcePosition("helm-version", "v2", sourcePosition))
assert.Len(t, f.spec.GetSources(), 2)
assert.Equal(t, len(f.spec.GetSources()), 2)
assert.Equal(t, f.spec.GetSources()[sourcePosition].Helm.Version, "v2")
})
t.Run("Kustomize", func(t *testing.T) {
@@ -276,7 +276,7 @@ func Test_setAppSpecOptionsMultiSourceApp(t *testing.T) {
t.Run("Helm", func(t *testing.T) {
assert.NoError(t, f.SetFlagWithSourcePosition("helm-version", "v2", sourcePosition1))
assert.NoError(t, f.SetFlagWithSourcePosition("helm-version", "v3", sourcePosition2))
assert.Len(t, f.spec.GetSources(), 2)
assert.Equal(t, len(f.spec.GetSources()), 2)
assert.Equal(t, f.spec.GetSources()[sourcePosition1-1].Helm.Version, "v2")
assert.Equal(t, f.spec.GetSources()[sourcePosition2-1].Helm.Version, "v3")
})
@@ -358,7 +358,7 @@ func TestReadAppsFromURI(t *testing.T) {
apps := make([]*v1alpha1.Application, 0)
err = readAppsFromURI(file.Name(), &apps)
assert.NoError(t, err)
assert.Len(t, apps, 2)
assert.Equal(t, 2, len(apps))
assert.Equal(t, "sth1", apps[0].Name)
assert.Equal(t, "sth2", apps[1].Name)
@@ -389,7 +389,7 @@ func TestConstructAppFromStdin(t *testing.T) {
log.Fatal(err)
}
assert.NoError(t, err)
assert.Len(t, apps, 2)
assert.Equal(t, 2, len(apps))
assert.Equal(t, "sth1", apps[0].Name)
assert.Equal(t, "sth2", apps[1].Name)
@@ -399,7 +399,7 @@ func TestConstructBasedOnName(t *testing.T) {
apps, err := ConstructApps("", "test", []string{}, []string{}, []string{}, AppOptions{}, nil)
assert.NoError(t, err)
assert.Len(t, apps, 1)
assert.Equal(t, 1, len(apps))
assert.Equal(t, "test", apps[0].Name)
}

View File

@@ -5,10 +5,9 @@ import (
"net/url"
"os"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/config"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
)
func ConstructApplicationSet(fileURL string) ([]*argoprojiov1alpha1.ApplicationSet, error) {

View File

@@ -3,9 +3,8 @@ package util
import (
"testing"
"github.com/stretchr/testify/assert"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
)
var appSet = `apiVersion: argoproj.io/v1alpha1
@@ -37,5 +36,5 @@ func TestReadAppSet(t *testing.T) {
if err != nil {
t.Logf("Failed reading appset file")
}
assert.Len(t, appSets, 1)
assert.Equal(t, len(appSets), 1)
}

View File

@@ -11,7 +11,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"k8s.io/utils/pointer"
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
@@ -115,7 +115,7 @@ func GetOrphanedResourcesSettings(flagSet *pflag.FlagSet, opts ProjectOpts) *v1a
if opts.orphanedResourcesEnabled || warnChanged {
settings := v1alpha1.OrphanedResourcesMonitorSettings{}
if warnChanged {
settings.Warn = ptr.To(opts.orphanedResourcesWarn)
settings.Warn = pointer.Bool(opts.orphanedResourcesWarn)
}
return &settings
}

View File

@@ -2,12 +2,8 @@ package apiclient
import (
"context"
"math"
"time"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/util/env"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
log "github.com/sirupsen/logrus"
@@ -18,9 +14,9 @@ import (
"github.com/argoproj/argo-cd/v2/util/io"
)
var (
const (
// MaxGRPCMessageSize contains max grpc message size
MaxGRPCMessageSize = env.ParseNumFromEnv(common.EnvGRPCMaxSizeMB, 100, 0, math.MaxInt32) * 1024 * 1024
MaxGRPCMessageSize = 100 * 1024 * 1024
)
// Clientset represents config management plugin server api clients

View File

@@ -24,7 +24,7 @@ import (
"github.com/argoproj/argo-cd/v2/util/io/files"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/cyphar/filepath-securejoin"
"github.com/mattn/go-zglob"
log "github.com/sirupsen/logrus"
)
@@ -128,8 +128,8 @@ func runCommand(ctx context.Context, command Command, path string, env []string)
if len(output) == 0 {
logCtx.Warn("Plugin command returned zero output")
} else {
// Log stderr even on successful commands to help develop plugins
logCtx.Info("Plugin command successful")
// Log stderr even on successfull commands to help develop plugins
logCtx.Info("Plugin command successfull")
}
return strings.TrimSuffix(output, "\n"), nil

View File

@@ -369,7 +369,7 @@ func TestRunCommandEmptyCommand(t *testing.T) {
assert.ErrorContains(t, err, "Command is empty")
}
// TestRunCommandContextTimeoutWithCleanup makes sure that the process is given enough time to cleanup before sending SIGKILL.
// TestRunCommandContextTimeoutWithGracefulTermination makes sure that the process is given enough time to cleanup before sending SIGKILL.
func TestRunCommandContextTimeoutWithCleanup(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 900*time.Millisecond)
defer cancel()

View File

@@ -18,8 +18,6 @@ import (
"google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/reflection"
"google.golang.org/grpc/keepalive"
"github.com/argoproj/argo-cd/v2/cmpserver/apiclient"
"github.com/argoproj/argo-cd/v2/cmpserver/plugin"
"github.com/argoproj/argo-cd/v2/common"
@@ -27,6 +25,7 @@ import (
"github.com/argoproj/argo-cd/v2/server/version"
"github.com/argoproj/argo-cd/v2/util/errors"
grpc_util "github.com/argoproj/argo-cd/v2/util/grpc"
"google.golang.org/grpc/keepalive"
)
// ArgoCDCMPServer is the config management plugin server implementation

View File

@@ -113,17 +113,11 @@ const (
// LegacyShardingAlgorithm is the default value for Sharding Algorithm it uses an `uid` based distribution (non-uniform)
LegacyShardingAlgorithm = "legacy"
// RoundRobinShardingAlgorithm is a flag value that can be opted for Sharding Algorithm it uses an equal distribution across all shards
// RoundRobinShardingAlgorithm is a flag value that can be opted for Sharding Algorithm it uses an equal distribution accross all shards
RoundRobinShardingAlgorithm = "round-robin"
// AppControllerHeartbeatUpdateRetryCount is the retry count for updating the Shard Mapping to the Shard Mapping ConfigMap used by Application Controller
AppControllerHeartbeatUpdateRetryCount = 3
// ConsistentHashingWithBoundedLoadsAlgorithm uses an algorithm that tries to use an equal distribution across
// all shards but is optimised to handle sharding and/or cluster addition or removal. In case of sharding or
// cluster changes, this algorithm minimises the changes between shard and clusters assignments.
ConsistentHashingWithBoundedLoadsAlgorithm = "consistent-hashing"
DefaultShardingAlgorithm = LegacyShardingAlgorithm
DefaultShardingAlgorithm = LegacyShardingAlgorithm
)
// Dex related constants
@@ -212,7 +206,7 @@ const (
EnvVarTLSDataPath = "ARGOCD_TLS_DATA_PATH"
// EnvGitAttemptsCount specifies number of git remote operations attempts count
EnvGitAttemptsCount = "ARGOCD_GIT_ATTEMPTS_COUNT"
// EnvGitRetryMaxDuration specifies max duration of git remote operation retry
// EnvGitRetryMaxDuration specifices max duration of git remote operation retry
EnvGitRetryMaxDuration = "ARGOCD_GIT_RETRY_MAX_DURATION"
// EnvGitRetryDuration specifies duration of git remote operation retry
EnvGitRetryDuration = "ARGOCD_GIT_RETRY_DURATION"
@@ -279,8 +273,6 @@ const (
// EnvServerSideDiff defines the env var used to enable ServerSide Diff feature.
// If defined, value must be "true" or "false".
EnvServerSideDiff = "ARGOCD_APPLICATION_CONTROLLER_SERVER_SIDE_DIFF"
// EnvGRPCMaxSizeMB is the environment variable to look for a max GRPC message size
EnvGRPCMaxSizeMB = "ARGOCD_GRPC_MAX_SIZE_MB"
)
// Config Management Plugin related constants
@@ -359,7 +351,7 @@ func GetCMPChunkSize() int {
}
// GetCMPWorkDir will return the full path of the work directory used by the CMP server.
// This directory and all it's contents will be deleted during CMP bootstrap.
// This directory and all it's contents will be deleted durring CMP bootstrap.
func GetCMPWorkDir() string {
if workDir := os.Getenv(EnvCMPWorkDir); workDir != "" {
return filepath.Join(workDir, DefaultCMPWorkDirName)

View File

@@ -97,15 +97,6 @@ func (a CompareWith) Pointer() *CompareWith {
return &a
}
func getAppLog(app *appv1.Application) *log.Entry {
return log.WithFields(log.Fields{
"application": app.Name,
"app-namespace": app.Namespace,
"app-qualified-name": app.QualifiedName(),
"project": app.Spec.Project,
})
}
// ApplicationController is the controller for application resources.
type ApplicationController struct {
cache *appstatecache.Cache
@@ -422,11 +413,10 @@ func (ctrl *ApplicationController) handleObjectUpdated(managedByApp map[string]b
continue
}
logCtx := getAppLog(app)
// Enforce application's permission for the source namespace
_, err = ctrl.getAppProj(app)
if err != nil {
logCtx.Errorf("Unable to determine project for app '%s': %v", app.QualifiedName(), err)
log.Errorf("Unable to determine project for app '%s': %v", app.QualifiedName(), err)
continue
}
@@ -439,14 +429,15 @@ func (ctrl *ApplicationController) handleObjectUpdated(managedByApp map[string]b
if ref.Namespace == "" {
namespace = "(cluster-scoped)"
}
logCtx.WithFields(log.Fields{
"comparison-level": level,
"namespace": namespace,
"name": ref.Name,
"api-version": ref.APIVersion,
"kind": ref.Kind,
"server": app.Spec.Destination.Server,
"cluster-name": app.Spec.Destination.Name,
log.WithFields(log.Fields{
"application": appKey,
"level": level,
"namespace": namespace,
"name": ref.Name,
"api-version": ref.APIVersion,
"kind": ref.Kind,
"server": app.Spec.Destination.Server,
"cluster-name": app.Spec.Destination.Name,
}).Debug("Requesting app refresh caused by object update")
ctrl.requestAppRefresh(app.QualifiedName(), &level, nil)
@@ -923,7 +914,7 @@ func (ctrl *ApplicationController) processAppOperationQueueItem() (processNext b
// We cannot rely on informer since applications might be updated by both application controller and api server.
freshApp, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(app.ObjectMeta.Namespace).Get(context.Background(), app.ObjectMeta.Name, metav1.GetOptions{})
if err != nil {
getAppLog(app).Errorf("Failed to retrieve latest application state: %v", err)
log.Errorf("Failed to retrieve latest application state: %v", err)
return
}
app = freshApp
@@ -1070,24 +1061,23 @@ func (ctrl *ApplicationController) getPermittedAppLiveObjects(app *appv1.Applica
}
func (ctrl *ApplicationController) isValidDestination(app *appv1.Application) (bool, *appv1.Cluster) {
logCtx := getAppLog(app)
// Validate the cluster using the Application destination's `name` field, if applicable,
// and set the Server field, if needed.
if err := argo.ValidateDestination(context.Background(), &app.Spec.Destination, ctrl.db); err != nil {
logCtx.Warnf("Unable to validate destination of the Application being deleted: %v", err)
log.Warnf("Unable to validate destination of the Application being deleted: %v", err)
return false, nil
}
cluster, err := ctrl.db.GetCluster(context.Background(), app.Spec.Destination.Server)
if err != nil {
logCtx.Warnf("Unable to locate cluster URL for Application being deleted: %v", err)
log.Warnf("Unable to locate cluster URL for Application being deleted: %v", err)
return false, nil
}
return true, cluster
}
func (ctrl *ApplicationController) finalizeApplicationDeletion(app *appv1.Application, projectClusters func(project string) ([]*appv1.Cluster, error)) error {
logCtx := getAppLog(app)
logCtx := log.WithField("application", app.QualifiedName())
// Get refreshed application info, since informer app copy might be stale
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(app.Namespace).Get(context.Background(), app.Name, metav1.GetOptions{})
if err != nil {
@@ -1235,7 +1225,6 @@ func (ctrl *ApplicationController) updateFinalizers(app *appv1.Application) erro
}
func (ctrl *ApplicationController) setAppCondition(app *appv1.Application, condition appv1.ApplicationCondition) {
logCtx := getAppLog(app)
// do nothing if app already has same condition
for _, c := range app.Status.Conditions {
if c.Message == condition.Message && c.Type == condition.Type {
@@ -1255,12 +1244,12 @@ func (ctrl *ApplicationController) setAppCondition(app *appv1.Application, condi
_, err = ctrl.applicationClientset.ArgoprojV1alpha1().Applications(app.Namespace).Patch(context.Background(), app.Name, types.MergePatchType, patch, metav1.PatchOptions{})
}
if err != nil {
logCtx.Errorf("Unable to set application condition: %v", err)
log.Errorf("Unable to set application condition: %v", err)
}
}
func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Application) {
logCtx := getAppLog(app)
logCtx := log.WithField("application", app.QualifiedName())
var state *appv1.OperationState
// Recover from any unexpected panics and automatically set the status to be failed
defer func() {
@@ -1367,7 +1356,7 @@ func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Appli
// sync/health information
if _, err := cache.MetaNamespaceKeyFunc(app); err == nil {
// force app refresh with using CompareWithLatest comparison type and trigger app reconciliation loop
ctrl.requestAppRefresh(app.QualifiedName(), CompareWithLatestForceResolve.Pointer(), nil)
ctrl.requestAppRefresh(app.QualifiedName(), CompareWithLatest.Pointer(), nil)
} else {
logCtx.Warnf("Fails to requeue application: %v", err)
}
@@ -1375,7 +1364,8 @@ func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Appli
}
func (ctrl *ApplicationController) setOperationState(app *appv1.Application, state *appv1.OperationState) {
logCtx := getAppLog(app)
logCtx := log.WithFields(log.Fields{"application": app.Name, "appNamespace": app.Namespace, "project": app.Spec.Project})
if state.Phase == "" {
// expose any bugs where we neglect to set phase
panic("no phase was set")
@@ -1453,7 +1443,7 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
// writeBackToInformer writes a just recently updated App back into the informer cache.
// This prevents the situation where the controller operates on a stale app and repeats work
func (ctrl *ApplicationController) writeBackToInformer(app *appv1.Application) {
logCtx := getAppLog(app).WithField("informer-writeBack", true)
logCtx := log.WithFields(log.Fields{"application": app.Name, "appNamespace": app.Namespace, "project": app.Spec.Project, "informer-writeBack": true})
err := ctrl.appInformer.GetStore().Update(app)
if err != nil {
logCtx.Errorf("failed to update informer store: %v", err)
@@ -1507,11 +1497,12 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
return
}
app := origApp.DeepCopy()
logCtx := getAppLog(app).WithFields(log.Fields{
"comparison-level": comparisonLevel,
"dest-server": origApp.Spec.Destination.Server,
"dest-name": origApp.Spec.Destination.Name,
"dest-namespace": origApp.Spec.Destination.Namespace,
logCtx := log.WithFields(log.Fields{
"application": app.QualifiedName(),
"level": comparisonLevel,
"dest-server": origApp.Spec.Destination.Server,
"dest-name": origApp.Spec.Destination.Name,
"dest-namespace": origApp.Spec.Destination.Namespace,
})
startTime := time.Now()
@@ -1551,10 +1542,10 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
patchMs = ctrl.persistAppStatus(origApp, &app.Status)
if err := ctrl.cache.SetAppResourcesTree(app.InstanceName(ctrl.namespace), &appv1.ApplicationTree{}); err != nil {
logCtx.Warnf("failed to set app resource tree: %v", err)
log.Warnf("failed to set app resource tree: %v", err)
}
if err := ctrl.cache.SetAppManagedResources(app.InstanceName(ctrl.namespace), nil); err != nil {
logCtx.Warnf("failed to set app managed resources tree: %v", err)
log.Warnf("failed to set app managed resources tree: %v", err)
}
return
}
@@ -1678,7 +1669,7 @@ func currentSourceEqualsSyncedSource(app *appv1.Application) bool {
// Additionally, it returns whether full refresh was requested or not.
// If full refresh is requested then target and live state should be reconciled, else only live state tree should be updated.
func (ctrl *ApplicationController) needRefreshAppStatus(app *appv1.Application, statusRefreshTimeout, statusHardRefreshTimeout time.Duration) (bool, appv1.RefreshType, CompareWith) {
logCtx := getAppLog(app)
logCtx := log.WithFields(log.Fields{"application": app.QualifiedName()})
var reason string
compareWith := CompareWithLatest
refreshType := appv1.RefreshTypeNormal
@@ -1755,8 +1746,8 @@ func (ctrl *ApplicationController) refreshAppConditions(app *appv1.Application)
// normalizeApplication normalizes an application.spec and additionally persists updates if it changed
func (ctrl *ApplicationController) normalizeApplication(orig, app *appv1.Application) {
logCtx := log.WithFields(log.Fields{"application": app.QualifiedName()})
app.Spec = *argo.NormalizeApplicationSpec(&app.Spec)
logCtx := getAppLog(app)
patch, modified, err := diff.CreateTwoWayMergePatch(orig, app, appv1.Application{})
@@ -1774,7 +1765,7 @@ func (ctrl *ApplicationController) normalizeApplication(orig, app *appv1.Applica
// persistAppStatus persists updates to application status. If no changes were made, it is a no-op
func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, newStatus *appv1.ApplicationStatus) (patchMs time.Duration) {
logCtx := getAppLog(orig)
logCtx := log.WithFields(log.Fields{"application": orig.QualifiedName()})
if orig.Status.Sync.Status != newStatus.Sync.Status {
message := fmt.Sprintf("Updated sync status: %s -> %s", orig.Status.Sync.Status, newStatus.Sync.Status)
ctrl.auditLogger.LogAppEvent(orig, argo.EventInfo{Reason: argo.EventReasonResourceUpdated, Type: v1.EventTypeNormal}, message, "")
@@ -1821,7 +1812,7 @@ func (ctrl *ApplicationController) autoSync(app *appv1.Application, syncStatus *
if app.Spec.SyncPolicy == nil || app.Spec.SyncPolicy.Automated == nil {
return nil, 0
}
logCtx := getAppLog(app)
logCtx := log.WithFields(log.Fields{"application": app.QualifiedName()})
if app.Operation != nil {
logCtx.Infof("Skipping auto-sync: another operation is in progress")
@@ -2019,7 +2010,7 @@ func (ctrl *ApplicationController) canProcessApp(obj interface{}) bool {
if annotations := app.GetAnnotations(); annotations != nil {
if skipVal, ok := annotations[common.AnnotationKeyAppSkipReconcile]; ok {
logCtx := getAppLog(app)
logCtx := log.WithFields(log.Fields{"application": app.QualifiedName()})
if skipReconcile, err := strconv.ParseBool(skipVal); err == nil {
if skipReconcile {
logCtx.Debugf("Skipping Application reconcile based on annotation %s", common.AnnotationKeyAppSkipReconcile)
@@ -2155,7 +2146,7 @@ func (ctrl *ApplicationController) newApplicationInformerAndLister() (cache.Shar
newApp, newOK := new.(*appv1.Application)
if oldOK && newOK {
if automatedSyncEnabled(oldApp, newApp) {
getAppLog(newApp).Info("Enabled automated sync")
log.WithField("application", newApp.QualifiedName()).Info("Enabled automated sync")
compareWith = CompareWithLatest.Pointer()
}
if ctrl.statusRefreshJitter != 0 && oldApp.ResourceVersion == newApp.ResourceVersion {

View File

@@ -19,6 +19,7 @@ import (
statecache "github.com/argoproj/argo-cd/v2/controller/cache"
"github.com/argoproj/argo-cd/v2/controller/sharding"
dbmocks "github.com/argoproj/argo-cd/v2/util/db/mocks"
"github.com/argoproj/gitops-engine/pkg/cache/mocks"
synccommon "github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
@@ -35,8 +36,6 @@ import (
"k8s.io/client-go/tools/cache"
"sigs.k8s.io/yaml"
dbmocks "github.com/argoproj/argo-cd/v2/util/db/mocks"
mockstatecache "github.com/argoproj/argo-cd/v2/controller/cache/mocks"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake"
@@ -1410,7 +1409,7 @@ func TestRefreshAppConditions(t *testing.T) {
_, hasErrors := ctrl.refreshAppConditions(app)
assert.False(t, hasErrors)
assert.Empty(t, app.Status.Conditions)
assert.Len(t, app.Status.Conditions, 0)
})
t.Run("PreserveExistingWarningCondition", func(t *testing.T) {
@@ -1719,36 +1718,6 @@ func TestProcessRequestedAppOperation_HasRetriesTerminated(t *testing.T) {
assert.Equal(t, string(synccommon.OperationFailed), phase)
}
func TestProcessRequestedAppOperation_Successful(t *testing.T) {
app := newFakeApp()
app.Spec.Project = "default"
app.Operation = &v1alpha1.Operation{
Sync: &v1alpha1.SyncOperation{},
}
ctrl := newFakeController(&fakeData{
apps: []runtime.Object{app, &defaultProj},
manifestResponses: []*apiclient.ManifestResponse{{
Manifests: []string{},
}},
}, nil)
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
receivedPatch := map[string]interface{}{}
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
}
return true, &v1alpha1.Application{}, nil
})
ctrl.processRequestedAppOperation(app)
phase, _, _ := unstructured.NestedString(receivedPatch, "status", "operationState", "phase")
assert.Equal(t, string(synccommon.OperationSucceeded), phase)
ok, level := ctrl.isRefreshRequested(ctrl.toAppKey(app.Name))
assert.True(t, ok)
assert.Equal(t, CompareWithLatestForceResolve, level)
}
func TestGetAppHosts(t *testing.T) {
app := newFakeApp()
data := &fakeData{

View File

@@ -41,8 +41,6 @@ import (
"github.com/argoproj/argo-cd/v2/util/settings"
)
//go:generate go run github.com/vektra/mockery/v2@v2.40.2 --name=LiveStateCache
const (
// EnvClusterCacheResyncDuration is the env variable that holds cluster cache re-sync duration
EnvClusterCacheResyncDuration = "ARGOCD_CLUSTER_CACHE_RESYNC_DURATION"

View File

@@ -127,7 +127,7 @@ func TestHandleAddEvent_ClusterExcluded(t *testing.T) {
Config: appv1.ClusterConfig{Username: "bar"},
})
assert.Empty(t, clustersCache.clusters)
assert.Len(t, clustersCache.clusters, 0)
}
func TestHandleDeleteEvent_CacheDeadlock(t *testing.T) {

View File

@@ -314,7 +314,7 @@ status:
func TestGetServiceInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testService, info, []string{})
assert.Empty(t, info.Info)
assert.Equal(t, 0, len(info.Info))
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
TargetLabels: map[string]string{"app": "guestbook"},
Ingress: []v1.LoadBalancerIngress{{Hostname: "localhost"}},
@@ -324,7 +324,7 @@ func TestGetServiceInfo(t *testing.T) {
func TestGetLinkAnnotatedServiceInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testLinkAnnotatedService, info, []string{})
assert.Empty(t, info.Info)
assert.Equal(t, 0, len(info.Info))
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
TargetLabels: map[string]string{"app": "guestbook"},
Ingress: []v1.LoadBalancerIngress{{Hostname: "localhost"}},
@@ -335,7 +335,7 @@ func TestGetLinkAnnotatedServiceInfo(t *testing.T) {
func TestGetIstioVirtualServiceInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testIstioVirtualService, info, []string{})
assert.Empty(t, info.Info)
assert.Equal(t, 0, len(info.Info))
require.NotNil(t, info.NetworkingInfo)
require.NotNil(t, info.NetworkingInfo.TargetRefs)
assert.Contains(t, info.NetworkingInfo.TargetRefs, v1alpha1.ResourceRef{
@@ -365,7 +365,7 @@ func TestGetIngressInfo(t *testing.T) {
for _, tc := range tests {
info := &ResourceInfo{}
populateNodeInfo(tc.Ingress, info, []string{})
assert.Empty(t, info.Info)
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
})
@@ -390,7 +390,7 @@ func TestGetIngressInfo(t *testing.T) {
func TestGetLinkAnnotatedIngressInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testLinkAnnotatedIngress, info, []string{})
assert.Empty(t, info.Info)
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
})
@@ -414,7 +414,7 @@ func TestGetLinkAnnotatedIngressInfo(t *testing.T) {
func TestGetIngressInfoWildCardPath(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testIngressWildCardPath, info, []string{})
assert.Empty(t, info.Info)
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
})
@@ -438,7 +438,7 @@ func TestGetIngressInfoWildCardPath(t *testing.T) {
func TestGetIngressInfoWithoutTls(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testIngressWithoutTls, info, []string{})
assert.Empty(t, info.Info)
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
})
@@ -525,7 +525,7 @@ func TestGetIngressInfoNoHost(t *testing.T) {
Name: "helm-guestbook",
}},
}, info.NetworkingInfo)
assert.Empty(t, info.NetworkingInfo.ExternalURLs)
assert.Equal(t, len(info.NetworkingInfo.ExternalURLs), 0)
}
func TestExternalUrlWithSubPath(t *testing.T) {
ingress := strToUnstructured(`
@@ -660,7 +660,7 @@ func TestCustomLabel(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(configmap, info, []string{"my-label"})
assert.Empty(t, info.Info)
assert.Equal(t, 0, len(info.Info))
configmap = strToUnstructured(`
apiVersion: v1
@@ -673,7 +673,7 @@ func TestCustomLabel(t *testing.T) {
info = &ResourceInfo{}
populateNodeInfo(configmap, info, []string{"my-label", "other-label"})
assert.Len(t, info.Info, 1)
assert.Equal(t, 1, len(info.Info))
assert.Equal(t, "my-label", info.Info[0].Name)
assert.Equal(t, "value", info.Info[0].Value)
@@ -689,7 +689,7 @@ func TestCustomLabel(t *testing.T) {
info = &ResourceInfo{}
populateNodeInfo(configmap, info, []string{"my-label", "other-label"})
assert.Len(t, info.Info, 2)
assert.Equal(t, 2, len(info.Info))
assert.Equal(t, "my-label", info.Info[0].Name)
assert.Equal(t, "value", info.Info[0].Value)
assert.Equal(t, "other-label", info.Info[1].Name)
@@ -752,5 +752,5 @@ func TestManifestHash(t *testing.T) {
hash, err := generateManifestHash(manifest, ignores, nil, normalizers.IgnoreNormalizerOpts{})
assert.Equal(t, expected, hash)
assert.NoError(t, err)
assert.Nil(t, err)
}

View File

@@ -1,4 +1,4 @@
// Code generated by mockery v2.40.2. DO NOT EDIT.
// Code generated by mockery v1.0.0. DO NOT EDIT.
package mocks
@@ -29,15 +29,7 @@ type LiveStateCache struct {
func (_m *LiveStateCache) GetClusterCache(server string) (cache.ClusterCache, error) {
ret := _m.Called(server)
if len(ret) == 0 {
panic("no return value specified for GetClusterCache")
}
var r0 cache.ClusterCache
var r1 error
if rf, ok := ret.Get(0).(func(string) (cache.ClusterCache, error)); ok {
return rf(server)
}
if rf, ok := ret.Get(0).(func(string) cache.ClusterCache); ok {
r0 = rf(server)
} else {
@@ -46,6 +38,7 @@ func (_m *LiveStateCache) GetClusterCache(server string) (cache.ClusterCache, er
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(server)
} else {
@@ -59,10 +52,6 @@ func (_m *LiveStateCache) GetClusterCache(server string) (cache.ClusterCache, er
func (_m *LiveStateCache) GetClustersInfo() []cache.ClusterInfo {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for GetClustersInfo")
}
var r0 []cache.ClusterInfo
if rf, ok := ret.Get(0).(func() []cache.ClusterInfo); ok {
r0 = rf()
@@ -79,15 +68,7 @@ func (_m *LiveStateCache) GetClustersInfo() []cache.ClusterInfo {
func (_m *LiveStateCache) GetManagedLiveObjs(a *v1alpha1.Application, targetObjs []*unstructured.Unstructured) (map[kube.ResourceKey]*unstructured.Unstructured, error) {
ret := _m.Called(a, targetObjs)
if len(ret) == 0 {
panic("no return value specified for GetManagedLiveObjs")
}
var r0 map[kube.ResourceKey]*unstructured.Unstructured
var r1 error
if rf, ok := ret.Get(0).(func(*v1alpha1.Application, []*unstructured.Unstructured) (map[kube.ResourceKey]*unstructured.Unstructured, error)); ok {
return rf(a, targetObjs)
}
if rf, ok := ret.Get(0).(func(*v1alpha1.Application, []*unstructured.Unstructured) map[kube.ResourceKey]*unstructured.Unstructured); ok {
r0 = rf(a, targetObjs)
} else {
@@ -96,6 +77,7 @@ func (_m *LiveStateCache) GetManagedLiveObjs(a *v1alpha1.Application, targetObjs
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*v1alpha1.Application, []*unstructured.Unstructured) error); ok {
r1 = rf(a, targetObjs)
} else {
@@ -109,15 +91,7 @@ func (_m *LiveStateCache) GetManagedLiveObjs(a *v1alpha1.Application, targetObjs
func (_m *LiveStateCache) GetNamespaceTopLevelResources(server string, namespace string) (map[kube.ResourceKey]v1alpha1.ResourceNode, error) {
ret := _m.Called(server, namespace)
if len(ret) == 0 {
panic("no return value specified for GetNamespaceTopLevelResources")
}
var r0 map[kube.ResourceKey]v1alpha1.ResourceNode
var r1 error
if rf, ok := ret.Get(0).(func(string, string) (map[kube.ResourceKey]v1alpha1.ResourceNode, error)); ok {
return rf(server, namespace)
}
if rf, ok := ret.Get(0).(func(string, string) map[kube.ResourceKey]v1alpha1.ResourceNode); ok {
r0 = rf(server, namespace)
} else {
@@ -126,6 +100,7 @@ func (_m *LiveStateCache) GetNamespaceTopLevelResources(server string, namespace
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string) error); ok {
r1 = rf(server, namespace)
} else {
@@ -139,22 +114,14 @@ func (_m *LiveStateCache) GetNamespaceTopLevelResources(server string, namespace
func (_m *LiveStateCache) GetVersionsInfo(serverURL string) (string, []kube.APIResourceInfo, error) {
ret := _m.Called(serverURL)
if len(ret) == 0 {
panic("no return value specified for GetVersionsInfo")
}
var r0 string
var r1 []kube.APIResourceInfo
var r2 error
if rf, ok := ret.Get(0).(func(string) (string, []kube.APIResourceInfo, error)); ok {
return rf(serverURL)
}
if rf, ok := ret.Get(0).(func(string) string); ok {
r0 = rf(serverURL)
} else {
r0 = ret.Get(0).(string)
}
var r1 []kube.APIResourceInfo
if rf, ok := ret.Get(1).(func(string) []kube.APIResourceInfo); ok {
r1 = rf(serverURL)
} else {
@@ -163,6 +130,7 @@ func (_m *LiveStateCache) GetVersionsInfo(serverURL string) (string, []kube.APIR
}
}
var r2 error
if rf, ok := ret.Get(2).(func(string) error); ok {
r2 = rf(serverURL)
} else {
@@ -176,10 +144,6 @@ func (_m *LiveStateCache) GetVersionsInfo(serverURL string) (string, []kube.APIR
func (_m *LiveStateCache) Init() error {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Init")
}
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
@@ -194,21 +158,14 @@ func (_m *LiveStateCache) Init() error {
func (_m *LiveStateCache) IsNamespaced(server string, gk schema.GroupKind) (bool, error) {
ret := _m.Called(server, gk)
if len(ret) == 0 {
panic("no return value specified for IsNamespaced")
}
var r0 bool
var r1 error
if rf, ok := ret.Get(0).(func(string, schema.GroupKind) (bool, error)); ok {
return rf(server, gk)
}
if rf, ok := ret.Get(0).(func(string, schema.GroupKind) bool); ok {
r0 = rf(server, gk)
} else {
r0 = ret.Get(0).(bool)
}
var r1 error
if rf, ok := ret.Get(1).(func(string, schema.GroupKind) error); ok {
r1 = rf(server, gk)
} else {
@@ -222,10 +179,6 @@ func (_m *LiveStateCache) IsNamespaced(server string, gk schema.GroupKind) (bool
func (_m *LiveStateCache) IterateHierarchy(server string, key kube.ResourceKey, action func(v1alpha1.ResourceNode, string) bool) error {
ret := _m.Called(server, key, action)
if len(ret) == 0 {
panic("no return value specified for IterateHierarchy")
}
var r0 error
if rf, ok := ret.Get(0).(func(string, kube.ResourceKey, func(v1alpha1.ResourceNode, string) bool) error); ok {
r0 = rf(server, key, action)
@@ -240,10 +193,6 @@ func (_m *LiveStateCache) IterateHierarchy(server string, key kube.ResourceKey,
func (_m *LiveStateCache) IterateResources(server string, callback func(*cache.Resource, *controllercache.ResourceInfo)) error {
ret := _m.Called(server, callback)
if len(ret) == 0 {
panic("no return value specified for IterateResources")
}
var r0 error
if rf, ok := ret.Get(0).(func(string, func(*cache.Resource, *controllercache.ResourceInfo)) error); ok {
r0 = rf(server, callback)
@@ -258,10 +207,6 @@ func (_m *LiveStateCache) IterateResources(server string, callback func(*cache.R
func (_m *LiveStateCache) Run(ctx context.Context) error {
ret := _m.Called(ctx)
if len(ret) == 0 {
panic("no return value specified for Run")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
r0 = rf(ctx)
@@ -271,17 +216,3 @@ func (_m *LiveStateCache) Run(ctx context.Context) error {
return r0
}
// NewLiveStateCache creates a new instance of LiveStateCache. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewLiveStateCache(t interface {
mock.TestingT
Cleanup(func())
}) *LiveStateCache {
mock := &LiveStateCache{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -3,18 +3,16 @@ package controller
import (
"context"
"fmt"
"github.com/argoproj/argo-cd/v2/common"
"time"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/util/env"
"github.com/argoproj/gitops-engine/pkg/cache"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"github.com/argoproj/argo-cd/v2/util/env"
"github.com/argoproj/argo-cd/v2/controller/metrics"
appv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/pkg/client/listers/application/v1alpha1"

Some files were not shown because too many files have changed in this diff Show More