Compare commits

...

46 Commits

Author SHA1 Message Date
github-actions[bot]
bf0fa07aed Bump version to 2.8.21 (#19628)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: jessesuen <12677113+jessesuen@users.noreply.github.com>
2024-08-21 16:37:45 -07:00
Alexander Matyushentsev
e19aaaa73a fix: ArgoCD 2.11 - Loop of PATCH calls to Application objects (#19340) (#19570)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2024-08-21 08:33:44 -06:00
gcp-cherry-pick-bot[bot]
6ebbc75e2a fix: Update braces package to 3.0.3 (#18459) (#18666)
Signed-off-by: Keith Chong <kykchong@redhat.com>
Co-authored-by: Keith Chong <kykchong@redhat.com>
2024-06-14 09:19:32 -04:00
gcp-cherry-pick-bot[bot]
dbb7f0363e test: fix e2e tests after GHSA-3cqf-953p-h5cp (#18543) (#18555)
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-06-07 11:50:03 -04:00
github-actions[bot]
aa77055fd4 Bump version to 2.8.20 (#18386)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: pasha-codefresh <39732895+pasha-codefresh@users.noreply.github.com>
2024-05-23 16:35:12 +03:00
pasha-codefresh
5aa0bb9124 fix: remove Egress NetworkPolicy for argocd-redis and argocd-redis-ha-haproxy (#18367) - 2.8 (#18383) 2024-05-23 09:05:41 -04:00
github-actions[bot]
b5bdef0d06 Bump version to 2.8.19 (#18322)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: pasha-codefresh <39732895+pasha-codefresh@users.noreply.github.com>
2024-05-21 17:01:07 +03:00
Leonardo Luz Almeida
4e2fe302c3 Merge pull request from GHSA-9766-5277-j5hr
* fix: Enable Redis authentication in the default installation

Signed-off-by: May Zhang <may_zhang@intuit.com>

* chore: fix git_test unit test

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

---------

Signed-off-by: May Zhang <may_zhang@intuit.com>
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
Co-authored-by: May Zhang <may_zhang@intuit.com>
2024-05-21 16:23:10 +03:00
Leonardo Luz Almeida
35a7d6c7fa Merge pull request from GHSA-9766-5277-j5hr
* fix: Enable Redis authentication in the default installation

Signed-off-by: May Zhang <may_zhang@intuit.com>

* chore: fix git_test unit test

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

---------

Signed-off-by: May Zhang <may_zhang@intuit.com>
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
Co-authored-by: May Zhang <may_zhang@intuit.com>
2024-05-21 16:22:43 +03:00
gcp-cherry-pick-bot[bot]
c227d2277b docs: fix 404 styling (#18094) (#18107)
* docs: fix 404 styling



* hack around custom tag destruction



---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-05-07 09:08:17 -04:00
Alexander Matyushentsev
bc54c768ae fix: status.sync.comparedTo should use replace patch strategy (#18061) (#18077)
* fix: status.sync.comparedTo should use replace patch strategy



* add e2e tests



---------

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2024-05-05 11:54:35 -07:00
github-actions[bot]
a67037a944 Bump version to 2.8.18 (#18036)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: jannfis <3942683+jannfis@users.noreply.github.com>
2024-04-30 13:38:16 -04:00
Jann Fischer
47f929501d fix: enable sha256 and sha512 for git ssh (#18031)
Signed-off-by: jannfis <jann@mistrust.net>
2024-04-30 13:00:53 -04:00
github-actions[bot]
f2ae45b10a Bump version to 2.8.17 (#17988)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: pasha-codefresh <39732895+pasha-codefresh@users.noreply.github.com>
2024-04-26 15:49:01 +03:00
pasha-codefresh
85c70c7f4b chore: fix codegen after security fix (#17983)
Signed-off-by: pashakostohrys <pavel@codefresh.io>
2024-04-26 08:14:22 -04:00
pasha-codefresh
11959ade81 Merge pull request from GHSA-9m6p-x4h2-6frq
* feat: limit jq.Run with timeout

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: ignore normalizer jq execution timeout as env variable

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: customize error message and add doc section

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: improve log and change a way how to get variable

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: reorganize imports

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* chore: fix import`s order

Signed-off-by: pashakostohrys <pavel@codefresh.io>

---------

Signed-off-by: pashakostohrys <pavel@codefresh.io>
2024-04-26 12:24:32 +03:00
pasha-codefresh
7893979a1e Merge pull request from GHSA-9m6p-x4h2-6frq
* feat: limit jq.Run with timeout

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: ignore normalizer jq execution timeout as env variable

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: customize error message and add doc section

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: improve log and change a way how to get variable

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: reorganize imports

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* chore: fix import`s order

Signed-off-by: pashakostohrys <pavel@codefresh.io>

---------

Signed-off-by: pashakostohrys <pavel@codefresh.io>
2024-04-26 12:24:02 +03:00
Tais P. Hansen
a64649dd05 chore: upgrade redis to 7.0.15 (#17668)
Upgrade to latest stable 7.0.x version to fix CVEs:

CVE-2023-41056
CVE-2023-45145
CVE-2023-41053
CVE-2022-24834
CVE-2023-36824

Signed-off-by: Tais P. Hansen <taishansen@gmail.com>
2024-04-16 12:54:36 +03:00
Michael Crenshaw
a0b0c3bfdb fix(security): use Chainguard fork of git-urls (#17737)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-04-16 09:31:14 +03:00
pasha-codefresh
ae04112320 fix: codegen and e2e tests (#17846)
Signed-off-by: pashakostohrys <pavel@codefresh.io>
2024-04-15 10:59:47 -04:00
pashakostohrys
a5ae7bd161 fix: docker build fails due to "The repository 'http://deb.debian.org/debian buster-backports Release' does not have a Release file."
Signed-off-by: pashakostohrys <pavel@codefresh.io>
2024-04-15 11:50:31 +03:00
github-actions[bot]
0fa1c8b0d6 Bump version to 2.8.16 (#17833)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: pasha-codefresh <pasha-codefresh@users.noreply.github.com>
2024-04-15 10:44:13 +03:00
pasha-codefresh
c5a252c4cc Merge pull request from GHSA-2gvw-w6fj-7m3c
Signed-off-by: pashakostohrys <pavel@codefresh.io>
2024-04-15 10:20:07 +03:00
github-actions[bot]
e94f6a8f84 Bump version to 2.8.15 (#17741)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: alexmt <alexmt@users.noreply.github.com>
2024-04-04 16:35:07 -07:00
Alexander Matyushentsev
6f9ae9d4f7 fix: fix calculating patch for respect ignore diff feature (#17693)
* test: unit test for respectIgnoreDifferences bug

Signed-off-by: Jesse Suen <jesse@akuity.io>

* test: simplify unit test

Signed-off-by: Jesse Suen <jesse@akuity.io>

* fix: fix calculating patch for respect ignore diff feature

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>

---------

Signed-off-by: Jesse Suen <jesse@akuity.io>
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
Co-authored-by: Jesse Suen <jesse@akuity.io>
2024-04-04 11:20:19 -07:00
gcp-cherry-pick-bot[bot]
08fdc9c7c4 chore(deps): bump webpack-dev-middleware from 5.3.1 to 5.3.4 in /ui (#17598) (#17688)
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.1 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.1...v5.3.4)

---
updated-dependencies:
- dependency-name: webpack-dev-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 10:24:14 -04:00
pasha-codefresh
9324949efc chore(ci): cosign fix (cherry pick v2.8) (#17661)
* fix cosign

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* fix cosign

Signed-off-by: pashakostohrys <pavel@codefresh.io>

---------

Signed-off-by: pashakostohrys <pavel@codefresh.io>
Co-authored-by: Justin Marquis <justin@akuity.io>
2024-03-28 18:12:56 +02:00
github-actions[bot]
e2a36c3e7a Bump version to 2.8.14 (#17652)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: pasha-codefresh <pasha-codefresh@users.noreply.github.com>
2024-03-28 14:53:01 +02:00
pasha-codefresh
36b8a12a38 Merge pull request from GHSA-jhwx-mhww-rgc3
* sec: limit helm index max size

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* sec: limit helm index max size

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: fix tests and linter

Signed-off-by: pashakostohrys <pavel@codefresh.io>

---------

Signed-off-by: pashakostohrys <pavel@codefresh.io>
2024-03-28 14:38:03 +02:00
gcp-cherry-pick-bot[bot]
3be5efa79c fix: elements should be optional (#17424) (#17511)
A bug was reported, where an applicationset with an empty elements
array, when created with `argocd appset create <filename>.yaml` gets a
`...list.elements: Required value` error.

My hypothesis is that when calling the K8s API, golang JSON marshalling
mangles the empty `elements` array to `nil`, rather than creating an
empty array when submitting the `POST`.

Still need to figure out why the same setup seemingly works fine when
the same appset is in an app-of-apps.

Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2024-03-28 00:28:00 -04:00
github-actions[bot]
231e359c22 Bump version to 2.8.13 (#17556)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2024-03-18 04:03:06 -04:00
Dan Garfield
2a22e19e06 Merge pull request from GHSA-6v85-wr92-q4p7
* fix: Fix concurrency issue in session manager

Signed-off-by: jannfis <jann@mistrust.net>

* Add note that modification to the map must be done in a thread safe manner

* chore: fix linter issues

Signed-off-by: pashakostohrys <pavel@codefresh.io>

---------

Signed-off-by: jannfis <jann@mistrust.net>
Signed-off-by: pashakostohrys <pavel@codefresh.io>
Co-authored-by: jannfis <jann@mistrust.net>
Co-authored-by: pashakostohrys <pavel@codefresh.io>
2024-03-18 03:59:06 -04:00
pasha-codefresh
17b0df1168 Merge pull request from GHSA-2vgg-9h6w-m454
* feat: pick random user and exclude admin user and current user from deletion candidates

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* feat: increase default max cache size

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* add nil protection

Signed-off-by: pashakostohrys <pavel@codefresh.io>

* Update util/session/sessionmanager.go

Signed-off-by: Dan Garfield <dan@codefresh.io>

Signed-off-by: Dan Garfield <dan@codefresh.io>

* chore: fix linter issues

Signed-off-by: pashakostohrys <pavel@codefresh.io>

---------

Signed-off-by: pashakostohrys <pavel@codefresh.io>
Signed-off-by: Dan Garfield <dan@codefresh.io>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2024-03-18 03:58:18 -04:00
gcp-cherry-pick-bot[bot]
4df9a46e72 fix: registry argument to be only the host instead full URL (#17381) (#17536)
Signed-off-by: Pablo Aguilar <pablo.aguilar@outlook.com.br>
Co-authored-by: Pablo Aguilar <pablo.aguilar@outlook.com.br>
2024-03-15 17:32:32 -04:00
github-actions[bot]
7113616085 Bump version to 2.8.12 (#17515)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2024-03-13 14:45:10 -04:00
Michael Crenshaw
c74355d838 Merge pull request from GHSA-g623-jcgg-mhmm
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-03-13 14:28:43 -04:00
Alexandre Gaudreault
4629a2b033 Merge pull request from GHSA-jwv5-8mqv-g387
* fix: Validate external URLs for applicatins

Signed-off-by: Ry0taK <49341894+Ry0taK@users.noreply.github.com>

* fix(ui): remove invalid external-link

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* linting

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

---------

Signed-off-by: Ry0taK <49341894+Ry0taK@users.noreply.github.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Ry0taK <49341894+Ry0taK@users.noreply.github.com>
2024-03-13 14:26:47 -04:00
Justin Marquis
3983cc4b9d fix: free disk space for release (#17443)
Signed-off-by: Justin Marquis <justin@akuity.io>
2024-03-07 18:30:32 -05:00
github-actions[bot]
951656f083 Bump version to 2.8.11 (#17375)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2024-03-01 17:28:41 -05:00
gcp-cherry-pick-bot[bot]
02f7c231b5 fix: The argocd server api-content-type flag does not allow empty content-type header (#17331) (#17348)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2024-02-28 10:15:19 -08:00
github-actions[bot]
6f2274a6a1 Bump version to 2.8.10 (#17079)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2024-02-02 13:12:23 -05:00
gcp-cherry-pick-bot[bot]
36f80e5f5c fix(redis): go-redis v9 regression missing metrics and reconnect hook (#13415) (#15275) (#17023)
* fix(redis): go-redis v9 regression missing metrics and reconnect hook



* fix: golangci lint return values not checked in tests



* chore: move dnsError var locally into func



---------

Signed-off-by: phanama <yudiandreanp@gmail.com>
Co-authored-by: Yudi A Phanama <11147376+phanama@users.noreply.github.com>
2024-01-30 09:44:27 -05:00
gcp-cherry-pick-bot[bot]
2b45cc8478 fix(ui): Badge for apps in any namespace (#16739) (#17009)
Signed-off-by: sshenoy6 <sonamkaup_shenoy@intuit.com>
Co-authored-by: Sonam <49382298+sonamkshenoy@users.noreply.github.com>
Co-authored-by: sshenoy6 <sonamkaup_shenoy@intuit.com>
2024-01-26 15:04:20 -05:00
Michael Crenshaw
152565a32e fix(server): allow disabling content-type check (#16959) (#16978)
* fix(server): allow disabling content-type check



* fix spacing



---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-01-24 18:07:21 -05:00
github-actions[bot]
3ef5ba76a9 Bump version to 2.8.9 (#16938)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2024-01-19 13:15:16 -05:00
gcp-cherry-pick-bot[bot]
104fb13769 fix(ui): set content-type for certain UI requests (#16923) (#16930) (#16934)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-01-19 11:49:19 -05:00
119 changed files with 4233 additions and 1819 deletions

View File

@@ -428,7 +428,7 @@ jobs:
run: |
docker pull ghcr.io/dexidp/dex:v2.37.0
docker pull argoproj/argo-cd-ci-builder:v1.0.0
docker pull redis:7.0.11-alpine
docker pull redis:7.0.15-alpine
- name: Create target directory for binaries in the build-process
run: |
mkdir -p dist

View File

@@ -74,9 +74,7 @@ jobs:
go-version: ${{ inputs.go-version }}
- name: Install cosign
uses: sigstore/cosign-installer@d13028333d784fcc802b67ec924bcebe75aa0a5f # v3.1.0
with:
cosign-release: 'v2.0.0'
uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4 # v3.4.0
- uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
- uses: docker/setup-buildx-action@ecf95283f03858871ff00b787d79c419715afc34 # v2.7.0
@@ -135,6 +133,14 @@ jobs:
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
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@4d9e71b726748f254fe64fa44d273194bd18ec91
with:
large-packages: false
docker-images: false
swap-storage: false
tool-cache: false
- name: Build and push container image
id: image
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 #v4.1.1

View File

@@ -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@v1.9.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

@@ -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@v1.9.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 }}
@@ -120,7 +120,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@v1.9.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"
@@ -204,7 +204,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@v1.9.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"

View File

@@ -6,7 +6,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:22.04@sha256:0bced47fffa3361afa981854fca
####################################################################################################
FROM docker.io/library/golang:1.20.10@sha256:ed6c4a5918b0a1ffb97970f6493d742dc5c7ebf3ccbd417c215d52830b57b994 AS builder
RUN echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
RUN echo 'deb http://archive.debian.org/debian buster-backports main' >> /etc/apt/sources.list
RUN apt-get update && apt-get install --no-install-recommends -y \
openssh-server \

View File

@@ -1 +1 @@
2.8.8
2.8.21

View File

@@ -42,6 +42,7 @@ import (
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/glob"
@@ -609,7 +610,7 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
},
}
action, err := utils.CreateOrUpdate(ctx, r.Client, found, func() error {
action, err := utils.CreateOrUpdate(ctx, r.Client, found, normalizers.IgnoreNormalizerOpts{}, func() error {
// Copy only the Application/ObjectMeta fields that are significant, from the generatedApp
found.Spec = generatedApp.Spec

View File

@@ -14,6 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
)
// CreateOrUpdate overrides "sigs.k8s.io/controller-runtime" function
@@ -29,7 +30,7 @@ import (
// The MutateFn is called regardless of creating or updating an object.
//
// It returns the executed operation and an error.
func CreateOrUpdate(ctx context.Context, c client.Client, obj client.Object, f controllerutil.MutateFn) (controllerutil.OperationResult, error) {
func CreateOrUpdate(ctx context.Context, c client.Client, obj client.Object, ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts, f controllerutil.MutateFn) (controllerutil.OperationResult, error) {
key := client.ObjectKeyFromObject(obj)
if err := c.Get(ctx, key, obj); err != nil {
@@ -94,4 +95,4 @@ func mutate(f controllerutil.MutateFn, key client.ObjectKey, obj client.Object)
return fmt.Errorf("MutateFn cannot mutate object name and/or object namespace")
}
return nil
}
}

View File

@@ -7302,6 +7302,7 @@
"properties": {
"elements": {
"type": "array",
"title": "+kubebuilder:validation:Optional",
"items": {
"$ref": "#/definitions/v1JSON"
}

View File

@@ -20,6 +20,7 @@ import (
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
cacheutil "github.com/argoproj/argo-cd/v2/util/cache"
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
"github.com/argoproj/argo-cd/v2/util/cli"
@@ -64,6 +65,7 @@ func NewCommand() *cobra.Command {
applicationNamespaces []string
persistResourceHealth bool
shardingAlgorithm string
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
)
var command = cobra.Command{
Use: cliName,
@@ -155,6 +157,7 @@ func NewCommand() *cobra.Command {
persistResourceHealth,
clusterFilter,
applicationNamespaces,
ignoreNormalizerOpts,
)
errors.CheckError(err)
cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer())
@@ -199,6 +202,7 @@ func NewCommand() *cobra.Command {
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] ")
command.Flags().DurationVar(&ignoreNormalizerOpts.JQExecutionTimeout, "ignore-normalizer-jq-execution-timeout-seconds", env.ParseDurationFromEnv("ARGOCD_IGNORE_NORMALIZER_JQ_TIMEOUT", 0*time.Second, 0, math.MaxInt64), "Set ignore normalizer JQ execution timeout")
cacheSrc = appstatecache.AddCacheFlagsToCmd(&command, func(client *redis.Client) {
redisClient = client
})

View File

@@ -83,6 +83,7 @@ func NewCommand() *cobra.Command {
streamedManifestMaxTarSize string
streamedManifestMaxExtractedSize string
helmManifestMaxExtractedSize string
helmRegistryMaxIndexSize string
disableManifestMaxExtractedSize bool
)
var command = cobra.Command{
@@ -125,6 +126,9 @@ func NewCommand() *cobra.Command {
helmManifestMaxExtractedSizeQuantity, err := resource.ParseQuantity(helmManifestMaxExtractedSize)
errors.CheckError(err)
helmRegistryMaxIndexSizeQuantity, err := resource.ParseQuantity(helmRegistryMaxIndexSize)
errors.CheckError(err)
askPassServer := askpass.NewServer()
metricsServer := metrics.NewMetricsServer()
cacheutil.CollectMetrics(redisClient, metricsServer)
@@ -140,6 +144,7 @@ func NewCommand() *cobra.Command {
StreamedManifestMaxExtractedSize: streamedManifestMaxExtractedSizeQuantity.ToDec().Value(),
StreamedManifestMaxTarSize: streamedManifestMaxTarSizeQuantity.ToDec().Value(),
HelmManifestMaxExtractedSize: helmManifestMaxExtractedSizeQuantity.ToDec().Value(),
HelmRegistryMaxIndexSize: helmRegistryMaxIndexSizeQuantity.ToDec().Value(),
}, askPassServer)
errors.CheckError(err)
@@ -223,6 +228,7 @@ func NewCommand() *cobra.Command {
command.Flags().StringVar(&streamedManifestMaxTarSize, "streamed-manifest-max-tar-size", env.StringFromEnv("ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_TAR_SIZE", "100M"), "Maximum size of streamed manifest archives")
command.Flags().StringVar(&streamedManifestMaxExtractedSize, "streamed-manifest-max-extracted-size", env.StringFromEnv("ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_EXTRACTED_SIZE", "1G"), "Maximum size of streamed manifest archives when extracted")
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")
tlsConfigCustomizerSrc = tls.AddTLSFlagsToCmd(&command)
cacheSrc = reposervercache.AddCacheFlagsToCmd(&command, func(client *redis.Client) {

View File

@@ -168,6 +168,11 @@ func NewCommand() *cobra.Command {
baseHRef = rootPath
}
var contentTypesList []string
if contentTypes != "" {
contentTypesList = strings.Split(contentTypes, ";")
}
argoCDOpts := server.ArgoCDServerOpts{
Insecure: insecure,
ListenPort: listenPort,
@@ -183,7 +188,7 @@ func NewCommand() *cobra.Command {
DexServerAddr: dexServerAddress,
DexTLSConfig: dexTlsConfig,
DisableAuth: disableAuth,
ContentTypes: strings.Split(contentTypes, ";"),
ContentTypes: contentTypesList,
EnableGZip: enableGZip,
TLSConfigCustomizer: tlsConfigCustomizer,
Cache: cache,
@@ -231,7 +236,7 @@ func NewCommand() *cobra.Command {
command.Flags().StringVar(&repoServerAddress, "repo-server", env.StringFromEnv("ARGOCD_SERVER_REPO_SERVER", common.DefaultRepoServerAddr), "Repo server address")
command.Flags().StringVar(&dexServerAddress, "dex-server", env.StringFromEnv("ARGOCD_SERVER_DEX_SERVER", common.DefaultDexServerAddr), "Dex server address")
command.Flags().BoolVar(&disableAuth, "disable-auth", env.ParseBoolFromEnv("ARGOCD_SERVER_DISABLE_AUTH", false), "Disable client authentication")
command.Flags().StringVar(&contentTypes, "api-content-types", "application/json", "Semicolon separated list of allowed content types for non GET api requests. Any content type is allowed if empty.")
command.Flags().StringVar(&contentTypes, "api-content-types", env.StringFromEnv("ARGOCD_API_CONTENT_TYPES", "application/json", env.StringFromEnvOpts{AllowEmpty: true}), "Semicolon separated list of allowed content types for non GET api requests. Any content type is allowed if empty.")
command.Flags().BoolVar(&enableGZip, "enable-gzip", env.ParseBoolFromEnv("ARGOCD_SERVER_ENABLE_GZIP", true), "Enable GZIP compression")
command.AddCommand(cli.NewVersionCmd(cliName))
command.Flags().StringVar(&listenHost, "address", env.StringFromEnv("ARGOCD_SERVER_LISTEN_ADDRESS", common.DefaultAddressAPIServer), "Listen on given address")

View File

@@ -59,6 +59,7 @@ func NewAdminCommand() *cobra.Command {
command.AddCommand(NewDashboardCommand())
command.AddCommand(NewNotificationsCommand())
command.AddCommand(NewInitialPasswordCommand())
command.AddCommand(NewRedisInitialPasswordCommand())
command.Flags().StringVar(&cmdutil.LogFormat, "logformat", "text", "Set the logging format. One of: text|json")
command.Flags().StringVar(&cmdutil.LogLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")

View File

@@ -28,6 +28,7 @@ import (
appinformers "github.com/argoproj/argo-cd/v2/pkg/client/informers/externalversions"
argocdclient "github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/util/argo"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
cacheutil "github.com/argoproj/argo-cd/v2/util/cache"
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
"github.com/argoproj/argo-cd/v2/util/cli"
@@ -231,6 +232,7 @@ func NewReconcileCommand() *cobra.Command {
repoServerAddress string
outputFormat string
refresh bool
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
)
var command = &cobra.Command{
@@ -267,7 +269,7 @@ func NewReconcileCommand() *cobra.Command {
appClientset := appclientset.NewForConfigOrDie(cfg)
kubeClientset := kubernetes.NewForConfigOrDie(cfg)
result, err = reconcileApplications(ctx, kubeClientset, appClientset, namespace, repoServerClient, selector, newLiveStateCache)
result, err = reconcileApplications(ctx, kubeClientset, appClientset, namespace, repoServerClient, selector, newLiveStateCache, ignoreNormalizerOpts)
errors.CheckError(err)
} else {
appClientset := appclientset.NewForConfigOrDie(cfg)
@@ -282,7 +284,7 @@ func NewReconcileCommand() *cobra.Command {
command.Flags().StringVar(&selector, "l", "", "Label selector")
command.Flags().StringVar(&outputFormat, "o", "yaml", "Output format (yaml|json)")
command.Flags().BoolVar(&refresh, "refresh", false, "If set to true then recalculates apps reconciliation")
command.Flags().DurationVar(&ignoreNormalizerOpts.JQExecutionTimeout, "ignore-normalizer-jq-execution-timeout", normalizers.DefaultJQExecutionTimeout, "Set ignore normalizer JQ execution timeout")
return command
}
@@ -331,6 +333,7 @@ func reconcileApplications(
repoServerClient argocdclient.Clientset,
selector string,
createLiveStateCache func(argoDB db.ArgoDB, appInformer kubecache.SharedIndexInformer, settingsMgr *settings.SettingsManager, server *metrics.MetricsServer) cache.LiveStateCache,
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts,
) ([]appReconcileResult, error) {
settingsMgr := settings.NewSettingsManager(ctx, kubeClientset, namespace)
argoDB := db.NewDB(namespace, settingsMgr, kubeClientset)
@@ -371,7 +374,7 @@ func reconcileApplications(
)
appStateManager := controller.NewAppStateManager(
argoDB, appClientset, repoServerClient, namespace, kubeutil.NewKubectl(), settingsMgr, stateCache, projInformer, server, cache, time.Second, argo.NewResourceTracking(), false)
argoDB, appClientset, repoServerClient, namespace, kubeutil.NewKubectl(), settingsMgr, stateCache, projInformer, server, cache, time.Second, argo.NewResourceTracking(), false, ignoreNormalizerOpts)
appsList, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(ctx, v1.ListOptions{LabelSelector: selector})
if err != nil {

View File

@@ -23,6 +23,7 @@ import (
argocdclient "github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient/mocks"
"github.com/argoproj/argo-cd/v2/test"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/settings"
)
@@ -113,6 +114,7 @@ func TestGetReconcileResults_Refresh(t *testing.T) {
func(argoDB db.ArgoDB, appInformer cache.SharedIndexInformer, settingsMgr *settings.SettingsManager, server *metrics.MetricsServer) statecache.LiveStateCache {
return &liveStateCache
},
normalizers.IgnoreNormalizerOpts{},
)
if !assert.NoError(t, err) {

View File

@@ -0,0 +1,98 @@
package admin
import (
"context"
"crypto/rand"
"fmt"
"math/big"
"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/spf13/cobra"
corev1 "k8s.io/api/core/v1"
)
const defaulRedisInitialPasswordSecretName = "argocd-redis"
const defaultResisInitialPasswordKey = "auth"
func generateRandomPassword() (string, error) {
const initialPasswordLength = 16
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
randBytes := make([]byte, initialPasswordLength)
for i := 0; i < initialPasswordLength; i++ {
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
if err != nil {
return "", err
}
randBytes[i] = letters[num.Int64()]
}
initialPassword := string(randBytes)
return initialPassword, nil
}
// NewRedisInitialPasswordCommand defines a new command to ensure Argo CD Redis password secret exists.
func NewRedisInitialPasswordCommand() *cobra.Command {
var (
clientConfig clientcmd.ClientConfig
)
var command = cobra.Command{
Use: "redis-initial-password",
Short: "Ensure the Redis password exists, creating a new one if necessary.",
Run: func(c *cobra.Command, args []string) {
namespace, _, err := clientConfig.Namespace()
errors.CheckError(err)
redisInitialPasswordSecretName := defaulRedisInitialPasswordSecretName
redisInitialPasswordKey := defaultResisInitialPasswordKey
fmt.Printf("Checking for initial Redis password in secret %s/%s at key %s. \n", namespace, redisInitialPasswordSecretName, redisInitialPasswordKey)
config, err := clientConfig.ClientConfig()
errors.CheckError(err)
errors.CheckError(v1alpha1.SetK8SConfigDefaults(config))
kubeClientset := kubernetes.NewForConfigOrDie(config)
randomPassword, err := generateRandomPassword()
errors.CheckError(err)
data := map[string][]byte{
redisInitialPasswordKey: []byte(randomPassword),
}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: redisInitialPasswordSecretName,
Namespace: namespace,
},
Data: data,
Type: corev1.SecretTypeOpaque,
}
_, err = kubeClientset.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{})
if err != nil && !apierr.IsAlreadyExists(err) {
errors.CheckError(err)
}
fmt.Println("Argo CD Redis secret state confirmed: secret name argocd-redis.")
secret, err = kubeClientset.CoreV1().Secrets(namespace).Get(context.Background(), redisInitialPasswordSecretName, v1.GetOptions{})
errors.CheckError(err)
if _, ok := secret.Data[redisInitialPasswordKey]; ok {
fmt.Println("Password secret is configured properly.")
} else {
err := fmt.Errorf("key %s doesn't exist in secret %s. \n", redisInitialPasswordKey, redisInitialPasswordSecretName)
errors.CheckError(err)
}
},
}
clientConfig = cli.AddKubectlFlagsToCmd(&command)
return &command
}

View File

@@ -432,7 +432,7 @@ argocd admin settings resource-overrides ignore-differences ./deploy.yaml --argo
// configurations. This requires access to live resources which is not the
// purpose of this command. This will just apply jsonPointers and
// jqPathExpressions configurations.
normalizer, err := normalizers.NewIgnoreNormalizer(nil, overrides)
normalizer, err := normalizers.NewIgnoreNormalizer(nil, overrides, normalizers.IgnoreNormalizerOpts{})
errors.CheckError(err)
normalizedRes := res.DeepCopy()
@@ -457,6 +457,9 @@ argocd admin settings resource-overrides ignore-differences ./deploy.yaml --argo
}
func NewResourceIgnoreResourceUpdatesCommand(cmdCtx commandContext) *cobra.Command {
var (
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
)
var command = &cobra.Command{
Use: "ignore-resource-updates RESOURCE_YAML_PATH",
Short: "Renders fields excluded from resource updates",
@@ -478,7 +481,7 @@ argocd admin settings resource-overrides ignore-resource-updates ./deploy.yaml -
return
}
normalizer, err := normalizers.NewIgnoreNormalizer(nil, overrides)
normalizer, err := normalizers.NewIgnoreNormalizer(nil, overrides, ignoreNormalizerOpts)
errors.CheckError(err)
normalizedRes := res.DeepCopy()
@@ -499,6 +502,7 @@ argocd admin settings resource-overrides ignore-resource-updates ./deploy.yaml -
})
},
}
command.Flags().DurationVar(&ignoreNormalizerOpts.JQExecutionTimeout, "ignore-normalizer-jq-execution-timeout", normalizers.DefaultJQExecutionTimeout, "Set ignore normalizer JQ execution timeout")
return command
}

View File

@@ -44,6 +44,7 @@ import (
"github.com/argoproj/argo-cd/v2/reposerver/repository"
"github.com/argoproj/argo-cd/v2/util/argo"
argodiff "github.com/argoproj/argo-cd/v2/util/argo/diff"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/util/errors"
"github.com/argoproj/argo-cd/v2/util/git"
@@ -925,6 +926,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
localRepoRoot string
serverSideGenerate bool
localIncludes []string
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
)
shortDesc := "Perform a diff against the target and live state."
var command = &cobra.Command{
@@ -989,7 +991,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
diffOption.cluster = cluster
}
}
foundDiffs := findandPrintDiff(ctx, app, resources, argoSettings, diffOption)
foundDiffs := findandPrintDiff(ctx, app, resources, argoSettings, diffOption, ignoreNormalizerOpts)
if foundDiffs && exitCode {
os.Exit(1)
}
@@ -1003,6 +1005,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
command.Flags().StringVar(&localRepoRoot, "local-repo-root", "/", "Path to the repository root. Used together with --local allows setting the repository root")
command.Flags().BoolVar(&serverSideGenerate, "server-side-generate", false, "Used with --local, this will send your manifests to the server for diffing")
command.Flags().StringArrayVar(&localIncludes, "local-include", []string{"*.yaml", "*.yml", "*.json"}, "Used with --server-side-generate, specify patterns of filenames to send. Matching is based on filename and not path.")
command.Flags().DurationVar(&ignoreNormalizerOpts.JQExecutionTimeout, "ignore-normalizer-jq-execution-timeout", normalizers.DefaultJQExecutionTimeout, "Set ignore normalizer JQ execution timeout")
return command
}
@@ -1017,7 +1020,7 @@ type DifferenceOption struct {
}
// findandPrintDiff ... Prints difference between application current state and state stored in git or locally, returns boolean as true if difference is found else returns false
func findandPrintDiff(ctx context.Context, app *argoappv1.Application, resources *application.ManagedResourcesResponse, argoSettings *settings.Settings, diffOptions *DifferenceOption) bool {
func findandPrintDiff(ctx context.Context, app *argoappv1.Application, resources *application.ManagedResourcesResponse, argoSettings *settings.Settings, diffOptions *DifferenceOption, ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts) bool {
var foundDiffs bool
liveObjs, err := cmdutil.LiveObjects(resources.Items)
errors.CheckError(err)
@@ -1072,7 +1075,7 @@ func findandPrintDiff(ctx context.Context, app *argoappv1.Application, resources
// compareOptions in the protobuf
ignoreAggregatedRoles := false
diffConfig, err := argodiff.NewDiffConfigBuilder().
WithDiffSettings(app.Spec.IgnoreDifferences, overrides, ignoreAggregatedRoles).
WithDiffSettings(app.Spec.IgnoreDifferences, overrides, ignoreAggregatedRoles, ignoreNormalizerOpts).
WithTracking(argoSettings.AppLabelKey, argoSettings.TrackingMethod).
WithNoCache().
Build()
@@ -1543,6 +1546,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
diffChanges bool
diffChangesConfirm bool
projects []string
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
)
var command = &cobra.Command{
Use: "sync [APPNAME... | -l selector | --project project-name]",
@@ -1764,7 +1768,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
foundDiffs := false
fmt.Printf("====== Previewing differences between live and desired state of application %s ======\n", appQualifiedName)
foundDiffs = findandPrintDiff(ctx, app, resources, argoSettings, diffOption)
foundDiffs = findandPrintDiff(ctx, app, resources, argoSettings, diffOption, ignoreNormalizerOpts)
if foundDiffs {
if !diffChangesConfirm {
yesno := cli.AskToProceed(fmt.Sprintf("Please review changes to application %s shown above. Do you want to continue the sync process? (y/n): ", appQualifiedName))
@@ -1820,6 +1824,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
command.Flags().BoolVar(&diffChangesConfirm, "assumeYes", false, "Assume yes as answer for all user queries or prompts")
command.Flags().BoolVar(&diffChanges, "preview-changes", false, "Preview difference against the target and live state before syncing app and wait for user confirmation")
command.Flags().StringArrayVar(&projects, "project", []string{}, "Sync apps that belong to the specified projects. This option may be specified repeatedly.")
command.Flags().DurationVar(&ignoreNormalizerOpts.JQExecutionTimeout, "ignore-normalizer-jq-execution-timeout", normalizers.DefaultJQExecutionTimeout, "Set ignore normalizer JQ execution timeout")
return command
}

View File

@@ -51,6 +51,7 @@ import (
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/util/argo"
argodiff "github.com/argoproj/argo-cd/v2/util/argo/diff"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
"github.com/argoproj/argo-cd/v2/util/db"
@@ -120,6 +121,7 @@ type ApplicationController struct {
clusterFilter func(cluster *appv1.Cluster) bool
projByNameCache sync.Map
applicationNamespaces []string
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
}
// NewApplicationController creates new instance of ApplicationController.
@@ -141,6 +143,7 @@ func NewApplicationController(
persistResourceHealth bool,
clusterFilter func(cluster *appv1.Cluster) bool,
applicationNamespaces []string,
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts,
) (*ApplicationController, error) {
log.Infof("appResyncPeriod=%v, appHardResyncPeriod=%v", appResyncPeriod, appHardResyncPeriod)
db := db.NewDB(namespace, settingsMgr, kubeClientset)
@@ -166,6 +169,7 @@ func NewApplicationController(
clusterFilter: clusterFilter,
projByNameCache: sync.Map{},
applicationNamespaces: applicationNamespaces,
ignoreNormalizerOpts: ignoreNormalizerOpts,
}
if kubectlParallelismLimit > 0 {
ctrl.kubectlSemaphore = semaphore.NewWeighted(kubectlParallelismLimit)
@@ -216,7 +220,7 @@ func NewApplicationController(
}
}
stateCache := statecache.NewLiveStateCache(db, appInformer, ctrl.settingsMgr, kubectl, ctrl.metricsServer, ctrl.handleObjectUpdated, clusterFilter, argo.NewResourceTracking())
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectl, ctrl.settingsMgr, stateCache, projInformer, ctrl.metricsServer, argoCache, ctrl.statusRefreshTimeout, argo.NewResourceTracking(), persistResourceHealth)
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectl, ctrl.settingsMgr, stateCache, projInformer, ctrl.metricsServer, argoCache, ctrl.statusRefreshTimeout, argo.NewResourceTracking(), persistResourceHealth, ignoreNormalizerOpts)
ctrl.appInformer = appInformer
ctrl.appLister = appLister
ctrl.projInformer = projInformer
@@ -666,7 +670,7 @@ func (ctrl *ApplicationController) hideSecretData(app *appv1.Application, compar
return nil, fmt.Errorf("error getting cluster cache: %s", err)
}
diffConfig, err := argodiff.NewDiffConfigBuilder().
WithDiffSettings(app.Spec.IgnoreDifferences, resourceOverrides, compareOptions.IgnoreAggregatedRoles).
WithDiffSettings(app.Spec.IgnoreDifferences, resourceOverrides, compareOptions.IgnoreAggregatedRoles, ctrl.ignoreNormalizerOpts).
WithTracking(appLabelKey, trackingMethod).
WithNoCache().
WithLogger(logutils.NewLogrusLogger(logutils.NewWithCurrentConfig())).
@@ -1601,6 +1605,22 @@ func (ctrl *ApplicationController) normalizeApplication(orig, app *appv1.Applica
}
}
func createMergePatch(orig, new interface{}) ([]byte, bool, error) {
origBytes, err := json.Marshal(orig)
if err != nil {
return nil, false, err
}
newBytes, err := json.Marshal(new)
if err != nil {
return nil, false, err
}
patch, err := jsonpatch.CreateMergePatch(origBytes, newBytes)
if err != nil {
return nil, false, err
}
return patch, string(patch) != "{}", nil
}
// 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) {
logCtx := log.WithFields(log.Fields{"application": orig.QualifiedName()})
@@ -1620,9 +1640,9 @@ func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, new
}
delete(newAnnotations, appv1.AnnotationKeyRefresh)
}
patch, modified, err := diff.CreateTwoWayMergePatch(
patch, modified, err := createMergePatch(
&appv1.Application{ObjectMeta: metav1.ObjectMeta{Annotations: orig.GetAnnotations()}, Status: orig.Status},
&appv1.Application{ObjectMeta: metav1.ObjectMeta{Annotations: newAnnotations}, Status: *newStatus}, appv1.Application{})
&appv1.Application{ObjectMeta: metav1.ObjectMeta{Annotations: newAnnotations}, Status: *newStatus})
if err != nil {
logCtx.Errorf("Error constructing app status patch: %v", err)
return

View File

@@ -21,6 +21,7 @@ import (
"github.com/argoproj/gitops-engine/pkg/utils/kube/kubetest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -38,6 +39,7 @@ import (
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
mockrepoclient "github.com/argoproj/argo-cd/v2/reposerver/apiclient/mocks"
"github.com/argoproj/argo-cd/v2/test"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
cacheutil "github.com/argoproj/argo-cd/v2/util/cache"
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
"github.com/argoproj/argo-cd/v2/util/settings"
@@ -123,6 +125,7 @@ func newFakeController(data *fakeData) *ApplicationController {
true,
nil,
data.applicationNamespaces,
normalizers.IgnoreNormalizerOpts{},
)
if err != nil {
panic(err)
@@ -821,7 +824,7 @@ func TestNormalizeApplication(t *testing.T) {
normalized := false
fakeAppCs.AddReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
if string(patchAction.GetPatch()) == `{"spec":{"project":"default"}}` {
if string(patchAction.GetPatch()) == `{"spec":{"project":"default"},"status":{"sync":{"comparedTo":{"destination":{},"source":{"repoURL":""}}}}}` {
normalized = true
}
}
@@ -1726,3 +1729,65 @@ func TestAddControllerNamespace(t *testing.T) {
assert.Equal(t, test.FakeArgoCDNamespace, updatedApp.Status.ControllerNamespace)
})
}
func TestHelmValuesObjectHasReplaceStrategy(t *testing.T) {
app := v1alpha1.Application{
Status: v1alpha1.ApplicationStatus{Sync: v1alpha1.SyncStatus{ComparedTo: v1alpha1.ComparedTo{
Source: v1alpha1.ApplicationSource{
Helm: &v1alpha1.ApplicationSourceHelm{
ValuesObject: &runtime.RawExtension{
Object: &unstructured.Unstructured{Object: map[string]interface{}{"key": []string{"value"}}},
},
},
},
}}},
}
appModified := v1alpha1.Application{
Status: v1alpha1.ApplicationStatus{Sync: v1alpha1.SyncStatus{ComparedTo: v1alpha1.ComparedTo{
Source: v1alpha1.ApplicationSource{
Helm: &v1alpha1.ApplicationSourceHelm{
ValuesObject: &runtime.RawExtension{
Object: &unstructured.Unstructured{Object: map[string]interface{}{"key": []string{"value-modified1"}}},
},
},
},
}}},
}
patch, _, err := createMergePatch(
app,
appModified)
require.NoError(t, err)
assert.Equal(t, `{"status":{"sync":{"comparedTo":{"source":{"helm":{"valuesObject":{"key":["value-modified1"]}}}}}}}`, string(patch))
}
func TestAppStatusIsReplaced(t *testing.T) {
original := &v1alpha1.ApplicationStatus{Sync: v1alpha1.SyncStatus{
ComparedTo: v1alpha1.ComparedTo{
Destination: v1alpha1.ApplicationDestination{
Server: "https://mycluster",
},
},
}}
updated := &v1alpha1.ApplicationStatus{Sync: v1alpha1.SyncStatus{
ComparedTo: v1alpha1.ComparedTo{
Destination: v1alpha1.ApplicationDestination{
Name: "mycluster",
},
},
}}
patchData, ok, err := createMergePatch(original, updated)
require.NoError(t, err)
require.True(t, ok)
patchObj := map[string]interface{}{}
require.NoError(t, json.Unmarshal(patchData, &patchObj))
val, has, err := unstructured.NestedFieldNoCopy(patchObj, "sync", "comparedTo", "destination", "server")
require.NoError(t, err)
require.True(t, has)
require.Nil(t, val)
}

View File

@@ -32,6 +32,7 @@ import (
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
appv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/argo"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/env"
logutils "github.com/argoproj/argo-cd/v2/util/log"
@@ -197,6 +198,7 @@ type liveStateCache struct {
metricsServer *metrics.MetricsServer
clusterFilter func(cluster *appv1.Cluster) bool
resourceTracking argo.ResourceTracking
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
clusters map[string]clustercache.ClusterCache
cacheSettings cacheSettings
@@ -473,7 +475,7 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
gvk := un.GroupVersionKind()
if cacheSettings.ignoreResourceUpdatesEnabled && shouldHashManifest(appName, gvk) {
hash, err := generateManifestHash(un, nil, cacheSettings.resourceOverrides)
hash, err := generateManifestHash(un, nil, cacheSettings.resourceOverrides, c.ignoreNormalizerOpts)
if err != nil {
log.Errorf("Failed to generate manifest hash: %v", err)
} else {

View File

@@ -390,8 +390,8 @@ func populateHostNodeInfo(un *unstructured.Unstructured, res *ResourceInfo) {
}
}
func generateManifestHash(un *unstructured.Unstructured, ignores []v1alpha1.ResourceIgnoreDifferences, overrides map[string]v1alpha1.ResourceOverride) (string, error) {
normalizer, err := normalizers.NewIgnoreNormalizer(ignores, overrides)
func generateManifestHash(un *unstructured.Unstructured, ignores []v1alpha1.ResourceIgnoreDifferences, overrides map[string]v1alpha1.ResourceOverride, opts normalizers.IgnoreNormalizerOpts) (string, error) {
normalizer, err := normalizers.NewIgnoreNormalizer(ignores, overrides, opts)
if err != nil {
return "", fmt.Errorf("error creating normalizer: %w", err)
}

View File

@@ -16,6 +16,7 @@ import (
"sigs.k8s.io/yaml"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
)
func strToUnstructured(jsonStr string) *unstructured.Unstructured {
@@ -749,7 +750,7 @@ func TestManifestHash(t *testing.T) {
expected := hash(data)
hash, err := generateManifestHash(manifest, ignores, nil)
hash, err := generateManifestHash(manifest, ignores, nil, normalizers.IgnoreNormalizerOpts{})
assert.Equal(t, expected, hash)
assert.Nil(t, err)
}

View File

@@ -4,11 +4,12 @@ import (
"context"
"encoding/json"
"fmt"
v1 "k8s.io/api/core/v1"
"reflect"
"strings"
"time"
v1 "k8s.io/api/core/v1"
"github.com/argoproj/gitops-engine/pkg/diff"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/sync"
@@ -32,6 +33,7 @@ import (
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/util/argo"
argodiff "github.com/argoproj/argo-cd/v2/util/argo/diff"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/gpg"
@@ -105,6 +107,7 @@ type appStateManager struct {
statusRefreshTimeout time.Duration
resourceTracking argo.ResourceTracking
persistResourceHealth bool
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
}
func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, sources []v1alpha1.ApplicationSource, appLabelKey string, revisions []string, noCache, noRevisionCache, verifySignature bool, proj *v1alpha1.AppProject) ([]*unstructured.Unstructured, []*apiclient.ManifestResponse, error) {
@@ -564,7 +567,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
noCache = noCache || refreshRequested || app.Status.Expired(m.statusRefreshTimeout) || specChanged || revisionChanged
diffConfigBuilder := argodiff.NewDiffConfigBuilder().
WithDiffSettings(app.Spec.IgnoreDifferences, resourceOverrides, compareOptions.IgnoreAggregatedRoles).
WithDiffSettings(app.Spec.IgnoreDifferences, resourceOverrides, compareOptions.IgnoreAggregatedRoles, m.ignoreNormalizerOpts).
WithTracking(appLabelKey, string(trackingMethod))
if noCache {
@@ -830,6 +833,7 @@ func NewAppStateManager(
statusRefreshTimeout time.Duration,
resourceTracking argo.ResourceTracking,
persistResourceHealth bool,
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts,
) AppStateManager {
return &appStateManager{
liveStateCache: liveStateCache,
@@ -845,6 +849,7 @@ func NewAppStateManager(
statusRefreshTimeout: statusRefreshTimeout,
resourceTracking: resourceTracking,
persistResourceHealth: persistResourceHealth,
ignoreNormalizerOpts: ignoreNormalizerOpts,
}
}

View File

@@ -2,7 +2,6 @@ package controller
import (
"context"
"encoding/json"
"fmt"
"os"
"strconv"
@@ -10,6 +9,7 @@ import (
"time"
cdcommon "github.com/argoproj/argo-cd/v2/common"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"github.com/argoproj/gitops-engine/pkg/sync"
"github.com/argoproj/gitops-engine/pkg/sync/common"
@@ -20,6 +20,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/managedfields"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/kubectl/pkg/util/openapi"
"github.com/argoproj/argo-cd/v2/controller/metrics"
@@ -370,11 +371,10 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
}
}
// normalizeTargetResources will apply the diff normalization in all live and target resources.
// Then it calculates the merge patch between the normalized live and the current live resources.
// Finally it applies the merge patch in the normalized target resources. This is done to ensure
// that target resources have the same ignored diff fields values from live ones to avoid them to
// be applied in the cluster. Returns the list of normalized target resources.
// normalizeTargetResources modifies target resources to ensure ignored fields are not touched during synchronization:
// - applies normalization to the target resources based on the live resources
// - copies ignored fields from the matching live resources: apply normalizer to the live resource,
// calculates the patch performed by normalizer and applies the patch to the target resource
func normalizeTargetResources(cr *comparisonResult) ([]*unstructured.Unstructured, error) {
// normalize live and target resources
normalized, err := diff.Normalize(cr.reconciliationResult.Live, cr.reconciliationResult.Target, cr.diffConfig)
@@ -393,94 +393,35 @@ func normalizeTargetResources(cr *comparisonResult) ([]*unstructured.Unstructure
patchedTargets = append(patchedTargets, originalTarget)
continue
}
// calculate targetPatch between normalized and target resource
targetPatch, err := getMergePatch(normalizedTarget, originalTarget)
var lookupPatchMeta *strategicpatch.PatchMetaFromStruct
versionedObject, err := scheme.Scheme.New(normalizedTarget.GroupVersionKind())
if err == nil {
meta, err := strategicpatch.NewPatchMetaFromStruct(versionedObject)
if err != nil {
return nil, err
}
lookupPatchMeta = &meta
}
livePatch, err := getMergePatch(normalized.Lives[idx], live, lookupPatchMeta)
if err != nil {
return nil, err
}
// check if there is a patch to apply. An empty patch is identified by a '{}' string.
if len(targetPatch) > 2 {
livePatch, err := getMergePatch(normalized.Lives[idx], live)
if err != nil {
return nil, err
}
// generate a minimal patch that uses the fields from targetPatch (template)
// with livePatch values
patch, err := compilePatch(targetPatch, livePatch)
if err != nil {
return nil, err
}
normalizedTarget, err = applyMergePatch(normalizedTarget, patch)
if err != nil {
return nil, err
}
} else {
// if there is no patch just use the original target
normalizedTarget = originalTarget
normalizedTarget, err = applyMergePatch(normalizedTarget, livePatch, versionedObject)
if err != nil {
return nil, err
}
patchedTargets = append(patchedTargets, normalizedTarget)
}
return patchedTargets, nil
}
// compilePatch will generate a patch using the fields from templatePatch with
// the values from valuePatch.
func compilePatch(templatePatch, valuePatch []byte) ([]byte, error) {
templateMap := make(map[string]interface{})
err := json.Unmarshal(templatePatch, &templateMap)
if err != nil {
return nil, err
}
valueMap := make(map[string]interface{})
err = json.Unmarshal(valuePatch, &valueMap)
if err != nil {
return nil, err
}
resultMap := intersectMap(templateMap, valueMap)
return json.Marshal(resultMap)
}
// intersectMap will return map with the fields intersection from the 2 provided
// maps populated with the valueMap values.
func intersectMap(templateMap, valueMap map[string]interface{}) map[string]interface{} {
result := make(map[string]interface{})
for k, v := range templateMap {
if innerTMap, ok := v.(map[string]interface{}); ok {
if innerVMap, ok := valueMap[k].(map[string]interface{}); ok {
result[k] = intersectMap(innerTMap, innerVMap)
}
} else if innerTSlice, ok := v.([]interface{}); ok {
if innerVSlice, ok := valueMap[k].([]interface{}); ok {
items := []interface{}{}
for idx, innerTSliceValue := range innerTSlice {
if idx < len(innerVSlice) {
if tSliceValueMap, ok := innerTSliceValue.(map[string]interface{}); ok {
if vSliceValueMap, ok := innerVSlice[idx].(map[string]interface{}); ok {
item := intersectMap(tSliceValueMap, vSliceValueMap)
items = append(items, item)
}
} else {
items = append(items, innerVSlice[idx])
}
}
}
if len(items) > 0 {
result[k] = items
}
}
} else {
if _, ok := valueMap[k]; ok {
result[k] = valueMap[k]
}
}
}
return result
}
// getMergePatch calculates and returns the patch between the original and the
// modified unstructures.
func getMergePatch(original, modified *unstructured.Unstructured) ([]byte, error) {
func getMergePatch(original, modified *unstructured.Unstructured, lookupPatchMeta *strategicpatch.PatchMetaFromStruct) ([]byte, error) {
originalJSON, err := original.MarshalJSON()
if err != nil {
return nil, err
@@ -489,20 +430,30 @@ func getMergePatch(original, modified *unstructured.Unstructured) ([]byte, error
if err != nil {
return nil, err
}
if lookupPatchMeta != nil {
return strategicpatch.CreateThreeWayMergePatch(modifiedJSON, modifiedJSON, originalJSON, lookupPatchMeta, true)
}
return jsonpatch.CreateMergePatch(originalJSON, modifiedJSON)
}
// applyMergePatch will apply the given patch in the obj and return the patched
// unstructure.
func applyMergePatch(obj *unstructured.Unstructured, patch []byte) (*unstructured.Unstructured, error) {
func applyMergePatch(obj *unstructured.Unstructured, patch []byte, versionedObject interface{}) (*unstructured.Unstructured, error) {
originalJSON, err := obj.MarshalJSON()
if err != nil {
return nil, err
}
patchedJSON, err := jsonpatch.MergePatch(originalJSON, patch)
var patchedJSON []byte
if versionedObject == nil {
patchedJSON, err = jsonpatch.MergePatch(originalJSON, patch)
} else {
patchedJSON, err = strategicpatch.StrategicMergePatch(originalJSON, patch, versionedObject)
}
if err != nil {
return nil, err
}
patchedObj := &unstructured.Unstructured{}
_, _, err = unstructured.UnstructuredJSONScheme.Decode(patchedJSON, nil, patchedObj)
if err != nil {

View File

@@ -19,6 +19,7 @@ import (
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/test"
"github.com/argoproj/argo-cd/v2/util/argo/diff"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
)
func TestPersistRevisionHistory(t *testing.T) {
@@ -263,7 +264,7 @@ func TestNormalizeTargetResources(t *testing.T) {
setup := func(t *testing.T, ignores []v1alpha1.ResourceIgnoreDifferences) *fixture {
t.Helper()
dc, err := diff.NewDiffConfigBuilder().
WithDiffSettings(ignores, nil, true).
WithDiffSettings(ignores, nil, true, normalizers.IgnoreNormalizerOpts{}).
WithNoCache().
Build()
require.NoError(t, err)
@@ -388,3 +389,207 @@ func TestNormalizeTargetResources(t *testing.T) {
assert.Equal(t, 2, len(containers))
})
}
func TestNormalizeTargetResourcesWithList(t *testing.T) {
type fixture struct {
comparisonResult *comparisonResult
}
setupHttpProxy := func(t *testing.T, ignores []v1alpha1.ResourceIgnoreDifferences) *fixture {
t.Helper()
dc, err := diff.NewDiffConfigBuilder().
WithDiffSettings(ignores, nil, true, normalizers.IgnoreNormalizerOpts{}).
WithNoCache().
Build()
require.NoError(t, err)
live := test.YamlToUnstructured(testdata.LiveHTTPProxy)
target := test.YamlToUnstructured(testdata.TargetHTTPProxy)
return &fixture{
&comparisonResult{
reconciliationResult: sync.ReconciliationResult{
Live: []*unstructured.Unstructured{live},
Target: []*unstructured.Unstructured{target},
},
diffConfig: dc,
},
}
}
t.Run("will properly ignore nested fields within arrays", func(t *testing.T) {
// given
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
Group: "projectcontour.io",
Kind: "HTTPProxy",
JQPathExpressions: []string{".spec.routes[]"},
//JSONPointers: []string{"/spec/routes"},
},
}
f := setupHttpProxy(t, ignores)
target := test.YamlToUnstructured(testdata.TargetHTTPProxy)
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
// when
patchedTargets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
require.Equal(t, 1, len(f.comparisonResult.reconciliationResult.Live))
require.Equal(t, 1, len(f.comparisonResult.reconciliationResult.Target))
require.Equal(t, 1, len(patchedTargets))
// live should have 1 entry
require.Len(t, dig(f.comparisonResult.reconciliationResult.Live[0].Object, []interface{}{"spec", "routes", 0, "rateLimitPolicy", "global", "descriptors"}), 1)
// assert some arbitrary field to show `entries[0]` is not an empty object
require.Equal(t, "sample-header", dig(f.comparisonResult.reconciliationResult.Live[0].Object, []interface{}{"spec", "routes", 0, "rateLimitPolicy", "global", "descriptors", 0, "entries", 0, "requestHeader", "headerName"}))
// target has 2 entries
require.Len(t, dig(f.comparisonResult.reconciliationResult.Target[0].Object, []interface{}{"spec", "routes", 0, "rateLimitPolicy", "global", "descriptors", 0, "entries"}), 2)
// assert some arbitrary field to show `entries[0]` is not an empty object
require.Equal(t, "sample-header", dig(f.comparisonResult.reconciliationResult.Target[0].Object, []interface{}{"spec", "routes", 0, "rateLimitPolicy", "global", "descriptors", 0, "entries", 0, "requestHeaderValueMatch", "headers", 0, "name"}))
// It should be *1* entries in the array
require.Len(t, dig(patchedTargets[0].Object, []interface{}{"spec", "routes", 0, "rateLimitPolicy", "global", "descriptors"}), 1)
// and it should NOT equal an empty object
require.Len(t, dig(patchedTargets[0].Object, []interface{}{"spec", "routes", 0, "rateLimitPolicy", "global", "descriptors", 0, "entries", 0}), 1)
})
t.Run("will correctly set array entries if new entries have been added", func(t *testing.T) {
// given
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
Group: "apps",
Kind: "Deployment",
JQPathExpressions: []string{".spec.template.spec.containers[].env[] | select(.name == \"SOME_ENV_VAR\")"},
},
}
f := setupHttpProxy(t, ignores)
live := test.YamlToUnstructured(testdata.LiveDeploymentEnvVarsYaml)
target := test.YamlToUnstructured(testdata.TargetDeploymentEnvVarsYaml)
f.comparisonResult.reconciliationResult.Live = []*unstructured.Unstructured{live}
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
// when
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
require.Equal(t, 1, len(targets))
containers, ok, err := unstructured.NestedSlice(targets[0].Object, "spec", "template", "spec", "containers")
require.NoError(t, err)
require.True(t, ok)
assert.Equal(t, 1, len(containers))
ports := containers[0].(map[string]interface{})["ports"].([]interface{})
assert.Equal(t, 1, len(ports))
env := containers[0].(map[string]interface{})["env"].([]interface{})
assert.Equal(t, 3, len(env))
first := env[0]
second := env[1]
third := env[2]
// Currently the defined order at this time is the insertion order of the target manifest.
assert.Equal(t, "SOME_ENV_VAR", first.(map[string]interface{})["name"])
assert.Equal(t, "some_value", first.(map[string]interface{})["value"])
assert.Equal(t, "SOME_OTHER_ENV_VAR", second.(map[string]interface{})["name"])
assert.Equal(t, "some_other_value", second.(map[string]interface{})["value"])
assert.Equal(t, "YET_ANOTHER_ENV_VAR", third.(map[string]interface{})["name"])
assert.Equal(t, "yet_another_value", third.(map[string]interface{})["value"])
})
t.Run("ignore-deployment-image-replicas-changes-additive", func(t *testing.T) {
// given
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
Group: "apps",
Kind: "Deployment",
JSONPointers: []string{"/spec/replicas"},
}, {
Group: "apps",
Kind: "Deployment",
JQPathExpressions: []string{".spec.template.spec.containers[].image"},
},
}
f := setupHttpProxy(t, ignores)
live := test.YamlToUnstructured(testdata.MinimalImageReplicaDeploymentYaml)
target := test.YamlToUnstructured(testdata.AdditionalImageReplicaDeploymentYaml)
f.comparisonResult.reconciliationResult.Live = []*unstructured.Unstructured{live}
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
// when
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
require.Equal(t, 1, len(targets))
metadata, ok, err := unstructured.NestedMap(targets[0].Object, "metadata")
require.NoError(t, err)
require.True(t, ok)
labels, ok := metadata["labels"].(map[string]interface{})
require.True(t, ok)
assert.Equal(t, 2, len(labels))
assert.Equal(t, "web", labels["appProcess"])
spec, ok, err := unstructured.NestedMap(targets[0].Object, "spec")
require.NoError(t, err)
require.True(t, ok)
assert.Equal(t, int64(1), spec["replicas"])
template, ok := spec["template"].(map[string]interface{})
require.True(t, ok)
tMetadata, ok := template["metadata"].(map[string]interface{})
require.True(t, ok)
tLabels, ok := tMetadata["labels"].(map[string]interface{})
require.True(t, ok)
assert.Equal(t, 2, len(tLabels))
assert.Equal(t, "web", tLabels["appProcess"])
tSpec, ok := template["spec"].(map[string]interface{})
require.True(t, ok)
containers, ok, err := unstructured.NestedSlice(tSpec, "containers")
require.NoError(t, err)
require.True(t, ok)
assert.Equal(t, 1, len(containers))
first := containers[0].(map[string]interface{})
assert.Equal(t, "alpine:3", first["image"])
resources, ok := first["resources"].(map[string]interface{})
require.True(t, ok)
requests, ok := resources["requests"].(map[string]interface{})
require.True(t, ok)
assert.Equal(t, "400m", requests["cpu"])
env, ok, err := unstructured.NestedSlice(first, "env")
require.NoError(t, err)
require.True(t, ok)
assert.Equal(t, 1, len(env))
env0 := env[0].(map[string]interface{})
assert.Equal(t, "EV", env0["name"])
assert.Equal(t, "here", env0["value"])
})
}
func dig(obj interface{}, path []interface{}) interface{} {
i := obj
for _, segment := range path {
switch segment.(type) {
case int:
i = i.([]interface{})[segment.(int)]
case string:
i = i.(map[string]interface{})[segment.(string)]
default:
panic("invalid path for object")
}
}
return i
}

View File

@@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: client
appProcess: web
name: client
spec:
replicas: 2
selector:
matchLabels:
app: client
strategy: {}
template:
metadata:
labels:
app: client
appProcess: web
spec:
containers:
- image: alpine:2
name: alpine
resources:
requests:
cpu: 400m
env:
- name: EV
value: here

View File

@@ -11,4 +11,22 @@ var (
//go:embed target-deployment-new-entries.yaml
TargetDeploymentNewEntries string
//go:embed live-httpproxy.yaml
LiveHTTPProxy string
//go:embed target-httpproxy.yaml
TargetHTTPProxy string
//go:embed live-deployment-env-vars.yaml
LiveDeploymentEnvVarsYaml string
//go:embed target-deployment-env-vars.yaml
TargetDeploymentEnvVarsYaml string
//go:embed minimal-image-replicas-deployment.yaml
MinimalImageReplicaDeploymentYaml string
//go:embed additional-image-replicas-deployment.yaml
AdditionalImageReplicaDeploymentYaml string
)

View File

@@ -0,0 +1,177 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
argocd.argoproj.io/tracking-id: 'guestbook:apps/Deployment:default/kustomize-guestbook-ui'
deployment.kubernetes.io/revision: '9'
iksm-version: '2.0'
kubectl.kubernetes.io/last-applied-configuration: >
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"argocd.argoproj.io/tracking-id":"guestbook:apps/Deployment:default/kustomize-guestbook-ui","iksm-version":"2.0"},"name":"kustomize-guestbook-ui","namespace":"default"},"spec":{"replicas":4,"revisionHistoryLimit":3,"selector":{"matchLabels":{"app":"guestbook-ui"}},"template":{"metadata":{"labels":{"app":"guestbook-ui"}},"spec":{"containers":[{"env":[{"name":"SOME_ENV_VAR","value":"some_value"}],"image":"gcr.io/heptio-images/ks-guestbook-demo:0.1","name":"guestbook-ui","ports":[{"containerPort":80}],"resources":{"requests":{"cpu":"50m","memory":"100Mi"}}}]}}}}
creationTimestamp: '2022-01-05T15:45:21Z'
generation: 119
managedFields:
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
'f:metadata':
'f:annotations':
'f:iksm-version': {}
manager: janitor
operation: Apply
time: '2022-01-06T18:21:04Z'
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
'f:metadata':
'f:annotations':
.: {}
'f:argocd.argoproj.io/tracking-id': {}
'f:kubectl.kubernetes.io/last-applied-configuration': {}
'f:spec':
'f:progressDeadlineSeconds': {}
'f:replicas': {}
'f:revisionHistoryLimit': {}
'f:selector': {}
'f:strategy':
'f:rollingUpdate':
.: {}
'f:maxSurge': {}
'f:maxUnavailable': {}
'f:type': {}
'f:template':
'f:metadata':
'f:labels':
.: {}
'f:app': {}
'f:spec':
'f:containers':
'k:{"name":"guestbook-ui"}':
.: {}
'f:env':
.: {}
'k:{"name":"SOME_ENV_VAR"}':
.: {}
'f:name': {}
'f:value': {}
'f:image': {}
'f:imagePullPolicy': {}
'f:name': {}
'f:ports':
.: {}
'k:{"containerPort":80,"protocol":"TCP"}':
.: {}
'f:containerPort': {}
'f:protocol': {}
'f:resources':
.: {}
'f:requests':
.: {}
'f:cpu': {}
'f:memory': {}
'f:terminationMessagePath': {}
'f:terminationMessagePolicy': {}
'f:dnsPolicy': {}
'f:restartPolicy': {}
'f:schedulerName': {}
'f:securityContext': {}
'f:terminationGracePeriodSeconds': {}
manager: argocd
operation: Update
time: '2022-01-06T15:04:15Z'
- apiVersion: apps/v1
fieldsType: FieldsV1
fieldsV1:
'f:metadata':
'f:annotations':
'f:deployment.kubernetes.io/revision': {}
'f:status':
'f:availableReplicas': {}
'f:conditions':
.: {}
'k:{"type":"Available"}':
.: {}
'f:lastTransitionTime': {}
'f:lastUpdateTime': {}
'f:message': {}
'f:reason': {}
'f:status': {}
'f:type': {}
'k:{"type":"Progressing"}':
.: {}
'f:lastTransitionTime': {}
'f:lastUpdateTime': {}
'f:message': {}
'f:reason': {}
'f:status': {}
'f:type': {}
'f:observedGeneration': {}
'f:readyReplicas': {}
'f:replicas': {}
'f:updatedReplicas': {}
manager: kube-controller-manager
operation: Update
time: '2022-01-06T18:15:14Z'
name: kustomize-guestbook-ui
namespace: default
resourceVersion: '8289211'
uid: ef253575-ce44-4c5e-84ad-16e81d0df6eb
spec:
progressDeadlineSeconds: 600
replicas: 4
revisionHistoryLimit: 3
selector:
matchLabels:
app: guestbook-ui
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: guestbook-ui
spec:
containers:
- env:
- name: SOME_ENV_VAR
value: some_value
image: 'gcr.io/heptio-images/ks-guestbook-demo:0.1'
imagePullPolicy: IfNotPresent
name: guestbook-ui
ports:
- containerPort: 80
protocol: TCP
resources:
requests:
cpu: 50m
memory: 100Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 4
conditions:
- lastTransitionTime: '2022-01-05T22:20:37Z'
lastUpdateTime: '2022-01-05T22:43:47Z'
message: >-
ReplicaSet "kustomize-guestbook-ui-6549d54677" has successfully
progressed.
reason: NewReplicaSetAvailable
status: 'True'
type: Progressing
- lastTransitionTime: '2022-01-06T18:15:14Z'
lastUpdateTime: '2022-01-06T18:15:14Z'
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: 'True'
type: Available
observedGeneration: 119
readyReplicas: 4
replicas: 4
updatedReplicas: 4

14
controller/testdata/live-httpproxy.yaml vendored Normal file
View File

@@ -0,0 +1,14 @@
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: my-http-proxy
namespace: default
spec:
routes:
- rateLimitPolicy:
global:
descriptors:
- entries:
- requestHeader:
descriptorKey: sample-key
headerName: sample-header

View File

@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: client
name: client
spec:
replicas: 1
selector:
matchLabels:
app: client
strategy: {}
template:
metadata:
labels:
app: client
spec:
containers:
- image: alpine:3
name: alpine
resources: {}

View File

@@ -0,0 +1,35 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
argocd.argoproj.io/tracking-id: 'guestbook:apps/Deployment:default/kustomize-guestbook-ui'
iksm-version: '1.0'
name: kustomize-guestbook-ui
namespace: default
spec:
replicas: 1
revisionHistoryLimit: 3
selector:
matchLabels:
app: guestbook-ui
template:
metadata:
labels:
app: guestbook-ui
spec:
containers:
- env:
- name: SOME_OTHER_ENV_VAR
value: some_other_value
- name: YET_ANOTHER_ENV_VAR
value: yet_another_value
- name: SOME_ENV_VAR
value: different_value!
image: 'gcr.io/heptio-images/ks-guestbook-demo:0.1'
name: guestbook-ui
ports:
- containerPort: 80
resources:
requests:
cpu: 50m
memory: 100Mi

View File

@@ -0,0 +1,23 @@
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: my-http-proxy
namespace: default
spec:
routes:
- rateLimitPolicy:
global:
descriptors:
- entries:
- requestHeaderValueMatch:
headers:
- contains: sample-key
name: sample-header
value: third
- requestHeader:
descriptorKey: sample-key
headerName: sample-header
- entries:
- requestHeader:
descriptorKey: sample-key
headerName: sample-header

View File

@@ -259,3 +259,45 @@ The most common instance of this error is with `env:` fields for `containers`.
!!! note "Dynamic applications"
It's possible that your application is being generated by a tool in which case the duplication might not be evident within the scope of a single file. If you have trouble debugging this problem, consider filing a ticket to the owner of the generator tool asking them to improve its validation and error reporting.
## How to rotate Redis secret?
* Delete `argocd-redis` secret in the namespace where Argo CD is installed.
```bash
kubectl delete secret argocd-redis -n <argocd namesapce>
```
* If you are running Redis in HA mode, restart Redis in HA.
```bash
kubectl rollout restart deployment argocd-redis-ha-haproxy
kubectl rollout restart statefulset argocd-redis-ha-server
```
* If you are running Redis in non-HA mode, restart Redis.
```bash
kubectl rollout restart deployment argocd-redis
```
* Restart other components.
```bash
kubectl rollout restart deployment argocd-server argocd-repo-server
kubectl rollout restart statefulset argocd-application-controller
```
## How to turn off Redis auth if users really want to?
Argo CD default installation is now configured automatically enable Redis authentication.
If for some reason authenticated Redis does not work for you and you want to use non-authenticated Redis, here are the steps:
* You need to have your own Redis installation.
* Configure Argo CD to use your own Redis instance. See this [doc](https://argo-cd.readthedocs.io/en/stable/operator-manual/argocd-cmd-params-cm-yaml/) for the Argo CD configuration.
* If you already installed Redis shipped with Argo CD, you also need to clean up the existing components:
* When HA Redis is used:
* kubectl delete deployment argocd-redis-ha-haproxy
* kubectl delete statefulset argocd-redis-ha-server
* When non-HA Redis is used:
* kubectl delete deployment argocd-redis
* Remove environment variable `REDIS_PASSWORD` from the following manifests
* Deployment: argocd-repo-server:
* Deployment: argocd-server
* StatefulSet: argocd-application-controller
## How do I provide my own Redis credentials?
The Redis password is stored in Kubernetes secret `argocd-redis` with key `auth` in the namespace where Argo CD is installed.
You can config your secret provider to generate Kubernetes secret accordingly.

View File

@@ -38,6 +38,9 @@ Do one of:
Use `argocd login --core` to [configure](./user-guide/commands/argocd_login.md) CLI access and skip steps 3-5.
!!! note
This default installation for Redis is using password authentication. The Redis password is stored in Kubernetes secret `argocd-redis` with key `auth` in the namespace where Argo CD is installed.
## 2. Download Argo CD CLI
Download the latest Argo CD version from [https://github.com/argoproj/argo-cd/releases/latest](https://github.com/argoproj/argo-cd/releases/latest). More detailed installation instructions can be found via the [CLI installation documentation](cli_installation.md).

View File

@@ -72,6 +72,9 @@ data:
server.rootpath: ""
# Directory path that contains additional static assets
server.staticassets: "/shared/app"
# Semicolon-separated list of content types allowed on non-GET requests. Set an empty string to allow all. Be aware
# that allowing content types besides application/json may make your API more vulnerable to CSRF attacks.
server.api.content.types: "application/json"
# Set the logging format. One of: text|json (default "text")
server.log.format: "text"

View File

@@ -13,57 +13,58 @@ argocd-application-controller [flags]
### Options
```
--app-hard-resync int Time period in seconds for application hard resync.
--app-resync int Time period in seconds for application resync. (default 180)
--app-state-cache-expiration duration Cache expiration for app state (default 1h0m0s)
--application-namespaces strings List of additional namespaces that applications are allowed to be reconciled from
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--default-cache-expiration duration Cache expiration default (default 24h0m0s)
--gloglevel int Set the glog logging level
-h, --help help for argocd-application-controller
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to a kube config. Only required if out-of-cluster
--kubectl-parallelism-limit int Number of allowed concurrent kubectl fork/execs. Any value less than 1 means no limit. (default 20)
--logformat string Set the logging format. One of: text|json (default "text")
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
--metrics-application-labels strings List of Application labels that will be added to the argocd_application_labels metric
--metrics-cache-expiration duration Prometheus metrics cache expiration (disabled by default. e.g. 24h0m0s)
--metrics-port int Start metrics server on given port (default 8082)
-n, --namespace string If present, the namespace scope for this CLI request
--operation-processors int Number of application operation processors (default 10)
--otlp-address string OpenTelemetry collector address to send traces to
--password string Password for basic authentication to the API server
--persist-resource-health Enables storing the managed resources health in the Application CRD (default true)
--proxy-url string If provided, this URL will be used to connect via proxy
--redis string Redis server hostname and port (e.g. argocd-redis:6379).
--redis-ca-certificate string Path to Redis server CA certificate (e.g. /etc/certs/redis/ca.crt). If not specified, system trusted CAs will be used for server certificate validation.
--redis-client-certificate string Path to Redis client certificate (e.g. /etc/certs/redis/client.crt).
--redis-client-key string Path to Redis client key (e.g. /etc/certs/redis/client.crt).
--redis-compress string Enable compression for data sent to Redis with the required compression algorithm. (possible values: gzip, none) (default "gzip")
--redis-insecure-skip-tls-verify Skip Redis server certificate validation.
--redis-use-tls Use TLS when connecting to Redis.
--redisdb int Redis database.
--repo-server string Repo server address. (default "argocd-repo-server:8081")
--repo-server-plaintext Disable TLS on connections to repo server
--repo-server-strict-tls Whether to use strict validation of the TLS cert presented by the repo server
--repo-server-timeout-seconds int Repo server RPC call timeout seconds. (default 60)
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--self-heal-timeout-seconds int Specifies timeout between application self heal attempts (default 5)
--sentinel stringArray Redis sentinel hostname and port (e.g. argocd-redis-ha-announce-0:6379).
--sentinelmaster string Redis sentinel master group name. (default "master")
--server string The address and port of the Kubernetes API server
--sharding-method string Enables choice of sharding method. Supported sharding methods are : [legacy, round-robin] (default "legacy")
--status-processors int Number of application status processors (default 20)
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
--app-hard-resync int Time period in seconds for application hard resync.
--app-resync int Time period in seconds for application resync. (default 180)
--app-state-cache-expiration duration Cache expiration for app state (default 1h0m0s)
--application-namespaces strings List of additional namespaces that applications are allowed to be reconciled from
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--default-cache-expiration duration Cache expiration default (default 24h0m0s)
--gloglevel int Set the glog logging level
-h, --help help for argocd-application-controller
--ignore-normalizer-jq-execution-timeout-seconds duration Set ignore normalizer JQ execution timeout
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to a kube config. Only required if out-of-cluster
--kubectl-parallelism-limit int Number of allowed concurrent kubectl fork/execs. Any value less than 1 means no limit. (default 20)
--logformat string Set the logging format. One of: text|json (default "text")
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
--metrics-application-labels strings List of Application labels that will be added to the argocd_application_labels metric
--metrics-cache-expiration duration Prometheus metrics cache expiration (disabled by default. e.g. 24h0m0s)
--metrics-port int Start metrics server on given port (default 8082)
-n, --namespace string If present, the namespace scope for this CLI request
--operation-processors int Number of application operation processors (default 10)
--otlp-address string OpenTelemetry collector address to send traces to
--password string Password for basic authentication to the API server
--persist-resource-health Enables storing the managed resources health in the Application CRD (default true)
--proxy-url string If provided, this URL will be used to connect via proxy
--redis string Redis server hostname and port (e.g. argocd-redis:6379).
--redis-ca-certificate string Path to Redis server CA certificate (e.g. /etc/certs/redis/ca.crt). If not specified, system trusted CAs will be used for server certificate validation.
--redis-client-certificate string Path to Redis client certificate (e.g. /etc/certs/redis/client.crt).
--redis-client-key string Path to Redis client key (e.g. /etc/certs/redis/client.crt).
--redis-compress string Enable compression for data sent to Redis with the required compression algorithm. (possible values: gzip, none) (default "gzip")
--redis-insecure-skip-tls-verify Skip Redis server certificate validation.
--redis-use-tls Use TLS when connecting to Redis.
--redisdb int Redis database.
--repo-server string Repo server address. (default "argocd-repo-server:8081")
--repo-server-plaintext Disable TLS on connections to repo server
--repo-server-strict-tls Whether to use strict validation of the TLS cert presented by the repo server
--repo-server-timeout-seconds int Repo server RPC call timeout seconds. (default 60)
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--self-heal-timeout-seconds int Specifies timeout between application self heal attempts (default 5)
--sentinel stringArray Redis sentinel hostname and port (e.g. argocd-redis-ha-announce-0:6379).
--sentinelmaster string Redis sentinel master group name. (default "master")
--server string The address and port of the Kubernetes API server
--sharding-method string Enables choice of sharding method. Supported sharding methods are : [legacy, round-robin] (default "legacy")
--status-processors int Number of application status processors (default 20)
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
```

View File

@@ -19,6 +19,7 @@ argocd-repo-server [flags]
--disable-helm-manifest-max-extracted-size Disable maximum size of helm manifest archives when extracted
--disable-tls Disable TLS on the gRPC endpoint
--helm-manifest-max-extracted-size string Maximum size of helm manifest archives when extracted (default "1G")
--helm-registry-max-index-size string Maximum size of registry index file (default "1G")
-h, --help help for argocd-repo-server
--logformat string Set the logging format. One of: text|json (default "text")
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")

View File

@@ -46,6 +46,7 @@ argocd admin [flags]
* [argocd admin initial-password](argocd_admin_initial-password.md) - Prints initial password to log in to Argo CD for the first time
* [argocd admin notifications](argocd_admin_notifications.md) - Set of CLI commands that helps manage notifications settings
* [argocd admin proj](argocd_admin_proj.md) - Manage projects configuration
* [argocd admin redis-initial-password](argocd_admin_redis-initial-password.md) - Ensure the Redis password exists, creating a new one if necessary.
* [argocd admin repo](argocd_admin_repo.md) - Manage repositories configuration
* [argocd admin settings](argocd_admin_settings.md) - Provides set of commands for settings validation and troubleshooting

View File

@@ -9,30 +9,31 @@ argocd admin app get-reconcile-results PATH [flags]
### Options
```
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
-h, --help help for get-reconcile-results
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to a kube config. Only required if out-of-cluster
--l string Label selector
-n, --namespace string If present, the namespace scope for this CLI request
--o string Output format (yaml|json) (default "yaml")
--password string Password for basic authentication to the API server
--proxy-url string If provided, this URL will be used to connect via proxy
--refresh If set to true then recalculates apps reconciliation
--repo-server string Repo server address.
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--server string The address and port of the Kubernetes API server
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
-h, --help help for get-reconcile-results
--ignore-normalizer-jq-execution-timeout duration Set ignore normalizer JQ execution timeout (default 1s)
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to a kube config. Only required if out-of-cluster
--l string Label selector
-n, --namespace string If present, the namespace scope for this CLI request
--o string Output format (yaml|json) (default "yaml")
--password string Password for basic authentication to the API server
--proxy-url string If provided, this URL will be used to connect via proxy
--refresh If set to true then recalculates apps reconciliation
--repo-server string Repo server address.
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--server string The address and port of the Kubernetes API server
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
```
### Options inherited from parent commands

View File

@@ -0,0 +1,67 @@
# `argocd admin redis-initial-password` Command Reference
## argocd admin redis-initial-password
Ensure the Redis password exists, creating a new one if necessary.
```
argocd admin redis-initial-password [flags]
```
### Options
```
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
-h, --help help for redis-initial-password
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to a kube config. Only required if out-of-cluster
-n, --namespace string If present, the namespace scope for this CLI request
--password string Password for basic authentication to the API server
--proxy-url string If provided, this URL will be used to connect via proxy
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--server string The address and port of the Kubernetes API server
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
```
### Options inherited from parent commands
```
--auth-token string Authentication token
--client-crt string Client certificate file
--client-crt-key string Client certificate key file
--config string Path to Argo CD config (default "/home/user/.config/argocd/config")
--controller-name string Name of the Argo CD Application controller; set this or the ARGOCD_APPLICATION_CONTROLLER_NAME environment variable when the controller's name label differs from the default, for example when installing via the Helm chart (default "argocd-application-controller")
--core If set to true then CLI talks directly to Kubernetes instead of talking to Argo CD API server
--grpc-web Enables gRPC-web protocol. Useful if Argo CD server is behind proxy which does not support HTTP2.
--grpc-web-root-path string Enables gRPC-web protocol. Useful if Argo CD server is behind proxy which does not support HTTP2. Set web root.
-H, --header strings 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)
--http-retry-max int Maximum number of retries to establish http connection to Argo CD server
--insecure Skip server certificate and domain verification
--kube-context string Directs the command to the given kube-context
--logformat string Set the logging format. One of: text|json (default "text")
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
--plaintext Disable TLS
--port-forward Connect to a random argocd-server port using port forwarding
--port-forward-namespace string Namespace name which should be used for port forwarding
--redis-haproxy-name string Name of the Redis HA Proxy; set this or the ARGOCD_REDIS_HAPROXY_NAME environment variable when the HA Proxy's name label differs from the default, for example when installing via the Helm chart (default "argocd-redis-ha-haproxy")
--redis-name string Name of the Redis deployment; set this or the ARGOCD_REDIS_NAME environment variable when the Redis's name label differs from the default, for example when installing via the Helm chart (default "argocd-redis")
--repo-server-name string Name of the Argo CD Repo server; set this or the ARGOCD_REPO_SERVER_NAME environment variable when the server's name label differs from the default, for example when installing via the Helm chart (default "argocd-repo-server")
--server-crt string Server certificate file
--server-name string Name of the Argo CD API server; set this or the ARGOCD_SERVER_NAME environment variable when the server's name label differs from the default, for example when installing via the Helm chart (default "argocd-server")
```
### SEE ALSO
* [argocd admin](argocd_admin.md) - Contains a set of commands useful for Argo CD administrators and requires direct Kubernetes access

View File

@@ -20,7 +20,8 @@ argocd admin settings resource-overrides ignore-resource-updates ./deploy.yaml -
### Options
```
-h, --help help for ignore-resource-updates
-h, --help help for ignore-resource-updates
--ignore-normalizer-jq-execution-timeout duration Set ignore normalizer JQ execution timeout (default 1s)
```
### Options inherited from parent commands

View File

@@ -15,15 +15,16 @@ argocd app diff APPNAME [flags]
### Options
```
--exit-code Return non-zero exit code when there is a diff (default true)
--hard-refresh Refresh application data as well as target manifests cache
-h, --help help for diff
--local string Compare live app to a local manifests
--local-include stringArray Used with --server-side-generate, specify patterns of filenames to send. Matching is based on filename and not path. (default [*.yaml,*.yml,*.json])
--local-repo-root string Path to the repository root. Used together with --local allows setting the repository root (default "/")
--refresh Refresh application data when retrieving
--revision string Compare live app to a particular revision
--server-side-generate Used with --local, this will send your manifests to the server for diffing
--exit-code Return non-zero exit code when there is a diff (default true)
--hard-refresh Refresh application data as well as target manifests cache
-h, --help help for diff
--ignore-normalizer-jq-execution-timeout duration Set ignore normalizer JQ execution timeout (default 1s)
--local string Compare live app to a local manifests
--local-include stringArray Used with --server-side-generate, specify patterns of filenames to send. Matching is based on filename and not path. (default [*.yaml,*.yml,*.json])
--local-repo-root string Path to the repository root. Used together with --local allows setting the repository root (default "/")
--refresh Refresh application data when retrieving
--revision string Compare live app to a particular revision
--server-side-generate Used with --local, this will send your manifests to the server for diffing
```
### Options inherited from parent commands

View File

@@ -36,29 +36,30 @@ argocd app sync [APPNAME... | -l selector | --project project-name] [flags]
### Options
```
--assumeYes Assume yes as answer for all user queries or prompts
--async Do not wait for application to sync before continuing
--dry-run Preview apply without affecting cluster
--force Use a force apply
-h, --help help for sync
--info stringArray A list of key-value pairs during sync process. These infos will be persisted in app.
--label stringArray Sync only specific resources with a label. This option may be specified repeatedly.
--local string Path to a local directory. When this flag is present no git queries will be made
--local-repo-root string Path to the repository root. Used together with --local allows setting the repository root (default "/")
--preview-changes Preview difference against the target and live state before syncing app and wait for user confirmation
--project stringArray Sync apps that belong to the specified projects. This option may be specified repeatedly.
--prune Allow deleting unexpected resources
--replace Use a kubectl create/replace instead apply
--resource stringArray Sync only specific resources as GROUP:KIND:NAME or !GROUP:KIND:NAME. Fields may be blank and '*' can be used. This option may be specified repeatedly
--retry-backoff-duration duration Retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h) (default 5s)
--retry-backoff-factor int Factor multiplies the base duration after each failed retry (default 2)
--retry-backoff-max-duration duration Max retry backoff duration. Input needs to be a duration (e.g. 2m, 1h) (default 3m0s)
--retry-limit int Max number of allowed sync retries
--revision string Sync to a specific revision. Preserves parameter overrides
-l, --selector string Sync apps that match this label. Supports '=', '==', '!=', in, notin, exists & not exists. Matching apps must satisfy all of the specified label constraints.
--server-side Use server-side apply while syncing the application
--strategy string Sync strategy (one of: apply|hook)
--timeout uint Time out after this many seconds
--assumeYes Assume yes as answer for all user queries or prompts
--async Do not wait for application to sync before continuing
--dry-run Preview apply without affecting cluster
--force Use a force apply
-h, --help help for sync
--ignore-normalizer-jq-execution-timeout duration Set ignore normalizer JQ execution timeout (default 1s)
--info stringArray A list of key-value pairs during sync process. These infos will be persisted in app.
--label stringArray Sync only specific resources with a label. This option may be specified repeatedly.
--local string Path to a local directory. When this flag is present no git queries will be made
--local-repo-root string Path to the repository root. Used together with --local allows setting the repository root (default "/")
--preview-changes Preview difference against the target and live state before syncing app and wait for user confirmation
--project stringArray Sync apps that belong to the specified projects. This option may be specified repeatedly.
--prune Allow deleting unexpected resources
--replace Use a kubectl create/replace instead apply
--resource stringArray Sync only specific resources as GROUP:KIND:NAME or !GROUP:KIND:NAME. Fields may be blank and '*' can be used. This option may be specified repeatedly
--retry-backoff-duration duration Retry backoff base duration. Input needs to be a duration (e.g. 2m, 1h) (default 5s)
--retry-backoff-factor int Factor multiplies the base duration after each failed retry (default 2)
--retry-backoff-max-duration duration Max retry backoff duration. Input needs to be a duration (e.g. 2m, 1h) (default 3m0s)
--retry-limit int Max number of allowed sync retries
--revision string Sync to a specific revision. Preserves parameter overrides
-l, --selector string Sync apps that match this label. Supports '=', '==', '!=', in, notin, exists & not exists. Matching apps must satisfy all of the specified label constraints.
--server-side Use server-side apply while syncing the application
--strategy string Sync strategy (one of: apply|hook)
--timeout uint Time out after this many seconds
```
### Options inherited from parent commands

View File

@@ -182,3 +182,16 @@ data:
```
The list of supported Kubernetes types is available in [diffing_known_types.txt](https://raw.githubusercontent.com/argoproj/argo-cd/master/util/argo/normalizers/diffing_known_types.txt)
### JQ Path expression timeout
By default, the evaluation of a JQPathExpression is limited to one second. If you encounter a "JQ patch execution timed out" error message due to a complex JQPathExpression that requires more time to evaluate, you can extend the timeout period by configuring the `ignore.normalizer.jq.timeout` setting within the `argocd-cmd-params-cm` ConfigMap.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cmd-params-cm
data:
ignore.normalizer.jq.timeout: "5s"

7
go.mod
View File

@@ -217,7 +217,7 @@ require (
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/client_model v0.3.0
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
@@ -226,7 +226,7 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect
github.com/slack-go/slack v0.12.1 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
@@ -276,6 +276,9 @@ replace (
github.com/golang/protobuf => github.com/golang/protobuf v1.4.2
github.com/grpc-ecosystem/grpc-gateway => github.com/grpc-ecosystem/grpc-gateway v1.16.0
// Avoid CVE-2023-46402
github.com/whilp/git-urls => github.com/chainguard-dev/git-urls v1.0.2
// Avoid CVE-2022-3064
gopkg.in/yaml.v2 => gopkg.in/yaml.v2 v2.4.0

8
go.sum
View File

@@ -211,6 +211,8 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 h1:HD4PLRzjuCVW79mQ0/pdsalOLHJ+FaEoqJLxfltpb2U=
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/chainguard-dev/git-urls v1.0.2 h1:pSpT7ifrpc5X55n4aTTm7FFUE+ZQHKiqpiwNkJrVcKQ=
github.com/chainguard-dev/git-urls v1.0.2/go.mod h1:rbGgj10OS7UgZlbzdUQIQpT0k/D4+An04HJY7Ol+Y/o=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
@@ -1084,8 +1086,8 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c h1:fyKiXKO1/I/B6Y2U8T7WdQGWzwehOuGIrljPtt7YTTI=
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/slack-go/slack v0.12.1 h1:X97b9g2hnITDtNsNe5GkGx6O2/Sz/uC20ejRZN6QxOw=
@@ -1178,8 +1180,6 @@ github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/whilp/git-urls v1.0.0 h1:95f6UMWN5FKW71ECsXRUd3FVYiXdrE7aX4NZKcPmIjU=
github.com/whilp/git-urls v1.0.0/go.mod h1:J16SAmobsqc3Qcy98brfl5f5+e0clUvg1krgwk/qCfE=
github.com/xanzy/go-gitlab v0.86.0 h1:jR8V9cK9jXRQDb46KOB20NCF3ksY09luaG0IfXE6p7w=
github.com/xanzy/go-gitlab v0.86.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=

View File

@@ -1,6 +1,7 @@
package main
import (
"bytes"
"fmt"
"log"
"os"
@@ -61,6 +62,11 @@ func updateMkDocsNav(parent string, child string, subchild string, files []strin
if err != nil {
return err
}
// The marshaller drops custom tags, so re-add this one. Turns out this is much less invasive than trying to handle
// it at the YAML parser level.
newmkdocs = bytes.Replace(newmkdocs, []byte("site_url: READTHEDOCS_CANONICAL_URL"), []byte("site_url: !ENV READTHEDOCS_CANONICAL_URL"), 1)
return os.WriteFile("mkdocs.yml", newmkdocs, 0644)
}

View File

@@ -21,6 +21,11 @@ spec:
- args:
- /usr/local/bin/argocd-application-controller
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_CONTROLLER_REPLICAS
value: "1"
- name: ARGOCD_RECONCILIATION_TIMEOUT
@@ -155,6 +160,12 @@ spec:
name: argocd-cmd-params-cm
key: controller.kubectl.parallelism.limit
optional: true
- name: ARGOCD_IGNORE_NORMALIZER_JQ_TIMEOUT
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: controller.ignore.normalizer.jq.timeout
optional: true
image: quay.io/argoproj/argocd:latest
imagePullPolicy: Always
name: argocd-application-controller

View File

@@ -5,7 +5,7 @@ kind: Kustomization
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.8.8
newTag: v2.8.21
resources:
- ./application-controller
- ./dex

View File

@@ -15,6 +15,23 @@ spec:
labels:
app.kubernetes.io/name: argocd-redis
spec:
initContainers:
- command:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
securityContext:
runAsNonRoot: true
runAsUser: 999
@@ -23,13 +40,20 @@ spec:
serviceAccountName: argocd-redis
containers:
- name: redis
image: redis:7.0.11-alpine
image: redis:7.0.15-alpine
imagePullPolicy: Always
args:
- "--save"
- ""
- "--appendonly"
- "no"
- --requirepass $(REDIS_PASSWORD)
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
ports:
- containerPort: 6379
securityContext:

View File

@@ -8,7 +8,6 @@ spec:
app.kubernetes.io/name: argocd-redis
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
@@ -23,9 +22,3 @@ spec:
ports:
- protocol: TCP
port: 6379
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP

View File

@@ -0,0 +1,23 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis
app.kubernetes.io/part-of: argocd
name: argocd-redis
rules:
- apiGroups:
- ""
resources:
- secrets
resourceNames:
- argocd-redis
verbs:
- get
- apiGroups:
- ""
resources:
- secrets
verbs:
- create

View File

@@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis
app.kubernetes.io/part-of: argocd
name: argocd-redis
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: argocd-redis
subjects:
- kind: ServiceAccount
name: argocd-redis

View File

@@ -6,3 +6,5 @@ resources:
- argocd-redis-sa.yaml
- argocd-redis-service.yaml
- argocd-redis-network-policy.yaml
- argocd-redis-role.yaml
- argocd-redis-rolebinding.yaml

View File

@@ -24,6 +24,11 @@ spec:
args:
- /usr/local/bin/argocd-repo-server
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_RECONCILIATION_TIMEOUT
valueFrom:
configMapKeyRef:

View File

@@ -23,138 +23,143 @@ spec:
args:
- /usr/local/bin/argocd-server
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_SERVER_INSECURE
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.insecure
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.insecure
optional: true
- name: ARGOCD_SERVER_BASEHREF
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.basehref
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.basehref
optional: true
- name: ARGOCD_SERVER_ROOTPATH
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.rootpath
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.rootpath
optional: true
- name: ARGOCD_SERVER_LOGFORMAT
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.log.format
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.log.format
optional: true
- name: ARGOCD_SERVER_LOG_LEVEL
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.log.level
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.log.level
optional: true
- name: ARGOCD_SERVER_REPO_SERVER
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: repo.server
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: repo.server
optional: true
- name: ARGOCD_SERVER_DEX_SERVER
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.dex.server
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.dex.server
optional: true
- name: ARGOCD_SERVER_DISABLE_AUTH
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.disable.auth
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.disable.auth
optional: true
- name: ARGOCD_SERVER_ENABLE_GZIP
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.enable.gzip
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.enable.gzip
optional: true
- name: ARGOCD_SERVER_REPO_SERVER_TIMEOUT_SECONDS
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.repo.server.timeout.seconds
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.repo.server.timeout.seconds
optional: true
- name: ARGOCD_SERVER_X_FRAME_OPTIONS
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.x.frame.options
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.x.frame.options
optional: true
- name: ARGOCD_SERVER_CONTENT_SECURITY_POLICY
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.content.security.policy
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.content.security.policy
optional: true
- name: ARGOCD_SERVER_REPO_SERVER_PLAINTEXT
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.repo.server.plaintext
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.repo.server.plaintext
optional: true
- name: ARGOCD_SERVER_REPO_SERVER_STRICT_TLS
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.repo.server.strict.tls
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.repo.server.strict.tls
optional: true
- name: ARGOCD_SERVER_DEX_SERVER_PLAINTEXT
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.dex.server.plaintext
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.dex.server.plaintext
optional: true
- name: ARGOCD_SERVER_DEX_SERVER_STRICT_TLS
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.dex.server.strict.tls
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.dex.server.strict.tls
optional: true
- name: ARGOCD_TLS_MIN_VERSION
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.tls.minversion
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.tls.minversion
optional: true
- name: ARGOCD_TLS_MAX_VERSION
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.tls.maxversion
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.tls.maxversion
optional: true
- name: ARGOCD_TLS_CIPHERS
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.tls.ciphers
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.tls.ciphers
optional: true
- name: ARGOCD_SERVER_CONNECTION_STATUS_CACHE_EXPIRATION
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.connection.status.cache.expiration
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.connection.status.cache.expiration
optional: true
- name: ARGOCD_SERVER_OIDC_CACHE_EXPIRATION
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.oidc.cache.expiration
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.oidc.cache.expiration
optional: true
- name: ARGOCD_SERVER_LOGIN_ATTEMPTS_EXPIRATION
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.login.attempts.expiration
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.login.attempts.expiration
optional: true
- name: ARGOCD_SERVER_STATIC_ASSETS
valueFrom:
configMapKeyRef:
@@ -163,16 +168,16 @@ spec:
optional: true
- name: ARGOCD_APP_STATE_CACHE_EXPIRATION
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.app.state.cache.expiration
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.app.state.cache.expiration
optional: true
- name: REDIS_SERVER
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: redis.server
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: redis.server
optional: true
- name: REDIS_COMPRESSION
valueFrom:
configMapKeyRef:
@@ -181,52 +186,58 @@ spec:
optional: true
- name: REDISDB
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: redis.db
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: redis.db
optional: true
- name: ARGOCD_DEFAULT_CACHE_EXPIRATION
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.default.cache.expiration
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.default.cache.expiration
optional: true
- name: ARGOCD_MAX_COOKIE_NUMBER
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.http.cookie.maxnumber
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.http.cookie.maxnumber
optional: true
- name: ARGOCD_SERVER_LISTEN_ADDRESS
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.listen.address
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.listen.address
optional: true
- name: ARGOCD_SERVER_METRICS_LISTEN_ADDRESS
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.metrics.listen.address
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.metrics.listen.address
optional: true
- name: ARGOCD_SERVER_OTLP_ADDRESS
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: otlp.address
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: otlp.address
optional: true
- name: ARGOCD_APPLICATION_NAMESPACES
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: application.namespaces
optional: true
configMapKeyRef:
name: argocd-cmd-params-cm
key: application.namespaces
optional: true
- name: ARGOCD_SERVER_ENABLE_PROXY_EXTENSION
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.enable.proxy.extension
optional: true
- name: ARGOCD_API_CONTENT_TYPES
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: server.api.content.types
optional: true
volumeMounts:
- name: ssh-known-hosts
mountPath: /app/config/ssh

View File

@@ -6585,8 +6585,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
properties:
@@ -8657,8 +8655,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
x-kubernetes-preserve-unknown-fields: true
@@ -13136,8 +13132,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
x-kubernetes-preserve-unknown-fields: true
@@ -18530,6 +18524,30 @@ rules:
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis
app.kubernetes.io/part-of: argocd
name: argocd-redis
rules:
- apiGroups:
- ""
resourceNames:
- argocd-redis
resources:
- secrets
verbs:
- get
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
@@ -18582,6 +18600,22 @@ subjects:
name: argocd-applicationset-controller
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis
app.kubernetes.io/part-of: argocd
name: argocd-redis
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: argocd-redis
subjects:
- kind: ServiceAccount
name: argocd-redis
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
@@ -18880,7 +18914,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -18975,7 +19009,14 @@ spec:
- ""
- --appendonly
- "no"
image: redis:7.0.11-alpine
- --requirepass $(REDIS_PASSWORD)
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: redis:7.0.15-alpine
imagePullPolicy: Always
name: redis
ports:
@@ -18986,6 +19027,23 @@ spec:
drop:
- ALL
readOnlyRootFilesystem: true
initContainers:
- command:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
securityContext:
runAsNonRoot: true
runAsUser: 999
@@ -19030,6 +19088,11 @@ spec:
- args:
- /usr/local/bin/argocd-repo-server
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_RECONCILIATION_TIMEOUT
valueFrom:
configMapKeyRef:
@@ -19180,7 +19243,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -19232,7 +19295,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -19317,6 +19380,11 @@ spec:
- args:
- /usr/local/bin/argocd-application-controller
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_CONTROLLER_REPLICAS
value: "1"
- name: ARGOCD_RECONCILIATION_TIMEOUT
@@ -19451,7 +19519,13 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
- name: ARGOCD_IGNORE_NORMALIZER_JQ_TIMEOUT
valueFrom:
configMapKeyRef:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-application-controller
ports:
@@ -19533,12 +19607,6 @@ kind: NetworkPolicy
metadata:
name: argocd-redis-network-policy
spec:
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
ingress:
- from:
- podSelector:
@@ -19558,7 +19626,6 @@ spec:
app.kubernetes.io/name: argocd-redis
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

View File

@@ -12,4 +12,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.8.8
newTag: v2.8.21

View File

@@ -2098,8 +2098,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
properties:
@@ -4170,8 +4168,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
x-kubernetes-preserve-unknown-fields: true
@@ -8649,8 +8645,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
x-kubernetes-preserve-unknown-fields: true

View File

@@ -12,7 +12,7 @@ patches:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.8.8
newTag: v2.8.21
resources:
- ../../base/application-controller
- ../../base/applicationset-controller

View File

@@ -8,7 +8,6 @@ spec:
app.kubernetes.io/name: argocd-redis-ha-haproxy
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
@@ -25,18 +24,4 @@ spec:
protocol: TCP
- port: 26379
protocol: TCP
egress:
- to:
- podSelector:
matchLabels:
app.kubernetes.io/name: argocd-redis-ha
ports:
- port: 6379
protocol: TCP
- port: 26379
protocol: TCP
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP

View File

@@ -1,6 +1,6 @@
dependencies:
- name: redis-ha
repository: https://dandydeveloper.github.io/charts
version: 4.22.3
digest: sha256:ae773caf65b172bdd2216072c03ba76ef3c0383dbd1e2478934a67b9455f6a2e
generated: "2022-11-02T16:57:25.047025473-07:00"
version: 4.26.6
digest: sha256:c363f48ea8339c4bdb7c8a2cca62aa487b69d0a52a6fe6267fbbbbc07e468abd
generated: "2024-04-10T11:02:32.957812-07:00"

View File

@@ -1,4 +1,4 @@
dependencies:
- name: redis-ha
version: 4.22.3
version: 4.26.6
repository: https://dandydeveloper.github.io/charts

View File

@@ -9,8 +9,10 @@ metadata:
labels:
heritage: Helm
release: argocd
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
app: argocd-redis-ha
secrets:
- name: argocd-redis
---
# Source: redis-ha/charts/redis-ha/templates/redis-haproxy-serviceaccount.yaml
apiVersion: v1
@@ -21,7 +23,7 @@ metadata:
labels:
heritage: Helm
release: argocd
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
app: argocd-redis-ha
---
# Source: redis-ha/charts/redis-ha/templates/redis-ha-configmap.yaml
@@ -33,7 +35,7 @@ metadata:
labels:
heritage: Helm
release: argocd
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
app: argocd-redis-ha
data:
redis.conf: |
@@ -50,6 +52,8 @@ data:
rdbcompression yes
repl-diskless-sync yes
save ""
requirepass replace-default-auth
masterauth replace-default-auth
sentinel.conf: |
dir "/data"
@@ -59,6 +63,7 @@ data:
sentinel failover-timeout argocd 180000
maxclients 10000
sentinel parallel-syncs argocd 5
sentinel auth-pass argocd replace-default-auth
init.sh: |
echo "$(date) Start..."
@@ -82,7 +87,7 @@ data:
sentinel_get_master() {
set +e
if [ "$SENTINEL_PORT" -eq 0 ]; then
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
grep -E '((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?s*$))'
else
redis-cli -h "${SERVICE}" -p "${SENTINEL_PORT}" sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
@@ -191,9 +196,9 @@ data:
redis_ping() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
redis-cli -h "${MASTER}" -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
else
redis-cli -h "${MASTER}" -p "${REDIS_PORT}" ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" ping
fi
set -e
}
@@ -226,7 +231,7 @@ data:
if [ "$SENTINEL_PORT" -eq 0 ]; then
echo " on sentinel (${SERVICE}:${SENTINEL_TLS_PORT}), sentinel grp (${MASTER_GROUP})"
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
echo " $(date) Failover returned with 'NOGOODSLAVE'"
echo "Setting defaults for this pod.."
setup_defaults
@@ -345,7 +350,7 @@ data:
sentinel_get_master() {
set +e
if [ "$SENTINEL_PORT" -eq 0 ]; then
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
grep -E '((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?s*$))'
else
redis-cli -h "${SERVICE}" -p "${SENTINEL_PORT}" sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
@@ -454,9 +459,9 @@ data:
redis_ping() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
redis-cli -h "${MASTER}" -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
else
redis-cli -h "${MASTER}" -p "${REDIS_PORT}" ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" ping
fi
set -e
}
@@ -489,7 +494,7 @@ data:
if [ "$SENTINEL_PORT" -eq 0 ]; then
echo " on sentinel (${SERVICE}:${SENTINEL_TLS_PORT}), sentinel grp (${MASTER_GROUP})"
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
echo " $(date) Failover returned with 'NOGOODSLAVE'"
echo "Setting defaults for this pod.."
setup_defaults
@@ -554,9 +559,9 @@ data:
redis_role() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
ROLE=$(redis-cli -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep role | sed 's/role://' | sed 's/\r//')
ROLE=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep role | sed 's/role://' | sed 's/\r//')
else
ROLE=$(redis-cli -p "${REDIS_PORT}" info | grep role | sed 's/role://' | sed 's/\r//')
ROLE=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" info | grep role | sed 's/role://' | sed 's/\r//')
fi
set -e
}
@@ -564,9 +569,9 @@ data:
identify_redis_master() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
REDIS_MASTER=$(redis-cli -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep master_host | sed 's/master_host://' | sed 's/\r//')
REDIS_MASTER=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep master_host | sed 's/master_host://' | sed 's/\r//')
else
REDIS_MASTER=$(redis-cli -p "${REDIS_PORT}" info | grep master_host | sed 's/master_host://' | sed 's/\r//')
REDIS_MASTER=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" info | grep master_host | sed 's/master_host://' | sed 's/\r//')
fi
set -e
}
@@ -576,9 +581,9 @@ data:
sh /readonly-config/init.sh
if [ "$REDIS_PORT" -eq 0 ]; then
echo "shutdown" | redis-cli -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key
echo "shutdown" | redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key
else
echo "shutdown" | redis-cli -p "${REDIS_PORT}"
echo "shutdown" | redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}"
fi
set -e
}
@@ -591,6 +596,7 @@ data:
identify_announce_ip
done
trap "exit 0" TERM
while true; do
sleep 60
@@ -674,6 +680,8 @@ data:
mode tcp
option tcp-check
tcp-check connect
tcp-check send "AUTH ${AUTH}"\r\n
tcp-check expect string +OK
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check send info\ replication\r\n
@@ -723,6 +731,7 @@ data:
get_redis_role() {
is_master=$(
redis-cli \
-a "${AUTH}" --no-auth-warning \
-h localhost \
-p 6379 \
info | grep -c 'role:master' || true
@@ -759,12 +768,13 @@ metadata:
labels:
heritage: Helm
release: argocd
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
app: argocd-redis-ha
data:
redis_liveness.sh: |
response=$(
redis-cli \
-a "${AUTH}" --no-auth-warning \
-h localhost \
-p 6379 \
ping
@@ -777,6 +787,7 @@ data:
redis_readiness.sh: |
response=$(
redis-cli \
-a "${AUTH}" --no-auth-warning \
-h localhost \
-p 6379 \
ping
@@ -809,7 +820,7 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
rules:
- apiGroups:
- ""
@@ -828,7 +839,7 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
component: argocd-redis-ha-haproxy
rules:
- apiGroups:
@@ -848,7 +859,7 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
subjects:
- kind: ServiceAccount
name: argocd-redis-ha
@@ -867,7 +878,7 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
component: argocd-redis-ha-haproxy
subjects:
- kind: ServiceAccount
@@ -887,9 +898,8 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
publishNotReadyAddresses: true
type: ClusterIP
@@ -917,9 +927,8 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
publishNotReadyAddresses: true
type: ClusterIP
@@ -947,9 +956,8 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
publishNotReadyAddresses: true
type: ClusterIP
@@ -977,7 +985,7 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
annotations:
spec:
type: ClusterIP
@@ -1005,7 +1013,7 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
component: argocd-redis-ha-haproxy
annotations:
spec:
@@ -1029,7 +1037,7 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
spec:
strategy:
type: RollingUpdate
@@ -1045,9 +1053,8 @@ spec:
labels:
app: redis-ha-haproxy
release: argocd
revision: "1"
annotations:
checksum/config: 718bbb277da8610063a7c0fd810984577c2e8ab215815a71211dfa6e20f67321
checksum/config: 2cb2cc491da078531f46cefd660dfcc1703f56dc3186217ec25d2f83d38a3736
spec:
# Needed when using unmodified rbac-setup.yml
@@ -1067,11 +1074,10 @@ spec:
matchLabels:
app: redis-ha-haproxy
release: argocd
revision: "1"
topologyKey: kubernetes.io/hostname
initContainers:
- name: config-init
image: haproxy:2.6.14-alpine
image: public.ecr.aws/docker/library/haproxy:2.6.14-alpine
imagePullPolicy: IfNotPresent
resources:
{}
@@ -1095,7 +1101,7 @@ spec:
mountPath: /data
containers:
- name: haproxy
image: haproxy:2.6.14-alpine
image: public.ecr.aws/docker/library/haproxy:2.6.14-alpine
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
@@ -1105,6 +1111,12 @@ spec:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
env:
- name: AUTH
valueFrom:
secretKeyRef:
name: argocd-redis
key: auth
livenessProbe:
httpGet:
path: /healthz
@@ -1151,7 +1163,7 @@ metadata:
app: redis-ha
heritage: "Helm"
release: "argocd"
chart: redis-ha-4.22.3
chart: redis-ha-4.26.6
annotations:
{}
spec:
@@ -1167,7 +1179,7 @@ spec:
template:
metadata:
annotations:
checksum/init-config: 69130412bda04eacad3530cb7bcf26cf121401e725e15d0959dd71a7380afe75
checksum/init-config: 9d3c019a5ea1fd98ab5cde397d8eecd351da884f15e6ba346c607cb2446c2198
labels:
release: argocd
app: redis-ha
@@ -1191,7 +1203,7 @@ spec:
automountServiceAccountToken: false
initContainers:
- name: config-init
image: redis:7.0.11-alpine
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
resources:
{}
@@ -1215,6 +1227,11 @@ spec:
value: 40000915ab58c3fa8fd888fb8b24711944e6cbb4
- name: SENTINEL_ID_2
value: 2bbec7894d954a8af3bb54d13eaec53cb024e2ca
- name: AUTH
valueFrom:
secretKeyRef:
name: argocd-redis
key: auth
volumeMounts:
- name: config
mountPath: /readonly-config
@@ -1225,12 +1242,12 @@ spec:
containers:
- name: redis
image: redis:7.0.11-alpine
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
command:
- redis-server
- redis-server
args:
- /data/conf/redis.conf
- /data/conf/redis.conf
securityContext:
allowPrivilegeEscalation: false
capabilities:
@@ -1240,6 +1257,12 @@ spec:
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
env:
- name: AUTH
valueFrom:
secretKeyRef:
name: argocd-redis
key: auth
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 15
@@ -1282,7 +1305,7 @@ spec:
- /bin/sh
- /readonly-config/trigger-failover-if-master.sh
- name: sentinel
image: redis:7.0.11-alpine
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
command:
- redis-sentinel
@@ -1297,6 +1320,12 @@ spec:
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
env:
- name: AUTH
valueFrom:
secretKeyRef:
name: argocd-redis
key: auth
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 15
@@ -1333,7 +1362,7 @@ spec:
{}
- name: split-brain-fix
image: redis:7.0.11-alpine
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
command:
- sh
@@ -1355,6 +1384,11 @@ spec:
value: 40000915ab58c3fa8fd888fb8b24711944e6cbb4
- name: SENTINEL_ID_2
value: 2bbec7894d954a8af3bb54d13eaec53cb024e2ca
- name: AUTH
valueFrom:
secretKeyRef:
name: argocd-redis
key: auth
resources:
{}
volumeMounts:

View File

@@ -1,4 +1,7 @@
redis-ha:
auth: true
authKey: auth
existingSecret: argocd-redis
persistentVolume:
enabled: false
redis:
@@ -18,7 +21,7 @@ redis-ha:
client: 6m
checkInterval: 3s
image:
tag: 7.0.11-alpine
tag: 7.0.15-alpine
containerSecurityContext: null
sentinel:
bind: "0.0.0.0"

View File

@@ -20,7 +20,7 @@ patches:
kind: ConfigMap
name: argocd-redis-ha-configmap
namespace: argocd
path: overlays/remove-namespace.yaml
path: overlays/remove-namespace.yaml
- target:
version: v1
group: ""
@@ -34,28 +34,28 @@ patches:
kind: ServiceAccount
name: argocd-redis-ha-haproxy
namespace: argocd
path: overlays/remove-namespace.yaml
path: overlays/remove-namespace.yaml
- target:
group: rbac.authorization.k8s.io
version: v1
kind: Role
name: argocd-redis-ha
namespace: argocd
path: overlays/remove-namespace.yaml
path: overlays/remove-namespace.yaml
- target:
group: rbac.authorization.k8s.io
version: v1
kind: Role
name: argocd-redis-ha-haproxy
namespace: argocd
path: overlays/remove-namespace.yaml
path: overlays/remove-namespace.yaml
- target:
group: rbac.authorization.k8s.io
version: v1
kind: RoleBinding
name: argocd-redis-ha
namespace: argocd
path: overlays/remove-namespace.yaml
path: overlays/remove-namespace.yaml
- target:
group: rbac.authorization.k8s.io
version: v1
@@ -294,3 +294,15 @@ patches:
kind: StatefulSet
name: argocd-redis-ha-server
path: overlays/statefulset-containers-securityContext.yaml
- target:
group: rbac.authorization.k8s.io
version: v1
kind: Role
name: argocd-redis-ha-haproxy
path: overlays/haproxy-role.yaml
- target:
group: apps
version: v1
kind: Deployment
name: argocd-redis-ha-haproxy
path: overlays/deployment-initContainers.yaml

View File

@@ -0,0 +1,16 @@
- op: add
path: /spec/template/spec/initContainers/0
value:
name: secret-init
command: [ 'argocd', 'admin', 'redis-initial-password' ]
image: quay.io/argoproj/argocd:latest
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault

View File

@@ -0,0 +1,20 @@
- op: add
path: /rules/0
value:
apiGroups:
- ""
resources:
- secrets
resourceNames:
- argocd-redis
verbs:
- get
- op: add
path: /rules/0
value:
apiGroups:
- ""
resources:
- secrets
verbs:
- create

View File

@@ -6585,8 +6585,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
properties:
@@ -8657,8 +8655,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
x-kubernetes-preserve-unknown-fields: true
@@ -13136,8 +13132,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
x-kubernetes-preserve-unknown-fields: true
@@ -18432,6 +18426,8 @@ metadata:
app.kubernetes.io/name: argocd-redis-ha
app.kubernetes.io/part-of: argocd
name: argocd-redis-ha
secrets:
- name: argocd-redis
---
apiVersion: v1
kind: ServiceAccount
@@ -18654,6 +18650,20 @@ metadata:
app.kubernetes.io/part-of: argocd
name: argocd-redis-ha-haproxy
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- apiGroups:
- ""
resourceNames:
- argocd-redis
resources:
- secrets
verbs:
- get
- apiGroups:
- ""
resources:
@@ -18991,7 +19001,7 @@ data:
sentinel_get_master() {
set +e
if [ "$SENTINEL_PORT" -eq 0 ]; then
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
grep -E '((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?s*$))'
else
redis-cli -h "${SERVICE}" -p "${SENTINEL_PORT}" sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
@@ -19100,9 +19110,9 @@ data:
redis_ping() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
redis-cli -h "${MASTER}" -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
else
redis-cli -h "${MASTER}" -p "${REDIS_PORT}" ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" ping
fi
set -e
}
@@ -19135,7 +19145,7 @@ data:
if [ "$SENTINEL_PORT" -eq 0 ]; then
echo " on sentinel (${SERVICE}:${SENTINEL_TLS_PORT}), sentinel grp (${MASTER_GROUP})"
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
echo " $(date) Failover returned with 'NOGOODSLAVE'"
echo "Setting defaults for this pod.."
setup_defaults
@@ -19200,9 +19210,9 @@ data:
redis_role() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
ROLE=$(redis-cli -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep role | sed 's/role://' | sed 's/\r//')
ROLE=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep role | sed 's/role://' | sed 's/\r//')
else
ROLE=$(redis-cli -p "${REDIS_PORT}" info | grep role | sed 's/role://' | sed 's/\r//')
ROLE=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" info | grep role | sed 's/role://' | sed 's/\r//')
fi
set -e
}
@@ -19210,9 +19220,9 @@ data:
identify_redis_master() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
REDIS_MASTER=$(redis-cli -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep master_host | sed 's/master_host://' | sed 's/\r//')
REDIS_MASTER=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep master_host | sed 's/master_host://' | sed 's/\r//')
else
REDIS_MASTER=$(redis-cli -p "${REDIS_PORT}" info | grep master_host | sed 's/master_host://' | sed 's/\r//')
REDIS_MASTER=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" info | grep master_host | sed 's/master_host://' | sed 's/\r//')
fi
set -e
}
@@ -19222,9 +19232,9 @@ data:
sh /readonly-config/init.sh
if [ "$REDIS_PORT" -eq 0 ]; then
echo "shutdown" | redis-cli -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key
echo "shutdown" | redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key
else
echo "shutdown" | redis-cli -p "${REDIS_PORT}"
echo "shutdown" | redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}"
fi
set -e
}
@@ -19237,6 +19247,7 @@ data:
identify_announce_ip
done
trap "exit 0" TERM
while true; do
sleep 60
@@ -19279,9 +19290,10 @@ data:
decide redis backend to use\n#master\nfrontend ft_redis_master\n bind :6379 \n
\ use_backend bk_redis_master\n# Check all redis servers to see if they think
they are master\nbackend bk_redis_master\n mode tcp\n option tcp-check\n tcp-check
connect\n tcp-check send PING\\r\\n\n tcp-check expect string +PONG\n tcp-check
send info\\ replication\\r\\n\n tcp-check expect string role:master\n tcp-check
send QUIT\\r\\n\n tcp-check expect string +OK\n use-server R0 if { srv_is_up(R0)
connect\n tcp-check send \"AUTH ${AUTH}\"\\r\\n\n tcp-check expect string +OK\n
\ tcp-check send PING\\r\\n\n tcp-check expect string +PONG\n tcp-check send
info\\ replication\\r\\n\n tcp-check expect string role:master\n tcp-check send
QUIT\\r\\n\n tcp-check expect string +OK\n use-server R0 if { srv_is_up(R0)
} { nbsrv(check_if_redis_is_master_0) ge 2 }\n server R0 argocd-redis-ha-announce-0:6379
check inter 3s fall 1 rise 1\n use-server R1 if { srv_is_up(R1) } { nbsrv(check_if_redis_is_master_1)
ge 2 }\n server R1 argocd-redis-ha-announce-1:6379 check inter 3s fall 1 rise
@@ -19342,7 +19354,7 @@ data:
sentinel_get_master() {
set +e
if [ "$SENTINEL_PORT" -eq 0 ]; then
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
grep -E '((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?s*$))'
else
redis-cli -h "${SERVICE}" -p "${SENTINEL_PORT}" sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
@@ -19451,9 +19463,9 @@ data:
redis_ping() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
redis-cli -h "${MASTER}" -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
else
redis-cli -h "${MASTER}" -p "${REDIS_PORT}" ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" ping
fi
set -e
}
@@ -19486,7 +19498,7 @@ data:
if [ "$SENTINEL_PORT" -eq 0 ]; then
echo " on sentinel (${SERVICE}:${SENTINEL_TLS_PORT}), sentinel grp (${MASTER_GROUP})"
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
echo " $(date) Failover returned with 'NOGOODSLAVE'"
echo "Setting defaults for this pod.."
setup_defaults
@@ -19594,6 +19606,8 @@ data:
rdbcompression yes
repl-diskless-sync yes
save ""
requirepass replace-default-auth
masterauth replace-default-auth
sentinel.conf: |
dir "/data"
port 26379
@@ -19602,10 +19616,12 @@ data:
sentinel failover-timeout argocd 180000
maxclients 10000
sentinel parallel-syncs argocd 5
sentinel auth-pass argocd replace-default-auth
trigger-failover-if-master.sh: |
get_redis_role() {
is_master=$(
redis-cli \
-a "${AUTH}" --no-auth-warning \
-h localhost \
-p 6379 \
info | grep -c 'role:master' || true
@@ -19645,6 +19661,7 @@ data:
redis_liveness.sh: |
response=$(
redis-cli \
-a "${AUTH}" --no-auth-warning \
-h localhost \
-p 6379 \
ping
@@ -19657,6 +19674,7 @@ data:
redis_readiness.sh: |
response=$(
redis-cli \
-a "${AUTH}" --no-auth-warning \
-h localhost \
-p 6379 \
ping
@@ -19844,8 +19862,6 @@ spec:
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis-ha
@@ -19870,8 +19886,6 @@ spec:
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis-ha
@@ -19896,8 +19910,6 @@ spec:
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis-ha
@@ -20129,7 +20141,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -20252,7 +20264,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -20328,7 +20340,7 @@ spec:
key: application.namespaces
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -20386,7 +20398,7 @@ spec:
template:
metadata:
annotations:
checksum/config: 718bbb277da8610063a7c0fd810984577c2e8ab215815a71211dfa6e20f67321
checksum/config: 2cb2cc491da078531f46cefd660dfcc1703f56dc3186217ec25d2f83d38a3736
labels:
app.kubernetes.io/name: argocd-redis-ha-haproxy
name: argocd-redis-ha-haproxy
@@ -20399,7 +20411,13 @@ spec:
app.kubernetes.io/name: argocd-redis-ha-haproxy
topologyKey: kubernetes.io/hostname
containers:
- image: haproxy:2.6.14-alpine
- env:
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/haproxy:2.6.14-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -20432,11 +20450,27 @@ spec:
- mountPath: /run/haproxy
name: shared-socket
initContainers:
- command:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
- args:
- /readonly/haproxy_init.sh
command:
- sh
image: haproxy:2.6.14-alpine
image: public.ecr.aws/docker/library/haproxy:2.6.14-alpine
imagePullPolicy: IfNotPresent
name: config-init
securityContext:
@@ -20504,6 +20538,11 @@ spec:
- args:
- /usr/local/bin/argocd-repo-server
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_RECONCILIATION_TIMEOUT
valueFrom:
configMapKeyRef:
@@ -20654,7 +20693,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -20706,7 +20745,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -20791,6 +20830,11 @@ spec:
env:
- name: ARGOCD_API_SERVER_REPLICAS
value: "2"
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_SERVER_INSECURE
valueFrom:
configMapKeyRef:
@@ -20995,7 +21039,13 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
- name: ARGOCD_API_CONTENT_TYPES
valueFrom:
configMapKeyRef:
key: server.api.content.types
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -21107,6 +21157,11 @@ spec:
- args:
- /usr/local/bin/argocd-application-controller
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_CONTROLLER_REPLICAS
value: "1"
- name: ARGOCD_RECONCILIATION_TIMEOUT
@@ -21241,7 +21296,13 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
- name: ARGOCD_IGNORE_NORMALIZER_JQ_TIMEOUT
valueFrom:
configMapKeyRef:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-application-controller
ports:
@@ -21301,7 +21362,7 @@ spec:
template:
metadata:
annotations:
checksum/init-config: 69130412bda04eacad3530cb7bcf26cf121401e725e15d0959dd71a7380afe75
checksum/init-config: 9d3c019a5ea1fd98ab5cde397d8eecd351da884f15e6ba346c607cb2446c2198
labels:
app.kubernetes.io/name: argocd-redis-ha
spec:
@@ -21318,7 +21379,13 @@ spec:
- /data/conf/redis.conf
command:
- redis-server
image: redis:7.0.11-alpine
env:
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
@@ -21372,7 +21439,13 @@ spec:
- /data/conf/sentinel.conf
command:
- redis-sentinel
image: redis:7.0.11-alpine
env:
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -21425,7 +21498,12 @@ spec:
value: 40000915ab58c3fa8fd888fb8b24711944e6cbb4
- name: SENTINEL_ID_2
value: 2bbec7894d954a8af3bb54d13eaec53cb024e2ca
image: redis:7.0.11-alpine
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
name: split-brain-fix
resources: {}
@@ -21455,7 +21533,12 @@ spec:
value: 40000915ab58c3fa8fd888fb8b24711944e6cbb4
- name: SENTINEL_ID_2
value: 2bbec7894d954a8af3bb54d13eaec53cb024e2ca
image: redis:7.0.11-alpine
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
name: config-init
securityContext:
@@ -21578,21 +21661,6 @@ kind: NetworkPolicy
metadata:
name: argocd-redis-ha-proxy-network-policy
spec:
egress:
- ports:
- port: 6379
protocol: TCP
- port: 26379
protocol: TCP
to:
- podSelector:
matchLabels:
app.kubernetes.io/name: argocd-redis-ha
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
ingress:
- from:
- podSelector:
@@ -21614,7 +21682,6 @@ spec:
app.kubernetes.io/name: argocd-redis-ha-haproxy
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

View File

@@ -43,6 +43,8 @@ metadata:
app.kubernetes.io/name: argocd-redis-ha
app.kubernetes.io/part-of: argocd
name: argocd-redis-ha
secrets:
- name: argocd-redis
---
apiVersion: v1
kind: ServiceAccount
@@ -265,6 +267,20 @@ metadata:
app.kubernetes.io/part-of: argocd
name: argocd-redis-ha-haproxy
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- apiGroups:
- ""
resourceNames:
- argocd-redis
resources:
- secrets
verbs:
- get
- apiGroups:
- ""
resources:
@@ -497,7 +513,7 @@ data:
sentinel_get_master() {
set +e
if [ "$SENTINEL_PORT" -eq 0 ]; then
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
grep -E '((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?s*$))'
else
redis-cli -h "${SERVICE}" -p "${SENTINEL_PORT}" sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
@@ -606,9 +622,9 @@ data:
redis_ping() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
redis-cli -h "${MASTER}" -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
else
redis-cli -h "${MASTER}" -p "${REDIS_PORT}" ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" ping
fi
set -e
}
@@ -641,7 +657,7 @@ data:
if [ "$SENTINEL_PORT" -eq 0 ]; then
echo " on sentinel (${SERVICE}:${SENTINEL_TLS_PORT}), sentinel grp (${MASTER_GROUP})"
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
echo " $(date) Failover returned with 'NOGOODSLAVE'"
echo "Setting defaults for this pod.."
setup_defaults
@@ -706,9 +722,9 @@ data:
redis_role() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
ROLE=$(redis-cli -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep role | sed 's/role://' | sed 's/\r//')
ROLE=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep role | sed 's/role://' | sed 's/\r//')
else
ROLE=$(redis-cli -p "${REDIS_PORT}" info | grep role | sed 's/role://' | sed 's/\r//')
ROLE=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" info | grep role | sed 's/role://' | sed 's/\r//')
fi
set -e
}
@@ -716,9 +732,9 @@ data:
identify_redis_master() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
REDIS_MASTER=$(redis-cli -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep master_host | sed 's/master_host://' | sed 's/\r//')
REDIS_MASTER=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key info | grep master_host | sed 's/master_host://' | sed 's/\r//')
else
REDIS_MASTER=$(redis-cli -p "${REDIS_PORT}" info | grep master_host | sed 's/master_host://' | sed 's/\r//')
REDIS_MASTER=$(redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" info | grep master_host | sed 's/master_host://' | sed 's/\r//')
fi
set -e
}
@@ -728,9 +744,9 @@ data:
sh /readonly-config/init.sh
if [ "$REDIS_PORT" -eq 0 ]; then
echo "shutdown" | redis-cli -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key
echo "shutdown" | redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key
else
echo "shutdown" | redis-cli -p "${REDIS_PORT}"
echo "shutdown" | redis-cli -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}"
fi
set -e
}
@@ -743,6 +759,7 @@ data:
identify_announce_ip
done
trap "exit 0" TERM
while true; do
sleep 60
@@ -785,9 +802,10 @@ data:
decide redis backend to use\n#master\nfrontend ft_redis_master\n bind :6379 \n
\ use_backend bk_redis_master\n# Check all redis servers to see if they think
they are master\nbackend bk_redis_master\n mode tcp\n option tcp-check\n tcp-check
connect\n tcp-check send PING\\r\\n\n tcp-check expect string +PONG\n tcp-check
send info\\ replication\\r\\n\n tcp-check expect string role:master\n tcp-check
send QUIT\\r\\n\n tcp-check expect string +OK\n use-server R0 if { srv_is_up(R0)
connect\n tcp-check send \"AUTH ${AUTH}\"\\r\\n\n tcp-check expect string +OK\n
\ tcp-check send PING\\r\\n\n tcp-check expect string +PONG\n tcp-check send
info\\ replication\\r\\n\n tcp-check expect string role:master\n tcp-check send
QUIT\\r\\n\n tcp-check expect string +OK\n use-server R0 if { srv_is_up(R0)
} { nbsrv(check_if_redis_is_master_0) ge 2 }\n server R0 argocd-redis-ha-announce-0:6379
check inter 3s fall 1 rise 1\n use-server R1 if { srv_is_up(R1) } { nbsrv(check_if_redis_is_master_1)
ge 2 }\n server R1 argocd-redis-ha-announce-1:6379 check inter 3s fall 1 rise
@@ -848,7 +866,7 @@ data:
sentinel_get_master() {
set +e
if [ "$SENTINEL_PORT" -eq 0 ]; then
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
grep -E '((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?s*$))'
else
redis-cli -h "${SERVICE}" -p "${SENTINEL_PORT}" sentinel get-master-addr-by-name "${MASTER_GROUP}" |\
@@ -957,9 +975,9 @@ data:
redis_ping() {
set +e
if [ "$REDIS_PORT" -eq 0 ]; then
redis-cli -h "${MASTER}" -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key ping
else
redis-cli -h "${MASTER}" -p "${REDIS_PORT}" ping
redis-cli -h "${MASTER}" -a "${AUTH}" --no-auth-warning -p "${REDIS_PORT}" ping
fi
set -e
}
@@ -992,7 +1010,7 @@ data:
if [ "$SENTINEL_PORT" -eq 0 ]; then
echo " on sentinel (${SERVICE}:${SENTINEL_TLS_PORT}), sentinel grp (${MASTER_GROUP})"
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
if redis-cli -h "${SERVICE}" -p "${SENTINEL_TLS_PORT}" --tls --cacert /tls-certs/ca.crt --cert /tls-certs/redis.crt --key /tls-certs/redis.key sentinel failover "${MASTER_GROUP}" | grep -q 'NOGOODSLAVE' ; then
echo " $(date) Failover returned with 'NOGOODSLAVE'"
echo "Setting defaults for this pod.."
setup_defaults
@@ -1100,6 +1118,8 @@ data:
rdbcompression yes
repl-diskless-sync yes
save ""
requirepass replace-default-auth
masterauth replace-default-auth
sentinel.conf: |
dir "/data"
port 26379
@@ -1108,10 +1128,12 @@ data:
sentinel failover-timeout argocd 180000
maxclients 10000
sentinel parallel-syncs argocd 5
sentinel auth-pass argocd replace-default-auth
trigger-failover-if-master.sh: |
get_redis_role() {
is_master=$(
redis-cli \
-a "${AUTH}" --no-auth-warning \
-h localhost \
-p 6379 \
info | grep -c 'role:master' || true
@@ -1151,6 +1173,7 @@ data:
redis_liveness.sh: |
response=$(
redis-cli \
-a "${AUTH}" --no-auth-warning \
-h localhost \
-p 6379 \
ping
@@ -1163,6 +1186,7 @@ data:
redis_readiness.sh: |
response=$(
redis-cli \
-a "${AUTH}" --no-auth-warning \
-h localhost \
-p 6379 \
ping
@@ -1350,8 +1374,6 @@ spec:
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis-ha
@@ -1376,8 +1398,6 @@ spec:
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis-ha
@@ -1402,8 +1422,6 @@ spec:
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis-ha
@@ -1635,7 +1653,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1758,7 +1776,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1834,7 +1852,7 @@ spec:
key: application.namespaces
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1892,7 +1910,7 @@ spec:
template:
metadata:
annotations:
checksum/config: 718bbb277da8610063a7c0fd810984577c2e8ab215815a71211dfa6e20f67321
checksum/config: 2cb2cc491da078531f46cefd660dfcc1703f56dc3186217ec25d2f83d38a3736
labels:
app.kubernetes.io/name: argocd-redis-ha-haproxy
name: argocd-redis-ha-haproxy
@@ -1905,7 +1923,13 @@ spec:
app.kubernetes.io/name: argocd-redis-ha-haproxy
topologyKey: kubernetes.io/hostname
containers:
- image: haproxy:2.6.14-alpine
- env:
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/haproxy:2.6.14-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -1938,11 +1962,27 @@ spec:
- mountPath: /run/haproxy
name: shared-socket
initContainers:
- command:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
- args:
- /readonly/haproxy_init.sh
command:
- sh
image: haproxy:2.6.14-alpine
image: public.ecr.aws/docker/library/haproxy:2.6.14-alpine
imagePullPolicy: IfNotPresent
name: config-init
securityContext:
@@ -2010,6 +2050,11 @@ spec:
- args:
- /usr/local/bin/argocd-repo-server
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_RECONCILIATION_TIMEOUT
valueFrom:
configMapKeyRef:
@@ -2160,7 +2205,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2212,7 +2257,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2297,6 +2342,11 @@ spec:
env:
- name: ARGOCD_API_SERVER_REPLICAS
value: "2"
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_SERVER_INSECURE
valueFrom:
configMapKeyRef:
@@ -2501,7 +2551,13 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
- name: ARGOCD_API_CONTENT_TYPES
valueFrom:
configMapKeyRef:
key: server.api.content.types
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2613,6 +2669,11 @@ spec:
- args:
- /usr/local/bin/argocd-application-controller
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_CONTROLLER_REPLICAS
value: "1"
- name: ARGOCD_RECONCILIATION_TIMEOUT
@@ -2747,7 +2808,13 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
- name: ARGOCD_IGNORE_NORMALIZER_JQ_TIMEOUT
valueFrom:
configMapKeyRef:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-application-controller
ports:
@@ -2807,7 +2874,7 @@ spec:
template:
metadata:
annotations:
checksum/init-config: 69130412bda04eacad3530cb7bcf26cf121401e725e15d0959dd71a7380afe75
checksum/init-config: 9d3c019a5ea1fd98ab5cde397d8eecd351da884f15e6ba346c607cb2446c2198
labels:
app.kubernetes.io/name: argocd-redis-ha
spec:
@@ -2824,7 +2891,13 @@ spec:
- /data/conf/redis.conf
command:
- redis-server
image: redis:7.0.11-alpine
env:
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
@@ -2878,7 +2951,13 @@ spec:
- /data/conf/sentinel.conf
command:
- redis-sentinel
image: redis:7.0.11-alpine
env:
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
lifecycle: {}
livenessProbe:
@@ -2931,7 +3010,12 @@ spec:
value: 40000915ab58c3fa8fd888fb8b24711944e6cbb4
- name: SENTINEL_ID_2
value: 2bbec7894d954a8af3bb54d13eaec53cb024e2ca
image: redis:7.0.11-alpine
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
name: split-brain-fix
resources: {}
@@ -2961,7 +3045,12 @@ spec:
value: 40000915ab58c3fa8fd888fb8b24711944e6cbb4
- name: SENTINEL_ID_2
value: 2bbec7894d954a8af3bb54d13eaec53cb024e2ca
image: redis:7.0.11-alpine
- name: AUTH
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
imagePullPolicy: IfNotPresent
name: config-init
securityContext:
@@ -3084,21 +3173,6 @@ kind: NetworkPolicy
metadata:
name: argocd-redis-ha-proxy-network-policy
spec:
egress:
- ports:
- port: 6379
protocol: TCP
- port: 26379
protocol: TCP
to:
- podSelector:
matchLabels:
app.kubernetes.io/name: argocd-redis-ha
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
ingress:
- from:
- podSelector:
@@ -3120,7 +3194,6 @@ spec:
app.kubernetes.io/name: argocd-redis-ha-haproxy
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

View File

@@ -6585,8 +6585,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
properties:
@@ -8657,8 +8655,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
x-kubernetes-preserve-unknown-fields: true
@@ -13136,8 +13132,6 @@ spec:
- metadata
- spec
type: object
required:
- elements
type: object
matrix:
x-kubernetes-preserve-unknown-fields: true
@@ -18622,6 +18616,30 @@ rules:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis
app.kubernetes.io/part-of: argocd
name: argocd-redis
rules:
- apiGroups:
- ""
resourceNames:
- argocd-redis
resources:
- secrets
verbs:
- get
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: server
@@ -18801,6 +18819,22 @@ subjects:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis
app.kubernetes.io/part-of: argocd
name: argocd-redis
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: argocd-redis
subjects:
- kind: ServiceAccount
name: argocd-redis
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: server
@@ -19230,7 +19264,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -19353,7 +19387,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -19429,7 +19463,7 @@ spec:
key: application.namespaces
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -19506,7 +19540,14 @@ spec:
- ""
- --appendonly
- "no"
image: redis:7.0.11-alpine
- --requirepass $(REDIS_PASSWORD)
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: redis:7.0.15-alpine
imagePullPolicy: Always
name: redis
ports:
@@ -19517,6 +19558,23 @@ spec:
drop:
- ALL
readOnlyRootFilesystem: true
initContainers:
- command:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
securityContext:
runAsNonRoot: true
runAsUser: 999
@@ -19561,6 +19619,11 @@ spec:
- args:
- /usr/local/bin/argocd-repo-server
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_RECONCILIATION_TIMEOUT
valueFrom:
configMapKeyRef:
@@ -19711,7 +19774,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -19763,7 +19826,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -19846,6 +19909,11 @@ spec:
- args:
- /usr/local/bin/argocd-server
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_SERVER_INSECURE
valueFrom:
configMapKeyRef:
@@ -20050,7 +20118,13 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
- name: ARGOCD_API_CONTENT_TYPES
valueFrom:
configMapKeyRef:
key: server.api.content.types
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -20162,6 +20236,11 @@ spec:
- args:
- /usr/local/bin/argocd-application-controller
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_CONTROLLER_REPLICAS
value: "1"
- name: ARGOCD_RECONCILIATION_TIMEOUT
@@ -20296,7 +20375,13 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
- name: ARGOCD_IGNORE_NORMALIZER_JQ_TIMEOUT
valueFrom:
configMapKeyRef:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-application-controller
ports:
@@ -20425,12 +20510,6 @@ kind: NetworkPolicy
metadata:
name: argocd-redis-network-policy
spec:
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
ingress:
- from:
- podSelector:
@@ -20450,7 +20529,6 @@ spec:
app.kubernetes.io/name: argocd-redis
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

View File

@@ -233,6 +233,30 @@ rules:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis
app.kubernetes.io/part-of: argocd
name: argocd-redis
rules:
- apiGroups:
- ""
resourceNames:
- argocd-redis
resources:
- secrets
verbs:
- get
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: server
@@ -341,6 +365,22 @@ subjects:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: redis
app.kubernetes.io/name: argocd-redis
app.kubernetes.io/part-of: argocd
name: argocd-redis
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: argocd-redis
subjects:
- kind: ServiceAccount
name: argocd-redis
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: server
@@ -736,7 +776,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -859,7 +899,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -935,7 +975,7 @@ spec:
key: application.namespaces
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1012,7 +1052,14 @@ spec:
- ""
- --appendonly
- "no"
image: redis:7.0.11-alpine
- --requirepass $(REDIS_PASSWORD)
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
image: redis:7.0.15-alpine
imagePullPolicy: Always
name: redis
ports:
@@ -1023,6 +1070,23 @@ spec:
drop:
- ALL
readOnlyRootFilesystem: true
initContainers:
- command:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
securityContext:
runAsNonRoot: true
runAsUser: 999
@@ -1067,6 +1131,11 @@ spec:
- args:
- /usr/local/bin/argocd-repo-server
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_RECONCILIATION_TIMEOUT
valueFrom:
configMapKeyRef:
@@ -1217,7 +1286,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1269,7 +1338,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.8.8
image: quay.io/argoproj/argocd:v2.8.21
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1352,6 +1421,11 @@ spec:
- args:
- /usr/local/bin/argocd-server
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_SERVER_INSECURE
valueFrom:
configMapKeyRef:
@@ -1556,7 +1630,13 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
- name: ARGOCD_API_CONTENT_TYPES
valueFrom:
configMapKeyRef:
key: server.api.content.types
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -1668,6 +1748,11 @@ spec:
- args:
- /usr/local/bin/argocd-application-controller
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: auth
name: argocd-redis
- name: ARGOCD_CONTROLLER_REPLICAS
value: "1"
- name: ARGOCD_RECONCILIATION_TIMEOUT
@@ -1802,7 +1887,13 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.8
- name: ARGOCD_IGNORE_NORMALIZER_JQ_TIMEOUT
valueFrom:
configMapKeyRef:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.21
imagePullPolicy: Always
name: argocd-application-controller
ports:
@@ -1931,12 +2022,6 @@ kind: NetworkPolicy
metadata:
name: argocd-redis-network-policy
spec:
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
ingress:
- from:
- podSelector:
@@ -1956,7 +2041,6 @@ spec:
app.kubernetes.io/name: argocd-redis
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy

View File

@@ -211,6 +211,7 @@ nav:
- Blog ⧉: https://blog.argoproj.io/
repo_url: https://github.com/argoproj/argo-cd
site_name: Argo CD - Declarative GitOps CD for Kubernetes
site_url: !ENV READTHEDOCS_CANONICAL_URL
strict: true
theme:
custom_dir: overrides

View File

@@ -95,6 +95,9 @@ API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/applicat
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ApplicationSourcePluginParameter,String_
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ClusterCacheInfo,APIsCount
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ConnectionState,ModifiedAt
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ErrApplicationNotAllowedToUseProject,application
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ErrApplicationNotAllowedToUseProject,namespace
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ErrApplicationNotAllowedToUseProject,project
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,HelmOptions,ValuesFileSchemes
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,JWTToken,ExpiresAt
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,JWTToken,IssuedAt

View File

@@ -17,6 +17,24 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
)
type ErrApplicationNotAllowedToUseProject struct {
application string
namespace string
project string
}
func NewErrApplicationNotAllowedToUseProject(application, namespace, project string) error {
return &ErrApplicationNotAllowedToUseProject{
application: application,
namespace: namespace,
project: project,
}
}
func (err *ErrApplicationNotAllowedToUseProject) Error() string {
return fmt.Sprintf("application '%s' in namespace '%s' is not allowed to use project %s", err.application, err.namespace, err.project)
}
// AppProjectList is list of AppProject resources
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type AppProjectList struct {

View File

@@ -224,6 +224,7 @@ func (g ApplicationSetTerminalGenerators) toApplicationSetNestedGenerators() []A
// ListGenerator include items info
type ListGenerator struct {
// +kubebuilder:validation:Optional
Elements []apiextensionsv1.JSON `json:"elements" protobuf:"bytes,1,name=elements"`
Template ApplicationSetTemplate `json:"template,omitempty" protobuf:"bytes,2,name=template"`
ElementsYaml string `json:"elementsYaml,omitempty" protobuf:"bytes,3,opt,name=elementsYaml"`

File diff suppressed because it is too large Load Diff

View File

@@ -873,6 +873,9 @@ message EnvEntry {
optional string value = 2;
}
message ErrApplicationNotAllowedToUseProject {
}
// ExecProviderConfig is config used to call an external command to perform cluster authentication
// See: https://godoc.org/k8s.io/client-go/tools/clientcmd/api#ExecConfig
message ExecProviderConfig {
@@ -1072,6 +1075,7 @@ message KustomizeReplica {
// ListGenerator include items info
message ListGenerator {
// +kubebuilder:validation:Optional
repeated k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1.JSON elements = 1;
optional ApplicationSetTemplate template = 2;

View File

@@ -14,154 +14,155 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AWSAuthConfig": schema_pkg_apis_application_v1alpha1_AWSAuthConfig(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AppProject": schema_pkg_apis_application_v1alpha1_AppProject(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AppProjectList": schema_pkg_apis_application_v1alpha1_AppProjectList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AppProjectSpec": schema_pkg_apis_application_v1alpha1_AppProjectSpec(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AppProjectStatus": schema_pkg_apis_application_v1alpha1_AppProjectStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Application": schema_pkg_apis_application_v1alpha1_Application(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationCondition": schema_pkg_apis_application_v1alpha1_ApplicationCondition(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationDestination": schema_pkg_apis_application_v1alpha1_ApplicationDestination(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationList": schema_pkg_apis_application_v1alpha1_ApplicationList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationMatchExpression": schema_pkg_apis_application_v1alpha1_ApplicationMatchExpression(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationPreservedFields": schema_pkg_apis_application_v1alpha1_ApplicationPreservedFields(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSet": schema_pkg_apis_application_v1alpha1_ApplicationSet(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetApplicationStatus": schema_pkg_apis_application_v1alpha1_ApplicationSetApplicationStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetCondition": schema_pkg_apis_application_v1alpha1_ApplicationSetCondition(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetGenerator": schema_pkg_apis_application_v1alpha1_ApplicationSetGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetList": schema_pkg_apis_application_v1alpha1_ApplicationSetList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetNestedGenerator": schema_pkg_apis_application_v1alpha1_ApplicationSetNestedGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetRolloutStep": schema_pkg_apis_application_v1alpha1_ApplicationSetRolloutStep(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetRolloutStrategy": schema_pkg_apis_application_v1alpha1_ApplicationSetRolloutStrategy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetSpec": schema_pkg_apis_application_v1alpha1_ApplicationSetSpec(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetStatus": schema_pkg_apis_application_v1alpha1_ApplicationSetStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetStrategy": schema_pkg_apis_application_v1alpha1_ApplicationSetStrategy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetSyncPolicy": schema_pkg_apis_application_v1alpha1_ApplicationSetSyncPolicy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetTemplate": schema_pkg_apis_application_v1alpha1_ApplicationSetTemplate(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetTemplateMeta": schema_pkg_apis_application_v1alpha1_ApplicationSetTemplateMeta(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetTerminalGenerator": schema_pkg_apis_application_v1alpha1_ApplicationSetTerminalGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSource": schema_pkg_apis_application_v1alpha1_ApplicationSource(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourceDirectory": schema_pkg_apis_application_v1alpha1_ApplicationSourceDirectory(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourceHelm": schema_pkg_apis_application_v1alpha1_ApplicationSourceHelm(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourceJsonnet": schema_pkg_apis_application_v1alpha1_ApplicationSourceJsonnet(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourceKustomize": schema_pkg_apis_application_v1alpha1_ApplicationSourceKustomize(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourcePlugin": schema_pkg_apis_application_v1alpha1_ApplicationSourcePlugin(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourcePluginParameter": schema_pkg_apis_application_v1alpha1_ApplicationSourcePluginParameter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSpec": schema_pkg_apis_application_v1alpha1_ApplicationSpec(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationStatus": schema_pkg_apis_application_v1alpha1_ApplicationStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSummary": schema_pkg_apis_application_v1alpha1_ApplicationSummary(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationTree": schema_pkg_apis_application_v1alpha1_ApplicationTree(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationWatchEvent": schema_pkg_apis_application_v1alpha1_ApplicationWatchEvent(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Backoff": schema_pkg_apis_application_v1alpha1_Backoff(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.BasicAuthBitbucketServer": schema_pkg_apis_application_v1alpha1_BasicAuthBitbucketServer(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.BearerTokenBitbucketCloud": schema_pkg_apis_application_v1alpha1_BearerTokenBitbucketCloud(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ChartDetails": schema_pkg_apis_application_v1alpha1_ChartDetails(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Cluster": schema_pkg_apis_application_v1alpha1_Cluster(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterCacheInfo": schema_pkg_apis_application_v1alpha1_ClusterCacheInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterConfig": schema_pkg_apis_application_v1alpha1_ClusterConfig(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterGenerator": schema_pkg_apis_application_v1alpha1_ClusterGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterInfo": schema_pkg_apis_application_v1alpha1_ClusterInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterList": schema_pkg_apis_application_v1alpha1_ClusterList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Command": schema_pkg_apis_application_v1alpha1_Command(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ComparedTo": schema_pkg_apis_application_v1alpha1_ComparedTo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ComponentParameter": schema_pkg_apis_application_v1alpha1_ComponentParameter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ConfigManagementPlugin": schema_pkg_apis_application_v1alpha1_ConfigManagementPlugin(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ConnectionState": schema_pkg_apis_application_v1alpha1_ConnectionState(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.DuckTypeGenerator": schema_pkg_apis_application_v1alpha1_DuckTypeGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.EnvEntry": schema_pkg_apis_application_v1alpha1_EnvEntry(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ExecProviderConfig": schema_pkg_apis_application_v1alpha1_ExecProviderConfig(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GitDirectoryGeneratorItem": schema_pkg_apis_application_v1alpha1_GitDirectoryGeneratorItem(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GitFileGeneratorItem": schema_pkg_apis_application_v1alpha1_GitFileGeneratorItem(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GitGenerator": schema_pkg_apis_application_v1alpha1_GitGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GnuPGPublicKey": schema_pkg_apis_application_v1alpha1_GnuPGPublicKey(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GnuPGPublicKeyList": schema_pkg_apis_application_v1alpha1_GnuPGPublicKeyList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HealthStatus": schema_pkg_apis_application_v1alpha1_HealthStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HelmFileParameter": schema_pkg_apis_application_v1alpha1_HelmFileParameter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HelmOptions": schema_pkg_apis_application_v1alpha1_HelmOptions(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HelmParameter": schema_pkg_apis_application_v1alpha1_HelmParameter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HostInfo": schema_pkg_apis_application_v1alpha1_HostInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HostResourceInfo": schema_pkg_apis_application_v1alpha1_HostResourceInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Info": schema_pkg_apis_application_v1alpha1_Info(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.InfoItem": schema_pkg_apis_application_v1alpha1_InfoItem(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.JWTToken": schema_pkg_apis_application_v1alpha1_JWTToken(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.JWTTokens": schema_pkg_apis_application_v1alpha1_JWTTokens(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.JsonnetVar": schema_pkg_apis_application_v1alpha1_JsonnetVar(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.KnownTypeField": schema_pkg_apis_application_v1alpha1_KnownTypeField(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.KustomizeOptions": schema_pkg_apis_application_v1alpha1_KustomizeOptions(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.KustomizeReplica": schema_pkg_apis_application_v1alpha1_KustomizeReplica(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ListGenerator": schema_pkg_apis_application_v1alpha1_ListGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ManagedNamespaceMetadata": schema_pkg_apis_application_v1alpha1_ManagedNamespaceMetadata(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.MatrixGenerator": schema_pkg_apis_application_v1alpha1_MatrixGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.MergeGenerator": schema_pkg_apis_application_v1alpha1_MergeGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.NestedMatrixGenerator": schema_pkg_apis_application_v1alpha1_NestedMatrixGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.NestedMergeGenerator": schema_pkg_apis_application_v1alpha1_NestedMergeGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Operation": schema_pkg_apis_application_v1alpha1_Operation(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OperationInitiator": schema_pkg_apis_application_v1alpha1_OperationInitiator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OperationState": schema_pkg_apis_application_v1alpha1_OperationState(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OptionalArray": schema_pkg_apis_application_v1alpha1_OptionalArray(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OptionalMap": schema_pkg_apis_application_v1alpha1_OptionalMap(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OrphanedResourceKey": schema_pkg_apis_application_v1alpha1_OrphanedResourceKey(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OrphanedResourcesMonitorSettings": schema_pkg_apis_application_v1alpha1_OrphanedResourcesMonitorSettings(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OverrideIgnoreDiff": schema_pkg_apis_application_v1alpha1_OverrideIgnoreDiff(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PluginConfigMapRef": schema_pkg_apis_application_v1alpha1_PluginConfigMapRef(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PluginGenerator": schema_pkg_apis_application_v1alpha1_PluginGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PluginInput": schema_pkg_apis_application_v1alpha1_PluginInput(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ProjectRole": schema_pkg_apis_application_v1alpha1_ProjectRole(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGenerator": schema_pkg_apis_application_v1alpha1_PullRequestGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorAzureDevOps": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorAzureDevOps(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorBitbucket": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorBitbucket(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorBitbucketServer": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorBitbucketServer(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorFilter": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorFilter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorGitLab": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorGitLab(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorGitea": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorGitea(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorGithub": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorGithub(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RefTarget": schema_pkg_apis_application_v1alpha1_RefTarget(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepoCreds": schema_pkg_apis_application_v1alpha1_RepoCreds(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepoCredsList": schema_pkg_apis_application_v1alpha1_RepoCredsList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Repository": schema_pkg_apis_application_v1alpha1_Repository(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepositoryCertificate": schema_pkg_apis_application_v1alpha1_RepositoryCertificate(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepositoryCertificateList": schema_pkg_apis_application_v1alpha1_RepositoryCertificateList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepositoryList": schema_pkg_apis_application_v1alpha1_RepositoryList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceAction": schema_pkg_apis_application_v1alpha1_ResourceAction(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceActionDefinition": schema_pkg_apis_application_v1alpha1_ResourceActionDefinition(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceActionParam": schema_pkg_apis_application_v1alpha1_ResourceActionParam(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceActions": schema_pkg_apis_application_v1alpha1_ResourceActions(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceDiff": schema_pkg_apis_application_v1alpha1_ResourceDiff(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceIgnoreDifferences": schema_pkg_apis_application_v1alpha1_ResourceIgnoreDifferences(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceNetworkingInfo": schema_pkg_apis_application_v1alpha1_ResourceNetworkingInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceNode": schema_pkg_apis_application_v1alpha1_ResourceNode(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceOverride": schema_pkg_apis_application_v1alpha1_ResourceOverride(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceRef": schema_pkg_apis_application_v1alpha1_ResourceRef(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceResult": schema_pkg_apis_application_v1alpha1_ResourceResult(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceStatus": schema_pkg_apis_application_v1alpha1_ResourceStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RetryStrategy": schema_pkg_apis_application_v1alpha1_RetryStrategy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RevisionHistory": schema_pkg_apis_application_v1alpha1_RevisionHistory(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RevisionMetadata": schema_pkg_apis_application_v1alpha1_RevisionMetadata(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGenerator": schema_pkg_apis_application_v1alpha1_SCMProviderGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorAWSCodeCommit": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorAWSCodeCommit(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorAzureDevOps": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorAzureDevOps(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorBitbucket": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorBitbucket(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorBitbucketServer": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorBitbucketServer(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorFilter": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorFilter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorGitea": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorGitea(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorGithub": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorGithub(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorGitlab": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorGitlab(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SecretRef": schema_pkg_apis_application_v1alpha1_SecretRef(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SignatureKey": schema_pkg_apis_application_v1alpha1_SignatureKey(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncOperation": schema_pkg_apis_application_v1alpha1_SyncOperation(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncOperationResource": schema_pkg_apis_application_v1alpha1_SyncOperationResource(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncOperationResult": schema_pkg_apis_application_v1alpha1_SyncOperationResult(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncPolicy": schema_pkg_apis_application_v1alpha1_SyncPolicy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncPolicyAutomated": schema_pkg_apis_application_v1alpha1_SyncPolicyAutomated(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncStatus": schema_pkg_apis_application_v1alpha1_SyncStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncStrategy": schema_pkg_apis_application_v1alpha1_SyncStrategy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncStrategyApply": schema_pkg_apis_application_v1alpha1_SyncStrategyApply(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncStrategyHook": schema_pkg_apis_application_v1alpha1_SyncStrategyHook(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncWindow": schema_pkg_apis_application_v1alpha1_SyncWindow(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.TLSClientConfig": schema_pkg_apis_application_v1alpha1_TLSClientConfig(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.TagFilter": schema_pkg_apis_application_v1alpha1_TagFilter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.objectMeta": schema_pkg_apis_application_v1alpha1_objectMeta(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.rawResourceOverride": schema_pkg_apis_application_v1alpha1_rawResourceOverride(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AWSAuthConfig": schema_pkg_apis_application_v1alpha1_AWSAuthConfig(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AppProject": schema_pkg_apis_application_v1alpha1_AppProject(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AppProjectList": schema_pkg_apis_application_v1alpha1_AppProjectList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AppProjectSpec": schema_pkg_apis_application_v1alpha1_AppProjectSpec(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.AppProjectStatus": schema_pkg_apis_application_v1alpha1_AppProjectStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Application": schema_pkg_apis_application_v1alpha1_Application(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationCondition": schema_pkg_apis_application_v1alpha1_ApplicationCondition(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationDestination": schema_pkg_apis_application_v1alpha1_ApplicationDestination(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationList": schema_pkg_apis_application_v1alpha1_ApplicationList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationMatchExpression": schema_pkg_apis_application_v1alpha1_ApplicationMatchExpression(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationPreservedFields": schema_pkg_apis_application_v1alpha1_ApplicationPreservedFields(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSet": schema_pkg_apis_application_v1alpha1_ApplicationSet(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetApplicationStatus": schema_pkg_apis_application_v1alpha1_ApplicationSetApplicationStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetCondition": schema_pkg_apis_application_v1alpha1_ApplicationSetCondition(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetGenerator": schema_pkg_apis_application_v1alpha1_ApplicationSetGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetList": schema_pkg_apis_application_v1alpha1_ApplicationSetList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetNestedGenerator": schema_pkg_apis_application_v1alpha1_ApplicationSetNestedGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetRolloutStep": schema_pkg_apis_application_v1alpha1_ApplicationSetRolloutStep(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetRolloutStrategy": schema_pkg_apis_application_v1alpha1_ApplicationSetRolloutStrategy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetSpec": schema_pkg_apis_application_v1alpha1_ApplicationSetSpec(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetStatus": schema_pkg_apis_application_v1alpha1_ApplicationSetStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetStrategy": schema_pkg_apis_application_v1alpha1_ApplicationSetStrategy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetSyncPolicy": schema_pkg_apis_application_v1alpha1_ApplicationSetSyncPolicy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetTemplate": schema_pkg_apis_application_v1alpha1_ApplicationSetTemplate(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetTemplateMeta": schema_pkg_apis_application_v1alpha1_ApplicationSetTemplateMeta(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSetTerminalGenerator": schema_pkg_apis_application_v1alpha1_ApplicationSetTerminalGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSource": schema_pkg_apis_application_v1alpha1_ApplicationSource(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourceDirectory": schema_pkg_apis_application_v1alpha1_ApplicationSourceDirectory(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourceHelm": schema_pkg_apis_application_v1alpha1_ApplicationSourceHelm(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourceJsonnet": schema_pkg_apis_application_v1alpha1_ApplicationSourceJsonnet(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourceKustomize": schema_pkg_apis_application_v1alpha1_ApplicationSourceKustomize(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourcePlugin": schema_pkg_apis_application_v1alpha1_ApplicationSourcePlugin(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSourcePluginParameter": schema_pkg_apis_application_v1alpha1_ApplicationSourcePluginParameter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSpec": schema_pkg_apis_application_v1alpha1_ApplicationSpec(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationStatus": schema_pkg_apis_application_v1alpha1_ApplicationStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSummary": schema_pkg_apis_application_v1alpha1_ApplicationSummary(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationTree": schema_pkg_apis_application_v1alpha1_ApplicationTree(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationWatchEvent": schema_pkg_apis_application_v1alpha1_ApplicationWatchEvent(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Backoff": schema_pkg_apis_application_v1alpha1_Backoff(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.BasicAuthBitbucketServer": schema_pkg_apis_application_v1alpha1_BasicAuthBitbucketServer(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.BearerTokenBitbucketCloud": schema_pkg_apis_application_v1alpha1_BearerTokenBitbucketCloud(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ChartDetails": schema_pkg_apis_application_v1alpha1_ChartDetails(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Cluster": schema_pkg_apis_application_v1alpha1_Cluster(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterCacheInfo": schema_pkg_apis_application_v1alpha1_ClusterCacheInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterConfig": schema_pkg_apis_application_v1alpha1_ClusterConfig(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterGenerator": schema_pkg_apis_application_v1alpha1_ClusterGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterInfo": schema_pkg_apis_application_v1alpha1_ClusterInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ClusterList": schema_pkg_apis_application_v1alpha1_ClusterList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Command": schema_pkg_apis_application_v1alpha1_Command(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ComparedTo": schema_pkg_apis_application_v1alpha1_ComparedTo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ComponentParameter": schema_pkg_apis_application_v1alpha1_ComponentParameter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ConfigManagementPlugin": schema_pkg_apis_application_v1alpha1_ConfigManagementPlugin(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ConnectionState": schema_pkg_apis_application_v1alpha1_ConnectionState(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.DuckTypeGenerator": schema_pkg_apis_application_v1alpha1_DuckTypeGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.EnvEntry": schema_pkg_apis_application_v1alpha1_EnvEntry(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ErrApplicationNotAllowedToUseProject": schema_pkg_apis_application_v1alpha1_ErrApplicationNotAllowedToUseProject(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ExecProviderConfig": schema_pkg_apis_application_v1alpha1_ExecProviderConfig(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GitDirectoryGeneratorItem": schema_pkg_apis_application_v1alpha1_GitDirectoryGeneratorItem(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GitFileGeneratorItem": schema_pkg_apis_application_v1alpha1_GitFileGeneratorItem(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GitGenerator": schema_pkg_apis_application_v1alpha1_GitGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GnuPGPublicKey": schema_pkg_apis_application_v1alpha1_GnuPGPublicKey(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GnuPGPublicKeyList": schema_pkg_apis_application_v1alpha1_GnuPGPublicKeyList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HealthStatus": schema_pkg_apis_application_v1alpha1_HealthStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HelmFileParameter": schema_pkg_apis_application_v1alpha1_HelmFileParameter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HelmOptions": schema_pkg_apis_application_v1alpha1_HelmOptions(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HelmParameter": schema_pkg_apis_application_v1alpha1_HelmParameter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HostInfo": schema_pkg_apis_application_v1alpha1_HostInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HostResourceInfo": schema_pkg_apis_application_v1alpha1_HostResourceInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Info": schema_pkg_apis_application_v1alpha1_Info(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.InfoItem": schema_pkg_apis_application_v1alpha1_InfoItem(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.JWTToken": schema_pkg_apis_application_v1alpha1_JWTToken(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.JWTTokens": schema_pkg_apis_application_v1alpha1_JWTTokens(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.JsonnetVar": schema_pkg_apis_application_v1alpha1_JsonnetVar(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.KnownTypeField": schema_pkg_apis_application_v1alpha1_KnownTypeField(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.KustomizeOptions": schema_pkg_apis_application_v1alpha1_KustomizeOptions(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.KustomizeReplica": schema_pkg_apis_application_v1alpha1_KustomizeReplica(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ListGenerator": schema_pkg_apis_application_v1alpha1_ListGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ManagedNamespaceMetadata": schema_pkg_apis_application_v1alpha1_ManagedNamespaceMetadata(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.MatrixGenerator": schema_pkg_apis_application_v1alpha1_MatrixGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.MergeGenerator": schema_pkg_apis_application_v1alpha1_MergeGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.NestedMatrixGenerator": schema_pkg_apis_application_v1alpha1_NestedMatrixGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.NestedMergeGenerator": schema_pkg_apis_application_v1alpha1_NestedMergeGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Operation": schema_pkg_apis_application_v1alpha1_Operation(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OperationInitiator": schema_pkg_apis_application_v1alpha1_OperationInitiator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OperationState": schema_pkg_apis_application_v1alpha1_OperationState(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OptionalArray": schema_pkg_apis_application_v1alpha1_OptionalArray(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OptionalMap": schema_pkg_apis_application_v1alpha1_OptionalMap(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OrphanedResourceKey": schema_pkg_apis_application_v1alpha1_OrphanedResourceKey(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OrphanedResourcesMonitorSettings": schema_pkg_apis_application_v1alpha1_OrphanedResourcesMonitorSettings(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.OverrideIgnoreDiff": schema_pkg_apis_application_v1alpha1_OverrideIgnoreDiff(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PluginConfigMapRef": schema_pkg_apis_application_v1alpha1_PluginConfigMapRef(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PluginGenerator": schema_pkg_apis_application_v1alpha1_PluginGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PluginInput": schema_pkg_apis_application_v1alpha1_PluginInput(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ProjectRole": schema_pkg_apis_application_v1alpha1_ProjectRole(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGenerator": schema_pkg_apis_application_v1alpha1_PullRequestGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorAzureDevOps": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorAzureDevOps(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorBitbucket": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorBitbucket(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorBitbucketServer": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorBitbucketServer(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorFilter": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorFilter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorGitLab": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorGitLab(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorGitea": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorGitea(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.PullRequestGeneratorGithub": schema_pkg_apis_application_v1alpha1_PullRequestGeneratorGithub(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RefTarget": schema_pkg_apis_application_v1alpha1_RefTarget(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepoCreds": schema_pkg_apis_application_v1alpha1_RepoCreds(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepoCredsList": schema_pkg_apis_application_v1alpha1_RepoCredsList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.Repository": schema_pkg_apis_application_v1alpha1_Repository(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepositoryCertificate": schema_pkg_apis_application_v1alpha1_RepositoryCertificate(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepositoryCertificateList": schema_pkg_apis_application_v1alpha1_RepositoryCertificateList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RepositoryList": schema_pkg_apis_application_v1alpha1_RepositoryList(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceAction": schema_pkg_apis_application_v1alpha1_ResourceAction(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceActionDefinition": schema_pkg_apis_application_v1alpha1_ResourceActionDefinition(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceActionParam": schema_pkg_apis_application_v1alpha1_ResourceActionParam(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceActions": schema_pkg_apis_application_v1alpha1_ResourceActions(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceDiff": schema_pkg_apis_application_v1alpha1_ResourceDiff(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceIgnoreDifferences": schema_pkg_apis_application_v1alpha1_ResourceIgnoreDifferences(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceNetworkingInfo": schema_pkg_apis_application_v1alpha1_ResourceNetworkingInfo(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceNode": schema_pkg_apis_application_v1alpha1_ResourceNode(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceOverride": schema_pkg_apis_application_v1alpha1_ResourceOverride(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceRef": schema_pkg_apis_application_v1alpha1_ResourceRef(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceResult": schema_pkg_apis_application_v1alpha1_ResourceResult(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceStatus": schema_pkg_apis_application_v1alpha1_ResourceStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RetryStrategy": schema_pkg_apis_application_v1alpha1_RetryStrategy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RevisionHistory": schema_pkg_apis_application_v1alpha1_RevisionHistory(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.RevisionMetadata": schema_pkg_apis_application_v1alpha1_RevisionMetadata(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGenerator": schema_pkg_apis_application_v1alpha1_SCMProviderGenerator(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorAWSCodeCommit": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorAWSCodeCommit(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorAzureDevOps": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorAzureDevOps(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorBitbucket": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorBitbucket(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorBitbucketServer": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorBitbucketServer(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorFilter": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorFilter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorGitea": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorGitea(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorGithub": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorGithub(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SCMProviderGeneratorGitlab": schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorGitlab(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SecretRef": schema_pkg_apis_application_v1alpha1_SecretRef(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SignatureKey": schema_pkg_apis_application_v1alpha1_SignatureKey(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncOperation": schema_pkg_apis_application_v1alpha1_SyncOperation(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncOperationResource": schema_pkg_apis_application_v1alpha1_SyncOperationResource(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncOperationResult": schema_pkg_apis_application_v1alpha1_SyncOperationResult(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncPolicy": schema_pkg_apis_application_v1alpha1_SyncPolicy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncPolicyAutomated": schema_pkg_apis_application_v1alpha1_SyncPolicyAutomated(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncStatus": schema_pkg_apis_application_v1alpha1_SyncStatus(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncStrategy": schema_pkg_apis_application_v1alpha1_SyncStrategy(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncStrategyApply": schema_pkg_apis_application_v1alpha1_SyncStrategyApply(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncStrategyHook": schema_pkg_apis_application_v1alpha1_SyncStrategyHook(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.SyncWindow": schema_pkg_apis_application_v1alpha1_SyncWindow(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.TLSClientConfig": schema_pkg_apis_application_v1alpha1_TLSClientConfig(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.TagFilter": schema_pkg_apis_application_v1alpha1_TagFilter(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.objectMeta": schema_pkg_apis_application_v1alpha1_objectMeta(ref),
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.rawResourceOverride": schema_pkg_apis_application_v1alpha1_rawResourceOverride(ref),
}
}
@@ -3090,6 +3091,40 @@ func schema_pkg_apis_application_v1alpha1_EnvEntry(ref common.ReferenceCallback)
}
}
func schema_pkg_apis_application_v1alpha1_ErrApplicationNotAllowedToUseProject(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"application": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"namespace": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"project": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"application", "namespace", "project"},
},
},
}
}
func schema_pkg_apis_application_v1alpha1_ExecProviderConfig(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{

View File

@@ -12,9 +12,9 @@ import (
"time"
"github.com/stretchr/testify/require"
"k8s.io/utils/pointer"
argocdcommon "github.com/argoproj/argo-cd/v2/common"
"k8s.io/utils/pointer"
"github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/stretchr/testify/assert"

View File

@@ -1785,6 +1785,22 @@ func (in *EnvEntry) DeepCopy() *EnvEntry {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ErrApplicationNotAllowedToUseProject) DeepCopyInto(out *ErrApplicationNotAllowedToUseProject) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ErrApplicationNotAllowedToUseProject.
func (in *ErrApplicationNotAllowedToUseProject) DeepCopy() *ErrApplicationNotAllowedToUseProject {
if in == nil {
return nil
}
out := new(ErrApplicationNotAllowedToUseProject)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExecProviderConfig) DeepCopyInto(out *ExecProviderConfig) {
*out = *in

View File

@@ -108,6 +108,7 @@ type RepoServerInitConstants struct {
StreamedManifestMaxExtractedSize int64
StreamedManifestMaxTarSize int64
HelmManifestMaxExtractedSize int64
HelmRegistryMaxIndexSize int64
DisableHelmManifestMaxExtractedSize bool
}
@@ -2307,7 +2308,7 @@ func (s *Service) newHelmClientResolveRevision(repo *v1alpha1.Repository, revisi
return helmClient, version.String(), nil
}
index, err := helmClient.GetIndex(noRevisionCache)
index, err := helmClient.GetIndex(noRevisionCache, s.initConstants.HelmRegistryMaxIndexSize)
if err != nil {
return nil, "", err
}
@@ -2385,7 +2386,7 @@ func checkoutRevision(gitClient git.Client, revision string, submoduleEnabled bo
}
func (s *Service) GetHelmCharts(ctx context.Context, q *apiclient.HelmChartsRequest) (*apiclient.HelmChartsResponse, error) {
index, err := s.newHelmClient(q.Repo.Repo, q.Repo.GetHelmCreds(), q.Repo.EnableOCI, q.Repo.Proxy, helm.WithChartPaths(s.chartPaths)).GetIndex(true)
index, err := s.newHelmClient(q.Repo.Repo, q.Repo.GetHelmCreds(), q.Repo.EnableOCI, q.Repo.Proxy, helm.WithChartPaths(s.chartPaths)).GetIndex(true, s.initConstants.HelmRegistryMaxIndexSize)
if err != nil {
return nil, err
}
@@ -2420,7 +2421,7 @@ func (s *Service) TestRepository(ctx context.Context, q *apiclient.TestRepositor
_, err := helm.NewClient(repo.Repo, repo.GetHelmCreds(), repo.EnableOCI, repo.Proxy).TestHelmOCI()
return err
} else {
_, err := helm.NewClient(repo.Repo, repo.GetHelmCreds(), repo.EnableOCI, repo.Proxy).GetIndex(false)
_, err := helm.NewClient(repo.Repo, repo.GetHelmCreds(), repo.EnableOCI, repo.Proxy).GetIndex(false, s.initConstants.HelmRegistryMaxIndexSize)
return err
}
},

View File

@@ -159,7 +159,7 @@ func TestGenerateYamlManifestInDir(t *testing.T) {
}
// update this value if we add/remove manifests
const countOfManifests = 48
const countOfManifests = 50
res1, err := service.GenerateManifest(context.Background(), &q)

View File

@@ -147,7 +147,7 @@ func NewServer(
//
// If the user does provide a "project," we can respond more specifically. If the user does not have access to the given
// app name in the given project, we return "permission denied." If the app exists, but the project is different from
func (s *Server) getAppEnforceRBAC(ctx context.Context, action, project, namespace, name string, getApp func() (*appv1.Application, error)) (*appv1.Application, error) {
func (s *Server) getAppEnforceRBAC(ctx context.Context, action, project, namespace, name string, getApp func() (*appv1.Application, error)) (*appv1.Application, *appv1.AppProject, error) {
logCtx := log.WithFields(map[string]interface{}{
"application": name,
"namespace": namespace,
@@ -164,7 +164,7 @@ func (s *Server) getAppEnforceRBAC(ctx context.Context, action, project, namespa
// but the app is in a different project" response. We don't want the user inferring the existence of the
// app from response time.
_, _ = getApp()
return nil, permissionDeniedErr
return nil, nil, permissionDeniedErr
}
}
a, err := getApp()
@@ -172,15 +172,15 @@ func (s *Server) getAppEnforceRBAC(ctx context.Context, action, project, namespa
if apierr.IsNotFound(err) {
if project != "" {
// We know that the user was allowed to get the Application, but the Application does not exist. Return 404.
return nil, status.Errorf(codes.NotFound, apierr.NewNotFound(schema.GroupResource{Group: "argoproj.io", Resource: "applications"}, name).Error())
return nil, nil, status.Errorf(codes.NotFound, apierr.NewNotFound(schema.GroupResource{Group: "argoproj.io", Resource: "applications"}, name).Error())
}
// We don't know if the user was allowed to get the Application, and we don't want to leak information about
// the Application's existence. Return 403.
logCtx.Warn("application does not exist")
return nil, permissionDeniedErr
return nil, nil, permissionDeniedErr
}
logCtx.Errorf("failed to get application: %s", err)
return nil, permissionDeniedErr
return nil, nil, permissionDeniedErr
}
// Even if we performed an initial RBAC check (because the request was fully parameterized), we still need to
// perform a second RBAC check to ensure that the user has access to the actual Application's project (not just the
@@ -194,11 +194,11 @@ func (s *Server) getAppEnforceRBAC(ctx context.Context, action, project, namespa
// The user specified a project. We would have returned a 404 if the user had access to the app, but the app
// did not exist. So we have to return a 404 when the app does exist, but the user does not have access.
// Otherwise, they could infer that the app exists based on the error code.
return nil, status.Errorf(codes.NotFound, apierr.NewNotFound(schema.GroupResource{Group: "argoproj.io", Resource: "applications"}, name).Error())
return nil, nil, status.Errorf(codes.NotFound, apierr.NewNotFound(schema.GroupResource{Group: "argoproj.io", Resource: "applications"}, name).Error())
}
// The user didn't specify a project. We always return permission denied for both lack of access and lack of
// existence.
return nil, permissionDeniedErr
return nil, nil, permissionDeniedErr
}
effectiveProject := "default"
if a.Spec.Project != "" {
@@ -211,15 +211,20 @@ func (s *Server) getAppEnforceRBAC(ctx context.Context, action, project, namespa
}).Warnf("user tried to %s application in project %s, but the application is in project %s", action, project, effectiveProject)
// The user has access to the app, but the app is in a different project. Return 404, meaning "app doesn't
// exist in that project".
return nil, status.Errorf(codes.NotFound, apierr.NewNotFound(schema.GroupResource{Group: "argoproj.io", Resource: "applications"}, name).Error())
return nil, nil, status.Errorf(codes.NotFound, apierr.NewNotFound(schema.GroupResource{Group: "argoproj.io", Resource: "applications"}, name).Error())
}
return a, nil
// Get the app's associated project, and make sure all project restrictions are enforced.
proj, err := s.getAppProject(ctx, a, logCtx)
if err != nil {
return a, nil, err
}
return a, proj, nil
}
// getApplicationEnforceRBACInformer uses an informer to get an Application. If the app does not exist, permission is
// denied, or any other error occurs when getting the app, we return a permission denied error to obscure any sensitive
// information.
func (s *Server) getApplicationEnforceRBACInformer(ctx context.Context, action, project, namespace, name string) (*appv1.Application, error) {
func (s *Server) getApplicationEnforceRBACInformer(ctx context.Context, action, project, namespace, name string) (*appv1.Application, *appv1.AppProject, error) {
namespaceOrDefault := s.appNamespaceOrDefault(namespace)
return s.getAppEnforceRBAC(ctx, action, project, namespaceOrDefault, name, func() (*appv1.Application, error) {
return s.appLister.Applications(namespaceOrDefault).Get(name)
@@ -229,9 +234,12 @@ func (s *Server) getApplicationEnforceRBACInformer(ctx context.Context, action,
// getApplicationEnforceRBACClient uses a client to get an Application. If the app does not exist, permission is denied,
// or any other error occurs when getting the app, we return a permission denied error to obscure any sensitive
// information.
func (s *Server) getApplicationEnforceRBACClient(ctx context.Context, action, project, namespace, name, resourceVersion string) (*appv1.Application, error) {
func (s *Server) getApplicationEnforceRBACClient(ctx context.Context, action, project, namespace, name, resourceVersion string) (*appv1.Application, *appv1.AppProject, error) {
namespaceOrDefault := s.appNamespaceOrDefault(namespace)
return s.getAppEnforceRBAC(ctx, action, project, namespaceOrDefault, name, func() (*appv1.Application, error) {
if !s.isNamespaceEnabled(namespaceOrDefault) {
return nil, security.NamespaceNotPermittedError(namespaceOrDefault)
}
return s.appclientset.ArgoprojV1alpha1().Applications(namespaceOrDefault).Get(ctx, name, metav1.GetOptions{
ResourceVersion: resourceVersion,
})
@@ -310,7 +318,13 @@ func (s *Server) Create(ctx context.Context, q *application.ApplicationCreateReq
if q.Validate != nil {
validate = *q.Validate
}
err := s.validateAndNormalizeApp(ctx, a, validate)
proj, err := s.getAppProject(ctx, a, log.WithField("application", a.Name))
if err != nil {
return nil, err
}
err = s.validateAndNormalizeApp(ctx, a, proj, validate)
if err != nil {
return nil, fmt.Errorf("error while validating and normalizing app: %w", err)
}
@@ -321,6 +335,15 @@ func (s *Server) Create(ctx context.Context, q *application.ApplicationCreateReq
return nil, security.NamespaceNotPermittedError(appNs)
}
// Don't let the app creator set the operation explicitly. Those requests should always go through the Sync API.
if a.Operation != nil {
log.WithFields(log.Fields{
"application": a.Name,
argocommon.SecurityField: argocommon.SecurityLow,
}).Warn("User attempted to set operation on application creation. This could have allowed them to bypass branch protection rules by setting manifests directly. Ignoring the set operation.")
a.Operation = nil
}
created, err := s.appclientset.ArgoprojV1alpha1().Applications(appNs).Create(ctx, a, metav1.CreateOptions{})
if err == nil {
s.logAppEvent(created, ctx, argo.EventReasonResourceCreated, "created application")
@@ -357,7 +380,7 @@ func (s *Server) Create(ctx context.Context, q *application.ApplicationCreateReq
return updated, nil
}
func (s *Server) queryRepoServer(ctx context.Context, a *appv1.Application, action func(
func (s *Server) queryRepoServer(ctx context.Context, a *appv1.Application, proj *appv1.AppProject, action func(
client apiclient.RepoServerServiceClient,
repo *appv1.Repository,
helmRepos []*appv1.Repository,
@@ -384,14 +407,6 @@ func (s *Server) queryRepoServer(ctx context.Context, a *appv1.Application, acti
if err != nil {
return fmt.Errorf("error getting kustomize settings options: %w", err)
}
proj, err := argo.GetAppProject(a, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx)
if err != nil {
if apierr.IsNotFound(err) {
return status.Errorf(codes.InvalidArgument, "application references project %s which does not exist", a.Spec.Project)
}
return fmt.Errorf("error getting application's project: %w", err)
}
helmRepos, err := s.db.ListHelmRepositories(ctx)
if err != nil {
return fmt.Errorf("error listing helm repositories: %w", err)
@@ -425,7 +440,7 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
if q.Name == nil || *q.Name == "" {
return nil, fmt.Errorf("invalid request: application name is missing")
}
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
a, proj, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, err
}
@@ -437,7 +452,7 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
}
var manifestInfo *apiclient.ManifestResponse
err = s.queryRepoServer(ctx, a, func(
err = s.queryRepoServer(ctx, a, proj, func(
client apiclient.RepoServerServiceClient, repo *appv1.Repository, helmRepos []*appv1.Repository, helmCreds []*appv1.RepoCreds, helmOptions *appv1.HelmOptions, kustomizeOptions *appv1.KustomizeOptions, enableGenerateManifests map[string]bool) error {
revision := source.TargetRevision
if q.GetRevision() != "" {
@@ -523,13 +538,13 @@ func (s *Server) GetManifestsWithFiles(stream application.ApplicationService_Get
return fmt.Errorf("invalid request: application name is missing")
}
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, query.GetProject(), query.GetAppNamespace(), query.GetName())
a, proj, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, query.GetProject(), query.GetAppNamespace(), query.GetName())
if err != nil {
return err
}
var manifestInfo *apiclient.ManifestResponse
err = s.queryRepoServer(ctx, a, func(
err = s.queryRepoServer(ctx, a, proj, func(
client apiclient.RepoServerServiceClient, repo *appv1.Repository, helmRepos []*appv1.Repository, helmCreds []*appv1.RepoCreds, helmOptions *appv1.HelmOptions, kustomizeOptions *appv1.KustomizeOptions, enableGenerateManifests map[string]bool) error {
appInstanceLabelKey, err := s.settingsMgr.GetAppInstanceLabelKey()
@@ -631,7 +646,7 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*app
// We must use a client Get instead of an informer Get, because it's common to call Get immediately
// following a Watch (which is not yet powered by an informer), and the Get must reflect what was
// previously seen by the client.
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, project, appNs, appName, q.GetResourceVersion())
a, proj, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, project, appNs, appName, q.GetResourceVersion())
if err != nil {
return nil, err
}
@@ -662,7 +677,7 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*app
if refreshType == appv1.RefreshTypeHard {
// force refresh cached application details
if err := s.queryRepoServer(ctx, a, func(
if err := s.queryRepoServer(ctx, a, proj, func(
client apiclient.RepoServerServiceClient,
repo *appv1.Repository,
helmRepos []*appv1.Repository,
@@ -714,7 +729,7 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*app
// ListResourceEvents returns a list of event resources
func (s *Server) ListResourceEvents(ctx context.Context, q *application.ApplicationResourceEventsQuery) (*v1.EventList, error) {
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
a, _, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, err
}
@@ -782,12 +797,12 @@ func (s *Server) validateAndUpdateApp(ctx context.Context, newApp *appv1.Applica
s.projectLock.RLock(newApp.Spec.GetProject())
defer s.projectLock.RUnlock(newApp.Spec.GetProject())
app, err := s.getApplicationEnforceRBACClient(ctx, action, currentProject, newApp.Namespace, newApp.Name, "")
app, proj, err := s.getApplicationEnforceRBACClient(ctx, action, currentProject, newApp.Namespace, newApp.Name, "")
if err != nil {
return nil, err
}
err = s.validateAndNormalizeApp(ctx, newApp, validate)
err = s.validateAndNormalizeApp(ctx, newApp, proj, validate)
if err != nil {
return nil, fmt.Errorf("error validating and normalizing app: %w", err)
}
@@ -899,7 +914,7 @@ func (s *Server) UpdateSpec(ctx context.Context, q *application.ApplicationUpdat
if q.GetSpec() == nil {
return nil, fmt.Errorf("error updating application spec: spec is nil in request")
}
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionUpdate, q.GetProject(), q.GetAppNamespace(), q.GetName(), "")
a, _, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionUpdate, q.GetProject(), q.GetAppNamespace(), q.GetName(), "")
if err != nil {
return nil, err
}
@@ -918,7 +933,7 @@ func (s *Server) UpdateSpec(ctx context.Context, q *application.ApplicationUpdat
// Patch patches an application
func (s *Server) Patch(ctx context.Context, q *application.ApplicationPatchRequest) (*appv1.Application, error) {
app, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName(), "")
app, _, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName(), "")
if err != nil {
return nil, err
}
@@ -961,11 +976,35 @@ func (s *Server) Patch(ctx context.Context, q *application.ApplicationPatchReque
return s.validateAndUpdateApp(ctx, newApp, false, true, rbacpolicy.ActionUpdate, q.GetProject())
}
func (s *Server) getAppProject(ctx context.Context, a *appv1.Application, logCtx *log.Entry) (*appv1.AppProject, error) {
proj, err := argo.GetAppProject(a, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx)
if err == nil {
return proj, nil
}
// If there's a permission issue or the app doesn't exist, return a vague error to avoid letting the user enumerate project names.
vagueError := status.Errorf(codes.InvalidArgument, "app is not allowed in project %q, or the project does not exist", a.Spec.Project)
if apierr.IsNotFound(err) {
return nil, vagueError
}
if _, ok := err.(*appv1.ErrApplicationNotAllowedToUseProject); ok {
logCtx.WithFields(map[string]interface{}{
"project": a.Spec.Project,
argocommon.SecurityField: argocommon.SecurityMedium,
}).Warnf("error getting app project: %s", err)
return nil, vagueError
}
return nil, vagueError
}
// Delete removes an application and all associated resources
func (s *Server) Delete(ctx context.Context, q *application.ApplicationDeleteRequest) (*application.ApplicationResponse, error) {
appName := q.GetName()
appNs := s.appNamespaceOrDefault(q.GetAppNamespace())
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, q.GetProject(), appNs, appName, "")
a, _, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, q.GetProject(), appNs, appName, "")
if err != nil {
return nil, err
}
@@ -1120,16 +1159,7 @@ func (s *Server) Watch(q *application.ApplicationQuery, ws application.Applicati
}
}
func (s *Server) validateAndNormalizeApp(ctx context.Context, app *appv1.Application, validate bool) error {
proj, err := argo.GetAppProject(app, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx)
if err != nil {
if apierr.IsNotFound(err) {
// Offer no hint that the project does not exist.
log.Warnf("User attempted to create/update application in non-existent project %q", app.Spec.Project)
return permissionDeniedErr
}
return fmt.Errorf("error getting application's project: %w", err)
}
func (s *Server) validateAndNormalizeApp(ctx context.Context, app *appv1.Application, proj *appv1.AppProject, validate bool) error {
if app.GetName() == "" {
return fmt.Errorf("resource name may not be empty")
}
@@ -1232,7 +1262,7 @@ func (s *Server) getAppResources(ctx context.Context, a *appv1.Application) (*ap
}
func (s *Server) getAppLiveResource(ctx context.Context, action string, q *application.ApplicationResourceRequest) (*appv1.ResourceNode, *rest.Config, *appv1.Application, error) {
a, err := s.getApplicationEnforceRBACInformer(ctx, action, q.GetProject(), q.GetAppNamespace(), q.GetName())
a, _, err := s.getApplicationEnforceRBACInformer(ctx, action, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, nil, nil, err
}
@@ -1369,7 +1399,7 @@ func (s *Server) DeleteResource(ctx context.Context, q *application.ApplicationR
}
func (s *Server) ResourceTree(ctx context.Context, q *application.ResourcesQuery) (*appv1.ApplicationTree, error) {
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetApplicationName())
a, _, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetApplicationName())
if err != nil {
return nil, err
}
@@ -1378,7 +1408,7 @@ func (s *Server) ResourceTree(ctx context.Context, q *application.ResourcesQuery
}
func (s *Server) WatchResourceTree(q *application.ResourcesQuery, ws application.ApplicationService_WatchResourceTreeServer) error {
_, err := s.getApplicationEnforceRBACInformer(ws.Context(), rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetApplicationName())
_, _, err := s.getApplicationEnforceRBACInformer(ws.Context(), rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetApplicationName())
if err != nil {
return err
}
@@ -1395,7 +1425,7 @@ func (s *Server) WatchResourceTree(q *application.ResourcesQuery, ws application
}
func (s *Server) RevisionMetadata(ctx context.Context, q *application.RevisionMetadataQuery) (*appv1.RevisionMetadata, error) {
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
a, proj, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, err
}
@@ -1405,12 +1435,6 @@ func (s *Server) RevisionMetadata(ctx context.Context, q *application.RevisionMe
if err != nil {
return nil, fmt.Errorf("error getting repository by URL: %w", err)
}
// We need to get some information with the project associated to the app,
// so we'll know whether GPG signatures are enforced.
proj, err := argo.GetAppProject(a, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx)
if err != nil {
return nil, fmt.Errorf("error getting app project: %w", err)
}
conn, repoClient, err := s.repoClientset.NewRepoServerClient()
if err != nil {
return nil, fmt.Errorf("error creating repo server client: %w", err)
@@ -1425,7 +1449,7 @@ func (s *Server) RevisionMetadata(ctx context.Context, q *application.RevisionMe
// RevisionChartDetails returns the helm chart metadata, as fetched from the reposerver
func (s *Server) RevisionChartDetails(ctx context.Context, q *application.RevisionMetadataQuery) (*appv1.ChartDetails, error) {
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
a, _, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, err
}
@@ -1456,7 +1480,7 @@ func isMatchingResource(q *application.ResourcesQuery, key kube.ResourceKey) boo
}
func (s *Server) ManagedResources(ctx context.Context, q *application.ResourcesQuery) (*application.ManagedResourcesResponse, error) {
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetApplicationName())
a, _, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetApplicationName())
if err != nil {
return nil, err
}
@@ -1513,7 +1537,7 @@ func (s *Server) PodLogs(q *application.ApplicationPodLogsQuery, ws application.
}
}
a, err := s.getApplicationEnforceRBACInformer(ws.Context(), rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
a, _, err := s.getApplicationEnforceRBACInformer(ws.Context(), rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return err
}
@@ -1705,19 +1729,11 @@ func isTheSelectedOne(currentNode *appv1.ResourceNode, q *application.Applicatio
// Sync syncs an application to its target state
func (s *Server) Sync(ctx context.Context, syncReq *application.ApplicationSyncRequest) (*appv1.Application, error) {
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, syncReq.GetProject(), syncReq.GetAppNamespace(), syncReq.GetName(), "")
a, proj, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, syncReq.GetProject(), syncReq.GetAppNamespace(), syncReq.GetName(), "")
if err != nil {
return nil, err
}
proj, err := argo.GetAppProject(a, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx)
if err != nil {
if apierr.IsNotFound(err) {
return a, status.Errorf(codes.InvalidArgument, "application references project %s which does not exist", a.Spec.Project)
}
return a, fmt.Errorf("error getting app project: %w", err)
}
s.inferResourcesStatusHealth(a)
if !proj.Spec.SyncWindows.Matches(a).CanSync(true) {
@@ -1814,7 +1830,7 @@ func (s *Server) Sync(ctx context.Context, syncReq *application.ApplicationSyncR
}
func (s *Server) Rollback(ctx context.Context, rollbackReq *application.ApplicationRollbackRequest) (*appv1.Application, error) {
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionSync, rollbackReq.GetProject(), rollbackReq.GetAppNamespace(), rollbackReq.GetName(), "")
a, _, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionSync, rollbackReq.GetProject(), rollbackReq.GetAppNamespace(), rollbackReq.GetName(), "")
if err != nil {
return nil, err
}
@@ -1873,7 +1889,7 @@ func (s *Server) Rollback(ctx context.Context, rollbackReq *application.Applicat
}
func (s *Server) ListLinks(ctx context.Context, req *application.ListAppLinksRequest) (*application.LinksResponse, error) {
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, req.GetProject(), req.GetNamespace(), req.GetName(), "")
a, proj, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, req.GetProject(), req.GetNamespace(), req.GetName(), "")
if err != nil {
return nil, err
}
@@ -1888,7 +1904,7 @@ func (s *Server) ListLinks(ctx context.Context, req *application.ListAppLinksReq
return nil, fmt.Errorf("failed to read application deep links from configmap: %w", err)
}
clstObj, _, err := s.getObjectsForDeepLinks(ctx, a)
clstObj, _, err := s.getObjectsForDeepLinks(ctx, a, proj)
if err != nil {
return nil, err
}
@@ -1903,12 +1919,7 @@ func (s *Server) ListLinks(ctx context.Context, req *application.ListAppLinksReq
return finalList, nil
}
func (s *Server) getObjectsForDeepLinks(ctx context.Context, app *appv1.Application) (cluster *unstructured.Unstructured, project *unstructured.Unstructured, err error) {
proj, err := argo.GetAppProject(app, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx)
if err != nil {
return nil, nil, fmt.Errorf("error getting app project: %w", err)
}
func (s *Server) getObjectsForDeepLinks(ctx context.Context, app *appv1.Application, proj *appv1.AppProject) (cluster *unstructured.Unstructured, project *unstructured.Unstructured, err error) {
// sanitize project jwt tokens
proj.Status = appv1.AppProjectStatus{}
@@ -1971,7 +1982,12 @@ func (s *Server) ListResourceLinks(ctx context.Context, req *application.Applica
return nil, err
}
clstObj, projObj, err := s.getObjectsForDeepLinks(ctx, app)
proj, err := s.getAppProject(ctx, app, log.WithField("application", app.GetName()))
if err != nil {
return nil, err
}
clstObj, projObj, err := s.getObjectsForDeepLinks(ctx, app, proj)
if err != nil {
return nil, err
}
@@ -2027,7 +2043,7 @@ func (s *Server) resolveRevision(ctx context.Context, app *appv1.Application, sy
func (s *Server) TerminateOperation(ctx context.Context, termOpReq *application.OperationTerminateRequest) (*application.OperationTerminateResponse, error) {
appName := termOpReq.GetName()
appNs := s.appNamespaceOrDefault(termOpReq.GetAppNamespace())
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionSync, termOpReq.GetProject(), appNs, appName, "")
a, _, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionSync, termOpReq.GetProject(), appNs, appName, "")
if err != nil {
return nil, err
}
@@ -2100,7 +2116,7 @@ func (s *Server) ListResourceActions(ctx context.Context, q *application.Applica
func (s *Server) getUnstructuredLiveResourceOrApp(ctx context.Context, rbacRequest string, q *application.ApplicationResourceRequest) (obj *unstructured.Unstructured, res *appv1.ResourceNode, app *appv1.Application, config *rest.Config, err error) {
if q.GetKind() == applicationType.ApplicationKind && q.GetGroup() == applicationType.Group && q.GetName() == q.GetResourceName() {
app, err = s.getApplicationEnforceRBACInformer(ctx, rbacRequest, q.GetProject(), q.GetAppNamespace(), q.GetName())
app, _, err = s.getApplicationEnforceRBACInformer(ctx, rbacRequest, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, nil, nil, nil, err
}
@@ -2196,6 +2212,11 @@ func (s *Server) RunResourceAction(ctx context.Context, q *application.ResourceA
}
}
proj, err := s.getAppProject(ctx, a, log.WithField("application", a.Name))
if err != nil {
return nil, err
}
// First, make sure all the returned resources are permitted, for each operation.
// Also perform create with dry-runs for all create-operation resources.
// This is performed separately to reduce the risk of only some of the resources being successfully created later.
@@ -2203,7 +2224,7 @@ func (s *Server) RunResourceAction(ctx context.Context, q *application.ResourceA
// the dry-run for relevant apply/delete operation would have to be invoked as well.
for _, impactedResource := range newObjects {
newObj := impactedResource.UnstructuredObj
err := s.verifyResourcePermitted(ctx, app, newObj)
err := s.verifyResourcePermitted(ctx, app, proj, newObj)
if err != nil {
return nil, err
}
@@ -2297,14 +2318,7 @@ func (s *Server) patchResource(ctx context.Context, config *rest.Config, liveObj
return &application.ApplicationResponse{}, nil
}
func (s *Server) verifyResourcePermitted(ctx context.Context, app *appv1.Application, obj *unstructured.Unstructured) error {
proj, err := argo.GetAppProject(app, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx)
if err != nil {
if apierr.IsNotFound(err) {
return fmt.Errorf("application references project %s which does not exist", app.Spec.Project)
}
return fmt.Errorf("failed to get project %s: %w", app.Spec.Project, err)
}
func (s *Server) verifyResourcePermitted(ctx context.Context, app *appv1.Application, proj *appv1.AppProject, obj *unstructured.Unstructured) error {
permitted, err := proj.IsResourcePermitted(schema.GroupKind{Group: obj.GroupVersionKind().Group, Kind: obj.GroupVersionKind().Kind}, obj.GetNamespace(), app.Spec.Destination, func(project string) ([]*appv1.Cluster, error) {
clusters, err := s.db.GetProjectClusters(context.TODO(), project)
if err != nil {
@@ -2364,16 +2378,11 @@ func splitStatusPatch(patch []byte) ([]byte, []byte, error) {
}
func (s *Server) GetApplicationSyncWindows(ctx context.Context, q *application.ApplicationSyncWindowsQuery) (*application.ApplicationSyncWindowsResponse, error) {
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName(), "")
a, proj, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName(), "")
if err != nil {
return nil, err
}
proj, err := argo.GetAppProject(a, applisters.NewAppProjectLister(s.projInformer.GetIndexer()), s.ns, s.settingsMgr, s.db, ctx)
if err != nil {
return nil, fmt.Errorf("error getting app project: %w", err)
}
windows := proj.Spec.SyncWindows.Matches(a)
sync := windows.CanSync(true)

View File

@@ -1438,6 +1438,27 @@ func TestCreateAppWithDestName(t *testing.T) {
assert.Equal(t, app.Spec.Destination.Server, "https://cluster-api.com")
}
// TestCreateAppWithOperation tests that an application created with an operation is created with the operation removed.
// Avoids regressions of https://github.com/argoproj/argo-cd/security/advisories/GHSA-g623-jcgg-mhmm
func TestCreateAppWithOperation(t *testing.T) {
appServer := newTestAppServer(t)
testApp := newTestAppWithDestName()
testApp.Operation = &appsv1.Operation{
Sync: &appsv1.SyncOperation{
Manifests: []string{
"test",
},
},
}
createReq := application.ApplicationCreateRequest{
Application: testApp,
}
app, err := appServer.Create(context.Background(), &createReq)
require.NoError(t, err)
require.NotNil(t, app)
assert.Nil(t, app.Operation)
}
func TestUpdateApp(t *testing.T) {
testApp := newTestApp()
appServer := newTestAppServer(t, testApp)
@@ -1796,7 +1817,7 @@ func TestServer_GetApplicationSyncWindowsState(t *testing.T) {
appServer := newTestAppServer(t, testApp)
active, err := appServer.GetApplicationSyncWindows(context.Background(), &application.ApplicationSyncWindowsQuery{Name: &testApp.Name})
assert.Contains(t, err.Error(), "not found")
assert.Contains(t, err.Error(), "not exist")
assert.Nil(t, active)
})
}
@@ -2343,3 +2364,255 @@ func TestIsApplicationPermitted(t *testing.T) {
assert.True(t, permitted)
})
}
func TestAppNamespaceRestrictions(t *testing.T) {
t.Run("List applications in controller namespace", func(t *testing.T) {
testApp := newTestApp()
appServer := newTestAppServer(t, testApp)
apps, err := appServer.List(context.TODO(), &application.ApplicationQuery{})
require.NoError(t, err)
require.Len(t, apps.Items, 1)
})
t.Run("List applications with non-allowed apps existing", func(t *testing.T) {
testApp1 := newTestApp()
testApp1.Namespace = "argocd-1"
appServer := newTestAppServer(t, testApp1)
apps, err := appServer.List(context.TODO(), &application.ApplicationQuery{})
require.NoError(t, err)
require.Len(t, apps.Items, 0)
})
t.Run("List applications with non-allowed apps existing and explicit ns request", func(t *testing.T) {
testApp1 := newTestApp()
testApp2 := newTestApp()
testApp2.Namespace = "argocd-1"
appServer := newTestAppServer(t, testApp1, testApp2)
apps, err := appServer.List(context.TODO(), &application.ApplicationQuery{AppNamespace: pointer.String("argocd-1")})
require.NoError(t, err)
require.Len(t, apps.Items, 0)
})
t.Run("List applications with allowed apps in other namespaces", func(t *testing.T) {
testApp1 := newTestApp()
testApp1.Namespace = "argocd-1"
appServer := newTestAppServer(t, testApp1)
appServer.enabledNamespaces = []string{"argocd-1"}
apps, err := appServer.List(context.TODO(), &application.ApplicationQuery{})
require.NoError(t, err)
require.Len(t, apps.Items, 1)
})
t.Run("Get application in control plane namespace", func(t *testing.T) {
testApp := newTestApp()
appServer := newTestAppServer(t, testApp)
app, err := appServer.Get(context.TODO(), &application.ApplicationQuery{
Name: pointer.String("test-app"),
})
require.NoError(t, err)
assert.Equal(t, "test-app", app.GetName())
})
t.Run("Get application in other namespace when forbidden", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
appServer := newTestAppServer(t, testApp)
app, err := appServer.Get(context.TODO(), &application.ApplicationQuery{
Name: pointer.String("test-app"),
AppNamespace: pointer.String("argocd-1"),
})
require.Error(t, err)
require.ErrorContains(t, err, "permission denied")
require.Nil(t, app)
})
t.Run("Get application in other namespace when allowed", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
testApp.Spec.Project = "other-ns"
otherNsProj := &appsv1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "other-ns", Namespace: "default"},
Spec: appsv1.AppProjectSpec{
SourceRepos: []string{"*"},
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
SourceNamespaces: []string{"argocd-1"},
},
}
appServer := newTestAppServer(t, testApp, otherNsProj)
appServer.enabledNamespaces = []string{"argocd-1"}
app, err := appServer.Get(context.TODO(), &application.ApplicationQuery{
Name: pointer.String("test-app"),
AppNamespace: pointer.String("argocd-1"),
})
require.NoError(t, err)
require.NotNil(t, app)
require.Equal(t, "argocd-1", app.Namespace)
require.Equal(t, "test-app", app.Name)
})
t.Run("Get application in other namespace when project is not allowed", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
testApp.Spec.Project = "other-ns"
otherNsProj := &appsv1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "other-ns", Namespace: "default"},
Spec: appsv1.AppProjectSpec{
SourceRepos: []string{"*"},
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
SourceNamespaces: []string{"argocd-2"},
},
}
appServer := newTestAppServer(t, testApp, otherNsProj)
appServer.enabledNamespaces = []string{"argocd-1"}
app, err := appServer.Get(context.TODO(), &application.ApplicationQuery{
Name: pointer.String("test-app"),
AppNamespace: pointer.String("argocd-1"),
})
require.Error(t, err)
require.Nil(t, app)
require.ErrorContains(t, err, "app is not allowed in project")
})
t.Run("Create application in other namespace when allowed", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
testApp.Spec.Project = "other-ns"
otherNsProj := &appsv1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "other-ns", Namespace: "default"},
Spec: appsv1.AppProjectSpec{
SourceRepos: []string{"*"},
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
SourceNamespaces: []string{"argocd-1"},
},
}
appServer := newTestAppServer(t, otherNsProj)
appServer.enabledNamespaces = []string{"argocd-1"}
app, err := appServer.Create(context.TODO(), &application.ApplicationCreateRequest{
Application: testApp,
})
require.NoError(t, err)
require.NotNil(t, app)
assert.Equal(t, "test-app", app.Name)
assert.Equal(t, "argocd-1", app.Namespace)
})
t.Run("Create application in other namespace when not allowed by project", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
testApp.Spec.Project = "other-ns"
otherNsProj := &appsv1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "other-ns", Namespace: "default"},
Spec: appsv1.AppProjectSpec{
SourceRepos: []string{"*"},
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
SourceNamespaces: []string{},
},
}
appServer := newTestAppServer(t, otherNsProj)
appServer.enabledNamespaces = []string{"argocd-1"}
app, err := appServer.Create(context.TODO(), &application.ApplicationCreateRequest{
Application: testApp,
})
require.Error(t, err)
require.Nil(t, app)
require.ErrorContains(t, err, "app is not allowed in project")
})
t.Run("Create application in other namespace when not allowed by configuration", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
testApp.Spec.Project = "other-ns"
otherNsProj := &appsv1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "other-ns", Namespace: "default"},
Spec: appsv1.AppProjectSpec{
SourceRepos: []string{"*"},
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
SourceNamespaces: []string{"argocd-1"},
},
}
appServer := newTestAppServer(t, otherNsProj)
appServer.enabledNamespaces = []string{"argocd-2"}
app, err := appServer.Create(context.TODO(), &application.ApplicationCreateRequest{
Application: testApp,
})
require.Error(t, err)
require.Nil(t, app)
require.ErrorContains(t, err, "namespace 'argocd-1' is not permitted")
})
t.Run("Get application sync window in other namespace when project is allowed", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
testApp.Spec.Project = "other-ns"
otherNsProj := &appsv1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "other-ns", Namespace: "default"},
Spec: appsv1.AppProjectSpec{
SourceRepos: []string{"*"},
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
SourceNamespaces: []string{"argocd-1"},
},
}
appServer := newTestAppServer(t, testApp, otherNsProj)
appServer.enabledNamespaces = []string{"argocd-1"}
active, err := appServer.GetApplicationSyncWindows(context.TODO(), &application.ApplicationSyncWindowsQuery{Name: &testApp.Name, AppNamespace: &testApp.Namespace})
assert.NoError(t, err)
assert.Equal(t, 0, len(active.ActiveWindows))
})
t.Run("Get application sync window in other namespace when project is not allowed", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
testApp.Spec.Project = "other-ns"
otherNsProj := &appsv1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "other-ns", Namespace: "default"},
Spec: appsv1.AppProjectSpec{
SourceRepos: []string{"*"},
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
SourceNamespaces: []string{"argocd-2"},
},
}
appServer := newTestAppServer(t, testApp, otherNsProj)
appServer.enabledNamespaces = []string{"argocd-1"}
active, err := appServer.GetApplicationSyncWindows(context.TODO(), &application.ApplicationSyncWindowsQuery{Name: &testApp.Name, AppNamespace: &testApp.Namespace})
require.Error(t, err)
require.Nil(t, active)
require.ErrorContains(t, err, "app is not allowed in project")
})
t.Run("Get list of links in other namespace when project is not allowed", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
testApp.Spec.Project = "other-ns"
otherNsProj := &appsv1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "other-ns", Namespace: "default"},
Spec: appsv1.AppProjectSpec{
SourceRepos: []string{"*"},
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
SourceNamespaces: []string{"argocd-2"},
},
}
appServer := newTestAppServer(t, testApp, otherNsProj)
appServer.enabledNamespaces = []string{"argocd-1"}
links, err := appServer.ListLinks(context.TODO(), &application.ListAppLinksRequest{
Name: pointer.String("test-app"),
Namespace: pointer.String("argocd-1"),
})
require.Error(t, err)
require.Nil(t, links)
require.ErrorContains(t, err, "app is not allowed in project")
})
t.Run("Get list of links in other namespace when project is allowed", func(t *testing.T) {
testApp := newTestApp()
testApp.Namespace = "argocd-1"
testApp.Spec.Project = "other-ns"
otherNsProj := &appsv1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "other-ns", Namespace: "default"},
Spec: appsv1.AppProjectSpec{
SourceRepos: []string{"*"},
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
SourceNamespaces: []string{"argocd-1"},
},
}
appServer := newTestAppServer(t, testApp, otherNsProj)
appServer.enabledNamespaces = []string{"argocd-1"}
links, err := appServer.ListLinks(context.TODO(), &application.ListAppLinksRequest{
Name: pointer.String("test-app"),
Namespace: pointer.String("argocd-1"),
})
require.NoError(t, err)
assert.Equal(t, 0, len(links.Items))
})
}

View File

@@ -38,12 +38,12 @@ type terminalHandler struct {
allowedShells []string
namespace string
enabledNamespaces []string
sessionManager util_session.SessionManager
sessionManager *util_session.SessionManager
}
// NewHandler returns a new terminal handler.
func NewHandler(appLister applisters.ApplicationLister, namespace string, enabledNamespaces []string, db db.ArgoDB, enf *rbac.Enforcer, cache *servercache.Cache,
appResourceTree AppResourceTreeFn, allowedShells []string, sessionManager util_session.SessionManager) *terminalHandler {
appResourceTree AppResourceTreeFn, allowedShells []string, sessionManager *util_session.SessionManager) *terminalHandler {
return &terminalHandler{
appLister: appLister,
db: db,

View File

@@ -37,7 +37,7 @@ type terminalSession struct {
tty bool
readLock sync.Mutex
writeLock sync.Mutex
sessionManager util_session.SessionManager
sessionManager *util_session.SessionManager
token *string
}
@@ -48,7 +48,7 @@ func getToken(r *http.Request) (string, error) {
}
// newTerminalSession create terminalSession
func newTerminalSession(w http.ResponseWriter, r *http.Request, responseHeader http.Header, sessionManager util_session.SessionManager) (*terminalSession, error) {
func newTerminalSession(w http.ResponseWriter, r *http.Request, responseHeader http.Header, sessionManager *util_session.SessionManager) (*terminalSession, error) {
token, err := getToken(r)
if err != nil {
return nil, err

View File

@@ -977,10 +977,12 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int, grpcWebHandl
}
if len(a.ContentTypes) > 0 {
handler = enforceContentTypes(handler, a.ContentTypes)
} else {
log.WithField(common.SecurityField, common.SecurityHigh).Warnf("Content-Type enforcement is disabled, which may make your API vulnerable to CSRF attacks")
}
mux.Handle("/api/", handler)
terminal := application.NewHandler(a.appLister, a.Namespace, a.ApplicationNamespaces, a.db, a.enf, a.Cache, appResourceTreeFn, a.settings.ExecShells, *a.sessionMgr).
terminal := application.NewHandler(a.appLister, a.Namespace, a.ApplicationNamespaces, a.db, a.enf, a.Cache, appResourceTreeFn, a.settings.ExecShells, a.sessionMgr).
WithFeatureFlagMiddleware(a.settingsMgr.GetSettings)
th := util_session.WithAuthMiddleware(a.DisableAuth, a.sessionMgr, terminal)
mux.Handle("/terminal", th)

View File

@@ -1349,3 +1349,46 @@ func TestReplaceBaseHRef(t *testing.T) {
})
}
}
func Test_enforceContentTypes(t *testing.T) {
getBaseHandler := func(t *testing.T, allow bool) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
assert.True(t, allow, "http handler was hit when it should have been blocked by content type enforcement")
writer.WriteHeader(200)
})
}
t.Parallel()
t.Run("GET - not providing a content type, should still succeed", func(t *testing.T) {
handler := enforceContentTypes(getBaseHandler(t, true), []string{"application/json"}).(http.HandlerFunc)
req := httptest.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
handler(w, req)
resp := w.Result()
assert.Equal(t, 200, resp.StatusCode)
})
t.Run("POST", func(t *testing.T) {
handler := enforceContentTypes(getBaseHandler(t, true), []string{"application/json"}).(http.HandlerFunc)
req := httptest.NewRequest("POST", "/", nil)
w := httptest.NewRecorder()
handler(w, req)
resp := w.Result()
assert.Equal(t, 415, resp.StatusCode, "didn't provide a content type, should have gotten an error")
req = httptest.NewRequest("POST", "/", nil)
req.Header = map[string][]string{"Content-Type": {"application/json"}}
w = httptest.NewRecorder()
handler(w, req)
resp = w.Result()
assert.Equal(t, 200, resp.StatusCode, "should have passed, since an allowed content type was provided")
req = httptest.NewRequest("POST", "/", nil)
req.Header = map[string][]string{"Content-Type": {"not-allowed"}}
w = httptest.NewRecorder()
handler(w, req)
resp = w.Result()
assert.Equal(t, 415, resp.StatusCode, "should not have passed, since a disallowed content type was provided")
})
}

View File

@@ -432,7 +432,7 @@ func TestNamespacedInvalidAppProject(t *testing.T) {
Then().
// We're not allowed to infer whether the project exists based on this error message. Instead, we get a generic
// permission denied error.
Expect(Error("", "permission denied"))
Expect(Error("", "is not allowed"))
}
func TestNamespacedAppDeletion(t *testing.T) {

View File

@@ -21,6 +21,7 @@ import (
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
@@ -547,7 +548,7 @@ func TestInvalidAppProject(t *testing.T) {
Then().
// We're not allowed to infer whether the project exists based on this error message. Instead, we get a generic
// permission denied error.
Expect(Error("", "permission denied"))
Expect(Error("", "is not allowed"))
}
func TestAppDeletion(t *testing.T) {
@@ -2846,3 +2847,44 @@ func TestAnnotationTrackingExtraResources(t *testing.T) {
Expect(HealthIs(health.HealthStatusHealthy))
}
// Test designed to cover #15126.
// The issue occurs in the controller, when a valuesObject field that contains non-strings (eg, a nested map) gets
// merged/patched.
// Note: Failure is observed by the test timing out, because the controller cannot 'merge' the patch.
func TestPatchValuesObject(t *testing.T) {
Given(t).
Timeout(30).
Path("helm").
When().
// app should be auto-synced once created
CreateFromFile(func(app *Application) {
app.Spec.Source.Helm = &ApplicationSourceHelm{
ValuesObject: &runtime.RawExtension{
// Setup by using nested YAML objects, which is what causes the patch error:
// "unable to find api field in struct RawExtension for the json field "some""
Raw: []byte(`{"some": {"foo": "bar"}}`),
},
}
}).
Then().
When().
PatchApp(`[{
"op": "add",
"path": "/spec/source/helm/valuesObject",
"value": {"some":{"foo":"bar","new":"field"}}
}]`).
Refresh(RefreshTypeNormal).
Sync().
Then().
Expect(Success("")).
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(NoConditions()).
And(func(app *Application) {
// Check that the patch was a success.
assert.Equal(t, `{"some":{"foo":"bar","new":"field"}}`, string(app.Spec.Source.Helm.ValuesObject.Raw))
})
}

View File

@@ -2266,3 +2266,88 @@ func TestGitGeneratorPrivateRepoGoTemplate(t *testing.T) {
When().
Delete().Then().Expect(ApplicationsDoNotExist(expectedAppsNewNamespace))
}
func TestUpdateHelmValuesObject(t *testing.T) {
expectedApp := argov1alpha1.Application{
TypeMeta: metav1.TypeMeta{
Kind: application.ApplicationKind,
APIVersion: "argoproj.io/v1alpha1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster-guestbook",
Namespace: fixture.TestNamespace(),
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
},
Spec: argov1alpha1.ApplicationSpec{
Project: "default",
Source: &argov1alpha1.ApplicationSource{
RepoURL: "https://github.com/argoproj/argocd-example-apps.git",
TargetRevision: "HEAD",
Path: "helm-guestbook",
Helm: &argov1alpha1.ApplicationSourceHelm{
ValuesObject: &runtime.RawExtension{
// This will always be converted as yaml
Raw: []byte(`{"some":{"foo":"bar"}}`),
},
},
},
Destination: argov1alpha1.ApplicationDestination{
Server: "https://kubernetes.default.svc",
Namespace: "guestbook",
},
},
}
Given(t).
// Create a ListGenerator-based ApplicationSet
When().Create(v1alpha1.ApplicationSet{ObjectMeta: metav1.ObjectMeta{
Name: "test-values-object-patch",
},
Spec: v1alpha1.ApplicationSetSpec{
GoTemplate: true,
Template: v1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook"},
Spec: argov1alpha1.ApplicationSpec{
Project: "default",
Source: &argov1alpha1.ApplicationSource{
RepoURL: "https://github.com/argoproj/argocd-example-apps.git",
TargetRevision: "HEAD",
Path: "helm-guestbook",
Helm: &argov1alpha1.ApplicationSourceHelm{
ValuesObject: &runtime.RawExtension{
Raw: []byte(`{"some":{"string":"{{.test}}"}}`),
},
},
},
Destination: argov1alpha1.ApplicationDestination{
Server: "{{.url}}",
Namespace: "guestbook",
},
},
},
Generators: []v1alpha1.ApplicationSetGenerator{
{
List: &v1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{{
Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc", "test": "Hello world"}`),
}},
},
},
},
},
}).Then().
Expect(ApplicationSetHasConditions("test-values-object-patch", ExpectedConditions)).
When().
// Update the app spec with some knew ValuesObject to force a merge
Update(func(as *argov1alpha1.ApplicationSet) {
as.Spec.Template.Spec.Source.Helm.ValuesObject = &runtime.RawExtension{
Raw: []byte(`{"some":{"foo":"bar"}}`),
}
}).
Then().
Expect(ApplicationsExist([]argov1alpha1.Application{expectedApp})).
When().
// Delete the ApplicationSet, and verify it deletes the Applications
Delete().Then().Expect(ApplicationsDoNotExist([]argov1alpha1.Application{expectedApp}))
}

View File

@@ -67,7 +67,7 @@ func TestClusterAddPermissionDenied(t *testing.T) {
Create().
Then().
AndCLIOutput(func(output string, err error) {
assert.True(t, strings.Contains(err.Error(), "PermissionDenied desc = permission denied: clusters, create"))
assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied")
})
}
@@ -232,7 +232,7 @@ func TestClusterDeleteDenied(t *testing.T) {
DeleteByName().
Then().
AndCLIOutput(func(output string, err error) {
assert.True(t, strings.Contains(err.Error(), "PermissionDenied desc = permission denied: clusters, delete"))
assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied")
})
// Attempt to remove cluster creds by server
@@ -246,7 +246,7 @@ func TestClusterDeleteDenied(t *testing.T) {
DeleteByServer().
Then().
AndCLIOutput(func(output string, err error) {
assert.True(t, strings.Contains(err.Error(), "PermissionDenied desc = permission denied: clusters, delete"))
assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied")
})
}

View File

@@ -54,12 +54,14 @@ func TestDeclarativeInvalidProject(t *testing.T) {
Expect(Success("")).
Expect(HealthIs(health.HealthStatusUnknown)).
Expect(SyncStatusIs(SyncStatusCodeUnknown)).
Expect(Condition(ApplicationConditionInvalidSpecError, "Application referencing project garbage which does not exist")).
When().
Delete(false).
Then().
Expect(Success("")).
Expect(DoesNotExist())
Expect(Condition(ApplicationConditionInvalidSpecError, "Application referencing project garbage which does not exist"))
// TODO: you can`t delete application with invalid project due to enforcment that was recently added,
// in https://github.com/argoproj/argo-cd/security/advisories/GHSA-2gvw-w6fj-7m3c
//When().
//Delete(false).
//Then().
//Expect(Success("")).
//Expect(DoesNotExist())
}
func TestDeclarativeInvalidRepoURL(t *testing.T) {

View File

@@ -15,7 +15,7 @@ import {
RevisionHelpIcon
} from '../../../shared/components';
import {BadgePanel, Spinner} from '../../../shared/components';
import {Consumer, ContextApis} from '../../../shared/context';
import {AuthSettingsCtx, Consumer, ContextApis} from '../../../shared/context';
import * as models from '../../../shared/models';
import {services} from '../../../shared/services';
@@ -30,6 +30,7 @@ import {EditAnnotations} from './edit-annotations';
import './application-summary.scss';
import {DeepLinks} from '../../../shared/components/deep-links';
import {ExternalLinks} from '../application-urls';
function swap(array: any[], a: number, b: number) {
array = array.slice();
@@ -47,6 +48,7 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
const source = getAppDefaultSource(app);
const isHelm = source.hasOwnProperty('chart');
const initialState = app.spec.destination.server === undefined ? 'NAME' : 'URL';
const useAuthSettingsCtx = React.useContext(AuthSettingsCtx);
const [destFormat, setDestFormat] = React.useState(initialState);
const [changeSync, setChangeSync] = React.useState(false);
@@ -325,20 +327,19 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
)
}
];
const urls = app.status.summary.externalURLs || [];
const urls = ExternalLinks(app.status.summary.externalURLs);
if (urls.length > 0) {
attributes.push({
title: 'URLs',
view: (
<React.Fragment>
{urls
.map(item => item.split('|'))
.map((parts, i) => (
<a key={i} href={parts.length > 1 ? parts[1] : parts[0]} target='__blank'>
{parts[0]} &nbsp;
{urls.map((url, i) => {
return (
<a key={i} href={url.ref} target='__blank'>
{url.title} &nbsp;
</a>
))}
);
})}
</React.Fragment>
)
});
@@ -589,7 +590,7 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
</div>
)}
</Consumer>
<BadgePanel app={props.app.metadata.name} />
<BadgePanel app={props.app.metadata.name} appNamespace={props.app.metadata.namespace} nsEnabled={useAuthSettingsCtx?.appsInAnyNamespaceEnabled} />
<EditablePanel
save={updateApp}
values={app}

View File

@@ -1,4 +1,4 @@
import {ExternalLink, InvalidExternalLinkError} from './application-urls';
import { ExternalLink, ExternalLinks, InvalidExternalLinkError } from './application-urls';
test('rejects malicious URLs', () => {
expect(() => {
@@ -7,6 +7,16 @@ test('rejects malicious URLs', () => {
expect(() => {
const _ = new ExternalLink('data:text/html;<h1>hi</h1>');
}).toThrowError(InvalidExternalLinkError);
expect(() => {
const _ = new ExternalLink('title|data:text/html;<h1>hi</h1>');
}).toThrowError(InvalidExternalLinkError);
expect(() => {
const _ = new ExternalLink('data:title|data:text/html;<h1>hi</h1>');
}).toThrowError(InvalidExternalLinkError);
expect(() => {
const _ = new ExternalLink('data:title|https://localhost:8080/applications');
}).not.toThrowError(InvalidExternalLinkError);
});
test('allows absolute URLs', () => {
@@ -18,3 +28,59 @@ test('allows relative URLs', () => {
window.location = new URL('https://localhost:8080/applications');
expect(new ExternalLink('/applications').ref).toEqual('/applications');
});
test('URLs format', () => {
expect(new ExternalLink('https://localhost:8080/applications')).toEqual({
ref: 'https://localhost:8080/applications',
title: 'https://localhost:8080/applications',
})
expect(new ExternalLink('title|https://localhost:8080/applications')).toEqual({
ref: 'https://localhost:8080/applications',
title: 'title',
})
});
test('malicious URLs from list to be removed', () => {
const urls: string[] = [
'javascript:alert("hi")',
'https://localhost:8080/applications',
]
const links = ExternalLinks(urls);
expect(links).toHaveLength(1);
expect(links).toContainEqual({
ref: 'https://localhost:8080/applications',
title: 'https://localhost:8080/applications',
});
});
test('list to be sorted', () => {
const urls: string[] = [
'https://a',
'https://b',
'a|https://c',
'z|https://c',
'x|https://d',
'x|https://c',
]
const links = ExternalLinks(urls);
// 'a|https://c',
// 'x|https://c',
// 'x|https://d',
// 'z|https://c',
// 'https://a',
// 'https://b',
expect(links).toHaveLength(6);
expect(links[0].title).toEqual('a')
expect(links[1].title).toEqual('x')
expect(links[1].ref).toEqual('https://c')
expect(links[2].title).toEqual('x')
expect(links[2].ref).toEqual('https://d')
expect(links[3].title).toEqual('z')
expect(links[4].title).toEqual('https://a')
expect(links[5].title).toEqual('https://b')
});

View File

@@ -29,7 +29,7 @@ export class ExternalLink {
}
}
export const ApplicationURLs = ({urls}: {urls: string[]}) => {
export const ExternalLinks = (urls?: string[]) => {
const externalLinks: ExternalLink[] = [];
for (const url of urls || []) {
try {
@@ -42,16 +42,26 @@ export const ApplicationURLs = ({urls}: {urls: string[]}) => {
// sorted alphabetically & links with titles first
externalLinks.sort((a, b) => {
if (a.title !== '' && b.title !== '') {
const hasTitle = (x: ExternalLink): boolean => {
return x.title !== x.ref && x.title !== '';
};
if (hasTitle(a) && hasTitle(b) && a.title !== b.title) {
return a.title > b.title ? 1 : -1;
} else if (a.title === '') {
} else if (hasTitle(b) && !hasTitle(a)) {
return 1;
} else if (b.title === '') {
} else if (hasTitle(a) && !hasTitle(b)) {
return -1;
}
return a.ref > b.ref ? 1 : -1;
});
return externalLinks;
};
export const ApplicationURLs = ({urls}: {urls: string[]}) => {
const externalLinks: ExternalLink[] = ExternalLinks(urls);
return (
((externalLinks || []).length > 0 && (
<div className='applications-list__external-links-icon-container'>

View File

@@ -6,7 +6,7 @@ import {Context} from '../../context';
require('./badge-panel.scss');
export const BadgePanel = ({app, project}: {app?: string; project?: string}) => {
export const BadgePanel = ({app, project, appNamespace, nsEnabled}: {app?: string; project?: string; appNamespace?: string; nsEnabled?: boolean}) => {
const [badgeType, setBadgeType] = React.useState('URL');
const context = React.useContext(Context);
if (!app && !project) {
@@ -20,6 +20,9 @@ export const BadgePanel = ({app, project}: {app?: string; project?: string}) =>
let alt = '';
if (app) {
badgeURL = `${root}api/badge?name=${app}&revision=true`;
if (nsEnabled) {
badgeURL += `&namespace=${appNamespace}`;
}
entityURL = `${root}applications/${app}`;
alt = 'App Status';
} else if (project) {

View File

@@ -51,19 +51,19 @@ export default {
},
post(url: string) {
return initHandlers(agent.post(`${apiRoot()}${url}`));
return initHandlers(agent.post(`${apiRoot()}${url}`)).set('Content-Type', 'application/json');
},
put(url: string) {
return initHandlers(agent.put(`${apiRoot()}${url}`));
return initHandlers(agent.put(`${apiRoot()}${url}`)).set('Content-Type', 'application/json');
},
patch(url: string) {
return initHandlers(agent.patch(`${apiRoot()}${url}`));
return initHandlers(agent.patch(`${apiRoot()}${url}`)).set('Content-Type', 'application/json');
},
delete(url: string) {
return initHandlers(agent.del(`${apiRoot()}${url}`));
return initHandlers(agent.del(`${apiRoot()}${url}`)).set('Content-Type', 'application/json');
},
loadEventSource(url: string): Observable<string> {

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