Compare commits

...

41 Commits

Author SHA1 Message Date
github-actions[bot]
eee1a8add2 Bump version to 2.8.0-rc5 (#14606)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2023-07-19 13:33:29 -04:00
gcp-cherry-pick-bot[bot]
c71664849a fix(api): return 404 when the app is not found if a project is specified (#13393) (#13394) (#14600)
* fix(api): return 404 when the app is not found if a project is specified (#13393)



simplify, respond 404 on project specified but doesn't match, always fetch app



handle project updates



* handle new endpoint, fix bad merge



* docs



---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-07-19 09:23:02 -04:00
gcp-cherry-pick-bot[bot]
27e9c13fb8 fix(cli): allow argocd cli app command for multi source apps (#14256) (#14586)
Signed-off-by: Lukas Wöhrl <lukas.woehrl@plentymarkets.com>
Co-authored-by: Lukas Wöhrl <lukas.woehrl@plentymarkets.com>
2023-07-18 16:35:09 -04:00
github-actions[bot]
982300a006 Bump version to 2.8.0-rc4 (#14580)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2023-07-18 16:24:05 -04:00
gcp-cherry-pick-bot[bot]
68a0d00f97 fix(cli): argocd CLI RBAC validation doesn't work on actions (#13911) (#14578) (#14581)
* #11602 fix : Object options menu truncated when selected in ApplicationListView.



* #11602 fix : Object options menu truncated when selected in ApplicationListView.



* changes for argocd_rbac



---------

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>
Signed-off-by: schakrad <chakradari.sindhu@gmail.com>
Co-authored-by: schakrad <58915923+schakrad@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-07-18 16:21:58 -04:00
gcp-cherry-pick-bot[bot]
af7f8af362 fix: Remove executable bit from default file mode (#14497) (#14576)
* Fix file/directory opening mode



* Fix TestUntgz/preserves_file_mode



* Mention file mode fix in 2.7-2.8 release docs



---------

Signed-off-by: ramikg <72725910+ramikg@users.noreply.github.com>
Co-authored-by: Rami <72725910+ramikg@users.noreply.github.com>
2023-07-18 13:30:01 -04:00
gcp-cherry-pick-bot[bot]
dacb2873f0 fix(server): not need send application if it is not under enabled namespaces (#14479) (#14575)
* fix: not need send application if it is not under enabled namespaces

* fix condition

* feat: Move application is permitted outside of watch function and cover with unit tests

* feat: Move application is permitted outside of watch function and cover with unit tests

Co-authored-by: pasha-codefresh <pavel@codefresh.io>
2023-07-18 10:38:39 -04:00
gcp-cherry-pick-bot[bot]
b0a1d82309 fix: Correct pod log viewer to support short log lines. Fixes #14402 (#14543) (#14561)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
Co-authored-by: Yuan Tang <terrytangyuan@gmail.com>
2023-07-18 08:49:10 -04:00
Noah Elzner
9612f73dbd chore: Generate SLSA provenance for SBOM (#14438) (cherry-pick #14507) (#14559)
* chore: Generate SLSA provenance for SBOM (#14438) (#14507)

* Add provenance generation for sbom

Signed-off-by: Noah Elzner <78953604+enteraga6@users.noreply.github.com>

* upload SBOM

Signed-off-by: Noah Elzner <78953604+enteraga6@users.noreply.github.com>

* Remove cosign setup

Signed-off-by: Noah Elzner <78953604+enteraga6@users.noreply.github.com>

* include hashes in generate-sbom output

Signed-off-by: Noah Elzner <78953604+enteraga6@users.noreply.github.com>

* Replace Cosign Verification command with SLSA command in docs

Signed-off-by: Noah Elzner <78953604+enteraga6@users.noreply.github.com>

* Remove id-token write permission - no longer needed

Signed-off-by: Noah Elzner <78953604+enteraga6@users.noreply.github.com>

---------

Signed-off-by: Noah Elzner <78953604+enteraga6@users.noreply.github.com>
Signed-off-by: Noah Elzner <elzner@google.com>

* change source tag in sbom verification command to v2.8.0

Signed-off-by: Noah Elzner <78953604+enteraga6@users.noreply.github.com>

---------

Signed-off-by: Noah Elzner <78953604+enteraga6@users.noreply.github.com>
Signed-off-by: Noah Elzner <elzner@google.com>
2023-07-18 08:34:38 -04:00
gcp-cherry-pick-bot[bot]
5dd9bdc37c fix(controller): populate ignoreDifferences in sync status (#14542) (#14557)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-07-17 15:50:12 -04:00
gcp-cherry-pick-bot[bot]
80ea9798ca fix(appset): normalize app spec before applying (#14481) (#14554)
* fix(appset): normalize app spec before applying



* fix nil ref, add test



* fix another test



---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-07-17 14:22:39 -04:00
gcp-cherry-pick-bot[bot]
05645b051e docs: Correct example ClusterRole to allow Events in any namespace (#14544) (#14550)
Fixes: #14477

Signed-off-by: Dimitar Georgievski <dgeorgievski@gmail.com>
Co-authored-by: Dimitar Georgievski <dgeorgievski@gmail.com>
2023-07-17 12:56:33 -04:00
gcp-cherry-pick-bot[bot]
9a79b19bdf fix: 'argocd-server-tls' Secret should be loaded from informer (#14522) (#14546)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2023-07-17 12:01:43 -04:00
gcp-cherry-pick-bot[bot]
667800737d fix(security): don't allow app enumeration via RevisionChartDetails (#14512) (#14517)
* fix(security): don't allow app enumeration via RevisionChartDetails



* better app name



---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-07-15 09:56:36 -04:00
gcp-cherry-pick-bot[bot]
6cece3f550 docs: improve ignoreResourceUpdates docs (cherry-pick #14475) (#14504)
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-07-13 11:59:25 -04:00
gcp-cherry-pick-bot[bot]
50325a908a chore: improve ignoreResourceUpdates logging (#14476) (#14500)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: pasha-codefresh <pavel@codefresh.io>
2023-07-13 10:45:57 -04:00
gcp-cherry-pick-bot[bot]
b5b443499b chore(deps): bump library/golang from 1.20.5 to 1.20.6 (#14480) (#14484)
Signed-off-by: fengshunli <1171313930@qq.com>
Co-authored-by: fsl <1171313930@qq.com>
2023-07-12 15:07:27 -04:00
github-actions[bot]
5d1d64fe83 Bump version to 2.8.0-rc3 (#14474)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2023-07-12 12:52:39 -04:00
gcp-cherry-pick-bot[bot]
83fa035f55 fix(cli): fix tracking annotation diff for non-namespaced resources (#13924) (#14473)
Signed-off-by: Maxime Brunet <max@brnt.mx>
Co-authored-by: Maxime Brunet <max@brnt.mx>
2023-07-12 09:36:17 -04:00
Ishita Sequeira
3ddee6d73f feat(appset): Add support for self-signed TLS / Certificates for Gitlab Scm Provider (#14348) (#14462)
* Add support for self-signed TLS / Certificates for Gitlab Scm Provider



* Add support for self-signed TLS / Certificates for Gitlab Pull Request



* Add TLS configuration for SCM and Pull request Gitlab Provider



* rebase with master



* add params to argocd-cmd-params-cm and docs



* fix generated manifests



* Address comments for docs



* Add test cases to validate insecure mode and ca cert combinations



* simplify (#24)



---------

Signed-off-by: ishitasequeira <ishiseq29@gmail.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-07-11 16:35:36 -04:00
gcp-cherry-pick-bot[bot]
53c582bced docs: Update SLSA verification commands (#14437) (#14454)
* update



* update



* update



* update



* update



* update



* update



---------

Signed-off-by: laurentsimon <laurentsimon@google.com>
Co-authored-by: laurentsimon <64505099+laurentsimon@users.noreply.github.com>
2023-07-11 10:54:12 -04:00
gcp-cherry-pick-bot[bot]
00d995d3fa fix: trigger refresh on changed ignoreDifferences (#12607) (#14403)
* fix: trigger refresh on changed ignoreDifferences



* make the tests mean things



---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-07-11 10:49:08 -04:00
gcp-cherry-pick-bot[bot]
b1efb745f0 fix: Fix pod log viewer scrollbars (#14199) (#14418)
* fix: Fix pod log viewer scrollbars



* fix scrolling



---------

Signed-off-by: Alex Collins <alex_collins@intuit.com>
Co-authored-by: Alex Collins <alexec@users.noreply.github.com>
2023-07-11 10:47:59 -04:00
gcp-cherry-pick-bot[bot]
d8c6e19501 fix(action): copy metadata on create-job action (#14232) (#14233) (#14453)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-07-11 10:37:34 -04:00
gcp-cherry-pick-bot[bot]
ca03596ea4 docs: fix typo (#14412) (#14413)
Signed-off-by: yukinakanaka <yuki.nakamura@mapbox.com>
Co-authored-by: Yuki Nakamura <yuki.nakamura@mapbox.com>
2023-07-10 14:04:40 -04:00
gcp-cherry-pick-bot[bot]
7c4eee26ef fix: adds WebSocket ping to interactive terminal (#14191) (cherry-pick #14192) (#14399)
* fix: adds WebSocket ping to interactive terminal (#14191) (#14192)

This adds a WebSocket ping message on a 5-second interval, sent
from the server to the client. This ensures that the interactive
terminal will remain open and won't be closed by load balancers
that are reaping idle connections.

Signed-off-by: Edmund Rhudy <erhudy@users.noreply.github.com>

* fix: adds WebSocket ping to interactive terminal (#14191) (#14192)

This adds a WebSocket ping message on a 5-second interval, sent
from the server to the client. This ensures that the interactive
terminal will remain open and won't be closed by load balancers
that are reaping idle connections.

Signed-off-by: Edmund Rhudy <erhudy@users.noreply.github.com>

---------

Signed-off-by: Edmund Rhudy <erhudy@users.noreply.github.com>
Co-authored-by: Edmund Rhudy <erhudy@users.noreply.github.com>
2023-07-07 11:00:13 -04:00
gcp-cherry-pick-bot[bot]
d36d31b367 fix: Update bitbucket.org rsa ssh key (#14392) (#14396)
The key change announcement at https://bitbucket.org/blog/ssh-host-key-changes

Signed-off-by: Haitao Li <hli@atlassian.com>
Co-authored-by: Haitao Li <39936070+hligit@users.noreply.github.com>
2023-07-07 10:24:06 -04:00
gcp-cherry-pick-bot[bot]
d75aaaa0f7 fix(sharding): recurring info logs to debug (#14383) (#14385)
Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>
Co-authored-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>
2023-07-06 19:39:54 -04:00
gcp-cherry-pick-bot[bot]
e03a7b76dd docs: managedFieldsManagers example in docs needs double-quotes (#14324) (#14371)
* is a Yaml special character and must be quoted, otherwise ArgoCD fails to parse and shows an error.

Signed-off-by: Paul Martin <paul.martin@gmail.com>
Co-authored-by: Paul Martin <paul.martin@gmail.com>
2023-07-06 13:49:39 -04:00
gcp-cherry-pick-bot[bot]
5cde94c9ab docs: Added information about scopes (#2782) (#14354) (#14380)
* Added information about scopes in the docs



* Apply suggestions from code review




---------

Signed-off-by: Christian Hernandez <christian@chernand.io>
Signed-off-by: Christian Hernandez <christianh814@users.noreply.github.com>
Co-authored-by: Christian Hernandez <christianh814@users.noreply.github.com>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2023-07-06 13:49:18 -04:00
gcp-cherry-pick-bot[bot]
f2b61ed39f docs: typofix (#14344) (#14355)
Signed-off-by: Julien Bouquillon <julien.bouquillon@sg.social.gouv.fr>
Co-authored-by: Julien Bouquillon <contact@revolunet.com>
2023-07-05 21:41:17 -04:00
github-actions[bot]
d24b263601 Bump version to 2.8.0-rc2 (#14352)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2023-07-05 15:24:10 -04:00
gcp-cherry-pick-bot[bot]
2d6d30c1df fix: Change disallowed application destination message (#14284) (#14307) (#14326)
* change disallowed application destinations message



* Changed e2e tests



---------

Signed-off-by: michaelkot97 <michael.kot97@gmail.com>
Co-authored-by: Michael Kotelnikov <36506417+michaelkotelnikov@users.noreply.github.com>
2023-07-03 12:52:07 -07:00
gcp-cherry-pick-bot[bot]
fa74998f45 feat: upgrade dexIDP from 2.36.0 -> 2.37.0 (#14305) (#14310) (#14312)
* feat: update dexidp image tag from v2.36.0 -> v2.37.0



* chore: adding GlueOps to USERS.md



---------

Signed-off-by: Venkata Mutyala <venkata@venkatamutyala.com>
Co-authored-by: Venkata Mutyala <venkata@venkatamutyala.com>
2023-07-02 19:07:18 -07:00
gcp-cherry-pick-bot[bot]
d11142e321 fix: deadlock in controller (#14304) (#14306)
Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>
Co-authored-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>
2023-07-01 13:45:03 -07:00
gcp-cherry-pick-bot[bot]
e45ff37aad docs: Adding explanation for CMP yaml/json generation (must be K8S object) (#9471) (#14295) (#14301)
Signed-off-by: Christian Hernandez <christian@chernand.io>
Co-authored-by: Christian Hernandez <christianh814@users.noreply.github.com>
2023-06-30 19:38:17 -04:00
gcp-cherry-pick-bot[bot]
9ec2a2e93c docs: Clarify "SSH known host public keys" text (#13537) (#14297)
Add `ssh_keyscan` example usage

Signed-off-by: Daniel Perevalov <daniel.perevalov@gmail.com>
Co-authored-by: Daniel Perevalov <daniel.perevalov@gmail.com>
2023-06-30 19:35:52 -04:00
gcp-cherry-pick-bot[bot]
5470a48c82 docs: change to the correct property for the dex server value (#14279) (#14291)
* fix: change to the correct property for dex server



* Update argocd-cmd-params-cm.yaml



---------

Signed-off-by: bjarneo <bjarneo@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: bjarneo <bjarneo@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-06-30 11:40:08 -04:00
gcp-cherry-pick-bot[bot]
a147c498e9 docs: explicit that ArgoCD hooks replaces the Helm ones (#14283) (#14287)
* docs: explicit that ArgoCD hooks replace the Helm ones

After digging a bit in the code, I've found this comment that confirms
that if we define some ArgoCD hooks the Helm ones are ignored.
425d65e076/pkg/sync/hook/hook.go (L36C2-L36C46)



* docs: add Back Market in the user list



* Update docs/user-guide/helm.md



---------

Signed-off-by: Benoît Sauvère <benoit.sauvere@backmarket.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Benoît Sauvère <benoit@sauve.re>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-06-30 11:38:24 -04:00
gcp-cherry-pick-bot[bot]
1477b0d874 fix: Correctly verify signatures when targetRevision is a branch name (#14214) (#14235)
* fix: Correctly verify signatures when targetRevision is a branch name



* Add more e2e tests



* Fix a bug and add unit test



---------

Signed-off-by: jannfis <jann@mistrust.net>
Co-authored-by: jannfis <jann@mistrust.net>
2023-06-29 17:38:13 -04:00
github-actions[bot]
be263caab3 Bump version to 2.8.0-rc1 (#14225)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2023-06-27 10:57:17 -04:00
110 changed files with 3789 additions and 1213 deletions

View File

@@ -426,7 +426,7 @@ jobs:
git config --global user.email "john.doe@example.com"
- name: Pull Docker image required for tests
run: |
docker pull ghcr.io/dexidp/dex:v2.36.0
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
- name: Create target directory for binaries in the build-process

View File

@@ -95,7 +95,7 @@ jobs:
args: release --clean --timeout 55m
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
KUBECTL_VERSION: ${{ env.KUBECTL_VERSION }}
KUBECTL_VERSION: ${{ env.KUBECTL_VERSION }}
GIT_TREE_STATE: ${{ env.GIT_TREE_STATE }}
- name: Generate subject for provenance
@@ -127,13 +127,14 @@ jobs:
upload-assets: true
generate-sbom:
name: Create Sbom and sign assets
name: Create SBOM and generate hash
needs:
- argocd-image
- goreleaser
permissions:
contents: write # Needed for release uploads
id-token: write # Needed for signing Sbom
outputs:
hashes: ${{ steps.sbom-hash.outputs.hashes}}
if: github.repository == 'argoproj/argo-cd'
runs-on: ubuntu-22.04
steps:
@@ -148,11 +149,6 @@ jobs:
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install cosign
uses: sigstore/cosign-installer@d13028333d784fcc802b67ec924bcebe75aa0a5f # v3.1.0
with:
cosign-release: 'v2.0.0'
- name: Generate SBOM (spdx)
id: spdx-builder
env:
@@ -183,21 +179,36 @@ jobs:
cd /tmp && tar -zcf sbom.tar.gz *.spdx
- name: Sign SBOM
- name: Generate SBOM hash
shell: bash
id: sbom-hash
run: |
cosign sign-blob \
--output-certificate=/tmp/sbom.tar.gz.pem \
--output-signature=/tmp/sbom.tar.gz.sig \
-y \
/tmp/sbom.tar.gz
# sha256sum generates sha256 hash for sbom.
# base64 -w0 encodes to base64 and outputs on a single line.
# sha256sum /tmp/sbom.tar.gz ... | base64 -w0
echo "hashes=$(sha256sum /tmp/sbom.tar.gz | base64 -w0)" >> "$GITHUB_OUTPUT"
- name: Upload SBOM and signature assets
- name: Upload SBOM
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: |
/tmp/sbom.tar.*
/tmp/sbom.tar.gz
sbom-provenance:
needs: [generate-sbom]
permissions:
actions: read # for detecting the Github Actions environment
id-token: write # Needed for provenance signing and ID
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.7.0
with:
base64-subjects: "${{ needs.generate-sbom.outputs.hashes }}"
provenance-name: "argocd-sbom.intoto.jsonl"
upload-assets: true
post-release:
needs:

View File

@@ -4,7 +4,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:22.04@sha256:ac58ff7fe25edc58bdf0067ca99
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
# Also used as the image in CI jobs so needs all dependencies
####################################################################################################
FROM docker.io/library/golang:1.20.5@sha256:4b1fc02d16fca272e5e6e6adc98396219b43ef663a377eef4a97e881d364393f AS builder
FROM docker.io/library/golang:1.20.6@sha256:8e5a0067e6b387263a01d06b91ef1a983f90e9638564f6e25392fd2695f7ab6c AS builder
RUN echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
@@ -101,7 +101,7 @@ RUN HOST_ARCH=$TARGETARCH NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OP
####################################################################################################
# Argo CD Build stage which performs the actual build of Argo CD binaries
####################################################################################################
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.20.5@sha256:4b1fc02d16fca272e5e6e6adc98396219b43ef663a377eef4a97e881d364393f AS argocd-build
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.20.6@sha256:8e5a0067e6b387263a01d06b91ef1a983f90e9638564f6e25392fd2695f7ab6c AS argocd-build
WORKDIR /go/src/github.com/argoproj/argo-cd

View File

@@ -25,6 +25,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Arctiq Inc.](https://www.arctiq.ca)
1. [ARZ Allgemeines Rechenzentrum GmbH](https://www.arz.at/)
1. [Axual B.V.](https://axual.com)
1. [Back Market](https://www.backmarket.com)
1. [Baloise](https://www.baloise.com)
1. [BCDevExchange DevOps Platform](https://bcdevexchange.org/DevOpsPlatform)
1. [Beat](https://thebeat.co/en/)
@@ -99,6 +100,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [gloat](https://gloat.com/)
1. [GLOBIS](https://globis.com)
1. [Glovo](https://www.glovoapp.com)
1. [GlueOps](https://glueops.dev)
1. [GMETRI](https://gmetri.com/)
1. [Gojek](https://www.gojek.io/)
1. [GoTo](https://www.goto.com/)

View File

@@ -1 +1 @@
2.8.0
2.8.0-rc5

View File

@@ -86,6 +86,7 @@ type ApplicationSetReconciler struct {
ArgoCDNamespace string
ApplicationSetNamespaces []string
EnableProgressiveSyncs bool
SCMRootCAPath string
}
// +kubebuilder:rbac:groups=argoproj.io,resources=applicationsets,verbs=get;list;watch;create;update;patch;delete
@@ -596,6 +597,9 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
appLog := log.WithFields(log.Fields{"app": generatedApp.Name, "appSet": applicationSet.Name})
generatedApp.Namespace = applicationSet.Namespace
// Normalize to avoid fighting with the application controller.
generatedApp.Spec = *argoutil.NormalizeApplicationSpec(&generatedApp.Spec)
found := &argov1alpha1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: generatedApp.Name,

View File

@@ -26,11 +26,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake"
"github.com/argoproj/argo-cd/v2/util/collections"
@@ -372,6 +373,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
Namespace: "namespace",
ResourceVersion: "1",
},
Spec: v1alpha1.ApplicationSpec{Project: "default"},
},
},
},
@@ -899,6 +901,60 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
},
},
},
}, {
name: "Ensure that the app spec is normalized before applying",
appSet: v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: v1alpha1.ApplicationSetSpec{
Template: v1alpha1.ApplicationSetTemplate{
Spec: v1alpha1.ApplicationSpec{
Project: "project",
Source: &v1alpha1.ApplicationSource{
Directory: &v1alpha1.ApplicationSourceDirectory{
Jsonnet: v1alpha1.ApplicationSourceJsonnet{},
},
},
},
},
},
},
desiredApps: []v1alpha1.Application{
{
ObjectMeta: metav1.ObjectMeta{
Name: "app1",
},
Spec: v1alpha1.ApplicationSpec{
Project: "project",
Source: &v1alpha1.ApplicationSource{
Directory: &v1alpha1.ApplicationSourceDirectory{
Jsonnet: v1alpha1.ApplicationSourceJsonnet{},
},
},
},
},
},
expected: []v1alpha1.Application{
{
TypeMeta: metav1.TypeMeta{
Kind: "Application",
APIVersion: "argoproj.io/v1alpha1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "app1",
Namespace: "namespace",
ResourceVersion: "1",
},
Spec: v1alpha1.ApplicationSpec{
Project: "project",
Source: &v1alpha1.ApplicationSource{
// Directory and jsonnet block are removed
},
},
},
},
},
} {
@@ -1230,13 +1286,15 @@ func TestCreateApplications(t *testing.T) {
err = v1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
for _, c := range []struct {
testCases := []struct {
name string
appSet v1alpha1.ApplicationSet
existsApps []v1alpha1.Application
apps []v1alpha1.Application
expected []v1alpha1.Application
}{
{
name: "no existing apps",
appSet: v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
@@ -1262,10 +1320,14 @@ func TestCreateApplications(t *testing.T) {
Namespace: "namespace",
ResourceVersion: "1",
},
Spec: v1alpha1.ApplicationSpec{
Project: "default",
},
},
},
},
{
name: "existing apps",
appSet: v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
@@ -1323,6 +1385,7 @@ func TestCreateApplications(t *testing.T) {
},
},
{
name: "existing apps with different project",
appSet: v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
@@ -1379,39 +1442,42 @@ func TestCreateApplications(t *testing.T) {
},
},
},
} {
initObjs := []crtclient.Object{&c.appSet}
for _, a := range c.existsApps {
err = controllerutil.SetControllerReference(&c.appSet, &a, scheme)
assert.Nil(t, err)
initObjs = append(initObjs, &a)
}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(initObjs...).Build()
r := ApplicationSetReconciler{
Client: client,
Scheme: scheme,
Recorder: record.NewFakeRecorder(len(initObjs) + len(c.expected)),
}
err = r.createInCluster(context.TODO(), c.appSet, c.apps)
assert.Nil(t, err)
for _, obj := range c.expected {
got := &v1alpha1.Application{}
_ = client.Get(context.Background(), crtclient.ObjectKey{
Namespace: obj.Namespace,
Name: obj.Name,
}, got)
err = controllerutil.SetControllerReference(&c.appSet, &obj, r.Scheme)
assert.Nil(t, err)
assert.Equal(t, obj, *got)
}
}
for _, c := range testCases {
t.Run(c.name, func(t *testing.T) {
initObjs := []crtclient.Object{&c.appSet}
for _, a := range c.existsApps {
err = controllerutil.SetControllerReference(&c.appSet, &a, scheme)
assert.Nil(t, err)
initObjs = append(initObjs, &a)
}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(initObjs...).Build()
r := ApplicationSetReconciler{
Client: client,
Scheme: scheme,
Recorder: record.NewFakeRecorder(len(initObjs) + len(c.expected)),
}
err = r.createInCluster(context.TODO(), c.appSet, c.apps)
assert.Nil(t, err)
for _, obj := range c.expected {
got := &v1alpha1.Application{}
_ = client.Get(context.Background(), crtclient.ObjectKey{
Namespace: obj.Namespace,
Name: obj.Name,
}, got)
err = controllerutil.SetControllerReference(&c.appSet, &obj, r.Scheme)
assert.Nil(t, err)
assert.Equal(t, obj, *got)
}
})
}
}
func TestDeleteInCluster(t *testing.T) {

View File

@@ -5,9 +5,6 @@ import (
"testing"
"time"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -17,6 +14,10 @@ import (
kubefake "k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
func TestRequeueAfter(t *testing.T) {
@@ -59,9 +60,9 @@ func TestRequeueAfter(t *testing.T) {
"List": generators.NewListGenerator(),
"Clusters": generators.NewClusterGenerator(k8sClient, ctx, appClientset, "argocd"),
"Git": generators.NewGitGenerator(mockServer),
"SCMProvider": generators.NewSCMProviderGenerator(fake.NewClientBuilder().WithObjects(&corev1.Secret{}).Build(), generators.SCMAuthProviders{}),
"SCMProvider": generators.NewSCMProviderGenerator(fake.NewClientBuilder().WithObjects(&corev1.Secret{}).Build(), generators.SCMAuthProviders{}, ""),
"ClusterDecisionResource": generators.NewDuckTypeGenerator(ctx, fakeDynClient, appClientset, "argocd"),
"PullRequest": generators.NewPullRequestGenerator(k8sClient, generators.SCMAuthProviders{}),
"PullRequest": generators.NewPullRequestGenerator(k8sClient, generators.SCMAuthProviders{}, ""),
}
nestedGenerators := map[string]generators.Generator{

View File

@@ -61,8 +61,7 @@ func (g *ClusterGenerator) GetTemplate(appSetGenerator *argoappsetv1alpha1.Appli
return &appSetGenerator.Clusters.Template
}
func (g *ClusterGenerator) GenerateParams(
appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator, appSet *argoappsetv1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator, appSet *argoappsetv1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError

View File

@@ -3,6 +3,7 @@ package generators
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
@@ -15,8 +16,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"testing"
)
const resourceApiVersion = "mallard.io/v1"

View File

@@ -4,9 +4,10 @@ import (
"fmt"
"reflect"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/jeremywohl/flatten"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"k8s.io/apimachinery/pkg/labels"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"

View File

@@ -4,13 +4,14 @@ import (
"context"
"testing"
"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/mock"

View File

@@ -5,8 +5,9 @@ import (
"fmt"
"time"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"sigs.k8s.io/yaml"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
var _ Generator = (*ListGenerator)(nil)

View File

@@ -25,12 +25,14 @@ type PullRequestGenerator struct {
client client.Client
selectServiceProviderFunc func(context.Context, *argoprojiov1alpha1.PullRequestGenerator, *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error)
auth SCMAuthProviders
scmRootCAPath string
}
func NewPullRequestGenerator(client client.Client, auth SCMAuthProviders) Generator {
func NewPullRequestGenerator(client client.Client, auth SCMAuthProviders, scmRootCAPath string) Generator {
g := &PullRequestGenerator{
client: client,
auth: auth,
client: client,
auth: auth,
scmRootCAPath: scmRootCAPath,
}
g.selectServiceProviderFunc = g.selectServiceProvider
return g
@@ -126,7 +128,7 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
if err != nil {
return nil, fmt.Errorf("error fetching Secret token: %v", err)
}
return pullrequest.NewGitLabService(ctx, token, providerConfig.API, providerConfig.Project, providerConfig.Labels, providerConfig.PullRequestState)
return pullrequest.NewGitLabService(ctx, token, providerConfig.API, providerConfig.Project, providerConfig.Labels, providerConfig.PullRequestState, g.scmRootCAPath, providerConfig.Insecure)
}
if generatorConfig.Gitea != nil {
providerConfig := generatorConfig.Gitea

View File

@@ -26,16 +26,18 @@ type SCMProviderGenerator struct {
// Testing hooks.
overrideProvider scm_provider.SCMProviderService
SCMAuthProviders
scmRootCAPath string
}
type SCMAuthProviders struct {
GitHubApps github_app_auth.Credentials
}
func NewSCMProviderGenerator(client client.Client, providers SCMAuthProviders) Generator {
func NewSCMProviderGenerator(client client.Client, providers SCMAuthProviders, scmRootCAPath string) Generator {
return &SCMProviderGenerator{
client: client,
SCMAuthProviders: providers,
scmRootCAPath: scmRootCAPath,
}
}
@@ -85,7 +87,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
if err != nil {
return nil, fmt.Errorf("error fetching Gitlab token: %v", err)
}
provider, err = scm_provider.NewGitlabProvider(ctx, providerConfig.Gitlab.Group, token, providerConfig.Gitlab.API, providerConfig.Gitlab.AllBranches, providerConfig.Gitlab.IncludeSubgroups)
provider, err = scm_provider.NewGitlabProvider(ctx, providerConfig.Gitlab.Group, token, providerConfig.Gitlab.API, providerConfig.Gitlab.AllBranches, providerConfig.Gitlab.IncludeSubgroups, providerConfig.Gitlab.Insecure, g.scmRootCAPath)
if err != nil {
return nil, fmt.Errorf("error initializing Gitlab service: %v", err)
}

View File

@@ -3,8 +3,11 @@ package pull_request
import (
"context"
"fmt"
"net/http"
"os"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/hashicorp/go-retryablehttp"
gitlab "github.com/xanzy/go-gitlab"
)
@@ -17,7 +20,7 @@ type GitLabService struct {
var _ PullRequestService = (*GitLabService)(nil)
func NewGitLabService(ctx context.Context, token, url, project string, labels []string, pullRequestState string) (PullRequestService, error) {
func NewGitLabService(ctx context.Context, token, url, project string, labels []string, pullRequestState string, scmRootCAPath string, insecure bool) (PullRequestService, error) {
var clientOptionFns []gitlab.ClientOptionFunc
// Set a custom Gitlab base URL if one is provided
@@ -29,6 +32,14 @@ func NewGitLabService(ctx context.Context, token, url, project string, labels []
token = os.Getenv("GITLAB_TOKEN")
}
tr := &http.Transport{
TLSClientConfig: utils.GetTlsConfig(scmRootCAPath, insecure),
}
retryClient := retryablehttp.NewClient()
retryClient.HTTPClient.Transport = tr
clientOptionFns = append(clientOptionFns, gitlab.WithHTTPClient(retryClient.HTTPClient))
client, err := gitlab.NewClient(token, clientOptionFns...)
if err != nil {
return nil, fmt.Errorf("error creating Gitlab client: %v", err)

View File

@@ -34,7 +34,7 @@ func TestGitLabServiceCustomBaseURL(t *testing.T) {
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", nil, "")
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", nil, "", "", false)
assert.NoError(t, err)
_, err = svc.List(context.Background())
@@ -53,7 +53,7 @@ func TestGitLabServiceToken(t *testing.T) {
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "token-123", server.URL, "278964", nil, "")
svc, err := NewGitLabService(context.Background(), "token-123", server.URL, "278964", nil, "", "", false)
assert.NoError(t, err)
_, err = svc.List(context.Background())
@@ -72,7 +72,7 @@ func TestList(t *testing.T) {
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "")
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "", "", false)
assert.NoError(t, err)
prs, err := svc.List(context.Background())
@@ -96,7 +96,7 @@ func TestListWithLabels(t *testing.T) {
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{"feature", "ready"}, "")
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{"feature", "ready"}, "", "", false)
assert.NoError(t, err)
_, err = svc.List(context.Background())
@@ -115,7 +115,7 @@ func TestListWithState(t *testing.T) {
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "opened")
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "opened", "", false)
assert.NoError(t, err)
_, err = svc.List(context.Background())

View File

@@ -7,6 +7,8 @@ import (
"os"
pathpkg "path"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/hashicorp/go-retryablehttp"
"github.com/xanzy/go-gitlab"
)
@@ -19,21 +21,28 @@ type GitlabProvider struct {
var _ SCMProviderService = &GitlabProvider{}
func NewGitlabProvider(ctx context.Context, organization string, token string, url string, allBranches, includeSubgroups bool) (*GitlabProvider, error) {
func NewGitlabProvider(ctx context.Context, organization string, token string, url string, allBranches, includeSubgroups, insecure bool, scmRootCAPath string) (*GitlabProvider, error) {
// Undocumented environment variable to set a default token, to be used in testing to dodge anonymous rate limits.
if token == "" {
token = os.Getenv("GITLAB_TOKEN")
}
var client *gitlab.Client
tr := &http.Transport{
TLSClientConfig: utils.GetTlsConfig(scmRootCAPath, insecure),
}
retryClient := retryablehttp.NewClient()
retryClient.HTTPClient.Transport = tr
if url == "" {
var err error
client, err = gitlab.NewClient(token)
client, err = gitlab.NewClient(token, gitlab.WithHTTPClient(retryClient.HTTPClient))
if err != nil {
return nil, err
}
} else {
var err error
client, err = gitlab.NewClient(token, gitlab.WithBaseURL(url))
client, err = gitlab.NewClient(token, gitlab.WithBaseURL(url), gitlab.WithHTTPClient(retryClient.HTTPClient))
if err != nil {
return nil, err
}

View File

@@ -286,10 +286,10 @@ func gitlabMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {
}
func TestGitlabListRepos(t *testing.T) {
cases := []struct {
name, proto, url string
hasError, allBranches, includeSubgroups bool
branches []string
filters []v1alpha1.SCMProviderGeneratorFilter
name, proto, url string
hasError, allBranches, includeSubgroups, insecure bool
branches []string
filters []v1alpha1.SCMProviderGeneratorFilter
}{
{
name: "blank protocol",
@@ -323,7 +323,7 @@ func TestGitlabListRepos(t *testing.T) {
}))
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
provider, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, c.allBranches, c.includeSubgroups)
provider, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, c.allBranches, c.includeSubgroups, c.insecure, "")
rawRepos, err := ListRepos(context.Background(), provider, c.filters, c.proto)
if c.hasError {
assert.NotNil(t, err)
@@ -352,7 +352,7 @@ func TestGitlabHasPath(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gitlabMockHandler(t)(w, r)
}))
host, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, false, true)
host, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, false, true, false, "")
repo := &Repository{
Organization: "test-argocd-proton",
Repository: "argocd",
@@ -398,7 +398,7 @@ func TestGitlabGetBranches(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gitlabMockHandler(t)(w, r)
}))
host, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, false, true)
host, _ := NewGitlabProvider(context.Background(), "test-argocd-proton", "", ts.URL, false, true, false, "")
repo := &Repository{
RepositoryId: 27084533,

View File

@@ -2,9 +2,12 @@ package utils
import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io"
"os"
"reflect"
"regexp"
"sort"
@@ -406,3 +409,38 @@ func SanitizeName(name string) string {
return strings.Trim(name, "-.")
}
func getTlsConfigWithCACert(scmRootCAPath string) *tls.Config {
tlsConfig := &tls.Config{}
if scmRootCAPath != "" {
_, err := os.Stat(scmRootCAPath)
if os.IsNotExist(err) {
log.Errorf("scmRootCAPath '%s' specified does not exist: %s", scmRootCAPath, err)
return tlsConfig
}
rootCA, err := os.ReadFile(scmRootCAPath)
if err != nil {
log.Errorf("error reading certificate from file '%s', proceeding without custom rootCA : %s", scmRootCAPath, err)
return tlsConfig
}
certPool := x509.NewCertPool()
ok := certPool.AppendCertsFromPEM([]byte(rootCA))
if !ok {
log.Errorf("failed to append certificates from PEM: proceeding without custom rootCA")
} else {
tlsConfig.RootCAs = certPool
}
}
return tlsConfig
}
func GetTlsConfig(scmRootCAPath string, insecure bool) *tls.Config {
tlsConfig := getTlsConfigWithCACert(scmRootCAPath)
if insecure {
tlsConfig.InsecureSkipVerify = true
}
return tlsConfig
}

View File

@@ -1,6 +1,9 @@
package utils
import (
"crypto/x509"
"os"
"path"
"testing"
"time"
@@ -1065,3 +1068,92 @@ func TestNormalizeBitbucketBasePath(t *testing.T) {
assert.Equal(t, c.expectedBasePath, result, c.testName)
}
}
func TestGetTLSConfig(t *testing.T) {
// certParsed, err := tls.X509KeyPair(test.Cert, test.PrivateKey)
// require.NoError(t, err)
temppath := t.TempDir()
cert := `
-----BEGIN CERTIFICATE-----
MIIFvTCCA6WgAwIBAgIUGrTmW3qc39zqnE08e3qNDhUkeWswDQYJKoZIhvcNAQEL
BQAwbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAklMMRAwDgYDVQQHDAdDaGljYWdv
MRQwEgYDVQQKDAtDYXBvbmUsIEluYzEQMA4GA1UECwwHU3BlY09wczEYMBYGA1UE
AwwPZm9vLmV4YW1wbGUuY29tMB4XDTE5MDcwODEzNTUwNVoXDTIwMDcwNzEzNTUw
NVowbjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAklMMRAwDgYDVQQHDAdDaGljYWdv
MRQwEgYDVQQKDAtDYXBvbmUsIEluYzEQMA4GA1UECwwHU3BlY09wczEYMBYGA1UE
AwwPZm9vLmV4YW1wbGUuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
AgEA3csSO13w7qQXKeSLNcpeuAe6wAjXYbRkRl6ariqzTEDcFTKmy2QiXJTKoEGn
bvwxq0T91var7rxY88SGL/qi8Zmo0tVSR0XvKSKcghFIkQOTyDmVgMPZGCvixt4q
gQ7hUVSk4KkFmtcqBVuvnzI1d/DKfZAGKdmGcfRpuAsnVhac3swP0w4Tl1BFrK9U
vuIkz4KwXG77s5oB8rMUnyuLasLsGNpvpvXhkcQRhp6vpcCO2bS7kOTTelAPIucw
P37qkOEdZdiWCLrr57dmhg6tmcVlmBMg6JtmfLxn2HQd9ZrCKlkWxMk5NYs6CAW5
kgbDZUWQTAsnHeoJKbcgtPkIbxDRxNpPukFMtbA4VEWv1EkODXy9FyEKDOI/PV6K
/80oLkgCIhCkP2mvwSFheU0RHTuZ0o0vVolP5TEOq5iufnDN4wrxqb12o//XLRc0
RiLqGVVxhFdyKCjVxcLfII9AAp5Tse4PMh6bf6jDfB3OMvGkhMbJWhKXdR2NUTl0
esKawMPRXIn5g3oBdNm8kyRsTTnvB567pU8uNSmA8j3jxfGCPynI8JdiwKQuW/+P
WgLIflgxqAfG85dVVOsFmF9o5o24dDslvv9yHnHH102c6ijPCg1EobqlyFzqqxOD
Wf2OPjIkzoTH+O27VRugnY/maIU1nshNO7ViRX5zIxEUtNMCAwEAAaNTMFEwHQYD
VR0OBBYEFNY4gDLgPBidogkmpO8nq5yAq5g+MB8GA1UdIwQYMBaAFNY4gDLgPBid
ogkmpO8nq5yAq5g+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB
AJ0WGioNtGNg3m6ywpmxNThorQD5ZvDMlmZlDVk78E2wfNyMhwbVhKhlAnONv0wv
kmsGjibY75nRZ+EK9PxSJ644841fryQXQ+bli5fhr7DW3uTKwaRsnzETJXRJuljq
6+c6Zyg1/mqwnyx7YvPgVh3w496DYx/jm6Fm1IEq3BzOmn6H/gGPq3gbURzEqI3h
P+kC2vJa8RZWrpa05Xk/Q1QUkErDX9vJghb9z3+GgirISZQzqWRghII/znv3NOE6
zoIgaaWNFn8KPeBVpUoboH+IhpgibsnbTbI0G7AMtFq6qm3kn/4DZ2N2tuh1G2tT
zR2Fh7hJbU7CrqxANrgnIoHG/nLSvzE24ckLb0Vj69uGQlwnZkn9fz6F7KytU+Az
NoB2rjufaB0GQi1azdboMvdGSOxhSCAR8otWT5yDrywCqVnEvjw0oxKmuRduNe2/
6AcG6TtK2/K+LHuhymiAwZM2qE6VD2odvb+tCzDkZOIeoIz/JcVlNpXE9FuVl250
9NWvugeghq7tUv81iJ8ninBefJ4lUfxAehTPQqX+zXcfxgjvMRCi/ig73nLyhmjx
r2AaraPFgrprnxUibP4L7jxdr+iiw5bWN9/B81PodrS7n5TNtnfnpZD6X6rThqOP
xO7Tr5lAo74vNUkF2EHNaI28/RGnJPm2TIxZqy4rNH6L
-----END CERTIFICATE-----
`
rootCAPath := path.Join(temppath, "foo.example.com")
err := os.WriteFile(rootCAPath, []byte(cert), 0666)
if err != nil {
panic(err)
}
certPool := x509.NewCertPool()
ok := certPool.AppendCertsFromPEM([]byte(cert))
assert.True(t, ok)
testCases := []struct {
name string
scmRootCAPath string
insecure bool
validateCertInTlsConfig bool
}{
{
name: "Insecure mode configured, SCM Root CA Path not set",
scmRootCAPath: "",
insecure: true,
validateCertInTlsConfig: false,
},
{
name: "SCM Root CA Path set, Insecure mode set to false",
scmRootCAPath: rootCAPath,
insecure: false,
validateCertInTlsConfig: true,
},
{
name: "SCM Root CA Path set, Insecure mode set to true",
scmRootCAPath: rootCAPath,
insecure: true,
validateCertInTlsConfig: true,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
tlsConfig := GetTlsConfig(testCase.scmRootCAPath, testCase.insecure)
assert.Equal(t, testCase.insecure, tlsConfig.InsecureSkipVerify)
if testCase.validateCertInTlsConfig {
assert.NotNil(t, tlsConfig)
assert.True(t, tlsConfig.RootCAs.Equal(certPool))
}
})
}
}

View File

@@ -20,12 +20,13 @@ import (
kubefake "k8s.io/client-go/kubernetes/fake"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argosettings "github.com/argoproj/argo-cd/v2/util/settings"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)
type generatorMock struct {

View File

@@ -401,6 +401,11 @@
"type": "boolean",
"name": "validate",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -462,6 +467,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -523,6 +533,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -649,6 +664,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -737,6 +757,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -773,6 +798,11 @@
"type": "string",
"name": "namespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -885,6 +915,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -935,6 +970,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -971,6 +1011,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1084,6 +1129,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1154,6 +1204,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1226,6 +1281,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1295,6 +1355,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1356,6 +1421,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1423,6 +1493,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1484,6 +1559,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1529,6 +1609,11 @@
"description": "the application's namespace.",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1574,6 +1659,11 @@
"description": "the application's namespace.",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1662,6 +1752,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -1737,6 +1832,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -3833,6 +3933,11 @@
"type": "string",
"name": "appNamespace",
"in": "query"
},
{
"type": "string",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -3998,6 +4103,9 @@
},
"name": {
"type": "string"
},
"project": {
"type": "string"
}
}
},
@@ -4027,6 +4135,9 @@
},
"patchType": {
"type": "string"
},
"project": {
"type": "string"
}
}
},
@@ -4057,6 +4168,9 @@
"name": {
"type": "string"
},
"project": {
"type": "string"
},
"prune": {
"type": "boolean"
}
@@ -4087,6 +4201,9 @@
"name": {
"type": "string"
},
"project": {
"type": "string"
},
"prune": {
"type": "boolean"
},
@@ -6767,6 +6884,13 @@
"destination": {
"$ref": "#/definitions/v1alpha1ApplicationDestination"
},
"ignoreDifferences": {
"type": "array",
"title": "IgnoreDifferences is a reference to the application's ignored differences used for comparison",
"items": {
"$ref": "#/definitions/v1alpha1ResourceIgnoreDifferences"
}
},
"source": {
"$ref": "#/definitions/v1alpha1ApplicationSource"
},
@@ -7588,6 +7712,10 @@
"description": "The GitLab API URL to talk to. If blank, uses https://gitlab.com/.",
"type": "string"
},
"insecure": {
"type": "boolean",
"title": "Skips validating the SCM provider's TLS certificate - useful for self-signed certificates.; default: false"
},
"labels": {
"type": "array",
"title": "Labels is used to filter the MRs that you want to target",
@@ -8558,6 +8686,10 @@
"type": "boolean",
"title": "Recurse through subgroups (true) or scan only the base group (false). Defaults to \"false\""
},
"insecure": {
"type": "boolean",
"title": "Skips validating the SCM provider's TLS certificate - useful for self-signed certificates.; default: false"
},
"tokenRef": {
"$ref": "#/definitions/v1alpha1SecretRef"
}

View File

@@ -64,6 +64,7 @@ func NewCommand() *cobra.Command {
repoServerStrictTLS bool
repoServerTimeoutSeconds int
maxConcurrentReconciliations int
scmRootCAPath string
)
scheme := runtime.NewScheme()
_ = clientgoscheme.AddToScheme(scheme)
@@ -158,9 +159,9 @@ func NewCommand() *cobra.Command {
"List": generators.NewListGenerator(),
"Clusters": generators.NewClusterGenerator(mgr.GetClient(), ctx, k8sClient, namespace),
"Git": generators.NewGitGenerator(argoCDService),
"SCMProvider": generators.NewSCMProviderGenerator(mgr.GetClient(), scmAuth),
"SCMProvider": generators.NewSCMProviderGenerator(mgr.GetClient(), scmAuth, scmRootCAPath),
"ClusterDecisionResource": generators.NewDuckTypeGenerator(ctx, dynamicClient, k8sClient, namespace),
"PullRequest": generators.NewPullRequestGenerator(mgr.GetClient(), scmAuth),
"PullRequest": generators.NewPullRequestGenerator(mgr.GetClient(), scmAuth, scmRootCAPath),
"Plugin": generators.NewPluginGenerator(mgr.GetClient(), ctx, k8sClient, namespace),
}
@@ -211,6 +212,7 @@ func NewCommand() *cobra.Command {
ArgoCDNamespace: namespace,
ApplicationSetNamespaces: applicationSetNamespaces,
EnableProgressiveSyncs: enableProgressiveSyncs,
SCMRootCAPath: scmRootCAPath,
}).SetupWithManager(mgr, enableProgressiveSyncs, maxConcurrentReconciliations); err != nil {
log.Error(err, "unable to create controller", "controller", "ApplicationSet")
os.Exit(1)
@@ -246,6 +248,7 @@ func NewCommand() *cobra.Command {
command.Flags().BoolVar(&repoServerStrictTLS, "repo-server-strict-tls", env.ParseBoolFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_STRICT_TLS", false), "Whether to use strict validation of the TLS cert presented by the repo server")
command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS", 60, 0, math.MaxInt64), "Repo server RPC call timeout seconds.")
command.Flags().IntVar(&maxConcurrentReconciliations, "concurrent-reconciliations", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_CONCURRENT_RECONCILIATIONS", 10, 1, 100), "Max concurrent reconciliations limit for the controller")
command.Flags().StringVar(&scmRootCAPath, "scm-root-ca-path", env.StringFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH", ""), "Provide Root CA Path for self-signed TLS Certificates")
return &command
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"os"
"strings"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -373,6 +374,9 @@ func resolveRBACResourceName(name string) string {
// isValidRBACAction checks whether a given action is a valid RBAC action
func isValidRBACAction(action string) bool {
if strings.HasPrefix(action, rbacpolicy.ActionAction+"/") {
return true
}
_, ok := validRBACActions[action]
return ok
}

View File

@@ -27,6 +27,11 @@ func Test_isValidRBACAction(t *testing.T) {
})
}
func Test_isValidRBACAction_ActionAction(t *testing.T) {
ok := isValidRBACAction("action/apps/Deployment/restart")
assert.True(t, ok)
}
func Test_isValidRBACResource(t *testing.T) {
for k := range validRBACResources {
t.Run(k, func(t *testing.T) {

View File

@@ -1027,7 +1027,7 @@ func findandPrintDiff(ctx context.Context, app *argoappv1.Application, proj *arg
items := make([]objKeyLiveTarget, 0)
if diffOptions.local != "" {
localObjs := groupObjsByKey(getLocalObjects(ctx, app, proj, diffOptions.local, diffOptions.localRepoRoot, argoSettings.AppLabelKey, diffOptions.cluster.Info.ServerVersion, diffOptions.cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.TrackingMethod), liveObjs, app.Spec.Destination.Namespace)
items = groupObjsForDiff(resources, localObjs, items, argoSettings, app.InstanceName(argoSettings.ControllerNamespace))
items = groupObjsForDiff(resources, localObjs, items, argoSettings, app.InstanceName(argoSettings.ControllerNamespace), app.Spec.Destination.Namespace)
} else if diffOptions.revision != "" {
var unstructureds []*unstructured.Unstructured
for _, mfst := range diffOptions.res.Manifests {
@@ -1036,7 +1036,7 @@ func findandPrintDiff(ctx context.Context, app *argoappv1.Application, proj *arg
unstructureds = append(unstructureds, obj)
}
groupedObjs := groupObjsByKey(unstructureds, liveObjs, app.Spec.Destination.Namespace)
items = groupObjsForDiff(resources, groupedObjs, items, argoSettings, app.InstanceName(argoSettings.ControllerNamespace))
items = groupObjsForDiff(resources, groupedObjs, items, argoSettings, app.InstanceName(argoSettings.ControllerNamespace), app.Spec.Destination.Namespace)
} else if diffOptions.serversideRes != nil {
var unstructureds []*unstructured.Unstructured
for _, mfst := range diffOptions.serversideRes.Manifests {
@@ -1045,7 +1045,7 @@ func findandPrintDiff(ctx context.Context, app *argoappv1.Application, proj *arg
unstructureds = append(unstructureds, obj)
}
groupedObjs := groupObjsByKey(unstructureds, liveObjs, app.Spec.Destination.Namespace)
items = groupObjsForDiff(resources, groupedObjs, items, argoSettings, app.InstanceName(argoSettings.ControllerNamespace))
items = groupObjsForDiff(resources, groupedObjs, items, argoSettings, app.InstanceName(argoSettings.ControllerNamespace), app.Spec.Destination.Namespace)
} else {
for i := range resources.Items {
res := resources.Items[i]
@@ -1105,7 +1105,7 @@ func findandPrintDiff(ctx context.Context, app *argoappv1.Application, proj *arg
return foundDiffs
}
func groupObjsForDiff(resources *application.ManagedResourcesResponse, objs map[kube.ResourceKey]*unstructured.Unstructured, items []objKeyLiveTarget, argoSettings *settings.Settings, appName string) []objKeyLiveTarget {
func groupObjsForDiff(resources *application.ManagedResourcesResponse, objs map[kube.ResourceKey]*unstructured.Unstructured, items []objKeyLiveTarget, argoSettings *settings.Settings, appName, namespace string) []objKeyLiveTarget {
resourceTracking := argo.NewResourceTracking()
for _, res := range resources.Items {
var live = &unstructured.Unstructured{}
@@ -1120,7 +1120,7 @@ func groupObjsForDiff(resources *application.ManagedResourcesResponse, objs map[
}
if local, ok := objs[key]; ok || live != nil {
if local != nil && !kube.IsCRD(local) {
err = resourceTracking.SetAppInstance(local, argoSettings.AppLabelKey, appName, "", argoappv1.TrackingMethod(argoSettings.GetTrackingMethod()))
err = resourceTracking.SetAppInstance(local, argoSettings.AppLabelKey, appName, namespace, argoappv1.TrackingMethod(argoSettings.GetTrackingMethod()))
errors.CheckError(err)
}
@@ -1661,8 +1661,15 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
errors.CheckError(err)
if app.Spec.HasMultipleSources() {
log.Fatal("argocd cli does not work on multi-source app")
return
if revision != "" {
log.Fatal("argocd cli does not work on multi-source app with --revision flag")
return
}
if local != "" {
log.Fatal("argocd cli does not work on multi-source app with --local flag")
return
}
}
// filters out only those resources that needs to be synced

View File

@@ -364,12 +364,14 @@ func (ctrl *ApplicationController) handleObjectUpdated(managedByApp map[string]b
namespace = "(cluster-scoped)"
}
log.WithFields(log.Fields{
"application": appKey,
"level": level,
"namespace": namespace,
"name": ref.Name,
"api-version": ref.APIVersion,
"kind": ref.Kind,
"application": appKey,
"level": level,
"namespace": namespace,
"name": ref.Name,
"api-version": ref.APIVersion,
"kind": ref.Kind,
"server": app.Spec.Destination.Server,
"cluster-name": app.Spec.Destination.Name,
}).Debug("Requesting app refresh caused by object update")
ctrl.requestAppRefresh(app.QualifiedName(), &level, nil)
@@ -1533,6 +1535,8 @@ func (ctrl *ApplicationController) needRefreshAppStatus(app *appv1.Application,
reason = "spec.destination differs"
} else if app.HasChangedManagedNamespaceMetadata() {
reason = "spec.syncPolicy.managedNamespaceMetadata differs"
} else if !app.Spec.IgnoreDifferences.Equals(app.Status.Sync.ComparedTo.IgnoreDifferences) {
reason = "spec.ignoreDifferences differs"
} else if requested, level := ctrl.isRefreshRequested(app.QualifiedName()); requested {
compareWith = level
reason = "controller refresh requested"

View File

@@ -943,7 +943,6 @@ func TestNeedRefreshAppStatus(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
ctrl := newFakeController(&fakeData{apps: []runtime.Object{}})
app := tc.app
now := metav1.Now()
app.Status.ReconciledAt = &now
@@ -951,7 +950,8 @@ func TestNeedRefreshAppStatus(t *testing.T) {
app.Status.Sync = v1alpha1.SyncStatus{
Status: v1alpha1.SyncStatusCodeSynced,
ComparedTo: v1alpha1.ComparedTo{
Destination: app.Spec.Destination,
Destination: app.Spec.Destination,
IgnoreDifferences: app.Spec.IgnoreDifferences,
},
}
@@ -961,44 +961,67 @@ func TestNeedRefreshAppStatus(t *testing.T) {
app.Status.Sync.ComparedTo.Source = app.Spec.GetSource()
}
// no need to refresh just reconciled application
needRefresh, _, _ := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.False(t, needRefresh)
ctrl := newFakeController(&fakeData{apps: []runtime.Object{}})
// refresh app using the 'deepest' requested comparison level
ctrl.requestAppRefresh(app.Name, CompareWithRecent.Pointer(), nil)
ctrl.requestAppRefresh(app.Name, ComparisonWithNothing.Pointer(), nil)
t.Run("no need to refresh just reconciled application", func(t *testing.T) {
needRefresh, _, _ := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.False(t, needRefresh)
})
needRefresh, refreshType, compareWith := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, v1alpha1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithRecent, compareWith)
t.Run("requested refresh is respected", func(t *testing.T) {
needRefresh, _, _ := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.False(t, needRefresh)
// refresh application which status is not reconciled using latest commit
app.Status.Sync = v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeUnknown}
// use a one-off controller so other tests don't have a manual refresh request
ctrl := newFakeController(&fakeData{apps: []runtime.Object{}})
needRefresh, refreshType, compareWith = ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, v1alpha1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithLatestForceResolve, compareWith)
t.Run("refresh app using the 'latest' level if comparison expired", func(t *testing.T) {
app := app.DeepCopy()
// refresh app using the 'deepest' requested comparison level
ctrl.requestAppRefresh(app.Name, CompareWithRecent.Pointer(), nil)
reconciledAt := metav1.NewTime(time.Now().UTC().Add(-1 * time.Hour))
app.Status.ReconciledAt = &reconciledAt
needRefresh, refreshType, compareWith = ctrl.needRefreshAppStatus(app, 1*time.Minute, 2*time.Hour)
ctrl.requestAppRefresh(app.Name, ComparisonWithNothing.Pointer(), nil)
needRefresh, refreshType, compareWith := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, v1alpha1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithRecent, compareWith)
})
t.Run("refresh application which status is not reconciled using latest commit", func(t *testing.T) {
app := app.DeepCopy()
needRefresh, _, _ := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.False(t, needRefresh)
app.Status.Sync = v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeUnknown}
needRefresh, refreshType, compareWith := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, v1alpha1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithLatestForceResolve, compareWith)
})
t.Run("refresh app using the 'latest' level if comparison expired", func(t *testing.T) {
app := app.DeepCopy()
// use a one-off controller so other tests don't have a manual refresh request
ctrl := newFakeController(&fakeData{apps: []runtime.Object{}})
needRefresh, _, _ := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.False(t, needRefresh)
ctrl.requestAppRefresh(app.Name, CompareWithRecent.Pointer(), nil)
reconciledAt := metav1.NewTime(time.Now().UTC().Add(-1 * time.Hour))
app.Status.ReconciledAt = &reconciledAt
needRefresh, refreshType, compareWith := ctrl.needRefreshAppStatus(app, 1*time.Minute, 2*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, v1alpha1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithLatest, compareWith)
})
t.Run("refresh app using the 'latest' level if comparison expired for hard refresh", func(t *testing.T) {
app := app.DeepCopy()
app.Status.Sync = v1alpha1.SyncStatus{
Status: v1alpha1.SyncStatusCodeSynced,
ComparedTo: v1alpha1.ComparedTo{
Destination: app.Spec.Destination,
Destination: app.Spec.Destination,
IgnoreDifferences: app.Spec.IgnoreDifferences,
},
}
if app.Spec.HasMultipleSources() {
@@ -1006,10 +1029,16 @@ func TestNeedRefreshAppStatus(t *testing.T) {
} else {
app.Status.Sync.ComparedTo.Source = app.Spec.GetSource()
}
// use a one-off controller so other tests don't have a manual refresh request
ctrl := newFakeController(&fakeData{apps: []runtime.Object{}})
needRefresh, _, _ := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.False(t, needRefresh)
ctrl.requestAppRefresh(app.Name, CompareWithRecent.Pointer(), nil)
reconciledAt := metav1.NewTime(time.Now().UTC().Add(-1 * time.Hour))
app.Status.ReconciledAt = &reconciledAt
needRefresh, refreshType, compareWith = ctrl.needRefreshAppStatus(app, 2*time.Hour, 1*time.Minute)
needRefresh, refreshType, compareWith := ctrl.needRefreshAppStatus(app, 2*time.Hour, 1*time.Minute)
assert.True(t, needRefresh)
assert.Equal(t, v1alpha1.RefreshTypeHard, refreshType)
assert.Equal(t, CompareWithLatest, compareWith)
@@ -1017,12 +1046,14 @@ func TestNeedRefreshAppStatus(t *testing.T) {
t.Run("execute hard refresh if app has refresh annotation", func(t *testing.T) {
app := app.DeepCopy()
needRefresh, _, _ := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.False(t, needRefresh)
reconciledAt := metav1.NewTime(time.Now().UTC().Add(-1 * time.Hour))
app.Status.ReconciledAt = &reconciledAt
app.Annotations = map[string]string{
v1alpha1.AnnotationKeyRefresh: string(v1alpha1.RefreshTypeHard),
}
needRefresh, refreshType, compareWith = ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
needRefresh, refreshType, compareWith := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, v1alpha1.RefreshTypeHard, refreshType)
assert.Equal(t, CompareWithLatestForceResolve, compareWith)
@@ -1030,7 +1061,8 @@ func TestNeedRefreshAppStatus(t *testing.T) {
t.Run("ensure that CompareWithLatest level is used if application source has changed", func(t *testing.T) {
app := app.DeepCopy()
ctrl.requestAppRefresh(app.Name, ComparisonWithNothing.Pointer(), nil)
needRefresh, _, _ := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.False(t, needRefresh)
// sample app source change
if app.Spec.HasMultipleSources() {
app.Spec.Sources[0].Helm = &v1alpha1.ApplicationSourceHelm{
@@ -1048,11 +1080,32 @@ func TestNeedRefreshAppStatus(t *testing.T) {
}
}
needRefresh, refreshType, compareWith = ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
needRefresh, refreshType, compareWith := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, v1alpha1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithLatestForceResolve, compareWith)
})
t.Run("ensure that CompareWithLatest level is used if ignored differences change", func(t *testing.T) {
app := app.DeepCopy()
needRefresh, _, _ := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.False(t, needRefresh)
app.Spec.IgnoreDifferences = []v1alpha1.ResourceIgnoreDifferences{
{
Group: "apps",
Kind: "Deployment",
JSONPointers: []string{
"/spec/template/spec/containers/0/image",
},
},
}
needRefresh, refreshType, compareWith := ctrl.needRefreshAppStatus(app, 1*time.Hour, 2*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, v1alpha1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithLatest, compareWith)
})
})
}
}
@@ -1163,7 +1216,7 @@ func TestUpdateReconciledAt(t *testing.T) {
app := newFakeApp()
reconciledAt := metav1.NewTime(time.Now().Add(-1 * time.Second))
app.Status = v1alpha1.ApplicationStatus{ReconciledAt: &reconciledAt}
app.Status.Sync = v1alpha1.SyncStatus{ComparedTo: v1alpha1.ComparedTo{Source: app.Spec.GetSource(), Destination: app.Spec.Destination}}
app.Status.Sync = v1alpha1.SyncStatus{ComparedTo: v1alpha1.ComparedTo{Source: app.Spec.GetSource(), Destination: app.Spec.Destination, IgnoreDifferences: app.Spec.IgnoreDifferences}}
ctrl := newFakeController(&fakeData{
apps: []runtime.Object{app, &defaultProj},
manifestResponse: &apiclient.ManifestResponse{

View File

@@ -513,7 +513,7 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
namespace = "(cluster-scoped)"
}
log.WithFields(log.Fields{
"server": clusterCache.GetClusterInfo().Server,
"server": cluster.Server,
"namespace": namespace,
"name": ref.Name,
"api-version": ref.APIVersion,

View File

@@ -84,7 +84,7 @@ func LegacyDistributionFunction() DistributionFunction {
h := fnv.New32a()
_, _ = h.Write([]byte(id))
shard := int32(h.Sum32() % uint32(replicas))
log.Infof("Cluster with id=%s will be processed by shard %d", id, shard)
log.Debugf("Cluster with id=%s will be processed by shard %d", id, shard)
return int(shard)
}
}
@@ -110,7 +110,7 @@ func RoundRobinDistributionFunction(db db.ArgoDB) DistributionFunction {
return -1
}
shard := int(clusterIndex % replicas)
log.Infof("Cluster with id=%s will be processed by shard %d", c.ID, shard)
log.Debugf("Cluster with id=%s will be processed by shard %d", c.ID, shard)
return shard
}
}

View File

@@ -351,7 +351,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
if hasMultipleSources {
return &comparisonResult{
syncStatus: &v1alpha1.SyncStatus{
ComparedTo: v1alpha1.ComparedTo{Destination: app.Spec.Destination, Sources: sources},
ComparedTo: v1alpha1.ComparedTo{Destination: app.Spec.Destination, Sources: sources, IgnoreDifferences: app.Spec.IgnoreDifferences},
Status: v1alpha1.SyncStatusCodeUnknown,
Revisions: revisions,
},
@@ -360,7 +360,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
} else {
return &comparisonResult{
syncStatus: &v1alpha1.SyncStatus{
ComparedTo: v1alpha1.ComparedTo{Source: sources[0], Destination: app.Spec.Destination},
ComparedTo: v1alpha1.ComparedTo{Source: sources[0], Destination: app.Spec.Destination, IgnoreDifferences: app.Spec.IgnoreDifferences},
Status: v1alpha1.SyncStatusCodeUnknown,
Revision: revisions[0],
},
@@ -506,7 +506,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
// restore comparison using cached diff result if previous comparison was performed for the same revision
revisionChanged := len(manifestInfos) != len(sources) || !reflect.DeepEqual(app.Status.Sync.Revisions, manifestRevisions)
specChanged := !reflect.DeepEqual(app.Status.Sync.ComparedTo, v1alpha1.ComparedTo{Source: app.Spec.GetSource(), Destination: app.Spec.Destination, Sources: sources})
specChanged := !reflect.DeepEqual(app.Status.Sync.ComparedTo, v1alpha1.ComparedTo{Source: app.Spec.GetSource(), Destination: app.Spec.Destination, Sources: sources, IgnoreDifferences: app.Spec.IgnoreDifferences})
_, refreshRequested := app.IsRefreshRequested()
noCache = noCache || refreshRequested || app.Status.Expired(m.statusRefreshTimeout) || specChanged || revisionChanged
@@ -647,8 +647,9 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
if hasMultipleSources {
syncStatus = v1alpha1.SyncStatus{
ComparedTo: v1alpha1.ComparedTo{
Destination: app.Spec.Destination,
Sources: sources,
Destination: app.Spec.Destination,
Sources: sources,
IgnoreDifferences: app.Spec.IgnoreDifferences,
},
Status: syncCode,
Revisions: manifestRevisions,
@@ -656,8 +657,9 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
} else {
syncStatus = v1alpha1.SyncStatus{
ComparedTo: v1alpha1.ComparedTo{
Destination: app.Spec.Destination,
Source: app.Spec.GetSource(),
Destination: app.Spec.Destination,
Source: app.Spec.GetSource(),
IgnoreDifferences: app.Spec.IgnoreDifferences,
},
Status: syncCode,
Revision: revision,

View File

@@ -1,6 +1,6 @@
# API Docs
You can find the Swagger docs by setting the path to `/swagger-ui` in your Argo CD UI's. E.g. [http://localhost:8080/swagger-ui](http://localhost:8080/swagger-ui).
You can find the Swagger docs by setting the path to `/swagger-ui` in your Argo CD UI. E.g. [http://localhost:8080/swagger-ui](http://localhost:8080/swagger-ui).
## Authorization
@@ -17,4 +17,17 @@ Then pass using the HTTP `Authorization` header, prefixing with `Bearer `:
$ curl $ARGOCD_SERVER/api/v1/applications -H "Authorization: Bearer $ARGOCD_TOKEN"
{"metadata":{"selfLink":"/apis/argoproj.io/v1alpha1/namespaces/argocd/applications","resourceVersion":"37755"},"items":...}
```
## Services
### Applications API
#### How to Avoid 403 Errors for Missing Applications
All endpoints of the Applications API accept an optional `project` query string parameter. If the parameter is
specified, and the specified Application does not exist, or if the Application does exist but is not in the given
project, the API will return a `404` error.
If the `project` query string parameter is specified, and the Application does not exist, the API will return a `403`
error. This is to prevent leaking information about the existence of Applications to users who do not have access to
them.

View File

@@ -130,7 +130,7 @@ For backwards compatibility, if the namespace of the Application is the control
### Application RBAC
The RBAC syntax for Application objects has been changed from `<project>/<application>` to `<project>/<namespace>/<application>` to accomodate the need to restrict access based on the source namespace of the Application to be managed.
The RBAC syntax for Application objects has been changed from `<project>/<application>` to `<project>/<namespace>/<application>` to accommodate the need to restrict access based on the source namespace of the Application to be managed.
For backwards compatibility, Applications in the `argocd` namespace can still be refered to as `<project>/<application>` in the RBAC policy rules.

View File

@@ -0,0 +1,9 @@
# Add support for self-signed TLS / Certificates for Gitlab SCM/PR Provider
## Implementation details
### Overview
In order for a self-signed TLS certificate be used by an ApplicationSet's SCM / PR Gitlab Generator, the certificate needs to be mounted on the application-controller. The path of the mounted certificate must be explicitly set using the environment variable `ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH` or alternatively using parameter `--scm-root-ca-path`. The applicationset controller will read the mounted certificate to create the Gitlab client for SCM/PR Providers
This can be achieved conveniently by setting `applicationsetcontroller.scm.root.ca.path` in the argocd-cmd-params-cm ConfigMap. Be sure to restart the ApplicationSet controller after setting this value.

View File

@@ -111,9 +111,9 @@ For backwards compatibility, if the namespace of the ApplicationSet is the contr
### Applicationsets RBAC
The RBAC syntax for Application objects has been changed from `<project>/<applicationset>` to `<project>/<namespace>/<applicationset>` to accomodate the need to restrict access based on the source namespace of the Application to be managed.
The RBAC syntax for Application objects has been changed from `<project>/<applicationset>` to `<project>/<namespace>/<applicationset>` to accommodate the need to restrict access based on the source namespace of the Application to be managed.
For backwards compatibility, Applications in the argocd namespace can still be refered to as `<project>/<applicationset>` in the RBAC policy rules.
For backwards compatibility, Applications in the argocd namespace can still be referred to as `<project>/<applicationset>` in the RBAC policy rules.
Wildcards do not make any distinction between project and applicationset namespaces yet. For example, the following RBAC rule would match any application belonging to project foo, regardless of the namespace it is created in:

View File

@@ -221,7 +221,7 @@ Some things to note here:
## With matrix and pull request example
In the following example, the plugin implementation is returning a set of image digests for the given branch. The returned list contains only one item correspondng to the latest builded image for the branch.
In the following example, the plugin implementation is returning a set of image digests for the given branch. The returned list contains only one item corresponding to the latest built image for the branch.
```yaml
apiVersion: argoproj.io/v1alpha1

View File

@@ -91,6 +91,8 @@ spec:
- preview
# MR state is used to filter MRs only with a certain state. (optional)
pullRequestState: opened
# If true, skips validating the SCM provider's TLS certificate - useful for self-signed certificates.
insecure: false
requeueAfterSeconds: 1800
template:
# ...
@@ -101,6 +103,9 @@ spec:
* `tokenRef`: A `Secret` name and key containing the GitLab access token to use for requests. If not specified, will make anonymous requests which have a lower rate limit and can only see public repositories. (Optional)
* `labels`: Labels is used to filter the MRs that you want to target. (Optional)
* `pullRequestState`: PullRequestState is an additional MRs filter to get only those with a certain state. Default: "" (all states)
* `insecure`: By default (false) - Skip checking the validity of the SCM's certificate - useful for self-signed TLS certificates.
As a preferable alternative to setting `insecure` to true, you can configure self-signed TLS certificates for Gitlab by [mounting self-signed certificate to the applicationset controller](./Add-self-signed-TLS-Certs.md).
## Gitea

View File

@@ -91,6 +91,8 @@ spec:
tokenRef:
secretName: gitlab-token
key: token
# If true, skips validating the SCM provider's TLS certificate - useful for self-signed certificates.
insecure: false
template:
# ...
```
@@ -100,6 +102,9 @@ spec:
* `allBranches`: By default (false) the template will only be evaluated for the default branch of each repo. If this is true, every branch of every repository will be passed to the filters. If using this flag, you likely want to use a `branchMatch` filter.
* `includeSubgroups`: By default (false) the controller will only search for repos directly in the base group. If this is true, it will recurse through all the subgroups searching for repos to scan.
* `tokenRef`: A `Secret` name and key containing the GitLab access token to use for requests. If not specified, will make anonymous requests which have a lower rate limit and can only see public repositories.
* `insecure`: By default (false) - Skip checking the validity of the SCM's certificate - useful for self-signed TLS certificates.
As a preferable alternative to setting `insecure` to true, you can configure self-signed TLS certificates for Gitlab by [mounting self-signed certificate to the applicationset controller](./Add-self-signed-TLS-Certs.md).
For label filtering, the repository tags are used.

View File

@@ -9,9 +9,6 @@ data:
# Repo server address. (default "argocd-repo-server:8081")
repo.server: "argocd-repo-server:8081"
# Dex server address (default "http://argocd-dex-server:5556")
dex.server: "http://argocd-dex-server:5556"
# Redis server hostname and port (e.g. argocd-redis:6379)
redis.server: "argocd-redis:6379"
# Enable compression for data sent to Redis with the required compression algorithm. (default 'gzip')
@@ -86,6 +83,8 @@ data:
server.repo.server.plaintext: "false"
# Perform strict validation of TLS certificates when connecting to repo server
server.repo.server.strict.tls: "false"
# Dex server address (default "http://argocd-dex-server:5556")
server.dex.server: "http://argocd-dex-server:5556"
# Use a plaintext client (non-TLS) to connect to dex server
server.dex.server.plaintext: "false"
# Perform strict validation of TLS certificates when connecting to dex server
@@ -178,9 +177,11 @@ data:
applicationsetcontroller.enable.progressive.syncs: "false"
# A list of glob patterns specifying where to look for ApplicationSet resources. (default is only the ns where the controller is installed)
applicationsetcontroller.namespaces: "argocd,argocd-appsets-*"
# Path of the self-signed TLS certificate for SCM/PR Gitlab Generator
applicationsetcontroller.scm.root.ca.path: ""
## Argo CD Notifications Controller Properties
# Set the logging level. One of: debug|info|warn|error (default "info")
notificationscontroller.log.level: "info"
# Set the logging format. One of: text|json (default "text")
notificationscontroller.log.format: "text"
notificationscontroller.log.format: "text"

View File

@@ -13,7 +13,7 @@ data:
[ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=

View File

@@ -42,7 +42,7 @@ spec:
command: [sh]
args: [-c, 'echo "Initializing..."']
# The generate command runs in the Application source directory each time manifests are generated. Standard output
# must be ONLY valid YAML manifests. A non-zero exit code will fail manifest generation.
# must be ONLY valid Kubernetes Objects in either YAML or JSON. A non-zero exit code will fail manifest generation.
# Error output will be sent to the UI, so avoid printing sensitive information (such as secrets).
generate:
command: [sh, -c]
@@ -115,7 +115,7 @@ spec:
While the ConfigManagementPlugin _looks like_ a Kubernetes object, it is not actually a custom resource.
It only follows kubernetes-style spec conventions.
The `generate` command must print a valid YAML stream to stdout. Both `init` and `generate` commands are executed inside the application source directory.
The `generate` command must print a valid Kubernetes YAML or JSON object stream to stdout. Both `init` and `generate` commands are executed inside the application source directory.
The `discover.fileName` is used as [glob](https://pkg.go.dev/path/filepath#Glob) pattern to determine whether an
application repository is supported by the plugin or not.
@@ -363,7 +363,7 @@ data:
init: # Optional command to initialize application source directory
command: ["sample command"]
args: ["sample args"]
generate: # Command to generate manifests YAML
generate: # Command to generate Kubernetes Objects in either YAML or JSON
command: ["sample command"]
args: ["sample args"]
lockRepo: true # Defaults to false. See below.
@@ -380,7 +380,7 @@ spec:
init: # Optional command to initialize application source directory
command: ["sample command"]
args: ["sample args"]
generate: # Command to generate manifests YAML
generate: # Command to generate Kubernetes Objects in either YAML or JSON
command: ["sample command"]
args: ["sample args"]
```

View File

@@ -416,9 +416,25 @@ data:
### SSH known host public keys
If you are connecting repositories via SSH, Argo CD will need to know the SSH known hosts public key of the repository servers. You can manage the SSH known hosts data in the ConfigMap named `argocd-ssh-known-hosts-cm`. This ConfigMap contains a single key/value pair, with `ssh_known_hosts` as the key and the actual public keys of the SSH servers as data. As opposed to TLS configuration, the public key(s) of each single repository server Argo CD will connect via SSH must be configured, otherwise the connections to the repository will fail. There is no fallback. The data can be copied from any existing `ssh_known_hosts` file, or from the output of the `ssh-keyscan` utility. The basic format is `<servername> <keydata>`, one entry per line.
If you are configuring repositories to use SSH, Argo CD will need to know their SSH public keys. In order for Argo CD to connect via SSH the public key(s) for each repository server must be pre-configured in Argo CD (unlike TLS configuration), otherwise the connections to the repository will fail.
An example ConfigMap object:
You can manage the SSH known hosts data in the `argocd-ssh-known-hosts-cm` ConfigMap. This ConfigMap contains a single entry, `ssh_known_hosts`, with the public keys of the SSH servers as its value. The value can be filled in from any existing `ssh_known_hosts` file, or from the output of the `ssh-keyscan` utility (which is part of OpenSSH's client package). The basic format is `<server_name> <keytype> <base64-encoded_key>`, one entry per line.
Here is an example of running `ssh-keyscan`:
```bash
$ for host in bitbucket.org github.com gitlab.com ssh.dev.azure.com vs-ssh.visualstudio.com ; do ssh-keyscan $host 2> /dev/null ; done
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
```
Here is an example `ConfigMap` object using the output from `ssh-keyscan` above:
```yaml
apiVersion: v1
@@ -436,7 +452,7 @@ data:
[ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=

View File

@@ -60,7 +60,7 @@ An example `argocd-cm.yaml` file with deep links and their variations :
# sample application level links
application.links: |
# pkg.go.dev/text/template is used for evaluating url templates
- url: https://mycompany.splunk.com?search={{.application.spec.destination.namespace}}&env={{.project.metadata.label.env}}
- url: https://mycompany.splunk.com?search={{.application.spec.destination.namespace}}&env={{.project.metadata.labels.env}}
title: Splunk
# conditionally show link e.g. for specific project
# github.com/antonmedv/expr is used for evaluation of conditions
@@ -72,7 +72,7 @@ An example `argocd-cm.yaml` file with deep links and their variations :
if: application.metadata.annotations.splunkhost != ""
# sample resource level links
resource.links: |
- url: https://mycompany.splunk.com?search={{.resource.metadata.name}}&env={{.project.metadata.label.env}}
- url: https://mycompany.splunk.com?search={{.resource.metadata.name}}&env={{.project.metadata.labels.env}}
title: Splunk
if: resource.kind == "Pod" || resource.kind == "Deployment"
```

View File

@@ -83,7 +83,7 @@ spec:
* The shard distribution algorithm of the `argocd-application-controller` can be set by using the `--sharding-method` parameter. Supported sharding methods are : [legacy (default), round-robin]. `legacy` mode uses an `uid` based distribution (non-uniform). `round-robin` uses an equal distribution across all shards. The `--sharding-method` parameter can also be overriden by setting the key `controller.sharding.algorithm` in the `argocd-cmd-params-cm` `configMap` (preferably) or by setting the `ARGOCD_CONTROLLER_SHARDING_ALGORITHM` environment variable and by specifiying the same possible values.
!!! warning "Alpha Feature"
The `round-robin` shard distribution algorithm is an experimental feature. Reshuffling is known to occur in certain scenarios with cluster removal. If the cluster at rank-0 is removed, reshuffling all clusters across shards will occur and may temporarly have negative performance impacts.
The `round-robin` shard distribution algorithm is an experimental feature. Reshuffling is known to occur in certain scenarios with cluster removal. If the cluster at rank-0 is removed, reshuffling all clusters across shards will occur and may temporarily have negative performance impacts.
* A cluster can be manually assigned and forced to a `shard` by patching the `shard` field in the cluster secret to contain the shard number, e.g.
```yaml

View File

@@ -171,6 +171,33 @@ g, db-admins, role:staging-db-admins
This example defines a *role* called `staging-db-admins` with *nine permissions* that allow that role to perform the *actions* (`create`/`delete`/`get`/`override`/`sync`/`update` applications, `get` logs, `create` exec and `get` appprojects) against `*` (all) objects in the `staging-db-admins` Argo CD AppProject.
!!! note
The `scopes` field controls which OIDC scopes to examine during rbac
enforcement (in addition to `sub` scope). If omitted, defaults to:
`'[groups]'`. The scope value can be a string, or a list of strings.
Following example shows targeting `email` as well as `groups` from your OIDC provider.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
labels:
app.kubernetes.io/name: argocd-rbac-cm
app.kubernetes.io/part-of: argocd
data:
policy.csv: |
p, my-org:team-alpha, applications, sync, my-project/*, allow
g, my-org:team-beta, role:admin
g, user@example.org, role:admin
policy.default: role:readonly
scopes: '[groups, email]'
```
For more information on `scopes` please review the [User Management Documentation](user-management/index.md).
## Policy CSV Composition
It is possible to provide additional entries in the `argocd-rbac-cm`

View File

@@ -1,6 +1,6 @@
# Reconcile Optimization
By default, an Argo CD Application is refreshed everytime a resource that belongs to it changes.
By default, an Argo CD Application is refreshed every time a resource that belongs to it changes.
Kubernetes controllers often update the resources they watch periodically, causing continuous reconcile operation on the Application
and a high CPU usage on the `argocd-application-controller`. Argo CD allows you to optionally ignore resource updates on specific fields
@@ -13,7 +13,8 @@ When a resource update is ignored, if the resource's [health status](./health.md
Argo CD allows ignoring resource updates at a specific JSON path, using [RFC6902 JSON patches](https://tools.ietf.org/html/rfc6902) and [JQ path expressions](https://stedolan.github.io/jq/manual/#path(path_expression)). It can be configured for a specified group and kind
in `resource.customizations` key of the `argocd-cm` ConfigMap.
The feature is behind a flag. To enable it, set `resource.ignoreResourceUpdatesEnabled` to `"true"` in the `argocd-cm` ConfigMap.
!!!important "Enabling the feature"
The feature is behind a flag. To enable it, set `resource.ignoreResourceUpdatesEnabled` to `"true"` in the `argocd-cm` ConfigMap.
Following is an example of a customization which ignores the `refreshTime` status field of an [`ExternalSecret`](https://external-secrets.io/main/api/externalsecret/) resource:
@@ -22,6 +23,9 @@ data:
resource.customizations.ignoreResourceUpdates.external-secrets.io_ExternalSecret: |
jsonPointers:
- /status/refreshTime
# JQ equivalent of the above:
# jqPathExpressions:
# - .status.refreshTime
```
It is possible to configure `ignoreResourceUpdates` to be applied to all tracked resources in every Application managed by an Argo CD instance. In order to do so, resource customizations can be configured like in the example below:
@@ -61,4 +65,49 @@ To find these logs, search for `"Requesting app refresh caused by object update"
fields for `api-version` and `kind`. Counting the number of refreshes triggered, by api-version/kind should
reveal the high-churn resource kinds.
Note that these logs are at the `debug` level. Configure the application-controller's log level to `debug`.
!!!note
These logs are at the `debug` level. Configure the application-controller's log level to `debug`.
Once you have identified some resources which change often, you can try to determine which fields are changing. Here is
one approach:
```shell
kubectl get <resource> -o yaml > /tmp/before.yaml
# Wait a minute or two.
kubectl get <resource> -o yaml > /tmp/after.yaml
diff /tmp/before.yaml /tmp/after
```
The diff can give you a sense for which fields are changing and should perhaps be ignored.
## Checking Whether Resource Updates are Ignored
Whenever Argo CD skips a refresh due to an ignored resource update, the controller logs the following line:
"Ignoring change of object because none of the watched resource fields have changed".
Search the application-controller logs for this line to confirm that your resource ignore rules are being applied.
!!!note
These logs are at the `debug` level. Configure the application-controller's log level to `debug`.
## Examples
### argoproj.io/Application
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
data:
resource.customizations.ignoreResourceUpdates.argoproj.io_Application: |
jsonPointers:
# Ignore when ownerReferences change, for example when a parent ApplicationSet changes often.
- /metadata/ownerReferences
# Ignore reconciledAt, since by itself it doesn't indicate any important change.
- /status/reconciledAt
jqPathExpressions:
# Ignore lastTransitionTime for conditions; helpful when SharedResourceWarnings are being regularly updated but not
# actually changing in content.
- .status.conditions[].lastTransitionTime
```

View File

@@ -3,6 +3,7 @@
## Prerequisites
- cosign `v2.0.0` or higher [installation instructions](https://docs.sigstore.dev/cosign/installation)
- slsa-verifier [installation instructions](https://github.com/slsa-framework/slsa-verifier#installation)
- crane [installation instructions](https://github.com/google/go-containerregistry/blob/main/cmd/crane/README.md) (for container verification only)
***
## Release Assets
@@ -60,47 +61,88 @@ The following checks were performed on each of these signatures:
```
***
## Verification of container image attestations
## Verification of container image with SLSA attestations
A [SLSA](https://slsa.dev/) Level 3 provenance is generated using [slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator).
The following command will verify the signature of an attestation and how it was issued. It will contain the payloadType, payload, and signature.
Run the following command as per the [slsa-verifier documentation](https://github.com/slsa-framework/slsa-verifier/tree/main#containers):
```bash
cosign verify-attestation --type slsaprovenance \
--certificate-identity-regexp https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
quay.io/argoproj/argocd:v2.7.0 | jq
# Get the immutable container image to prevent TOCTOU attacks https://github.com/slsa-framework/slsa-verifier#toctou-attacks
IMAGE=quay.io/argoproj/argocd:v2.7.0
IMAGE="${IMAGE}@"$(crane digest "${IMAGE}")
# Verify provenance, including the tag to prevent rollback attacks.
slsa-verifier verify-image "$IMAGE" \
--source-uri github.com/argoproj/argo-cd \
--source-tag v2.7.0
```
The payload is a non-falsifiable provenance which is base64 encoded and can be viewed by using the command below:
If you only want to verify up to the major or minor verion of the source repository tag (instead of the full tag), use the `--source-versioned-tag` which performs semantic versioning verification:
```shell
slsa-verifier verify-image "$IMAGE" \
--source-uri github.com/argoproj/argo-cd \
--source-versioned-tag v2 # Note: May use v2.7 for minor version verification.
```
The attestation payload contains a non-forgeable provenance which is base64 encoded and can be viewed by passing the `--print-provenance` option to the commands above:
```bash
cosign verify-attestation --type slsaprovenance \
--certificate-identity-regexp https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
quay.io/argoproj/argocd:v2.7.0 | jq -r .payload | base64 -d | jq
slsa-verifier verify-image "$IMAGE" \
--source-uri github.com/argoproj/argo-cd \
--source-tag v2.7.0
--print-provenance | jq
```
If you prefer using cosign, follow these [instructions](https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#cosign).
!!! tip
`cosign` or `slsa-verifier` can both be used to verify image attestations.
Check the documentation of each binary for detailed instructions.
***
## Verification of CLI artifacts with attestations
## Verification of CLI artifacts with SLSA attestations
A single attestation (`argocd-cli.intoto.jsonl`) from each release is provided. This can be used with [slsa-verifier](https://github.com/slsa-framework/slsa-verifier#verification-for-github-builders) to verify that a CLI binary was generated using Argo CD workflows on GitHub and ensures it was cryptographically signed.
```bash
slsa-verifier verify-artifact argocd-linux-amd64 --provenance-path argocd-cli.intoto.jsonl --source-uri github.com/argoproj/argo-cd
```
## Verifying an artifact and output the provenance
```bash
slsa-verifier verify-artifact argocd-linux-amd64 --provenance-path argocd-cli.intoto.jsonl --source-uri github.com/argoproj/argo-cd --print-provenance | jq
slsa-verifier verify-artifact argocd-linux-amd64 \
--provenance-path argocd-cli.intoto.jsonl \
--source-uri github.com/argoproj/argo-cd \
--source-tag v2.7.0
```
If you only want to verify up to the major or minor verion of the source repository tag (instead of the full tag), use the `--source-versioned-tag` which performs semantic versioning verification:
```shell
slsa-verifier verify-artifact argocd-linux-amd64 \
--provenance-path argocd-cli.intoto.jsonl \
--source-uri github.com/argoproj/argo-cd \
--source-versioned-tag v2 # Note: May use v2.7 for minor version verification.
```
The payload is a non-forgeable provenance which is base64 encoded and can be viewed by passing the `--print-provenance` option to the commands above:
```bash
slsa-verifier verify-artifact argocd-linux-amd64 \
--provenance-path argocd-cli.intoto.jsonl \
--source-uri github.com/argoproj/argo-cd \
--source-tag v2.7.0 \
--print-provenance | jq
```
## Verification of Sbom
A single attestation (`argocd-sbom.intoto.jsonl`) from each release is provided along with the sbom (`sbom.tar.gz`). This can be used with [slsa-verifier](https://github.com/slsa-framework/slsa-verifier#verification-for-github-builders) to verify that the SBOM was generated using Argo CD workflows on GitHub and ensures it was cryptographically signed.
```bash
cosign verify-blob --signature sbom.tar.gz.sig --certificate sbom.tar.gz.pem \
--certificate-identity-regexp ^https://github.com/argoproj/argo-cd/.github/workflows/release.yaml@refs/tags/v \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
~/Downloads/sbom.tar.gz | jq
slsa-verifier verify-artifact sbom.tar.gz \
--provenance-path argocd-sbom.intoto.jsonl \
--source-uri github.com/argoproj/argo-cd \
--source-tag v2.8.0
```
***

View File

@@ -1,6 +1,5 @@
| Argo CD version | Kubernetes versions |
|-----------------|---------------------|
| 2.8 | v1.27, v1.26, v1.25, v1.24 |
| 2.7 | v1.26, v1.25, v1.24, v1.23 |
| 2.6 | v1.24, v1.23, v1.22 |
| 2.5 | v1.24, v1.23, v1.22 |

View File

@@ -65,3 +65,8 @@ p, role:action-runner, applications, action/argoproj.io/WorkflowTemplate/create-
p, role:action-runner, applications, action/argoproj.io/CronWorkflow/create-workflow, *, allow
p, role:action-runner, applications, action/batch/CronJob/create-job, *, allow
```
## Change default file open mode
In version 2.7, the CMP plugin was changed to open Git/Helm files with all executable bits set (unless `preserveFileMode` was specified).
Version 2.8 removes the executable bits in cases where they are not necessary.

View File

@@ -60,8 +60,8 @@ To ignore fields owned by specific managers defined in your live resources:
```yaml
spec:
ignoreDifferences:
- group: *
kind: *
- group: "*"
kind: "*"
managedFieldsManagers:
- kube-controller-manager
```

View File

@@ -167,6 +167,9 @@ Argo CD supports many (most?) Helm hooks by mapping the Helm annotations onto Ar
Unsupported hooks are ignored. In Argo CD, hooks are created by using `kubectl apply`, rather than `kubectl create`. This means that if the hook is named and already exists, it will not change unless you have annotated it with `before-hook-creation`.
!!! warning "Helm hooks + ArgoCD hooks"
If you define some Argo CD hooks in addition to the Helm ones, the Helm hooks will be ignored.
!!! warning "'install' vs 'upgrade' vs 'sync'"
Argo CD cannot know if it is running a first-time "install" or an "upgrade" - every operation is a "sync'. This means that, by default, apps that have `pre-install` and `pre-upgrade` will have those hooks run at the same time.

View File

@@ -303,7 +303,7 @@ You can list all configured SSH known host entries using the `argocd cert list`
```bash
$ argocd cert list --cert-type ssh
HOSTNAME TYPE SUBTYPE FINGERPRINT/SUBJECT
bitbucket.org ssh ssh-rsa SHA256:zzXQOXSRBEiUtuE8AikJYKwbHaxvSc0ojez9YXaGp1A
bitbucket.org ssh ssh-rsa SHA256:46OSHA1Rmj8E8ERTC6xkNcmGOw9oFxYr0WF6zWW8l1E
github.com ssh ssh-rsa SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s
gitlab.com ssh ecdsa-sha2-nistp256 SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw
gitlab.com ssh ssh-ed25519 SHA256:eUXGGm1YGsMAS7vkcx6JOJdOGHPem5gQp4taiCfCLB8

View File

@@ -7,6 +7,12 @@ metadata:
app.kubernetes.io/component: server
name: argocd-server-cluster-apps
rules:
- apiGroups:
- ""
resources:
- events
verbs:
- create
- apiGroups:
- "argoproj.io"
resources:

4
go.mod
View File

@@ -12,7 +12,7 @@ require (
github.com/antonmedv/expr v1.12.5
github.com/argoproj/gitops-engine v0.7.1-0.20230607163028-425d65e07695
github.com/argoproj/notifications-engine v0.4.1-0.20230620204159-3446d4ae8520
github.com/argoproj/pkg v0.13.7-0.20221221191914-44694015343d
github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1
github.com/aws/aws-sdk-go v1.44.289
github.com/bmatcuk/doublestar/v4 v4.6.0
github.com/bombsimon/logrusr/v2 v2.0.1
@@ -178,7 +178,7 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/compress v1.16.5 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/malexdev/utfutil v0.0.0-20180510171754-00c8d4a8e7a8 // indirect

27
go.sum
View File

@@ -131,8 +131,8 @@ github.com/argoproj/gitops-engine v0.7.1-0.20230607163028-425d65e07695 h1:w8OPbq
github.com/argoproj/gitops-engine v0.7.1-0.20230607163028-425d65e07695/go.mod h1:WpA/B7tgwfz+sdNE3LqrTrb7ArEY1FOPI2pAGI0hfPc=
github.com/argoproj/notifications-engine v0.4.1-0.20230620204159-3446d4ae8520 h1:ZCpg1Zk78E8QxMI52w6ZIddxkBHv27YWmfWQdxxWUkw=
github.com/argoproj/notifications-engine v0.4.1-0.20230620204159-3446d4ae8520/go.mod h1:sbhf4EjAUGAqRdHIzifDIiWsjlsTfmytVJJCCiUdyVA=
github.com/argoproj/pkg v0.13.7-0.20221221191914-44694015343d h1:7fXEKF3OQ9i1PrgieA6FLrXOL3UAKyiotomn0RHevds=
github.com/argoproj/pkg v0.13.7-0.20221221191914-44694015343d/go.mod h1:RKjj5FJ6KxtktOY49GJSG49qO6Z4lH7RnrVCaS3tf18=
github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1 h1:qsHwwOJ21K2Ao0xPju1sNuqphyMnMYkyB3ZLoLtxWpo=
github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1/go.mod h1:CZHlkyAD1/+FbEn6cB2DQTj48IoLGvEYsWEvtzP3238=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -149,7 +149,6 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.44.164/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.289 h1:5CVEjiHFvdiVlKPBzv0rjG4zH/21W/onT18R5AH/qx0=
github.com/aws/aws-sdk-go v1.44.289/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
@@ -673,7 +672,6 @@ github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+h
github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ=
github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
@@ -730,11 +728,11 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -806,8 +804,8 @@ github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5/go.mod h1:PoGiBqK
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.45/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw=
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/minio/minio-go/v7 v7.0.58/go.mod h1:NUDy4A4oXPq1l2yK6LTSvCEzAMeIcoz9lcj5dbzSrRE=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
@@ -1023,7 +1021,7 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so=
github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
@@ -1047,7 +1045,7 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
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.1.1 h1:MTk78x9FPgDFVFkDLTrsnnfCJl7g1C/nnKvePgrIngE=
@@ -1079,7 +1077,6 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
@@ -1268,11 +1265,11 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1828,7 +1825,7 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=

View File

@@ -4,7 +4,7 @@
[ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=

View File

@@ -23,7 +23,7 @@ diff - <(ssh-keygen -l -f $KNOWN_HOSTS_FILE | sort -k 3) <<EOF
3072 SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s [ssh.github.com]:443 (RSA)
256 SHA256:FC73VB6C4OQLSCrjEayhMp9UMxS97caD/Yyi2bhW/J0 bitbucket.org (ECDSA)
256 SHA256:ybgmFkzwOSotHTHLJgHO0QN8L0xErw6vd0VhFA9m3SM bitbucket.org (ED25519)
2048 SHA256:zzXQOXSRBEiUtuE8AikJYKwbHaxvSc0ojez9YXaGp1A bitbucket.org (RSA)
2048 SHA256:46OSHA1Rmj8E8ERTC6xkNcmGOw9oFxYr0WF6zWW8l1E bitbucket.org (RSA)
256 SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM github.com (ECDSA)
256 SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU github.com (ED25519)
3072 SHA256:uNiVztksCsDhcc0u9e8BujQXVUpKZIDTMczCvj3tD2s github.com (RSA)

View File

@@ -127,6 +127,12 @@ spec:
key: applicationsetcontroller.namespaces
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH
valueFrom:
configMapKeyRef:
key: applicationsetcontroller.scm.root.ca.path
name: argocd-cmd-params-cm
optional: true
volumeMounts:
- mountPath: /app/config/ssh
name: ssh-known-hosts

View File

@@ -13,7 +13,7 @@ data:
[ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=

View File

@@ -37,7 +37,7 @@ spec:
type: RuntimeDefault
containers:
- name: dex
image: ghcr.io/dexidp/dex:v2.36.0
image: ghcr.io/dexidp/dex:v2.37.0
imagePullPolicy: Always
command: [/shared/argocd-dex, rundex]
env:

View File

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

View File

@@ -3807,6 +3807,42 @@ spec:
and must be set to the Kubernetes control plane API
type: string
type: object
ignoreDifferences:
description: IgnoreDifferences is a reference to the application's
ignored differences used for comparison
items:
description: ResourceIgnoreDifferences contains resource
filter and list of json paths which should be ignored
during comparison with live state.
properties:
group:
type: string
jqPathExpressions:
items:
type: string
type: array
jsonPointers:
items:
type: string
type: array
kind:
type: string
managedFieldsManagers:
description: ManagedFieldsManagers is a list of trusted
managers. Fields mutated by those managers will take
precedence over the desired state defined in the SCM
and won't be displayed in diffs
items:
type: string
type: array
name:
type: string
namespace:
type: string
required:
- kind
type: object
type: array
source:
description: Source is a reference to the application's source
used for comparison
@@ -9314,6 +9350,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -10004,6 +10042,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -13789,6 +13829,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -14479,6 +14521,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -16193,6 +16237,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -16883,6 +16929,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -18591,7 +18639,7 @@ data:
[ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
@@ -18820,7 +18868,13 @@ spec:
key: applicationsetcontroller.namespaces
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
- name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH
valueFrom:
configMapKeyRef:
key: applicationsetcontroller.scm.root.ca.path
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -19108,7 +19162,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -19160,7 +19214,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -19379,7 +19433,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -12,4 +12,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: latest
newTag: v2.8.0-rc5

View File

@@ -3806,6 +3806,42 @@ spec:
and must be set to the Kubernetes control plane API
type: string
type: object
ignoreDifferences:
description: IgnoreDifferences is a reference to the application's
ignored differences used for comparison
items:
description: ResourceIgnoreDifferences contains resource
filter and list of json paths which should be ignored
during comparison with live state.
properties:
group:
type: string
jqPathExpressions:
items:
type: string
type: array
jsonPointers:
items:
type: string
type: array
kind:
type: string
managedFieldsManagers:
description: ManagedFieldsManagers is a list of trusted
managers. Fields mutated by those managers will take
precedence over the desired state defined in the SCM
and won't be displayed in diffs
items:
type: string
type: array
name:
type: string
namespace:
type: string
required:
- kind
type: object
type: array
source:
description: Source is a reference to the application's source
used for comparison

View File

@@ -4863,6 +4863,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -5553,6 +5555,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -9338,6 +9342,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -10028,6 +10034,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -11742,6 +11750,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -12432,6 +12442,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:

View File

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

View File

@@ -3807,6 +3807,42 @@ spec:
and must be set to the Kubernetes control plane API
type: string
type: object
ignoreDifferences:
description: IgnoreDifferences is a reference to the application's
ignored differences used for comparison
items:
description: ResourceIgnoreDifferences contains resource
filter and list of json paths which should be ignored
during comparison with live state.
properties:
group:
type: string
jqPathExpressions:
items:
type: string
type: array
jsonPointers:
items:
type: string
type: array
kind:
type: string
managedFieldsManagers:
description: ManagedFieldsManagers is a list of trusted
managers. Fields mutated by those managers will take
precedence over the desired state defined in the SCM
and won't be displayed in diffs
items:
type: string
type: array
name:
type: string
namespace:
type: string
required:
- kind
type: object
type: array
source:
description: Source is a reference to the application's source
used for comparison
@@ -9314,6 +9350,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -10004,6 +10042,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -13789,6 +13829,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -14479,6 +14521,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -16193,6 +16237,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -16883,6 +16929,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -19635,7 +19683,7 @@ data:
[ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
@@ -20057,7 +20105,13 @@ spec:
key: applicationsetcontroller.namespaces
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
- name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH
valueFrom:
configMapKeyRef:
key: applicationsetcontroller.scm.root.ca.path
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -20151,7 +20205,7 @@ spec:
key: dexserver.disable.tls
name: argocd-cmd-params-cm
optional: true
image: ghcr.io/dexidp/dex:v2.36.0
image: ghcr.io/dexidp/dex:v2.37.0
imagePullPolicy: Always
name: dex
ports:
@@ -20180,7 +20234,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -20250,7 +20304,7 @@ spec:
key: notificationscontroller.log.level
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -20564,7 +20618,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -20616,7 +20670,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -20905,7 +20959,7 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -21151,7 +21205,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -1201,7 +1201,7 @@ data:
[ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
@@ -1623,7 +1623,13 @@ spec:
key: applicationsetcontroller.namespaces
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
- name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH
valueFrom:
configMapKeyRef:
key: applicationsetcontroller.scm.root.ca.path
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1717,7 +1723,7 @@ spec:
key: dexserver.disable.tls
name: argocd-cmd-params-cm
optional: true
image: ghcr.io/dexidp/dex:v2.36.0
image: ghcr.io/dexidp/dex:v2.37.0
imagePullPolicy: Always
name: dex
ports:
@@ -1746,7 +1752,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1816,7 +1822,7 @@ spec:
key: notificationscontroller.log.level
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2130,7 +2136,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2182,7 +2188,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2471,7 +2477,7 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2717,7 +2723,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -3807,6 +3807,42 @@ spec:
and must be set to the Kubernetes control plane API
type: string
type: object
ignoreDifferences:
description: IgnoreDifferences is a reference to the application's
ignored differences used for comparison
items:
description: ResourceIgnoreDifferences contains resource
filter and list of json paths which should be ignored
during comparison with live state.
properties:
group:
type: string
jqPathExpressions:
items:
type: string
type: array
jsonPointers:
items:
type: string
type: array
kind:
type: string
managedFieldsManagers:
description: ManagedFieldsManagers is a list of trusted
managers. Fields mutated by those managers will take
precedence over the desired state defined in the SCM
and won't be displayed in diffs
items:
type: string
type: array
name:
type: string
namespace:
type: string
required:
- kind
type: object
type: array
source:
description: Source is a reference to the application's source
used for comparison
@@ -9314,6 +9350,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -10004,6 +10042,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -13789,6 +13829,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -14479,6 +14521,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -16193,6 +16237,8 @@ spec:
properties:
api:
type: string
insecure:
type: boolean
labels:
items:
type: string
@@ -16883,6 +16929,8 @@ spec:
type: string
includeSubgroups:
type: boolean
insecure:
type: boolean
tokenRef:
properties:
key:
@@ -18839,7 +18887,7 @@ data:
[ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
@@ -19158,7 +19206,13 @@ spec:
key: applicationsetcontroller.namespaces
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
- name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH
valueFrom:
configMapKeyRef:
key: applicationsetcontroller.scm.root.ca.path
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -19252,7 +19306,7 @@ spec:
key: dexserver.disable.tls
name: argocd-cmd-params-cm
optional: true
image: ghcr.io/dexidp/dex:v2.36.0
image: ghcr.io/dexidp/dex:v2.37.0
imagePullPolicy: Always
name: dex
ports:
@@ -19281,7 +19335,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -19351,7 +19405,7 @@ spec:
key: notificationscontroller.log.level
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -19621,7 +19675,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -19673,7 +19727,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -19960,7 +20014,7 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -20206,7 +20260,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -405,7 +405,7 @@ data:
[ssh.github.com]:443 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
bitbucket.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIQmuzMBuKdWeF4+a2sjSSpBK0iqitSQ+5BM9KhpexuGt20JpTVM7u5BDZngncgrqDMbWdxMWWOGtZ9UgbqgZE=
bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
@@ -724,7 +724,13 @@ spec:
key: applicationsetcontroller.namespaces
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
- name: ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH
valueFrom:
configMapKeyRef:
key: applicationsetcontroller.scm.root.ca.path
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -818,7 +824,7 @@ spec:
key: dexserver.disable.tls
name: argocd-cmd-params-cm
optional: true
image: ghcr.io/dexidp/dex:v2.36.0
image: ghcr.io/dexidp/dex:v2.37.0
imagePullPolicy: Always
name: dex
ports:
@@ -847,7 +853,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -917,7 +923,7 @@ spec:
key: notificationscontroller.log.level
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1187,7 +1193,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1239,7 +1245,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1526,7 +1532,7 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -1772,7 +1778,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.8.0-rc5
imagePullPolicy: Always
name: argocd-application-controller
ports:

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,6 @@ API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/ap
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ApplicationSourceJsonnet,ExtVars
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ApplicationSourceJsonnet,Libs
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ApplicationSourceJsonnet,TLAs
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ApplicationSpec,IgnoreDifferences
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ApplicationSpec,Info
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ApplicationStatus,Conditions
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ApplicationStatus,Resources

View File

@@ -439,6 +439,8 @@ type SCMProviderGeneratorGitlab struct {
TokenRef *SecretRef `json:"tokenRef,omitempty" protobuf:"bytes,4,opt,name=tokenRef"`
// Scan all branches instead of just the default branch.
AllBranches bool `json:"allBranches,omitempty" protobuf:"varint,5,opt,name=allBranches"`
// Skips validating the SCM provider's TLS certificate - useful for self-signed certificates.; default: false
Insecure bool `json:"insecure,omitempty" protobuf:"varint,6,opt,name=insecure"`
}
// SCMProviderGeneratorBitbucket defines connection info specific to Bitbucket Cloud (API version 2).
@@ -589,6 +591,8 @@ type PullRequestGeneratorGitLab struct {
Labels []string `json:"labels,omitempty" protobuf:"bytes,4,rep,name=labels"`
// PullRequestState is an additional MRs filter to get only those with a certain state. Default: "" (all states)
PullRequestState string `json:"pullRequestState,omitempty" protobuf:"bytes,5,rep,name=pullRequestState"`
// Skips validating the SCM provider's TLS certificate - useful for self-signed certificates.; default: false
Insecure bool `json:"insecure,omitempty" protobuf:"varint,6,opt,name=insecure"`
}
// PullRequestGeneratorBitbucketServer defines connection info specific to BitbucketServer.

File diff suppressed because it is too large Load Diff

View File

@@ -807,6 +807,9 @@ message ComparedTo {
// Sources is a reference to the application's multiple sources used for comparison
repeated ApplicationSource sources = 3;
// IgnoreDifferences is a reference to the application's ignored differences used for comparison
repeated ResourceIgnoreDifferences ignoreDifferences = 4;
}
// ComponentParameter contains information about component parameter value
@@ -1373,6 +1376,9 @@ message PullRequestGeneratorGitLab {
// PullRequestState is an additional MRs filter to get only those with a certain state. Default: "" (all states)
optional string pullRequestState = 5;
// Skips validating the SCM provider's TLS certificate - useful for self-signed certificates.; default: false
optional bool insecure = 6;
}
// PullRequestGeneratorGitea defines connection info specific to Gitea.
@@ -2019,6 +2025,9 @@ message SCMProviderGeneratorGitlab {
// Scan all branches instead of just the default branch.
optional bool allBranches = 5;
// Skips validating the SCM provider's TLS certificate - useful for self-signed certificates.; default: false
optional bool insecure = 6;
}
// Utility struct for a reference to a secret key.

View File

@@ -2861,12 +2861,26 @@ func schema_pkg_apis_application_v1alpha1_ComparedTo(ref common.ReferenceCallbac
},
},
},
"ignoreDifferences": {
SchemaProps: spec.SchemaProps{
Description: "IgnoreDifferences is a reference to the application's ignored differences used for comparison",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceIgnoreDifferences"),
},
},
},
},
},
},
Required: []string{"destination"},
},
},
Dependencies: []string{
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationDestination", "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSource"},
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationDestination", "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ApplicationSource", "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.ResourceIgnoreDifferences"},
}
}
@@ -4849,6 +4863,13 @@ func schema_pkg_apis_application_v1alpha1_PullRequestGeneratorGitLab(ref common.
Format: "",
},
},
"insecure": {
SchemaProps: spec.SchemaProps{
Description: "Skips validating the SCM provider's TLS certificate - useful for self-signed certificates.; default: false",
Type: []string{"boolean"},
Format: "",
},
},
},
Required: []string{"project"},
},
@@ -6909,6 +6930,13 @@ func schema_pkg_apis_application_v1alpha1_SCMProviderGeneratorGitlab(ref common.
Format: "",
},
},
"insecure": {
SchemaProps: spec.SchemaProps{
Description: "Skips validating the SCM provider's TLS certificate - useful for self-signed certificates.; default: false",
Type: []string{"boolean"},
Format: "",
},
},
},
Required: []string{"group"},
},

View File

@@ -70,7 +70,7 @@ type ApplicationSpec struct {
// SyncPolicy controls when and how a sync will be performed
SyncPolicy *SyncPolicy `json:"syncPolicy,omitempty" protobuf:"bytes,4,name=syncPolicy"`
// IgnoreDifferences is a list of resources and their fields which should be ignored during comparison
IgnoreDifferences []ResourceIgnoreDifferences `json:"ignoreDifferences,omitempty" protobuf:"bytes,5,name=ignoreDifferences"`
IgnoreDifferences IgnoreDifferences `json:"ignoreDifferences,omitempty" protobuf:"bytes,5,name=ignoreDifferences"`
// Info contains a list of information (URLs, email addresses, and plain text) that relates to the application
Info []Info `json:"info,omitempty" protobuf:"bytes,6,name=info"`
// RevisionHistoryLimit limits the number of items kept in the application's revision history, which is used for informational purposes as well as for rollbacks to previous versions.
@@ -84,6 +84,12 @@ type ApplicationSpec struct {
Sources ApplicationSources `json:"sources,omitempty" protobuf:"bytes,8,opt,name=sources"`
}
type IgnoreDifferences []ResourceIgnoreDifferences
func (id IgnoreDifferences) Equals(other IgnoreDifferences) bool {
return reflect.DeepEqual(id, other)
}
type TrackingMethod string
// ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state.
@@ -1406,6 +1412,8 @@ type ComparedTo struct {
Destination ApplicationDestination `json:"destination" protobuf:"bytes,2,opt,name=destination"`
// Sources is a reference to the application's multiple sources used for comparison
Sources ApplicationSources `json:"sources,omitempty" protobuf:"bytes,3,opt,name=sources"`
// IgnoreDifferences is a reference to the application's ignored differences used for comparison
IgnoreDifferences IgnoreDifferences `json:"ignoreDifferences,omitempty" protobuf:"bytes,4,opt,name=ignoreDifferences"`
}
// SyncStatus contains information about the currently observed live and desired states of an application

View File

@@ -1174,7 +1174,7 @@ func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) {
}
if in.IgnoreDifferences != nil {
in, out := &in.IgnoreDifferences, &out.IgnoreDifferences
*out = make([]ResourceIgnoreDifferences, len(*in))
*out = make(IgnoreDifferences, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@@ -1635,6 +1635,13 @@ func (in *ComparedTo) DeepCopyInto(out *ComparedTo) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.IgnoreDifferences != nil {
in, out := &in.IgnoreDifferences, &out.IgnoreDifferences
*out = make(IgnoreDifferences, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
@@ -2022,6 +2029,28 @@ func (in *HostResourceInfo) DeepCopy() *HostResourceInfo {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in IgnoreDifferences) DeepCopyInto(out *IgnoreDifferences) {
{
in := &in
*out = make(IgnoreDifferences, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
return
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IgnoreDifferences.
func (in IgnoreDifferences) DeepCopy() IgnoreDifferences {
if in == nil {
return nil
}
out := new(IgnoreDifferences)
in.DeepCopyInto(out)
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Info) DeepCopyInto(out *Info) {
*out = *in

View File

@@ -417,7 +417,16 @@ func (s *Service) runRepoOperation(
return operation(gitClient.Root(), commitSHA, revision, func() (*operationContext, error) {
var signature string
if verifyCommit {
signature, err = gitClient.VerifyCommitSignature(unresolvedRevision)
// When the revision is an annotated tag, we need to pass the unresolved revision (i.e. the tag name)
// to the verification routine. For everything else, we work with the SHA that the target revision is
// pointing to (i.e. the resolved revision).
var rev string
if gitClient.IsAnnotatedTag(revision) {
rev = unresolvedRevision
} else {
rev = revision
}
signature, err = gitClient.VerifyCommitSignature(rev)
if err != nil {
return nil, err
}

View File

@@ -63,6 +63,7 @@ func newServiceWithMocks(root string, signed bool) (*Service, *gitmocks.Client)
gitClient.On("LsRemote", mock.Anything).Return(mock.Anything, nil)
gitClient.On("CommitSHA").Return(mock.Anything, nil)
gitClient.On("Root").Return(root)
gitClient.On("IsAnnotatedTag").Return(false)
if signed {
gitClient.On("VerifyCommitSignature", mock.Anything).Return(testSignature, nil)
} else {

View File

@@ -32,7 +32,10 @@ job = {}
job.apiVersion = "batch/v1"
job.kind = "Job"
job.metadata = {}
job.metadata = deepCopy(obj.spec.jobTemplate.metadata)
if job.metadata == nil then
job.metadata = {}
end
job.metadata.name = obj.metadata.name .. "-" ..os.date("!%Y%m%d%H%M")
job.metadata.namespace = obj.metadata.namespace
@@ -47,6 +50,7 @@ job.metadata.ownerReferences[1] = ownerRef
job.spec = {}
job.spec.suspend = false
job.spec.template = {}
job.spec.template.metadata = deepCopy(obj.spec.jobTemplate.spec.template.metadata)
job.spec.template.spec = deepCopy(obj.spec.jobTemplate.spec.template.spec)
impactedResource = {}

View File

@@ -7,8 +7,18 @@ metadata:
spec:
schedule: "* * * * *"
jobTemplate:
metadata:
labels:
my: label
annotations:
my: annotation
spec:
template:
metadata:
labels:
pod: label
annotations:
pod: annotation
spec:
containers:
- name: hello

View File

@@ -5,8 +5,17 @@
metadata:
name: hello-00000000000
namespace: test-ns
labels:
my: label
annotations:
my: annotation
spec:
template:
metadata:
labels:
pod: label
annotations:
pod: annotation
spec:
containers:
- name: hello

View File

@@ -50,7 +50,6 @@ import (
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/env"
"github.com/argoproj/argo-cd/v2/util/git"
"github.com/argoproj/argo-cd/v2/util/glob"
ioutil "github.com/argoproj/argo-cd/v2/util/io"
"github.com/argoproj/argo-cd/v2/util/lua"
"github.com/argoproj/argo-cd/v2/util/manifeststream"
@@ -141,42 +140,88 @@ func NewServer(
// getAppEnforceRBAC gets the Application with the given name in the given namespace. If no namespace is
// specified, the Application is fetched from the default namespace (the one in which the API server is running).
//
// If the Application does not exist, then we have no way of determining if the user would have had access to get that
// Application. Verifying access requires knowing the Application's name, namespace, and project. The user may specify,
// at minimum, the Application name.
// If the user does not provide a "project," then we have to be very careful how we respond. If an app with the given
// name exists, and the user has access to that app in the app's project, we return the app. If the app exists but the
// user does not have access, we return "permission denied." If the app does not exist, we return "permission denied" -
// if we responded with a 404, then the user could infer that the app exists when they get "permission denied."
//
// So to prevent a malicious user from inferring the existence or absense of the Application or namespace, we respond
// "permission denied" if the Application does not exist.
func (s *Server) getAppEnforceRBAC(ctx context.Context, action, namespace, name string, getApp func() (*appv1.Application, error)) (*appv1.Application, error) {
// 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) {
logCtx := log.WithFields(map[string]interface{}{
"application": name,
"namespace": namespace,
})
if project != "" {
// The user has provided everything we need to perform an initial RBAC check.
givenRBACName := security.RBACName(s.ns, project, namespace, name)
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceApplications, action, givenRBACName); err != nil {
logCtx.WithFields(map[string]interface{}{
"project": project,
argocommon.SecurityField: argocommon.SecurityMedium,
}).Warnf("user tried to %s application which they do not have access to: %s", action, err)
// Do a GET on the app. This ensures that the timing of a "no access" response is the same as a "yes access,
// 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
}
}
a, err := getApp()
if err != nil {
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())
}
// 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
}
logCtx.Errorf("failed to get application: %s", err)
return 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
// project they specified in the request).
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceApplications, action, a.RBACName(s.ns)); err != nil {
logCtx.WithFields(map[string]interface{}{
"project": a.Spec.Project,
argocommon.SecurityField: argocommon.SecurityMedium,
}).Warnf("user tried to %s application which they do not have access to: %s", action, err)
if project != "" {
// 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())
}
// The user didn't specify a project. We always return permission denied for both lack of access and lack of
// existence.
return nil, permissionDeniedErr
}
effectiveProject := "default"
if a.Spec.Project != "" {
effectiveProject = a.Spec.Project
}
if project != "" && effectiveProject != project {
logCtx.WithFields(map[string]interface{}{
"project": a.Spec.Project,
argocommon.SecurityField: argocommon.SecurityMedium,
}).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 a, 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, namespace, name string) (*appv1.Application, error) {
func (s *Server) getApplicationEnforceRBACInformer(ctx context.Context, action, project, namespace, name string) (*appv1.Application, error) {
namespaceOrDefault := s.appNamespaceOrDefault(namespace)
return s.getAppEnforceRBAC(ctx, action, namespaceOrDefault, name, func() (*appv1.Application, error) {
return s.getAppEnforceRBAC(ctx, action, project, namespaceOrDefault, name, func() (*appv1.Application, error) {
return s.appLister.Applications(namespaceOrDefault).Get(name)
})
}
@@ -184,9 +229,9 @@ 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, namespace, name, resourceVersion string) (*appv1.Application, error) {
func (s *Server) getApplicationEnforceRBACClient(ctx context.Context, action, project, namespace, name, resourceVersion string) (*appv1.Application, error) {
namespaceOrDefault := s.appNamespaceOrDefault(namespace)
return s.getAppEnforceRBAC(ctx, action, namespaceOrDefault, name, func() (*appv1.Application, error) {
return s.getAppEnforceRBAC(ctx, action, project, namespaceOrDefault, name, func() (*appv1.Application, error) {
return s.appclientset.ArgoprojV1alpha1().Applications(namespaceOrDefault).Get(ctx, name, metav1.GetOptions{
ResourceVersion: resourceVersion,
})
@@ -225,7 +270,7 @@ func (s *Server) List(ctx context.Context, q *application.ApplicationQuery) (*ap
for _, a := range filteredApps {
// Skip any application that is neither in the control plane's namespace
// nor in the list of enabled namespaces.
if a.Namespace != s.ns && !glob.MatchStringInList(s.enabledNamespaces, a.Namespace, false) {
if !s.isNamespaceEnabled(a.Namespace) {
continue
}
if s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionGet, a.RBACName(s.ns)) {
@@ -380,7 +425,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.GetAppNamespace(), q.GetName())
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, err
}
@@ -485,7 +530,7 @@ 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.GetAppNamespace(), query.GetName())
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, query.GetProject(), query.GetAppNamespace(), query.GetName())
if err != nil {
return err
}
@@ -591,10 +636,17 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*app
appName := q.GetName()
appNs := s.appNamespaceOrDefault(q.GetAppNamespace())
project := ""
projects := getProjectsFromApplicationQuery(*q)
if len(projects) == 1 {
project = projects[0]
} else if len(projects) > 1 {
return nil, status.Errorf(codes.InvalidArgument, "multiple projects specified - the get endpoint accepts either zero or one project")
}
// 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, appNs, appName, q.GetResourceVersion())
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, project, appNs, appName, q.GetResourceVersion())
if err != nil {
return nil, err
}
@@ -677,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.GetAppNamespace(), q.GetName())
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, err
}
@@ -739,11 +791,13 @@ func (s *Server) ListResourceEvents(ctx context.Context, q *application.Applicat
return list, nil
}
func (s *Server) validateAndUpdateApp(ctx context.Context, newApp *appv1.Application, merge bool, validate bool, action string) (*appv1.Application, error) {
// validateAndUpdateApp validates and updates the application. currentProject is the name of the project the app
// currently is under. If not specified, we assume that the app is under the project specified in the app spec.
func (s *Server) validateAndUpdateApp(ctx context.Context, newApp *appv1.Application, merge bool, validate bool, action string, currentProject string) (*appv1.Application, error) {
s.projectLock.RLock(newApp.Spec.GetProject())
defer s.projectLock.RUnlock(newApp.Spec.GetProject())
app, err := s.getApplicationEnforceRBACClient(ctx, action, newApp.Namespace, newApp.Name, "")
app, err := s.getApplicationEnforceRBACClient(ctx, action, currentProject, newApp.Namespace, newApp.Name, "")
if err != nil {
return nil, err
}
@@ -841,7 +895,7 @@ func (s *Server) updateApp(app *appv1.Application, newApp *appv1.Application, ct
// Update updates an application
func (s *Server) Update(ctx context.Context, q *application.ApplicationUpdateRequest) (*appv1.Application, error) {
if q.GetApplication() == nil {
return nil, fmt.Errorf("error creating application: application is nil in request")
return nil, fmt.Errorf("error updating application: application is nil in request")
}
a := q.GetApplication()
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionUpdate, a.RBACName(s.ns)); err != nil {
@@ -852,7 +906,7 @@ func (s *Server) Update(ctx context.Context, q *application.ApplicationUpdateReq
if q.Validate != nil {
validate = *q.Validate
}
return s.validateAndUpdateApp(ctx, q.Application, false, validate, rbacpolicy.ActionUpdate)
return s.validateAndUpdateApp(ctx, q.Application, false, validate, rbacpolicy.ActionUpdate, q.GetProject())
}
// UpdateSpec updates an application spec and filters out any invalid parameter overrides
@@ -860,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.GetAppNamespace(), q.GetName(), "")
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionUpdate, q.GetProject(), q.GetAppNamespace(), q.GetName(), "")
if err != nil {
return nil, err
}
@@ -870,7 +924,7 @@ func (s *Server) UpdateSpec(ctx context.Context, q *application.ApplicationUpdat
if q.Validate != nil {
validate = *q.Validate
}
a, err = s.validateAndUpdateApp(ctx, a, false, validate, rbacpolicy.ActionUpdate)
a, err = s.validateAndUpdateApp(ctx, a, false, validate, rbacpolicy.ActionUpdate, q.GetProject())
if err != nil {
return nil, fmt.Errorf("error validating and updating app: %w", err)
}
@@ -879,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.GetAppNamespace(), q.GetName(), "")
app, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName(), "")
if err != nil {
return nil, err
}
@@ -919,14 +973,14 @@ func (s *Server) Patch(ctx context.Context, q *application.ApplicationPatchReque
if err != nil {
return nil, fmt.Errorf("error unmarshaling patched app: %w", err)
}
return s.validateAndUpdateApp(ctx, newApp, false, true, rbacpolicy.ActionUpdate)
return s.validateAndUpdateApp(ctx, newApp, false, true, rbacpolicy.ActionUpdate, q.GetProject())
}
// 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, appNs, appName, "")
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, q.GetProject(), appNs, appName, "")
if err != nil {
return nil, err
}
@@ -986,6 +1040,31 @@ func (s *Server) Delete(ctx context.Context, q *application.ApplicationDeleteReq
return &application.ApplicationResponse{}, nil
}
func (s *Server) isApplicationPermitted(selector labels.Selector, minVersion int, claims any, appName, appNs string, projects map[string]bool, a appv1.Application) bool {
if len(projects) > 0 && !projects[a.Spec.GetProject()] {
return false
}
if appVersion, err := strconv.Atoi(a.ResourceVersion); err == nil && appVersion < minVersion {
return false
}
matchedEvent := (appName == "" || (a.Name == appName && a.Namespace == appNs)) && selector.Matches(labels.Set(a.Labels))
if !matchedEvent {
return false
}
if !s.isNamespaceEnabled(a.Namespace) {
return false
}
if !s.enf.Enforce(claims, rbacpolicy.ResourceApplications, rbacpolicy.ActionGet, a.RBACName(s.ns)) {
// do not emit apps user does not have accessing
return false
}
return true
}
func (s *Server) Watch(q *application.ApplicationQuery, ws application.ApplicationService_WatchServer) error {
appName := q.GetName()
appNs := s.appNamespaceOrDefault(q.GetAppNamespace())
@@ -1012,20 +1091,8 @@ func (s *Server) Watch(q *application.ApplicationQuery, ws application.Applicati
// sendIfPermitted is a helper to send the application to the client's streaming channel if the
// caller has RBAC privileges permissions to view it
sendIfPermitted := func(a appv1.Application, eventType watch.EventType) {
if len(projects) > 0 && !projects[a.Spec.GetProject()] {
return
}
if appVersion, err := strconv.Atoi(a.ResourceVersion); err == nil && appVersion < minVersion {
return
}
matchedEvent := (appName == "" || (a.Name == appName && a.Namespace == appNs)) && selector.Matches(labels.Set(a.Labels))
if !matchedEvent {
return
}
if !s.enf.Enforce(claims, rbacpolicy.ResourceApplications, rbacpolicy.ActionGet, a.RBACName(s.ns)) {
// do not emit apps user does not have accessing
permitted := s.isApplicationPermitted(selector, minVersion, claims, appName, appNs, projects, a)
if !permitted {
return
}
s.inferResourcesStatusHealth(&a)
@@ -1181,7 +1248,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.GetAppNamespace(), q.GetName())
a, err := s.getApplicationEnforceRBACInformer(ctx, action, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, nil, nil, err
}
@@ -1248,6 +1315,7 @@ func (s *Server) PatchResource(ctx context.Context, q *application.ApplicationRe
Kind: q.Kind,
Version: q.Version,
Group: q.Group,
Project: q.Project,
}
res, config, a, err := s.getAppLiveResource(ctx, rbacpolicy.ActionUpdate, resourceRequest)
if err != nil {
@@ -1290,6 +1358,7 @@ func (s *Server) DeleteResource(ctx context.Context, q *application.ApplicationR
Kind: q.Kind,
Version: q.Version,
Group: q.Group,
Project: q.Project,
}
res, config, a, err := s.getAppLiveResource(ctx, rbacpolicy.ActionDelete, resourceRequest)
if err != nil {
@@ -1316,7 +1385,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.GetAppNamespace(), q.GetApplicationName())
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetApplicationName())
if err != nil {
return nil, err
}
@@ -1325,7 +1394,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.GetAppNamespace(), q.GetApplicationName())
_, err := s.getApplicationEnforceRBACInformer(ws.Context(), rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetApplicationName())
if err != nil {
return err
}
@@ -1341,7 +1410,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.GetAppNamespace(), q.GetName())
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, err
}
@@ -1371,17 +1440,12 @@ 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) {
appName := q.GetName()
appNs := s.appNamespaceOrDefault(q.GetAppNamespace())
a, err := s.appLister.Applications(appNs).Get(appName)
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, fmt.Errorf("error getting app by name: %w", err)
}
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionGet, a.RBACName(s.ns)); err != nil {
return nil, fmt.Errorf("error enforcing claims: %w", err)
return nil, err
}
if a.Spec.Source.Chart == "" {
return nil, fmt.Errorf("no chart found for application: %v", appName)
return nil, fmt.Errorf("no chart found for application: %v", a.QualifiedName())
}
repo, err := s.db.GetRepository(ctx, a.Spec.Source.RepoURL)
if err != nil {
@@ -1407,7 +1471,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.GetAppNamespace(), q.GetApplicationName())
a, err := s.getApplicationEnforceRBACInformer(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetApplicationName())
if err != nil {
return nil, err
}
@@ -1464,7 +1528,7 @@ func (s *Server) PodLogs(q *application.ApplicationPodLogsQuery, ws application.
}
}
a, err := s.getApplicationEnforceRBACInformer(ws.Context(), rbacpolicy.ActionGet, q.GetAppNamespace(), q.GetName())
a, err := s.getApplicationEnforceRBACInformer(ws.Context(), rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return err
}
@@ -1656,7 +1720,7 @@ 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.GetAppNamespace(), syncReq.GetName(), "")
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, syncReq.GetProject(), syncReq.GetAppNamespace(), syncReq.GetName(), "")
if err != nil {
return nil, err
}
@@ -1765,7 +1829,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.GetAppNamespace(), rollbackReq.GetName(), "")
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionSync, rollbackReq.GetProject(), rollbackReq.GetAppNamespace(), rollbackReq.GetName(), "")
if err != nil {
return nil, err
}
@@ -1824,7 +1888,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.GetNamespace(), req.GetName(), "")
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, req.GetProject(), req.GetNamespace(), req.GetName(), "")
if err != nil {
return nil, err
}
@@ -1978,7 +2042,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, appNs, appName, "")
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionSync, termOpReq.GetProject(), appNs, appName, "")
if err != nil {
return nil, err
}
@@ -2051,7 +2115,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.GetAppNamespace(), q.GetName())
app, err = s.getApplicationEnforceRBACInformer(ctx, rbacRequest, q.GetProject(), q.GetAppNamespace(), q.GetName())
if err != nil {
return nil, nil, nil, nil, err
}
@@ -2106,6 +2170,7 @@ func (s *Server) RunResourceAction(ctx context.Context, q *application.ResourceA
Kind: q.Kind,
Version: q.Version,
Group: q.Group,
Project: q.Project,
}
actionRequest := fmt.Sprintf("%s/%s/%s/%s", rbacpolicy.ActionAction, q.GetGroup(), q.GetKind(), q.GetAction())
liveObj, res, a, config, err := s.getUnstructuredLiveResourceOrApp(ctx, actionRequest, resourceRequest)
@@ -2314,7 +2379,7 @@ 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.GetAppNamespace(), q.GetName(), "")
a, err := s.getApplicationEnforceRBACClient(ctx, rbacpolicy.ActionGet, q.GetProject(), q.GetAppNamespace(), q.GetName(), "")
if err != nil {
return nil, err
}

View File

@@ -13,7 +13,11 @@ import "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1/generated.p
import "github.com/argoproj/argo-cd/v2/reposerver/repository/repository.proto";
// ApplicationQuery is a query for application resources
// ApplicationQuery is a query for application resources. When getting multiple applications, the "projects" field acts
// as a filter. When getting a single application, you may specify either zero or one project. If you specify zero
// projects, the application will be returned regardless of which project it belongs to (assuming you have access). If
// you specify one project, the application will only be returned if it exists and belongs to the specified project.
// Otherwise you will receive a 404.
message ApplicationQuery {
// the application's name
optional string name = 1;
@@ -46,6 +50,7 @@ message RevisionMetadataQuery{
required string revision = 2;
// the application's namespace
optional string appNamespace = 3;
optional string project = 4;
}
// ApplicationEventsQuery is a query for application resource events
@@ -55,6 +60,7 @@ message ApplicationResourceEventsQuery {
optional string resourceName = 3;
optional string resourceUID = 4;
optional string appNamespace = 5;
optional string project = 6;
}
// ManifestQuery is a query for manifest resources
@@ -62,6 +68,7 @@ message ApplicationManifestQuery {
required string name = 1;
optional string revision = 2;
optional string appNamespace = 3;
optional string project = 4;
}
message FileChunk {
@@ -72,6 +79,7 @@ message ApplicationManifestQueryWithFiles {
required string name = 1;
required string checksum = 2;
optional string appNamespace = 3;
optional string project = 4;
}
message ApplicationManifestQueryWithFilesWrapper {
@@ -92,6 +100,7 @@ message ApplicationCreateRequest {
message ApplicationUpdateRequest {
required github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.Application application = 1;
optional bool validate = 2;
optional string project = 3;
}
message ApplicationDeleteRequest {
@@ -99,6 +108,7 @@ message ApplicationDeleteRequest {
optional bool cascade = 2;
optional string propagationPolicy = 3;
optional string appNamespace = 4;
optional string project = 5;
}
message SyncOptions {
@@ -118,6 +128,7 @@ message ApplicationSyncRequest {
optional github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.RetryStrategy retryStrategy = 10;
optional SyncOptions syncOptions = 11;
optional string appNamespace = 12;
optional string project = 13;
}
// ApplicationUpdateSpecRequest is a request to update application spec
@@ -126,6 +137,7 @@ message ApplicationUpdateSpecRequest {
required github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.ApplicationSpec spec = 2;
optional bool validate = 3;
optional string appNamespace = 4;
optional string project = 5;
}
// ApplicationPatchRequest is a request to patch an application
@@ -134,6 +146,7 @@ message ApplicationPatchRequest {
required string patch = 2;
required string patchType = 3;
optional string appNamespace = 5;
optional string project = 6;
}
message ApplicationRollbackRequest {
@@ -142,6 +155,7 @@ message ApplicationRollbackRequest {
optional bool dryRun = 3;
optional bool prune = 4;
optional string appNamespace = 6;
optional string project = 7;
}
message ApplicationResourceRequest {
@@ -152,6 +166,7 @@ message ApplicationResourceRequest {
optional string group = 5;
required string kind = 6;
optional string appNamespace = 7;
optional string project = 8;
}
message ApplicationResourcePatchRequest {
@@ -164,6 +179,7 @@ message ApplicationResourcePatchRequest {
required string patch = 7;
required string patchType = 8;
optional string appNamespace = 9;
optional string project = 10;
}
message ApplicationResourceDeleteRequest {
@@ -176,6 +192,7 @@ message ApplicationResourceDeleteRequest {
optional bool force = 7;
optional bool orphan = 8;
optional string appNamespace = 9;
optional string project = 10;
}
message ResourceActionRunRequest {
@@ -187,6 +204,7 @@ message ResourceActionRunRequest {
required string kind = 6;
required string action = 7;
optional string appNamespace = 8;
optional string project = 9;
}
message ResourceActionsListResponse {
@@ -213,6 +231,7 @@ message ApplicationPodLogsQuery {
optional string resourceName = 13 ;
optional bool previous = 14;
optional string appNamespace = 15;
optional string project = 16;
}
message LogEntry {
@@ -227,11 +246,13 @@ message LogEntry {
message OperationTerminateRequest {
required string name = 1;
optional string appNamespace = 2;
optional string project = 3;
}
message ApplicationSyncWindowsQuery {
required string name = 1;
optional string appNamespace = 2;
optional string project = 3;
}
message ApplicationSyncWindowsResponse {
@@ -260,6 +281,7 @@ message ResourcesQuery {
optional string group = 5;
optional string kind = 6;
optional string appNamespace = 7;
optional string project = 8;
}
message ManagedResourcesResponse {
@@ -280,6 +302,7 @@ message LinksResponse {
message ListAppLinksRequest {
required string name = 1;
optional string namespace = 3;
optional string project = 4;
}

View File

@@ -10,6 +10,8 @@ import (
"testing"
"time"
"k8s.io/apimachinery/pkg/labels"
"github.com/argoproj/gitops-engine/pkg/health"
synccommon "github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
@@ -88,14 +90,14 @@ func fakeAppList() *apiclient.AppList {
}
}
func fakeResolveRevesionResponse() *apiclient.ResolveRevisionResponse {
func fakeResolveRevisionResponse() *apiclient.ResolveRevisionResponse {
return &apiclient.ResolveRevisionResponse{
Revision: "f9ba9e98119bf8c1176fbd65dbae26a71d044add",
AmbiguousRevision: "HEAD (f9ba9e98119bf8c1176fbd65dbae26a71d044add)",
}
}
func fakeResolveRevesionResponseHelm() *apiclient.ResolveRevisionResponse {
func fakeResolveRevisionResponseHelm() *apiclient.ResolveRevisionResponse {
return &apiclient.ResolveRevisionResponse{
Revision: "0.7.*",
AmbiguousRevision: "0.7.* (0.7.2)",
@@ -113,11 +115,12 @@ func fakeRepoServerClient(isHelm bool) *mocks.RepoServerServiceClient {
mockWithFilesClient.On("Send", mock.Anything).Return(nil)
mockWithFilesClient.On("CloseAndRecv").Return(&apiclient.ManifestResponse{}, nil)
mockRepoServiceClient.On("GenerateManifestWithFiles", mock.Anything, mock.Anything).Return(mockWithFilesClient, nil)
mockRepoServiceClient.On("GetRevisionChartDetails", mock.Anything, mock.Anything).Return(&appsv1.ChartDetails{}, nil)
if isHelm {
mockRepoServiceClient.On("ResolveRevision", mock.Anything, mock.Anything).Return(fakeResolveRevesionResponseHelm(), nil)
mockRepoServiceClient.On("ResolveRevision", mock.Anything, mock.Anything).Return(fakeResolveRevisionResponseHelm(), nil)
} else {
mockRepoServiceClient.On("ResolveRevision", mock.Anything, mock.Anything).Return(fakeResolveRevesionResponse(), nil)
mockRepoServiceClient.On("ResolveRevision", mock.Anything, mock.Anything).Return(fakeResolveRevisionResponse(), nil)
}
return &mockRepoServiceClient
@@ -568,6 +571,7 @@ type TestServerStream struct {
ctx context.Context
appName string
headerSent bool
project string
}
func (t *TestServerStream) SetHeader(metadata.MD) error {
@@ -602,6 +606,7 @@ func (t *TestServerStream) Recv() (*application.ApplicationManifestQueryWithFile
return &application.ApplicationManifestQueryWithFilesWrapper{Part: &application.ApplicationManifestQueryWithFilesWrapper_Query{
Query: &application.ApplicationManifestQueryWithFiles{
Name: pointer.String(t.appName),
Project: pointer.String(t.project),
Checksum: pointer.String(""),
},
}}, nil
@@ -722,8 +727,31 @@ func TestNoAppEnumeration(t *testing.T) {
},
}
})
testHelmApp := newTestApp(func(app *appsv1.Application) {
app.Name = "test-helm"
app.Spec.Source.Path = ""
app.Spec.Source.Chart = "test"
app.Status.Resources = []appsv1.ResourceStatus{
{
Group: deployment.GroupVersionKind().Group,
Kind: deployment.GroupVersionKind().Kind,
Version: deployment.GroupVersionKind().Version,
Name: deployment.Name,
Namespace: deployment.Namespace,
Status: "Synced",
},
}
app.Status.History = []appsv1.RevisionHistory{
{
ID: 0,
Source: appsv1.ApplicationSource{
TargetRevision: "something-old",
},
},
}
})
testDeployment := kube.MustToUnstructured(&deployment)
appServer := newTestAppServerWithEnforcerConfigure(f, t, testApp, testDeployment)
appServer := newTestAppServerWithEnforcerConfigure(f, t, testApp, testHelmApp, testDeployment)
noRoleCtx := context.Background()
// nolint:staticcheck
@@ -739,6 +767,9 @@ func TestNoAppEnumeration(t *testing.T) {
// nolint:staticcheck
_, err = appServer.Get(adminCtx, &application.ApplicationQuery{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
// nolint:staticcheck
_, err = appServer.Get(adminCtx, &application.ApplicationQuery{Name: pointer.String("doest-not-exist"), Project: []string{"test"}})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("GetManifests", func(t *testing.T) {
@@ -748,6 +779,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.GetManifests(adminCtx, &application.ApplicationManifestQuery{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.GetManifests(adminCtx, &application.ApplicationManifestQuery{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("ListResourceEvents", func(t *testing.T) {
@@ -757,6 +790,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ListResourceEvents(adminCtx, &application.ApplicationResourceEventsQuery{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ListResourceEvents(adminCtx, &application.ApplicationResourceEventsQuery{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("UpdateSpec", func(t *testing.T) {
@@ -775,6 +810,11 @@ func TestNoAppEnumeration(t *testing.T) {
Source: &appsv1.ApplicationSource{RepoURL: "https://some-fake-source", Path: "."},
}})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.UpdateSpec(adminCtx, &application.ApplicationUpdateSpecRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test"), Spec: &appsv1.ApplicationSpec{
Destination: appsv1.ApplicationDestination{Namespace: "default", Server: "https://cluster-api.com"},
Source: &appsv1.ApplicationSource{RepoURL: "https://some-fake-source", Path: "."},
}})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("Patch", func(t *testing.T) {
@@ -784,6 +824,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.Patch(adminCtx, &application.ApplicationPatchRequest{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.Patch(adminCtx, &application.ApplicationPatchRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("GetResource", func(t *testing.T) {
@@ -793,6 +835,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.GetResource(adminCtx, &application.ApplicationResourceRequest{Name: pointer.String("doest-not-exist"), ResourceName: pointer.String("test"), Group: pointer.String("apps"), Kind: pointer.String("Deployment"), Namespace: pointer.String("test")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.GetResource(adminCtx, &application.ApplicationResourceRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test"), ResourceName: pointer.String("test"), Group: pointer.String("apps"), Kind: pointer.String("Deployment"), Namespace: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("PatchResource", func(t *testing.T) {
@@ -804,6 +848,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.PatchResource(adminCtx, &application.ApplicationResourcePatchRequest{Name: pointer.String("doest-not-exist"), ResourceName: pointer.String("test"), Group: pointer.String("apps"), Kind: pointer.String("Deployment"), Namespace: pointer.String("test"), Patch: pointer.String(`[{"op": "replace", "path": "/spec/replicas", "value": 3}]`)})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.PatchResource(adminCtx, &application.ApplicationResourcePatchRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test"), ResourceName: pointer.String("test"), Group: pointer.String("apps"), Kind: pointer.String("Deployment"), Namespace: pointer.String("test"), Patch: pointer.String(`[{"op": "replace", "path": "/spec/replicas", "value": 3}]`)})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("DeleteResource", func(t *testing.T) {
@@ -813,6 +859,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.DeleteResource(adminCtx, &application.ApplicationResourceDeleteRequest{Name: pointer.String("doest-not-exist"), ResourceName: pointer.String("test"), Group: pointer.String("apps"), Kind: pointer.String("Deployment"), Namespace: pointer.String("test")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.DeleteResource(adminCtx, &application.ApplicationResourceDeleteRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test"), ResourceName: pointer.String("test"), Group: pointer.String("apps"), Kind: pointer.String("Deployment"), Namespace: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("ResourceTree", func(t *testing.T) {
@@ -822,6 +870,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ResourceTree(adminCtx, &application.ResourcesQuery{ApplicationName: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ResourceTree(adminCtx, &application.ResourcesQuery{ApplicationName: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("RevisionMetadata", func(t *testing.T) {
@@ -831,6 +881,19 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.RevisionMetadata(adminCtx, &application.RevisionMetadataQuery{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.RevisionMetadata(adminCtx, &application.RevisionMetadataQuery{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("RevisionChartDetails", func(t *testing.T) {
_, err := appServer.RevisionChartDetails(adminCtx, &application.RevisionMetadataQuery{Name: pointer.String("test-helm")})
assert.NoError(t, err)
_, err = appServer.RevisionChartDetails(noRoleCtx, &application.RevisionMetadataQuery{Name: pointer.String("test-helm")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.RevisionChartDetails(adminCtx, &application.RevisionMetadataQuery{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.RevisionChartDetails(adminCtx, &application.RevisionMetadataQuery{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("ManagedResources", func(t *testing.T) {
@@ -840,6 +903,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ManagedResources(adminCtx, &application.ResourcesQuery{ApplicationName: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ManagedResources(adminCtx, &application.ResourcesQuery{ApplicationName: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("Sync", func(t *testing.T) {
@@ -849,6 +914,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.Sync(adminCtx, &application.ApplicationSyncRequest{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.Sync(adminCtx, &application.ApplicationSyncRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("TerminateOperation", func(t *testing.T) {
@@ -861,6 +928,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.TerminateOperation(adminCtx, &application.OperationTerminateRequest{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.TerminateOperation(adminCtx, &application.OperationTerminateRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("Rollback", func(t *testing.T) {
@@ -871,6 +940,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.Rollback(adminCtx, &application.ApplicationRollbackRequest{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.Rollback(adminCtx, &application.ApplicationRollbackRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("ListResourceActions", func(t *testing.T) {
@@ -882,6 +953,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ListResourceActions(adminCtx, &application.ApplicationResourceRequest{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ListResourceActions(adminCtx, &application.ApplicationResourceRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("RunResourceAction", func(t *testing.T) {
@@ -893,6 +966,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.RunResourceAction(adminCtx, &application.ResourceActionRunRequest{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.RunResourceAction(adminCtx, &application.ResourceActionRunRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("GetApplicationSyncWindows", func(t *testing.T) {
@@ -902,6 +977,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.GetApplicationSyncWindows(adminCtx, &application.ApplicationSyncWindowsQuery{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.GetApplicationSyncWindows(adminCtx, &application.ApplicationSyncWindowsQuery{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("GetManifestsWithFiles", func(t *testing.T) {
@@ -911,6 +988,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
err = appServer.GetManifestsWithFiles(&TestServerStream{ctx: adminCtx, appName: "does-not-exist"})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
err = appServer.GetManifestsWithFiles(&TestServerStream{ctx: adminCtx, appName: "does-not-exist", project: "test"})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"does-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("WatchResourceTree", func(t *testing.T) {
@@ -920,6 +999,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
err = appServer.WatchResourceTree(&application.ResourcesQuery{ApplicationName: pointer.String("does-not-exist")}, &TestResourceTreeServer{ctx: adminCtx})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
err = appServer.WatchResourceTree(&application.ResourcesQuery{ApplicationName: pointer.String("does-not-exist"), Project: pointer.String("test")}, &TestResourceTreeServer{ctx: adminCtx})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"does-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("PodLogs", func(t *testing.T) {
@@ -929,6 +1010,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
err = appServer.PodLogs(&application.ApplicationPodLogsQuery{Name: pointer.String("does-not-exist")}, &TestPodLogsServer{ctx: adminCtx})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
err = appServer.PodLogs(&application.ApplicationPodLogsQuery{Name: pointer.String("does-not-exist"), Project: pointer.String("test")}, &TestPodLogsServer{ctx: adminCtx})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"does-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("ListLinks", func(t *testing.T) {
@@ -938,6 +1021,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ListLinks(adminCtx, &application.ListAppLinksRequest{Name: pointer.String("does-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ListLinks(adminCtx, &application.ListAppLinksRequest{Name: pointer.String("does-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"does-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
t.Run("ListResourceLinks", func(t *testing.T) {
@@ -947,6 +1032,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ListResourceLinks(adminCtx, &application.ApplicationResourceRequest{Name: pointer.String("does-not-exist"), ResourceName: pointer.String("test"), Group: pointer.String("apps"), Kind: pointer.String("Deployment"), Namespace: pointer.String("test")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.ListResourceLinks(adminCtx, &application.ApplicationResourceRequest{Name: pointer.String("does-not-exist"), ResourceName: pointer.String("test"), Group: pointer.String("apps"), Kind: pointer.String("Deployment"), Namespace: pointer.String("test"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"does-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
// Do this last so other stuff doesn't fail.
@@ -957,6 +1044,8 @@ func TestNoAppEnumeration(t *testing.T) {
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.Delete(adminCtx, &application.ApplicationDeleteRequest{Name: pointer.String("doest-not-exist")})
assert.Equal(t, permissionDeniedErr.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about app existence")
_, err = appServer.Delete(adminCtx, &application.ApplicationDeleteRequest{Name: pointer.String("doest-not-exist"), Project: pointer.String("test")})
assert.Equal(t, "rpc error: code = NotFound desc = applications.argoproj.io \"doest-not-exist\" not found", err.Error(), "when the request specifies a project, we can return the standard k8s error message")
})
}
@@ -1616,7 +1705,7 @@ p, admin, applications, update, default/test-app, allow
p, admin, applications, create, my-proj/test-app, allow
`)
_, err := appServer.Update(ctx, &application.ApplicationUpdateRequest{Application: testApp})
assert.Equal(t, status.Code(err), codes.PermissionDenied)
assert.Equal(t, codes.PermissionDenied, status.Code(err))
})
t.Run("cannot change projects without update privileges in old project", func(t *testing.T) {
@@ -2202,3 +2291,55 @@ func TestRunOldStyleResourceAction(t *testing.T) {
assert.NotNil(t, appResponse)
})
}
func TestIsApplicationPermitted(t *testing.T) {
t.Run("Incorrect project", func(t *testing.T) {
testApp := newTestApp()
appServer := newTestAppServer(t, testApp)
projects := map[string]bool{"test-app": false}
permitted := appServer.isApplicationPermitted(labels.Everything(), 0, nil, "test", "default", projects, *testApp)
assert.False(t, permitted)
})
t.Run("Version is incorrect", func(t *testing.T) {
testApp := newTestApp()
appServer := newTestAppServer(t, testApp)
minVersion := 100000
testApp.ResourceVersion = strconv.Itoa(minVersion - 1)
permitted := appServer.isApplicationPermitted(labels.Everything(), minVersion, nil, "test", "default", nil, *testApp)
assert.False(t, permitted)
})
t.Run("Application name is incorrect", func(t *testing.T) {
testApp := newTestApp()
appServer := newTestAppServer(t, testApp)
appName := "test"
permitted := appServer.isApplicationPermitted(labels.Everything(), 0, nil, appName, "default", nil, *testApp)
assert.False(t, permitted)
})
t.Run("Application namespace is incorrect", func(t *testing.T) {
testApp := newTestApp()
appServer := newTestAppServer(t, testApp)
permitted := appServer.isApplicationPermitted(labels.Everything(), 0, nil, testApp.Name, "demo", nil, *testApp)
assert.False(t, permitted)
})
t.Run("Application is not part of enabled namespace", func(t *testing.T) {
testApp := newTestApp()
appServer := newTestAppServer(t, testApp)
appServer.ns = "server-ns"
appServer.enabledNamespaces = []string{"demo"}
permitted := appServer.isApplicationPermitted(labels.Everything(), 0, nil, testApp.Name, testApp.Namespace, nil, *testApp)
assert.False(t, permitted)
})
t.Run("Application is part of enabled namespace", func(t *testing.T) {
testApp := newTestApp()
appServer := newTestAppServer(t, testApp)
appServer.ns = "server-ns"
appServer.enabledNamespaces = []string{testApp.Namespace}
permitted := appServer.isApplicationPermitted(labels.Everything(), 0, nil, testApp.Name, testApp.Namespace, nil, *testApp)
assert.True(t, permitted)
})
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"io"
"net/http"
"time"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
log "github.com/sirupsen/logrus"
@@ -228,6 +229,10 @@ func (s *terminalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
defer session.Done()
// send pings across the WebSocket channel at regular intervals to keep it alive through
// load balancers which may close an idle connection after some period of time
go session.StartKeepalives(time.Second * 5)
if isValidShell(s.allowedShells, shell) {
cmd := []string{shell}
err = startProcess(kubeClientset, config, namespace, podName, container, cmd, session)

View File

@@ -51,6 +51,23 @@ func (t *terminalSession) Done() {
close(t.doneChan)
}
func (t *terminalSession) StartKeepalives(dur time.Duration) {
ticker := time.NewTicker(dur)
defer ticker.Stop()
for {
select {
case <-ticker.C:
err := t.Ping()
if err != nil {
log.Errorf("ping error: %v", err)
return
}
case <-t.doneChan:
return
}
}
}
// Next called in a loop from remotecommand as long as the process is running
func (t *terminalSession) Next() *remotecommand.TerminalSize {
select {
@@ -86,6 +103,17 @@ func (t *terminalSession) Read(p []byte) (int, error) {
}
}
// Ping called periodically to ensure connection stays alive through load balancers
func (t *terminalSession) Ping() error {
t.writeLock.Lock()
err := t.wsConn.WriteMessage(websocket.PingMessage, []byte("ping"))
t.writeLock.Unlock()
if err != nil {
log.Errorf("ping message err: %v", err)
}
return err
}
// Write called from remotecommand whenever there is any output
func (t *terminalSession) Write(p []byte) (int, error) {
msg, err := json.Marshal(TerminalMessage{

View File

@@ -1,5 +1,5 @@
# This file was automatically generated. DO NOT EDIT
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf

View File

@@ -8,7 +8,7 @@ RUN ln -s /usr/lib/$(uname -m)-linux-gnu /usr/lib/linux-gnu
# Please make sure to also check the contained yarn version and update the references below when upgrading this image's version
FROM docker.io/library/node:20.3.1@sha256:2f0b0c15f97441defa812268ee943bbfaaf666ea6cf7cac62ee3f127906b35c6 as node
FROM docker.io/library/golang:1.20.5@sha256:4b1fc02d16fca272e5e6e6adc98396219b43ef663a377eef4a97e881d364393f as golang
FROM docker.io/library/golang:1.20.6@sha256:8e5a0067e6b387263a01d06b91ef1a983f90e9638564f6e25392fd2695f7ab6c as golang
FROM docker.io/library/registry:2.8@sha256:41f413c22d6156587e2a51f3e80c09808b8c70e82be149b82b5e0196a88d49b4 as registry

View File

@@ -1,6 +1,6 @@
controller: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-application-controller $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''}"
api-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_BINARY_NAME=argocd-server $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''} "
dex: sh -c "test $ARGOCD_IN_CI = true && exit 0; ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/cmd gendexcfg -o `pwd`/dist/dex.yaml && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml ghcr.io/dexidp/dex:v2.36.0 serve /dex.yaml"
dex: sh -c "test $ARGOCD_IN_CI = true && exit 0; ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/cmd gendexcfg -o `pwd`/dist/dex.yaml && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml ghcr.io/dexidp/dex:v2.37.0 serve /dex.yaml"
redis: sh -c "/usr/local/bin/redis-server --save "" --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}"
repo-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_GNUPGHOME=${ARGOCD_GNUPGHOME:-/tmp/argocd-local/gpg/keys} ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} ARGOCD_BINARY_NAME=argocd-repo-server $COMMAND --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379}"
ui: sh -c "test $ARGOCD_IN_CI = true && exit 0; cd ui && ARGOCD_E2E_YARN_HOST=0.0.0.0 ${ARGOCD_E2E_YARN_CMD:-yarn} start"

View File

@@ -1179,7 +1179,7 @@ func TestNamespacedPermissions(t *testing.T) {
Create()
sourceError := fmt.Sprintf("application repo %s is not permitted in project 'argo-project'", RepoURL(RepoURLTypeFile))
destinationError := fmt.Sprintf("application destination {%s %s} is not permitted in project 'argo-project'", KubernetesInternalAPIServerAddr, DeploymentNamespace())
destinationError := fmt.Sprintf("application destination server '%s' and namespace '%s' do not match any of the allowed destinations in project 'argo-project'", KubernetesInternalAPIServerAddr, DeploymentNamespace())
appCtx.
Path("guestbook-logs").

View File

@@ -271,6 +271,61 @@ func TestSyncToSignedCommitWithKnownKey(t *testing.T) {
Expect(HealthIs(health.HealthStatusHealthy))
}
func TestSyncToSignedBranchWithKnownKey(t *testing.T) {
SkipOnEnv(t, "GPG")
Given(t).
Project("gpg").
Path(guestbookPath).
Revision("master").
GPGPublicKeyAdded().
Sleep(2).
When().
AddSignedFile("test.yaml", "null").
IgnoreErrors().
CreateApp().
Sync().
Then().
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(HealthIs(health.HealthStatusHealthy))
}
func TestSyncToSignedBranchWithUnknownKey(t *testing.T) {
SkipOnEnv(t, "GPG")
Given(t).
Project("gpg").
Path(guestbookPath).
Revision("master").
Sleep(2).
When().
AddSignedFile("test.yaml", "null").
IgnoreErrors().
CreateApp().
Sync().
Then().
Expect(OperationPhaseIs(OperationError)).
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
Expect(HealthIs(health.HealthStatusMissing))
}
func TestSyncToUnsignedBranch(t *testing.T) {
SkipOnEnv(t, "GPG")
Given(t).
Project("gpg").
Revision("master").
Path(guestbookPath).
GPGPublicKeyAdded().
Sleep(2).
When().
IgnoreErrors().
CreateApp().
Sync().
Then().
Expect(OperationPhaseIs(OperationError)).
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
Expect(HealthIs(health.HealthStatusMissing))
}
func TestSyncToSignedTagWithKnownKey(t *testing.T) {
SkipOnEnv(t, "GPG")
Given(t).
@@ -1417,7 +1472,7 @@ func TestPermissions(t *testing.T) {
Create()
sourceError := fmt.Sprintf("application repo %s is not permitted in project 'argo-project'", RepoURL(RepoURLTypeFile))
destinationError := fmt.Sprintf("application destination {%s %s} is not permitted in project 'argo-project'", KubernetesInternalAPIServerAddr, DeploymentNamespace())
destinationError := fmt.Sprintf("application destination server '%s' and namespace '%s' do not match any of the allowed destinations in project 'argo-project'", KubernetesInternalAPIServerAddr, DeploymentNamespace())
appCtx.
Path("guestbook-logs").
@@ -1573,7 +1628,7 @@ func TestPermissionDeniedWithNegatedNamespace(t *testing.T) {
IgnoreErrors().
CreateApp().
Then().
Expect(Error("", "is not permitted in project"))
Expect(Error("", "do not match any of the allowed destinations in project"))
}
func TestPermissionDeniedWithNegatedServer(t *testing.T) {
@@ -1600,7 +1655,7 @@ func TestPermissionDeniedWithNegatedServer(t *testing.T) {
IgnoreErrors().
CreateApp().
Then().
Expect(Error("", "is not permitted in project"))
Expect(Error("", "do not match any of the allowed destinations in project"))
}
// make sure that if we deleted a resource from the app, it is not pruned if annotated with Prune=false

View File

@@ -5,12 +5,14 @@ import (
"github.com/argoproj/gitops-engine/pkg/health"
. "github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/stretchr/testify/assert"
. "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
. "github.com/argoproj/argo-cd/v2/test/e2e/fixture"
. "github.com/argoproj/argo-cd/v2/test/e2e/fixture/app"
"github.com/argoproj/argo-cd/v2/util/argo"
)
// ensure that cluster scoped objects, like a cluster role, as a hok, can be successfully deployed
func TestClusterRoleBinding(t *testing.T) {
Given(t).
Path("cluster-role").
@@ -20,5 +22,35 @@ func TestClusterRoleBinding(t *testing.T) {
Then().
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(HealthIs(health.HealthStatusHealthy)).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
diffOutput, err := RunCli("app", "diff", app.Name, "--revision=HEAD")
assert.NoError(t, err)
assert.Empty(t, diffOutput)
}).
When().
SetTrackingMethod(string(argo.TrackingMethodAnnotation)).
Sync().
Then().
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(HealthIs(health.HealthStatusHealthy)).
And(func(app *Application) {
diffOutput, err := RunCli("app", "diff", app.Name, "--revision=HEAD")
assert.NoError(t, err)
assert.Empty(t, diffOutput)
})
}
// ensure that cluster scoped objects, like a cluster role, as a hook, can be successfully deployed
func TestClusterRoleBindingHook(t *testing.T) {
Given(t).
Path("cluster-role-hook").
When().
CreateApp().
Sync().
Then().
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(HealthIs(health.HealthStatusHealthy)).
Expect(SyncStatusIs(SyncStatusCodeSynced))
}

View File

@@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
namespace: cert-manager
name: my-cluster-role-binding
annotations:
argocd.argoproj.io/hook: PreSync
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: default
namespace: default

View File

@@ -1,10 +1,7 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
namespace: cert-manager
name: my-cluster-role-binding
annotations:
argocd.argoproj.io/hook: PreSync
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
@@ -12,4 +9,4 @@ roleRef:
subjects:
- kind: ServiceAccount
name: default
namespace: default
namespace: default

View File

@@ -1,6 +1,6 @@
ARG BASE_IMAGE=docker.io/library/ubuntu:22.04
FROM docker.io/library/golang:1.20.5@sha256:4b1fc02d16fca272e5e6e6adc98396219b43ef663a377eef4a97e881d364393f AS go
FROM docker.io/library/golang:1.20.6@sha256:8e5a0067e6b387263a01d06b91ef1a983f90e9638564f6e25392fd2695f7ab6c AS go
RUN go install github.com/mattn/goreman@latest && \
go install github.com/kisielk/godepgraph@latest

View File

@@ -8,7 +8,7 @@ import {LogEntry} from '../../../shared/models';
import {services, ViewPreferences} from '../../../shared/services';
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
import List from 'react-virtualized/dist/commonjs/List';
import Grid from 'react-virtualized/dist/commonjs/Grid';
import './pod-logs-viewer.scss';
import {CopyLogsButton} from './copy-logs-button';
@@ -26,6 +26,7 @@ import {TailSelector} from './tail-selector';
import {PodNamesToggleButton} from './pod-names-toggle-button';
import Ansi from 'ansi-to-react';
import {AutoScrollButton} from './auto-scroll-button';
import {GridCellProps} from 'react-virtualized/dist/es/Grid';
export interface PodLogsProps {
namespace: string;
@@ -133,14 +134,22 @@ export const PodsLogsViewer = (props: PodLogsProps) => {
// show the log content, highlight the filter text
log.content?.replace(highlight, (substring: string) => whiteOnYellow + substring + reset);
const rowRenderer = ({index, key, style}: {index: number; key: string; style: React.CSSProperties}) => {
const cellRenderer = ({rowIndex, key, style}: GridCellProps) => {
return (
<pre key={key} style={style} className='noscroll'>
<Ansi>{renderLog(logs[index], index)}</Ansi>
<Ansi>{renderLog(logs[rowIndex], rowIndex)}</Ansi>
</pre>
);
};
// calculate the width of the grid based on the longest log line
const maxWidth =
14 *
logs
.map(renderLog)
.map(v => v.length)
.reduce((a, b) => Math.max(a, b), 0);
return (
<DataLoader load={() => services.viewPreferences.getPreferences()}>
{(prefs: ViewPreferences) => {
@@ -178,18 +187,19 @@ export const PodsLogsViewer = (props: PodLogsProps) => {
<div
className={classNames('pod-logs-viewer', {'pod-logs-viewer--inverted': prefs.appDetails.darkMode})}
onWheel={e => {
if (e.deltaY !== 0) setScrollToBottom(false);
if (e.deltaY < 0) setScrollToBottom(false);
}}>
<AutoSizer>
{({width, height}: {width: number; height: number}) => (
<List
rowCount={logs.length}
<Grid
cellRenderer={cellRenderer}
columnCount={1}
columnWidth={Math.max(width, maxWidth)}
height={height}
rowCount={logs.length}
rowHeight={18}
rowRenderer={rowRenderer}
width={width}
noRowsRenderer={() => <>No logs</>}
scrollToIndex={scrollToBottom ? logs.length - 1 : undefined}
scrollToRow={scrollToBottom ? logs.length - 1 : undefined}
/>
)}
</AutoSizer>

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