Compare commits

...

598 Commits

Author SHA1 Message Date
argo-bot
ac8b7df946 Bump version to 2.3.4 2022-05-18 11:32:27 +00:00
argo-bot
5d515b8423 Bump version to 2.3.4 2022-05-18 11:32:11 +00:00
jannfis
69dcee049e Merge pull request from GHSA-r642-gv9p-2wjj
Signed-off-by: jannfis <jann@mistrust.net>

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-18 13:16:21 +02:00
Michael Crenshaw
d36d95dc9f Merge pull request from GHSA-6gcg-hp2x-q54h
* fix: do not allow symlinks from directory-type applications

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: add new util file

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: lint

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: use t.TempDir for simpler tests

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* address comments

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-18 13:13:41 +02:00
jannfis
df79d7db1d Merge pull request from GHSA-xmg8-99r8-jc2j
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-18 13:06:31 +02:00
Daniel Helfand
7165431a84 fix: allow cli/ui to follow logs (#8987) (#9065)
Signed-off-by: Daniel Helfand <helfand.4@gmail.com>
2022-04-11 11:34:42 -04:00
Michael Crenshaw
13ec3f43d8 chore: upgrade to go 1.17.8 (#8866) (#9004)
* chore: upgrade to go 1.17.8

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: use 1.17 so it's always latest in the series

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-04-05 08:45:56 -07:00
Alexander Matyushentsev
eea93c5103 fix: fix broken monaco editor collapse icons (#8709)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-03-30 14:19:23 -07:00
pasha-codefresh
2cc81959b4 fix: Fix docs build error (#8895)
* work with specific jinja version

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-03-30 11:29:28 -07:00
argo-bot
07ac038a8f Bump version to 2.3.3 2022-03-29 23:56:04 +00:00
argo-bot
3828da7f8c Bump version to 2.3.3 2022-03-29 23:55:46 +00:00
Alexander Matyushentsev
3bd9121545 docs: reflect v2.3 release changes in roadmap.md (#8747)
docs: reflect v2.3 release changes in roadmap.md (#8747)

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-03-29 16:49:52 -07:00
Ishita Sequeira
df6e7c169e docs: update v2.4+ roadmap items (#8593)
Signed-off-by: ishitasequeira <isequeir@redhat.com>
2022-03-29 16:49:48 -07:00
Alexander Matyushentsev
25b01666f0 fix: bump gitops engine version to v0.6.2
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-03-29 15:20:54 -07:00
Michael Crenshaw
9d6e6d84de fix: prevent excessive repo-server disk usage for large repos (#8845) (#8897)
fix: prevent excessive repo-server disk usage for large repos (#8845) (#8897)

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-03-29 15:14:10 -07:00
jannfis
7f9ff6e8c3 fix: Set QPS and burst rate for resource ops client (#8915)
* fix: Set QPS and burst rate for resource ops client

Signed-off-by: jannfis <jann@mistrust.net>
2022-03-29 07:34:31 +00:00
argo-bot
ecc2af9dca Bump version to 2.3.2 2022-03-23 00:32:13 +00:00
argo-bot
c5b0279050 Bump version to 2.3.2 2022-03-23 00:31:57 +00:00
Michael Crenshaw
6df17e7c56 chore: fix imports (#8859)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-03-22 12:55:09 -07:00
Michael Crenshaw
e55ecf9107 chore: remove lint-docs CI task (#8722) (#8858)
* chore: remove lint-docs CI task

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

* chore: remove not longer necessary url-allow-list

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

Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-03-22 12:54:37 -07:00
Alexander Matyushentsev
21f208f17e Merge pull request from GHSA-2f5v-8r3f-8pww
* fix: application resource APIs must enforce project restrictions

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

* Fix unit tests

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

Co-authored-by: jannfis <jann@mistrust.net>
2022-03-22 10:57:31 -07:00
argo-bot
b65c1699fa Bump version to 2.3.1 2022-03-10 22:43:44 +00:00
argo-bot
4c1428a6be Bump version to 2.3.1 2022-03-10 22:43:24 +00:00
Keith Chong
bca190bd0c fix: Retry checkbox unchecked unexpectedly; Sync up with YAML (#8682) (#8720)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2022-03-10 14:23:30 -08:00
Alexander Matyushentsev
88ca5aabf2 chore: Bump stable version of application set addon (#8744)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-03-10 13:19:44 -08:00
Alexander Matyushentsev
8297f827a8 fix: correct jsonnet paths resolution (#8721)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-03-08 15:59:03 -08:00
Yuan Tang
b85ef39e0d fix(ui): Applications page incorrectly resets to tiles view. Fixes #8702 (#8718)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2022-03-08 11:24:02 -08:00
argo-bot
fe42780229 Bump version to 2.3.0 2022-03-06 06:18:59 +00:00
argo-bot
057d95374d Bump version to 2.3.0 2022-03-06 06:18:41 +00:00
Yuan Tang
1546c1d314 fix: Health status bar button does not re-render properly. Fixes #8569 (#8668)
fix: Health status bar button does not re-render properly. Fixes #8569 (#8668)

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2022-03-04 10:41:25 -08:00
jannfis
31564c6067 fix: Allow quoted RBAC group names in API (#8650)
Signed-off-by: jannfis <jann@mistrust.net>
Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
2022-03-04 07:35:21 +00:00
Alexander Matyushentsev
6e54e59e82 fix: prevent file traversal using helm file values param and application details api (#8606)
* fix: prevent file traversal using helm file values param and application details api

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

* apply reviewer notes: move resolve.go into separate package; use uuid to generate random file

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:43:03 -08:00
Alexander Matyushentsev
196dab98dc Unique repo path and permissions (#8517)
Unique repo path and permissions (#8517)

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:42:59 -08:00
Michael Crenshaw
9d4ed2847e chore: bump redoc vesion to avoid CVE-2021-23820 (#8604)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-02-25 15:42:52 -08:00
Yuan Tang
ffc6080060 build: Bump up network timeout during yarn install (#8601)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2022-02-25 15:42:46 -08:00
Alexander Matyushentsev
ca2e3041f1 refactor: use argocd-git-ask-pass to pass git credentials to git/kustomize (#8516)
refactor: use argocd-git-ask-pass to pass git credentials to git/kustomize  (#8516)

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:42:11 -08:00
Michael Crenshaw
31676e2aea fix: add labels to sidecar CMP manifests (#8243) (#8367)
fix: add labels to sidecar CMP manifests (#8243) (#8367)

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-02-25 15:42:05 -08:00
Michael Crenshaw
81f9bc20ec chore: pass submodulesEnabled explicitly to avoid implicit parameter (#8337)
* chore: pass submodulesEnabled explicitly to avoid implicit parameter

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* fix: update mock

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: lint

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* fix: mock checkout invocations w/ 2 params

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: remove unnecessary comment

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-02-25 15:40:20 -08:00
Jesse Suen
0b868bd221 fix!: enforce app create/update privileges when getting repo details (#8558)
Signed-off-by: Jesse Suen <jesse@akuity.io>
2022-02-25 15:39:26 -08:00
Yuan Tang
37c1585c2f feat(cli): Allow to view previously terminated container logs (#8582)
* feat(cli): Allow to view previously terminated container logs

This is useful when we want to see the snapshot of previously terminated container logs.

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* chore: Generate docs

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2022-02-25 15:39:18 -08:00
pasha-codefresh
e095ef6e4c chore(deps): bump mkdocs from 1.1.2 to 1.2.3 in /docs (#8588)
chore(deps): bump mkdocs from 1.1.2 to 1.2.3 in /docs (#8588)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-02-25 15:39:04 -08:00
pasha-codefresh
8396e06121 fix: Upgrade monaco-editor from 0.15.6 to 0.27.0 (#8590)
fix: Upgrade monaco-editor from 0.15.6 to 0.27.0 (#8590)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-02-25 15:38:57 -08:00
Ben Ye
d4a6498d80 feat: expose cluster sync retry duration (#8481)
Signed-off-by: Ben Ye <ben.ye@bytedance.com>
2022-02-25 15:38:49 -08:00
Yi Cai
4fc814bc16 fix: UI: Favorite star icon is cut off (#8556)
* fix: UI: Favorite star icon is cut off

Signed-off-by: ciiay <yicai@redhat.com>

* fixed lint error

Signed-off-by: ciiay <yicai@redhat.com>
2022-02-25 15:38:39 -08:00
Michael Crenshaw
bf67d55f3f chore: upgrade redoc (#8573)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-02-25 15:38:33 -08:00
dependabot[bot]
87402fdc4c build(deps): bump url-parse from 1.5.3 to 1.5.7 in /ui (#8557)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.3 to 1.5.7.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.3...1.5.7)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-25 15:38:19 -08:00
Alexander Matyushentsev
10b4c47aad feat: support custom helm values file schemes (#8535)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:37:45 -08:00
Alexander Matyushentsev
e6a9400c38 feat: support disabling manifest generation using config management tools (#8514)
* feat: support disabling manifest generation using config management tools

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

* rename EnableManifestGenerationForSourceType to EnableSourceTypes

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:36:27 -08:00
Alexander Matyushentsev
ebb21736df fix: build ui as part of 'make release-cli' command (#8536)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:36:21 -08:00
Alexander Matyushentsev
ea7ad844cb fix: refreshing label is hidden by resource tree (#8391)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:36:12 -08:00
jannfis
76c0b32887 fix: Return early on error when updating clusters (#8526)
Signed-off-by: jannfis <jann@mistrust.net>
2022-02-25 15:36:06 -08:00
Christian Roth
827096c195 docs: Using Dex with OIDC needs the config element in yaml (#8510)
In order to get Dex working with an OIDC provider, I had to structure the Dex config according to the [Dex Documentation](https://dexidp.io/docs/connectors/oidc/#configuration).
This means placing the OIDC configuration within their own `config` element in the `dex.config`, rather than listing them on the same level as the generic connector settings.
2022-02-25 15:35:48 -08:00
Yuan Tang
bca450f7aa docs: Clarify sync wave precedence by kind and add note on delay between waves (#8518)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2022-02-25 15:35:33 -08:00
Yuan Tang
3c7d99f82c test: Support e2e tests and improve robustness on k8s v1.21-v1.23 (#8431)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
Co-authored-by: Jesse Suen <jesse@akuity.io>
2022-02-25 15:35:23 -08:00
Daniel Helfand
c5c25cd75b docs: update ApplicationSet controller getting started link (#8482)
Signed-off-by: Daniel Helfand <helfand.4@gmail.com>
2022-02-25 15:35:09 -08:00
Jesse Suen
f54d0a037f chore: update protoc to 3.17.3 and make install portable (#7932)
Signed-off-by: Jesse Suen <jesse@akuity.io>
2022-02-25 15:34:44 -08:00
Alexander Matyushentsev
6da138956a docs: update chagelog - add v2.3.0, v2.2.1 ~ v2.2.3 releases (#8310)
docs: update chagelog - add v2.3.0, v2.2.1 ~ v2.2.3 releases (#8310)

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:34:24 -08:00
Keith Chong
b3a181ea88 fix: Adjust z-index for newly added tree view toolbar (#8422) (#8423)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2022-02-25 15:33:20 -08:00
Alexander Matyushentsev
2f5da24654 feat: add RespectIgnoreDifferences sync option to UI (#8390)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:32:59 -08:00
Soumya Ghosh Dastidar
cc572a5eb2 fix(cli): argo app diff passes --api-versions to helm template (#8371)
Signed-off-by: Soumya Ghosh Dastidar <soumya@akuity.io>
2022-02-25 15:32:37 -08:00
Alexander Matyushentsev
ae03c3b872 chore: fix broken TestHelmIgnoreMissingValueFiles test (#8368)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:31:31 -08:00
Jonah Back
79ac472382 fix: check for issuing condition on Certificate (#7217)
Signed-off-by: Jonah Back <jonah@jonahback.com>

Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:31:16 -08:00
Chetan Banavikalmutt
061ba811f1 chore: upgrade Helm to v3.8.0 (#8301)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2022-02-25 15:29:49 -08:00
Alexander Matyushentsev
b5909d59ec refactor: update gitops-engine version to v0.6.0
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-25 15:27:15 -08:00
jannfis
68f17dbe8e feat: Make cluster cache sync more robust (#8438)
* feat: Support retry for list operations in cluster cache sync

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

* Fix default retries

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

* Pull in latest gitops-engine

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

* Default retry limit should be 1

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

* Make type conversion earlier

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

* Rename limit to attempt

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

* Revert Makefile change

Signed-off-by: jannfis <jann@mistrust.net>
2022-02-16 11:56:22 +00:00
Jesse Suen
bc6b4950ba docs: add security documentation related to git repositories (#8463)
Signed-off-by: Jesse Suen <jesse@akuity.io>
2022-02-11 13:48:10 -08:00
jannfis
c2cf633bbc feat: Allow fine-tuning of K8s rest client connection properties (#8404)
* feat: Allow fine-tuning of K8s rest client connection properties

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

* Move initialization

Signed-off-by: jannfis <jann@mistrust.net>
2022-02-09 09:05:24 +00:00
Jonathan West
bdd05d5c7a Update Argo CD V2.3 to ApplicationSet v0.4.0 (#8416)
Signed-off-by: Jonathan West <jonwest@redhat.com>
2022-02-07 10:49:14 -08:00
Ishita Sequeira
4b04a39180 fix: fix deployment config health status (#8376)
Signed-off-by: ishitasequeira <isequeir@redhat.com>
2022-02-06 11:20:56 -08:00
argo-bot
aa54aa7eda Bump version to 2.3.0-rc5 2022-02-04 23:32:12 +00:00
argo-bot
4bbd0e57dd Bump version to 2.3.0-rc5 2022-02-04 23:32:00 +00:00
fredericfran-gds
2d6b619a86 fix: reload ArgoCD config if OIDC config changes (#8350)
fix: reload ArgoCD config if OIDC config changes (#8350)

Signed-off-by: Frederic Francois <frederic.francois@digital.cabinet-office.gov.uk>
2022-02-04 15:08:59 -08:00
Leonardo Luz Almeida
39487ef7c7 chore: Generate spdx for the UI project (#8385)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-02-04 15:08:54 -08:00
jannfis
fcc7c0b080 fix: Resolve symlinked value files correctly (#8387)
* fix: Resolve symlinked value files correctly

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

* fix: Resolve symlinked value files correctly

Signed-off-by: jannfis <jann@mistrust.net>
2022-02-04 15:08:32 -08:00
argo-bot
ed734fedbb Bump version to 2.3.0-rc4 2022-02-03 21:46:08 +00:00
argo-bot
7414f2d42c Bump version to 2.3.0-rc4 2022-02-03 21:45:50 +00:00
jannfis
8139df8983 Merge pull request from GHSA-63qx-x74g-jcr7
Signed-off-by: jannfis <jann@mistrust.net>
2022-02-03 20:37:46 +01:00
pasha-codefresh
f364330de2 fix: fix example in project scoped repositories (#8357)
fix: fix example in project scoped repositories (#8357)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-02-03 09:45:43 -08:00
pasha-codefresh
4ec67d8b08 fix: applications page is crashing if nothing marked as favorites (#8356)
fix: applications page is crashing if nothing marked as favorites (#8356)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-02-03 09:45:39 -08:00
Leonardo Luz Almeida
3d3f81df4a chore: update actions/setup-go to v2 (#8349)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-02-03 09:45:34 -08:00
argo-bot
37f01f6f32 Bump version to 2.3.0-rc2 2022-02-02 22:37:02 +00:00
argo-bot
36eab6b82c Bump version to 2.3.0-rc2 2022-02-02 22:36:47 +00:00
Leonardo Luz Almeida
793acc147f chore: Use go install to add spdx-sbom-generator (#8346)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-02-02 13:51:14 -08:00
Leonardo Luz Almeida
b50609c0e6 chore: generate sbom for the released docker image (#8338)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-02-02 13:51:10 -08:00
Michael Crenshaw
5f48ce96c6 chore: use go install instead of deprecated go get (#8333)
* chore: use go install instead of deprecated go get

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* docs: readme fixes

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-02-02 13:30:43 -08:00
Alexander Matyushentsev
c32460a2bc chore: automate bundling argocd addons during release process (#8336)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-02 13:28:40 -08:00
Ben Ye
7eb1aba99b fix: register controller workqueue metrics correctly (#8318)
Signed-off-by: Ben Ye <ben.ye@bytedance.com>
2022-02-01 12:02:55 -08:00
Alexander Matyushentsev
1a8139f4d6 fix: make sure release workflow publish image with "v" in front of version (#8335)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-01 10:27:40 -08:00
Leonardo Luz Almeida
02c03c3b26 chore: generate and upload sbom during release (#8332)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-02-01 10:27:34 -08:00
Alexander Matyushentsev
cdb20d5060 docs: mention argocd notifications and applicationset changes in upgrade instructions (#8312)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-02-01 10:27:27 -08:00
argo-bot
7d7eed4932 Bump version to 2.3.0-rc1 2022-01-30 21:42:54 +00:00
argo-bot
af8c5eb07a Bump version to 2.3.0-rc1 2022-01-30 21:42:41 +00:00
Alexander Matyushentsev
1a476f7564 fix: argocd build fails on windows (#8319)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-30 13:02:01 -08:00
Saumeya Katyal
7f15389c72 feat: favourite ui feature (#8210)
* feat: favourite ui feature (#8210)

Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2022-01-28 12:55:23 -08:00
Alexander Matyushentsev
1a3556e1cc fix: add missing steps in release workflow to setup docker buildx (#8311)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-28 12:04:34 -08:00
Yujun Zhang
4aa614dafb fix: fetch revision only then fallback to default refspec (#5605)
* fix: fallback to fetch default only on error

Ignoring commit SHA breaks gerrit when the commit is not merged

Signed-off-by: Yujun Zhang <yujunz@nvidia.com>

* revert util/git/client.go changes

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

Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-28 10:58:36 -08:00
Yuan Tang
6abccea3f0 docs: Add link to new blog (#8308)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2022-01-28 09:06:05 -08:00
Guilhem Lettron
5ffc60f88d chore(bug_report): put instructions in comment (#8283)
Users reporting a bug will see instructions, can keep it, it will be ignored in final issue

Signed-off-by: Guilhem Lettron <guilhem@barpilot.io>
2022-01-28 10:08:31 +01:00
Keisuke Wada
04e05c5106 docs: Add ZOZO to list of users (#8300)
Signed-off-by: keisuke.wada <keisuke.wada@zozo.com>
2022-01-28 10:05:12 +01:00
Keith Chong
f387ab846b feat: Zoom in and out on resource view (#7183) (#8290)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2022-01-27 15:59:53 -08:00
pasha-codefresh
6dc544db99 chore: update slack version (#8299)
chore: update slack version (#8299)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-01-27 12:09:14 -08:00
Michael Crenshaw
061e575d82 chore: fix docs formatting (#8293)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-01-27 10:01:48 -08:00
Snaipe
d9c1af9f25 docs: update ambassador mappings to avoid --grpc-web-root-path (#8028)
I found it non-intuitive to have to tell our users to use `--grpc-web-root-path /`
when logging in when the defaults should have just worked.

This commit updates the Host-based ambassador mappings to avoid that, making
plain `argocd login <host>` calls work.

Signed-off-by: Franklin "Snaipe" Mathieu <me@snai.pe>
2022-01-27 08:18:46 -08:00
Alexander Matyushentsev
6abc85a3a5 Revert "chore: Run dex reverse proxy only when dex is configured (#7999)" (#8291)
This reverts commit 303cc4613b.

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-27 07:09:10 +01:00
Alexander Matyushentsev
a16471b8a5 chore: upgrade gitops engine (#8288)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-26 19:04:41 -08:00
Alexander Matyushentsev
ecc3ab3cab feat: Use encrypted cookie to store OAuth2 state nonce (instead of redis) (#8241)
feat: Use encrypted cookie to store OAuth2 state nonce (instead of redis) (#8241)

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-26 10:59:50 -08:00
Dong Wang
0aeda4366d feat: Expose ARGOCD_APP_NAME to the kustomize build command (#8096)
Signed-off-by: Dong Wang <wd@wdicc.com>
2022-01-26 08:18:14 -08:00
Ishita Sequeira
cf601c96d3 feat: bundle applicationset-controller with argocd (#8148)
* feat: bundle applicationset-controller with argocd

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* point applicationset to master branch

Signed-off-by: ishitasequeira <isequeir@redhat.com>
2022-01-26 06:18:23 -05:00
Michael Crenshaw
96f95ca1c1 Use gRPC timeout for sidecar CMPs (#8131) (#8236)
Use gRPC timeout for sidecar CMPs (#8131) (#8236)

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-01-25 15:45:37 -08:00
dependabot[bot]
0b2e585373 build(deps): bump nanoid from 3.1.23 to 3.2.0 in /ui (#8253)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.23 to 3.2.0.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.23...3.2.0)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-25 09:35:31 -08:00
Keith Chong
83458e0bd9 feat: Allow external links on Application (#3487) (#8231)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2022-01-25 09:34:36 -08:00
pasha-codefresh
4aa7cbfb91 chore: go version inside mod file (#8275)
* update go version

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

* update go version

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

* change version in docs

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-01-25 15:23:43 +01:00
Michael Crenshaw
26db08931e docs: add chart field to application.yaml (#8239)
* docs: add chart field to application.yaml

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* docs: more clarification

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-01-25 09:16:13 +01:00
Alexander Matyushentsev
3ae9bffa30 fix: argocd CLI fails in core mode (#8270)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-25 09:15:33 +01:00
jannfis
4c7651b5f8 chore: Update security policy (#8258)
Signed-off-by: jannfis <jann@mistrust.net>
2022-01-24 22:56:15 -08:00
pasha-codefresh
feaf949968 chore: update notifications version (#8267)
chore: update notifications version (#8267)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-01-24 13:43:23 -08:00
pasha-codefresh
b7bdb8ffe7 feat: Application generation strategies and clusters generation (#8263)
feat: Application generation strategies and clusters generation (#8263)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-01-24 09:24:39 -08:00
Patrick Jahns
c3b3521f59 fix: provide a semantic version parsed version for KUBE_VERSION (#8250)
Signed-off-by: Patrick Jahns <github@patrickjahns.de>
2022-01-23 13:01:12 +01:00
Ishita Sequeira
285454f011 chore: remove additional 'to' from description in swagger.json (#8254)
Signed-off-by: ishitasequeira <isequeir@redhat.com>
2022-01-23 12:51:58 +01:00
Saumeya Katyal
134f880aae docs: add saumeya to reviewers (#8248)
Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2022-01-21 09:52:45 -08:00
Michael Crenshaw
9ac935d59f docs: fix nested code block formatting (#8240)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-01-21 11:21:40 +01:00
Yi Cai
8c2cef6f28 docs: added ciiay to reviewers (#8242)
Signed-off-by: ciiay <yicai@redhat.com>

Co-authored-by: jannfis <jann@mistrust.net>
2022-01-21 11:12:28 +01:00
jannfis
26b9ba3dc6 chore: Publish latest build to quay instead of Docker Hub (#8238)
Signed-off-by: jannfis <jann@mistrust.net>
2022-01-21 10:08:32 +01:00
Leonardo Luz Almeida
de496d6b4b docs: add Leo and Michael as reviewers (#8244)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-01-21 09:25:53 +01:00
Chetan Banavikalmutt
ae71475869 chore: exclude argocd-server rbac for core-install (#8234)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2022-01-20 16:29:19 -08:00
Alexander Matyushentsev
ef8ae570bf chore: upgrade dex to v2.30.2 (https://github.com/dexidp/dex/issues/2326) (#8237)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-20 14:07:49 -08:00
Alexander Matyushentsev
6962fc22ee chore: upgrade base image to ubuntu:21.10 (#8230)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-20 08:29:47 +01:00
Alexander Matyushentsev
25698fd9f5 chore: upgrade k8s client to v1.23 (#8213)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-20 08:28:11 +01:00
Alexander Matyushentsev
44d596f0ee chore: upgrade kustomize to most recent version (v4.4.1) (#8227)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-19 15:33:29 -08:00
Leonardo Luz Almeida
1547b44ffc feat: Allow configuring system wide ignore differences for all resources (#8224)
* feat: Allow configuring system wide ignore differences for all resources

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

* Add example config to argocd-cm.yaml

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-01-19 14:57:43 -08:00
Alexander Matyushentsev
9155d14f9a chore: upgrade golang to 1.17.6 (#8229)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-19 14:44:31 -08:00
Alexander Matyushentsev
2fc0a25c0a chore: upgrade helm to most recent version (v3.7.2) (#8226)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-19 14:17:57 -08:00
Yujun Zhang
988d760474 chore: fix typo in description (#8217)
Signed-off-by: Yujun Zhang <yujunz@nvidia.com>
2022-01-19 08:18:04 +01:00
Alexander Matyushentsev
a17c77e238 feat: allow selecting application on detail page (#8176)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-18 14:43:43 -08:00
Michael Crenshaw
dc24d05a31 chore: make lint-docs less flakey (#8182)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-01-18 12:03:32 -08:00
Vladimir Avdoshka
113b3da691 docs: Specifying the value format to avoid ambiguity due to mentioned default "90 seconds timeout" (#8029)
Signed-off-by: Vladimir Avdoshka <vova.avdoshka@gmail.com>
Signed-off-by: Vladimir Avdoshka <vavdoshka@kyriba.com>
2022-01-18 11:51:12 -08:00
Leonardo Luz Almeida
8608a3192a docs: Add RespectIgnoreDifferences sync option documentation (#8212)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-01-18 09:54:54 -08:00
Tristan Keen
2fb3986386 fix: Allow all resources to add external links (#7923)
Signed-off-by: Tristan Keen <tristan.keen@gmail.com>
2022-01-18 08:23:58 -08:00
jannfis
8b95052720 chore: redis:alpine is incompatible with Dockerized toolchain (#8193)
Signed-off-by: jannfis <jann@mistrust.net>
2022-01-18 08:22:46 +01:00
jannfis
010411012f chore: Log out the resource triggering reconciliation (#8192)
* chore: Log out the resource triggering reconciliation

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

* chore: Log out the resource triggering reconciliation

Signed-off-by: jannfis <jann@mistrust.net>
2022-01-18 08:22:26 +01:00
Song Song Li
22f4a936cc fix invalid cmd (#8026)
Signed-off-by: Song Song Li <ssli@redhat.com>
2022-01-17 19:41:04 -08:00
Denis Krivenko
41fc70d17e fix: Add "Restarting MinIO" status to MiniO Tenant health check (#8191)
Signed-off-by: dnskr <dnskrv88@gmail.com>
2022-01-15 17:32:43 +01:00
Marco Kilchhofer
303cc4613b chore: Run dex reverse proxy only when dex is configured (#7999)
Signed-off-by: Marco Kilchhofer <mkilchhofer@users.noreply.github.com>
2022-01-15 16:18:47 +01:00
pasha-codefresh
2072d1a4b0 chore: upsert application e2e (#8190)
* move projects

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

* Revert "move projects"

This reverts commit d0e21353

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

* covering regression #8184 with e2e

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

* empty commit

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

* change semver

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

* fix test

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

* empty commit

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

* empty commit

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-01-15 15:41:08 +01:00
jannfis
d33caacb9b fix: Prevent possible out-of-bounds access when loading policies (#8186)
Signed-off-by: jannfis <jann@mistrust.net>
2022-01-15 07:30:40 +01:00
jannfis
3c5033c6bf refactor: Make user agent enforcer testable (#8174)
Signed-off-by: jannfis <jann@mistrust.net>
2022-01-15 07:30:14 +01:00
pasha-codefresh
978162fdee fix: application exist panic when execute api call (#8188)
fix: application exist panic when execute api call (#8188)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-01-14 17:19:43 -08:00
Alexander Matyushentsev
4f62aa4398 docs: update roadmap based on v2.3 progress (#8187)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-14 15:55:32 -08:00
Keith Chong
6f59fe660f feat: Add app list and details page views to navigation history (#7776) (#7937)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2022-01-14 14:46:53 -08:00
patst
0dfc125d95 feat: add skipCrds flag for helm charts (#8012)
* feat: add skipCrds flag for helm charts

* replace additionalTemplateArgs with includeCrds flag
* add testcase for skip crds

Signed-off-by: patst <patrick.steinig@googlemail.com>

* feat: add skipCrds flag for helm charts

* replace additionalTemplateArgs with includeCrds flag
* add testcase for skip crds

Signed-off-by: patst <patrick.steinig@googlemail.com>

* feat: add skipCrds flag for helm charts

* replace additionalTemplateArgs with includeCrds flag
* add testcase for skip crds

Signed-off-by: patst <patrick.steinig@googlemail.com>

* feat: add skipCrds flag for helm charts

* make sure include crds is not added for helm2

Signed-off-by: patst <patrick.steinig@googlemail.com>
2022-01-14 13:56:34 -08:00
pasha-codefresh
f65289748a feat: tool for generate argocd resources (#8037)
feat: tool for generate argocd resources  (#8037)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-01-14 12:53:51 -08:00
jannfis
47187bd30e fix: Prevent possible nil-pointer deref in normalizer (#8185)
Signed-off-by: jannfis <jann@mistrust.net>
2022-01-14 21:37:31 +01:00
pasha-codefresh
4f155b539b fix: argocd notifications troubleshooting cmd (#8183)
fix: argocd notifications troubleshooting cmd (#8183)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2022-01-14 11:45:02 -08:00
jannfis
cb47740d62 chore(deps): Update github.com/Masterminds/semver to v3.1.1 (#8180)
* chore(deps): Upgrade Masterminds/semver to v3.1.1

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

* Do not anchor regexp

Signed-off-by: jannfis <jann@mistrust.net>
2022-01-14 19:28:34 +01:00
jannfis
0b9b7c31f8 fix: Parse to correct uint32 type (#8177)
Signed-off-by: jannfis <jann@mistrust.net>
2022-01-14 10:17:30 -08:00
dependabot[bot]
35f5b32f53 build(deps): bump follow-redirects from 1.14.1 to 1.14.7 in /ui (#8161)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.1 to 1.14.7.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.1...v1.14.7)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-14 15:22:02 +01:00
inductor(Kohei)
2f83312800 docs: Update Ingress with GKE (#8163)
Signed-off-by: inductor <kohei.ota@hpe.com>
2022-01-14 12:43:33 +01:00
34FathomBelow
074db0cf28 docs: Update tls.md (#8169)
Signed-off-by: 34fathombelow <34fathombelow@protonmail.com>
2022-01-14 12:42:45 +01:00
dependabot[bot]
502762acc0 build(deps-dev): bump postcss from 8.2.10 to 8.2.13 in /ui (#8118)
Bumps [postcss](https://github.com/postcss/postcss) from 8.2.10 to 8.2.13.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.2.10...8.2.13)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-14 10:26:42 +01:00
Ishita Sequeira
55ea34292a fix: route health check stuck in 'Progressing' (#8170)
Signed-off-by: ishitasequeira <isequeir@redhat.com>
2022-01-14 10:02:51 +01:00
jannfis
7ff5f0755b chore: Update ghinstallation to v2.0.4 (#8171)
* chore: Update ghinstallation to v2.0.4

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

* Update go.sum

Signed-off-by: jannfis <jann@mistrust.net>
2022-01-14 10:01:48 +01:00
dependabot[bot]
4a04bb9096 build(deps): bump follow-redirects from 1.14.4 to 1.14.7 in /ui-test (#8173)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.4 to 1.14.7.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.4...v1.14.7)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-14 10:01:33 +01:00
pavan kumar ceemala
fb30f1bd03 Update USERS.md (#8166) 2022-01-13 15:58:56 -08:00
Yuan Tang
d6f3f87c69 chore: Migrate to use golang-jwt/jwt v4.2.0 (#8136)
chore: Migrate to use golang-jwt/jwt v4.2.0 (#8136)

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2022-01-13 13:12:21 -08:00
Leonardo Luz Almeida
6240ef00e7 feat: new sync option to use ignore diff configs during sync (#8078)
feat: new sync option to use ignore diff configs during sync (#8078)

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-01-13 13:00:17 -08:00
jannfis
5c85df90d5 fix: Fix a possible crash when parsing RBAC (#8165)
Signed-off-by: jannfis <jann@mistrust.net>
2022-01-13 16:28:08 +01:00
Ishita Sequeira
07cc533896 chore: move resolveRevision from api-server to repo-server (#7966)
* chore: move resolveRevision to repo-server

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* fix unit tests

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* Retrigger CI pipeline

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* Address PR comments

Signed-off-by: ishitasequeira <isequeir@redhat.com>
2022-01-12 22:06:00 +01:00
jannfis
d511fb8deb chore: Update to Redis 6.2.4 (#8157)
Signed-off-by: jannfis <jann@mistrust.net>
2022-01-12 12:37:10 -08:00
Michael Crenshaw
99583c74c3 docs: document fileParameters (#8156)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-01-12 19:43:34 +01:00
Michael Crenshaw
c92922e3d6 docs: reorganize and clarify CMP docs (#8130)
* docs: reorganize and clarify CMP docs

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* docs: note that an empty plugin block is acceptable

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-01-12 19:42:58 +01:00
Tanmay_Bhat
5e6aee5961 docs: add Skit to users list (#8152) 2022-01-12 14:46:01 +01:00
Márk Sági-Kazár
57e0ffceb7 feat: Support XDG Base directory standard (#7638) (#7791)
* feat: support XDG Base directory standard

Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>

* chore: set XDG_CONFIG_HOME env var for docs generation

Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>

* chore: regenerate cli docs

Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
2022-01-12 09:05:01 +01:00
Thomas Dy
c8bcabeba5 feat: Allow escaping dollar in Envsubst (#7961)
* feat: allow escaping dollar in Envsubst

Signed-off-by: Thomas Dy <thatsmydoing@gmail.com>

* docs: add variable escape documentation

Signed-off-by: Thomas Dy <thatsmydoing@gmail.com>
2022-01-12 08:09:41 +01:00
Chetan Banavikalmutt
4b5df692d7 docs: update the ARGOCD_SESSION_FAILURE_MAX_FAIL_COUNT variable in the docs (#8140)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2022-01-11 12:21:34 -08:00
Alexander Matyushentsev
5d770d6c54 chore: fix broken TestValidatePermissions unit test (#8147)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-11 12:17:11 -08:00
J. Mark Pim
dfd40efb93 fix: always call ValidateDestination (#7976)
* fix: always call ValidateDestination

Signed-off-by: Mark Pim <j.mark.pim@gmail.com>

* Revert part of the change to fix tests

Signed-off-by: Mark Pim <j.mark.pim@gmail.com>

* Fix linting

Signed-off-by: Mark Pim <j.mark.pim@gmail.com>
2022-01-11 09:02:23 -08:00
Alexander Matyushentsev
27af0b4924 refactor: introduce 'byClusterName' secret index to speedup cluster server URL lookup (#8133)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-10 12:38:44 -08:00
Alexander Matyushentsev
5d1fb9f775 chore: stop publishing image on every commit to dockerhub (#8135)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-10 12:38:26 -08:00
Alexander Matyushentsev
03c5d20d58 fix: fix broken image build and release workflows (#8119)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-10 10:24:23 -08:00
Brad Solomon
3fe924ebd6 docs: Add Deloitte to list of users (#8126) 2022-01-09 20:12:39 -08:00
Alexander Matyushentsev
5da1522b17 chore: build images on PR and conditionally build arm64 image on push (#8108)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-07 13:22:26 -08:00
Avinash Upadhyaya K R
8b57bc990c Provide address flag for admin dashboard command (#8095)
* feat: address flag for admin dashboard

Signed-off-by: Avinash Upadhyaya <avinashupadhya99@gmail.com>

* docs: address flag for admin dashboard

Signed-off-by: Avinash Upadhyaya <avinashupadhya99@gmail.com>
2022-01-06 23:25:38 -08:00
Alexander Matyushentsev
37851b165e refactor: move project filtering to server side (#8102)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-06 09:39:37 -08:00
Michael Crenshaw
722fe9273a chore: fix list depth (#8101)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-01-05 09:15:05 -08:00
icecoffee531
f1d4166a7c docs: Add Gllue to list of users (#8092)
Signed-off-by: icecoffee <2335250710@qq.com>
2022-01-04 23:39:41 -08:00
Mubarak Jama
d00e112791 docs: Add Ibotta to the list of users (#8087)
Signed-off-by: Mubarak Jama <mubarak.jama@gmail.com>
2022-01-04 22:57:46 -08:00
Alexander Matyushentsev
6cd0d97e23 docs: update roadmap document with v2.2 release changes (#8089)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-04 19:10:00 -08:00
Michael Crenshaw
2547176b29 chore: fix typo (#8088)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-01-04 16:00:08 -08:00
Yi Cai
9530b38f7a fix: Trailing line in Filter Dropdown Menus #7821 (#8001)
Signed-off-by: ciiay <yicai@redhat.com>
2022-01-04 11:09:16 -08:00
Sebastián Blázquez
4a55b13d66 docs: fix link (#8080)
Fix link in docs/user-guide/private-repositories.md

Signed-off-by: seblaz <sebastian.blazquez96@gmail.com>
2022-01-03 17:21:10 -08:00
Saumeya Katyal
c0349f3795 fix: network line colors and menu icon alignment (#8059)
* fix: network line colors and menu icon alignment

Signed-off-by: saumeya <saumeyakatyal@gmail.com>

* change color order

Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2022-01-03 16:07:50 -08:00
Alexander Matyushentsev
48d46e395f feat: support specifying cluster by name in addition to API server URL in Cluster API (#8077)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-03 15:26:36 -08:00
Ayrton Araújo Santana
9cb9a380da docs: Newly created Arch Linux package (#8058)
Signed-off-by: Ayrton Santana <ayrton@linux.com>
2022-01-03 14:49:56 -08:00
Thomas Decaux
399d2a830b docs: fix swagger description typo (#8065)
Signed-off-by: Thomas Decaux <ebuildy@gmail.com>
2022-01-03 14:08:07 -08:00
Alexander Matyushentsev
3247090838 feat: store "Group Nodes" button state in application details preferences (#8036)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-01-03 11:31:12 -08:00
ocraviotto
99d1dcad03 feat: added a new Helm option ignoreMissingValueFiles (#7767) (#8003)
so as to allow operators to prevent Argo CD from passing valueFiles
to helm template if they don't exist in the source under the specified path.

Signed-off-by: Oscar Craviotto <craviotto@avellaneda.com>
2022-01-03 09:51:31 -08:00
Pablo Aguilar
8e6fcde4d6 Add omegaUp to the list of argocd users (#8062) 2022-01-03 09:51:15 -08:00
Gusty Sapto Ady Prakoso
160a4fda5e docs: add Flip to USERS.md (#8070)
Signed-off-by: Gusty Sapto Ady Prakoso <gusty.prakoso@flip.id>
2022-01-03 09:50:58 -08:00
pasha-codefresh
cb1f06c72a fix: issue with project scoped resources (#8048)
fix: issue with project scoped resources (#8048)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-12-30 09:09:57 -08:00
plakyda-codefresh
62f29865e7 fix: Default value for retry validation #8055 (#8064)
fix: Default value for retry validation #8055 (#8064)

Signed-off-by: viktorplakida <plakyda1@gmail.com>
2021-12-30 09:04:18 -08:00
Saumeya Katyal
ae9abe5175 fix: application-icons-alignment (#8054)
Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2021-12-29 11:17:07 -08:00
pasha-codefresh
b558579f28 fix: sync window panel is crashed if resource name not contain letters (#8053)
fix: sync window panel is crashed if resource name not contain letters (#8053)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-12-29 11:07:23 -08:00
Alexander Matyushentsev
b3ea0a38bb chore: add argocd-notifications to 'dev' image (#8034)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-27 14:46:56 -08:00
Yi Cai
32838b1f71 fix: adding pagination to grouped nodes sliding panel#7837 (#7915)
fix: adding pagination to grouped nodes sliding panel#7837 (#7915)

Signed-off-by: ciiay <yicai@redhat.com>
2021-12-24 22:08:26 -08:00
Moulick Aggarwal
e822437eb3 chore: bump go-jsonnet to v0.18.0 (#8011)
Signed-off-by: Moulick Aggarwal <moulickaggarwal@gmail.com>
2021-12-24 21:44:28 -08:00
Saumeya Katyal
de582e0bd5 fix: refreshing label toast (#7979)
Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2021-12-23 09:12:50 -08:00
Alexander Matyushentsev
26f83501ad fix: Controller panics if resource manifest has incorrect annotation (#8022)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-23 08:14:06 -08:00
plakyda-codefresh
000f951b9c fix: retry disabled text (#8004)
fix: retry disabled text (#8004)

Signed-off-by: viktorplakida <plakyda1@gmail.com>
2021-12-22 11:40:11 -08:00
Yi Cai
129e9ea89e fix: Grouped node list missing resources on Compact resources view #8014 (#8018)
Signed-off-by: ciiay <yicai@redhat.com>
2021-12-22 11:38:55 -08:00
Regina Scott
d1d82c6d6f feat: add visual indicator for newly created pods (#8006)
Signed-off-by: Regina Scott <rescott@redhat.com>
2021-12-22 11:26:36 -08:00
Niklas Steiner
d8c3113c06 fix: Opening app details shows UI error on some apps (#8016) (#8019)
Signed-off-by: Niklas Steiner <niklas@sbg.at>
2021-12-22 11:06:11 -08:00
Leonardo Luz Almeida
7bac2c151a fix: Inconsistent normalization logic during diff (#7980)
fix: Inconsistent normalization logic during diff (#7980)

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2021-12-22 08:57:48 -08:00
Yi Cai
800b1093e7 fix: Nested Refresh dropdown does not work on Application Details page #1524 (#7950)
* fix: Nested Refresh dropdown does not work on Application Details page #1524

Signed-off-by: ciiay <yicai@redhat.com>

* Removed unnecessary changes

Signed-off-by: ciiay <yicai@redhat.com>
2021-12-22 14:10:28 +01:00
jannfis
18f7b416a8 chore: Some minor changes to the docs linter (#7996)
chore: Some minor changes to the docs linter (#7996)

Signed-off-by: jannfis <jann@mistrust.net>
2021-12-21 09:22:54 -08:00
Jesse Suen
63dfc78917 fix: remove vendor dependency in virtualized toolchain (#8000)
Signed-off-by: Jesse Suen <jesse@akuity.io>
2021-12-20 17:24:27 -08:00
Alexander Matyushentsev
487db973d3 fix: correctly handle project field during partial cluster update (#7994)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-20 12:52:34 -08:00
Clive Jevons
fcaa8abd01 feat: enable specifying root ca for oidc (#6712)
When configuring an external OIDC provider which uses a private PKI
for its certificates it was not possible to properly verify the certificate
being served. Also, when using ArgoCD in insecure mode, e.g. when running
behind istio for providing mTLS, this resulted in errors.

Signed-off-by: Clive Jevons <clive@jevons-it.net>
2021-12-20 09:57:20 +01:00
Didrik Finnøy
e32c07007c docs: Helm plugins via initContainers (#7815)
* Docs: Helm plugins via initContainers

Related: #7066

Include an alternative method for installing Helm plugins that don't require users to maintain their own version of the ArgoCD container image.

Signed-off-by: Didrik Finnøy <djfinnoy@protonmail.com>

* add codeblock

Signed-off-by: Didrik Finnøy <djfinnoy@protonmail.com>

* change helm repo name in example code

Signed-off-by: Didrik Finnøy <djfinnoy@protonmail.com>
2021-12-19 20:43:02 +01:00
Zadkiel
e50d03eb61 fix(ui): use consistent case for diff modes (#7945)
Signed-off-by: GitHub <noreply@github.com>
2021-12-19 19:54:00 +01:00
Michael Crenshaw
e15c8a58a6 docs: Add a link to docs/operator-manual/security.md from root-level security.md (#7840)
* docs: add a link from the base security doc to the operator manual security page

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: better copy

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: bump doc version

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2021-12-19 19:53:08 +01:00
Michael Crenshaw
3bd8688004 chore: escape proj in regex (#7985)
* chore: escape proj in regex

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: test normal cases

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: typo

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2021-12-19 17:09:36 +01:00
Michael Crenshaw
ad1ed1d51b chore: add target revision tests (#7963)
* fix: add nil check, add revision tests, add docs about webhook behavior

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: move single-use function into test

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: add comment about why some tests are absent

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: fix text names

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2021-12-17 13:33:57 -08:00
Michael Crenshaw
914fb8337e fix: webhook URL matching edge cases (#7981)
* fix: webhook URL matching edge cases

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* docs: docstring

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: lint

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

* chore: move logging to non-utility function

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2021-12-17 20:47:55 +01:00
Alexander Matyushentsev
0676b65f7e fix: add aws cli into final argocd image (#7973)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-16 18:46:59 -08:00
Michael Crenshaw
2e494689cd chore: lint docs + CI job (#7959)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2021-12-16 15:52:18 -08:00
Shyukri Shyukriev
561a44d0a8 chore: upgrade awscli to 2.4.6 and remove python deps (#7947)
Remove python3-pip and deps
Use hack/installers since AWS doesn't provide pip packages for v2

Side effect: image downsize 842 MB -> 483MB

Signed-off-by: Shyukri Shyukriev <shyukri.shyukriev@mariadb.com>
2021-12-16 15:37:10 -08:00
Jesse Suen
63e70a9f71 chore: portable and simpler toolchain install (#7920)
Signed-off-by: Jesse Suen <jesse@akuity.io>
2021-12-16 15:16:36 -08:00
Alexander Matyushentsev
656f790aed fix: resource details page crashes when resource is not deployed and hide managed fields is selected (#7971)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-16 14:42:29 -08:00
Alexander Matyushentsev
7f09331e3f fix: notifications controller manifests shuold use argocd image (#7970)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-16 13:58:42 -08:00
pasha-codefresh
f9ba9e9811 fix: issue with headless installation (#7958)
fix: issue with headless installation (#7958)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-12-16 10:17:16 -08:00
jomenxiao
17c6daa9ea fix: targetervision compatible without prefix refs/heads or refs/tags (#7939)
fix: targetervision compatible without prefix refs/heads or refs/tags (#7939)

Signed-off-by: jomen.xiao <jomenxiao@gmail.com>
2021-12-15 10:56:31 -08:00
Alexander Matyushentsev
f89d40c9e0 fix: add missing notifications base to Argo CD HA (#7934)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-14 15:22:32 -08:00
Xabier Larrakoetxea Gallego
6a1472371f Fix Kubernetes labels normalization for Prometheus (#7925)
* When adding Kubernetes labels as Prometheus labels, replace with  all the invalid Prometheus label chars

Signed-off-by: Xabier Larrakoetxea <me@slok.dev>

* Add Fonoa company to users doc

Signed-off-by: Xabier Larrakoetxea <me@slok.dev>

* Add comment and link to the Prometheus label valid characters

Signed-off-by: Xabier Larrakoetxea <me@slok.dev>
2021-12-14 12:38:25 -08:00
Alexander Matyushentsev
3ea2ba06f5 docs: update CHANGELOG: mention v2.2.0 release and v2.1.8 releases (#7930)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-14 12:28:08 -08:00
Leonardo Luz Almeida
29a6be4afe Feat: Ignore differences owned by trusted managers from managedFields (#7869)
* feat: implement managed fields normalizer

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2021-12-14 10:49:55 -08:00
Saumeya Katyal
bed36e2027 fix: add all resources in list view (#7295)
* fix: add all resources in list view

Signed-off-by: saumeya <saumeyakatyal@gmail.com>

add resources from applicationTree

Signed-off-by: saumeya <saumeyakatyal@gmail.com>

minor spacing fixes

Signed-off-by: saumeya <saumeyakatyal@gmail.com>

changes

Signed-off-by: saumeya <saumeyakatyal@gmail.com>

* merge conflicts and improvement

Signed-off-by: saumeya <saumeyakatyal@gmail.com>

* change variable name

Signed-off-by: saumeya <saumeyakatyal@gmail.com>

* review comments

Signed-off-by: saumeya <saumeyakatyal@gmail.com>

* lint-fix

Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2021-12-14 09:32:54 +01:00
Jesse Suen
9ff7c0b9c7 feat: update gitops-engine to v0.5.1 and add additional tuning options (#7917)
Signed-off-by: Jesse Suen <jesse@akuity.io>
2021-12-13 18:39:25 -08:00
May Zhang
cf78fe429a fix: during import, if stop-operation flag is provided, then nil oper… (#7916)
* fix: during import, if stop-operation flag is provided, then nil operation field of application

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

* fix: during import, if stop-operation flag is provided, then nil operation field of application

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

* run goimports -local

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

* updated docs

Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-12-13 15:30:43 -08:00
Yi Cai
5b17fc36d4 feat: Added toggle button for compact view #7836 (#7900)
feat: Added toggle button for compact view #7836 (#7900)

Signed-off-by: ciiay <yicai@redhat.com>
2021-12-13 13:39:57 -08:00
Alexander Matyushentsev
5978dfa167 fix: resource tracking normalization should not always drop old label (#7911)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-13 08:25:46 -08:00
Sho Iizuka
ddb90ab496 docs: fix flag name to use external variables in Jsonnet (#7659)
Signed-off-by: sho-iizuka <sho-iizuka@cybozu.co.jp>
2021-12-12 23:47:34 -08:00
Alexander Matyushentsev
0a792fefac fix: resource tracking normalization shuold drop empty labels (#7909)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-11 11:16:45 -08:00
jomenxiao
e48350756b fix nil point (#7905)
Signed-off-by: jomenxiao <jomenxiao@gmail.com>
2021-12-10 21:23:37 -08:00
Alexander Matyushentsev
6d8ff61b16 fix: improve migration from label to annotation tracking (#7899)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-10 16:14:38 -08:00
Michael Weibel
238ff275c4 docs: add Helio (#7902)
Signed-off-by: Michael Weibel <michael@helio.exchange>
2021-12-10 15:20:42 -08:00
Saumeya Katyal
7eccd21b47 fix: css warning icon color change (#7903)
Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2021-12-10 14:06:11 -08:00
Keith Chong
c9ddaabf08 fix: Event timestamp incorrectly shows unix epoch (#7879) (#7892)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2021-12-10 10:32:56 -08:00
May Zhang
a51169e8c0 fix: Cluster API does not support updating labels and annotations (#7901)
Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-12-09 16:39:34 -08:00
Alexander Matyushentsev
bea379b036 refactor: add indexes to secret informers to speedup settings parsing (#7882)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-07 14:15:11 -08:00
jannfis
b813301ed6 chore: Upgrade to golang 1.16.11 (#7874)
* chore: Upgrade to golang 1.16.11

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

* Missed this one

Signed-off-by: jannfis <jann@mistrust.net>
2021-12-07 12:59:25 -08:00
Alan Clucas
458a10310c docs: Add argocd-vault-replacer (#7814)
Adding argocd-vault-replacer as another hashicorp vault tool with different abilities from the IBM version. Primary differences:
* Ability to use kubernetes authentication
* Textual replacement rather than understanding the YAML so secrets can be anywhere, not just in limited locations.
* Ability to process the secrets into other forms (e.g. base64 encode)

Signed-off-by: Alan Clucas <alan@clucas.org>

Co-authored-by: jannfis <jann@mistrust.net>
2021-12-07 15:37:11 +01:00
Alexandre Gaudreault
6221ef20af feat(health): support of external-secrets.io/ExternalSecret (#7798)
* feat(health): support of external-secrets.io/ExternalSecret

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* move to folder

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>
2021-12-07 14:47:47 +01:00
pasha-codefresh
2087eaa4c7 fix: Resource tracking typo (#7873)
* move projects

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

* Revert "move projects"

This reverts commit d0e21353

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

* fix typo in resource tracking

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-12-07 14:05:23 +01:00
Saumeya Katyal
7d59cbb5be fix: css change for clear button in filters (#7868)
Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2021-12-06 15:44:39 -08:00
pasha-codefresh
dae43a23f9 fix: issue with keepalive (#7861)
* fix issue with keepalive

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

* empty commit

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-12-06 10:16:14 -08:00
Alexander Matyushentsev
78e256eef3 fix: fix UI build failure: use correct monaco editor setting name (#7856)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-03 14:29:51 -08:00
Alexander Matyushentsev
ccd15d1151 feat: allow hiding managed fields in resource manifest viewer (#7855)
* fix: remove double scroll in editor

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

* feat: add Hide Managed Fields checkbox

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-03 13:46:18 -08:00
Alexander Matyushentsev
05935a9d7e refactor: avoid loading project in frequently executed controller methods (#7853)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-03 13:18:08 -08:00
Jacob Wernette
891d9b2f38 docs: update argocd-vault-plugin repo (#7834)
Signed-off-by: Jacob Wernette <werne2j@gmail.com>
2021-12-02 09:26:26 -08:00
Chetan Banavikalmutt
0f845a0416 fix: admin dashboard doesn't use the right context (#7826)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2021-12-02 08:38:06 -08:00
Yuan Tang
a456a92493 build: Disable non-testing CI builds on forks (#7832)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-12-02 08:37:45 -08:00
Alexander Matyushentsev
e967f8836a fix: resource custom actions are not visible in resource actions dropdown (#7823)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-12-02 08:31:19 -08:00
Yi Cai
a8ed010921 feat: Compact application resources tree #7349 (#7632)
* feat: Compact application resources tree #7349 #7632

Signed-off-by: ciiay <yicai@redhat.com>

* Updates for comments

Signed-off-by: ciiay <yicai@redhat.com>
2021-12-02 08:01:03 -08:00
Yi Cai
0c352f8bd6 feat: add refresh/hard refresh apps button #7256 (#7411)
feat: add refresh/hard refresh apps button #7256 (#7411)

Signed-off-by: ciiay <yicai@redhat.com>
2021-12-01 15:28:48 -08:00
Regina Scott
e81f25026d feat: add quick-start buttons (#7292)
Signed-off-by: Regina Scott <rescott@redhat.com>
2021-12-01 15:21:33 -08:00
Phil Wright- Christie
cd497c4eec Fix secret key name (#7763) 2021-12-01 14:27:06 -08:00
Jonas Janz
7490ee483e docs: mention finalizer in app-of-apps doc (#7753)
* docs: mention finalizer in app-of-apps doc

As it's easy to overlook the need for a specific finalizer in the Application CR to ensure cascading deletion I added an extra section describing the need and linking to the ArgoCD Docs for further information about App deletion.

Signed-off-by: PixelJonas <5434875+PixelJonas@users.noreply.github.com>

* doc: fix typo in cluster-bootstrappring docs

small typo fix

Signed-off-by: PixelJonas <5434875+PixelJonas@users.noreply.github.com>
2021-12-01 14:26:29 -08:00
pasha-codefresh
ced5c1deed fix: notifications link (#7807)
fix: notifications link (#7807)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-12-01 14:15:48 -08:00
Yuan Tang
b977813e9a docs: Add 2.2-2.3 upgrading notes on ArgoCD binaries (#7812)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-12-01 09:42:34 -08:00
pasha-codefresh
a2f97af2e4 feat: resolve sync window for cluster name also, not only server (#7817)
* resolve sync window for clsuter name also, not only server

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-12-01 08:58:51 -08:00
pasha-codefresh
6b4a13c4bd feat: ToUpper and ToLower expression (#7816)
* ToUpper and ToLower expression

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-12-01 08:58:11 -08:00
ln3333
d64014364c fix: SyncWindow link not honoring basehref (#7811)
* fix SyncWindow link when using baseherf

Signed-off-by: ln3333 <liangxu@outlook.com>

* fix: SyncWindow link not honoring basehref

Signed-off-by: ln3333 <liangxu@outlook.com>
2021-11-30 14:10:11 -08:00
Alexander Matyushentsev
0f75eecbd2 chore: increase e2e tests timeout (#7803)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-30 10:58:43 -08:00
Márk Sági-Kazár
335becebb1 docs: add Cisco ETI to users (#7808)
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
2021-11-30 10:58:29 -08:00
Alexander Matyushentsev
d89c708399 refactor: upgrade casbin to latest stable version (v2.39.1) (#7802)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-30 10:51:05 -08:00
Yuan Tang
d8cfafbd92 feat: Configurable ArgoCD binary download links on Help page. Fixes #7698 (#7755)
feat: Configurable ArgoCD binary download links on Help page. Fixes #7698 (#7755)

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-11-30 10:10:43 -08:00
Marco Kilchhofer
394a2c8318 docs: Add Swiss Post to USERS.md (#7771)
Signed-off-by: Marco Kilchhofer <marco.kilchhofer.2@post.ch>
2021-11-30 10:03:05 -08:00
pasha-codefresh
faee047081 fix: flaky test (#7809)
* fix flaky test

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

* fix flaky test

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

* fix linter

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

* empty commit

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-11-30 09:54:42 -08:00
Takumasa Sakao
a05a2633ba docs: Fix invalid example manifest (#7792)
Signed-off-by: Takumasa Sakao <tsakao@zlab.co.jp>
2021-11-30 09:52:41 -08:00
pasha-codefresh
0f2f9a97e3 feat: Migrate argocd notifications to argocd (#7744)
feat: Migrate argocd notifications to argocd (#7744)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-11-29 18:47:46 -08:00
Moshe Avni
d346fceea9 Add critical part-of label (#7642) 2021-11-29 15:36:00 -08:00
Ardi Mehist
b40508323b Add Nitro to users list (#7789) 2021-11-29 14:26:01 -08:00
Greg
8851842d8e docs: update users in order to add Casavo (#7777)
Signed-off-by: Alessandro Gregori <alessandro.gregori@casavo.com>
2021-11-29 02:43:09 -08:00
pasha-codefresh
70a08a0aa6 chore: Remove deprecated action from CI (#7785)
* group diff should set resource id use new interface

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

* remove redundant

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

* remove eof

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

* update python version

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

* remove gh pages step

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

* remove gh pages step

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-11-26 13:01:56 +01:00
Jesse Suen
9cb9ef6752 fix: env vars to tune cluster cache were broken (#7779)
Signed-off-by: Jesse Suen <jesse@akuity.io>
2021-11-24 18:16:46 -08:00
Alexander Matyushentsev
23967f8717 Revert "chore: upgrade node-sass (#7631)" (#7765)
This reverts commit 012268d619.

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-22 09:36:16 -08:00
Gyorgy Hrabovszki
475bea599d docs: Add Allianz Direct to ArgoCD users (#7751)
Signed-off-by: Gyorgy Hrabovszki <gyoergy.hrabovszki@allianzdirect.de>
2021-11-19 21:36:05 -08:00
Yuan Tang
8e8a1ded27 build!: Remove non-Linux binaries from the image and fix image building on Mac ARM (#7668)
* build: Support image building on Mac ARM

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Pass GOOS and GOARCH explicitly

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Retrigger CI pipeline

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Remove windows and mac binaries in the image

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Update download handler registration

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Inject arch to env var via webpack

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Fix lint

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Add BUILD_ALL_CLIS env flag for make release-cli

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Run in release-cli target directly

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-11-18 21:42:14 -08:00
Alexander Matyushentsev
0c0bc1f769 refactor: use cached project while calculating resource tree (#7747)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-18 15:45:19 -08:00
Alexander Matyushentsev
8bbf8887d2 docs: add v2.2 changelog (#7681)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-18 08:41:49 -08:00
Remington Breeze
012268d619 chore: upgrade node-sass (#7631)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-11-18 08:40:48 -08:00
Matteo Ruina
af3fb9a4d0 docs: Add Skyscanner as ArgoCD user (#7730)
Signed-off-by: Matteo Ruina <matteo.ruina@gmail.com>
2021-11-18 08:13:06 -08:00
Kostis (Codefresh)
2370164c98 docs: clarify Helm application deployment (#7713)
Signed-off-by: Kostis Kapelonis <kostis@codefresh.io>
2021-11-17 07:51:06 -08:00
Mark Sarcevicz
18a1b07d1a Fix: Kuberenetes manifest to have new Github.com ssh known host keys for ArgoCD deployments (#7722)
* Kuberenetes manifest to have new ssh known host keys for ArgoCD deployments

https://github.blog/2021-09-01-improving-git-protocol-security-github/
Signed-off-by: smark88 <msarcevicz@influxdata.com>

* added to docs

Signed-off-by: smark88 <msarcevicz@influxdata.com>

* fix: regenerate manifests using 'make manifests'

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

Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-16 22:49:21 -08:00
Michael Crenshaw
fafa79fac1 feat: add health check for applicationset (#7695)
Signed-off-by: Michael Crenshaw <michael_crenshaw@intuit.com>
2021-11-16 16:54:26 -08:00
Oscar
8a5b34581a feat: only ask for confirmation when creating argocd-manager service account (#7720)
Signed-off-by: Oscar Chen <oscar.chen.btw@gmail.com>
2021-11-16 16:51:30 -08:00
Keith Chong
27928d0dc6 fix: Use binary units in pod view (#7649) (#7726)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2021-11-16 16:13:16 -08:00
Remington Breeze
0c91f65e67 chore(ui): Switch to esbuild instead of ts-loader for performance (#7336)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-11-16 13:00:52 -08:00
Jan Domanski
09c5d5f42a Add Devopsi Company (#7687)
Adding my software house company
2021-11-12 08:59:55 -08:00
Alexander Matyushentsev
caa246a38d refactor: allow using own config maps to register the cmp plugins instead of 'argocd-cmp-cm' (#7677)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-10 14:57:14 -08:00
pasha-codefresh
ebf27dea3e feat: Improve unit test coverage for util/app/app.go (#7641)
feat: Improve unit test coverage for util/app/app.go (#7641)
Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-11-10 13:41:04 -08:00
Yuan Tang
98fcb417eb build: Pin Python to 3.9.8 to work with arch x64 on GitHub Actions (#7678)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-11-10 12:44:48 -08:00
Yuan Tang
a3517d594b docs: Update CI troubleshooting guide on build steps (#7639)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-11-08 09:49:00 -08:00
Yuan Tang
e0c9827a37 chore: Correct function names in docstring in server/project/project.go (#7650)
* docs: Correct function names in docstring in server/project/project.go

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-11-08 09:48:28 -08:00
May Zhang
375e27bd7a Feat: cmp server (#6585)
* feat: config management plugin enhancement (#6585)

Signed-off-by: kshamajain99 <kshamajain99@gmail.com>
Signed-off-by: May Zhang <may_zhang@intuit.com>
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-08 09:47:10 -08:00
Yuan Tang
46fdb6f364 fix: Add missing passCredentials in swagger.json (#7640)
* fix: Add missing passCredentials in swagger.json

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Retrigger CI pipeline

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-11-08 08:49:28 -08:00
pasha-codefresh
2e84638827 fix: timezone fix test (#7643)
* group diff should set resource id use new interface

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

* remove redundant

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

* remove eof

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

* sync window broken tests

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

* sync window broken tests

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-11-07 19:08:02 +01:00
Yuan Tang
0a64781616 build: Add Helm v3.7.1 checksum for arm64 to fix build on Apple M1 (#7635)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-11-05 14:39:57 -07:00
Yuan Tang
43a29e6b2d docs: Add -s to sign off empty commits that retriggers CI (#7628)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-11-05 14:39:42 -07:00
Leonardo Luz Almeida
b77f947e1d fix: TestRepository should assume git by default (#7630)
* fix: TestRepository should assume git by default

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

* fix proto diff

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2021-11-05 13:51:02 -07:00
Leonardo Luz Almeida
dc24380065 chore: refactoring gpg test data embeding it in go code (#7625)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2021-11-05 08:45:14 +01:00
Leonardo Luz Almeida
b0278c4493 fix: handle repo creation when secret does not have proper label (#7617)
* fix: handle repo creation when secret does not have proper label

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

* address code review comments with linters

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

* remove gpg test data refactoring code

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2021-11-04 17:14:53 -07:00
Alexander Matyushentsev
1431e04b90 fix: add missing await on cluster list page (#7621)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-04 17:14:25 -07:00
Alexander Matyushentsev
5bb45435e0 docs: more post v2.3 roadmap items (#7509)
* docs: more post v2.3 roadmap items

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

* replace multiple sources with helm + repo; add app dependencies feature

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-04 09:36:48 -07:00
pasha-codefresh
691b77ff9e feat: split yamls (#7595)
feat: split yamls (#7595)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-11-04 08:33:08 -07:00
Yuan Tang
b52793ab07 docs: Add link to awesome-argo for more resources (#7619)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-11-04 08:25:34 -07:00
Chandler Wilkerson
fc13eda8d6 feat: Add KubeVirt custom health checks (#7176)
Signed-off-by: cwilkers <cwilkers@redhat.com>
2021-11-04 08:23:48 -07:00
Ishita Sequeira
ff45418948 feat: add timezone option to sync window (#7442)
* feat: add timezone option to sync window

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* Retrigger CI pipeline

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* Addressed PR comments

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* feat: add timezone option to sync window

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* Addressed PR comments

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* Addressed PR comments

Signed-off-by: ishitasequeira <isequeir@redhat.com>
2021-11-04 08:22:24 +01:00
Leonardo Luz Almeida
0d4e40ed6a fix: Address issue during diff when secret data is nil (#7603)
* fix: update gitops-engine to latest + log improvements

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

* run go mod tidy

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2021-11-03 12:46:05 -07:00
pasha-codefresh
fe3cc7218c feat: cache argo cd rbac (#7587)
feat: cache argo cd rbac (#7587)

Part of: #4296

Signed-off-by: Jan Jansen <jan.jansen@gdata.de>
Signed-off-by: pashavictorovich <pavel@codefresh.io>
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-03 11:28:52 -07:00
Alexander Matyushentsev
513d8a4ae0 fix: fix invalid resource icons (#7610)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-03 08:19:06 +01:00
plakyda-codefresh
6036e9b4c9 feat: remove cluster confirmation (#7602)
feat: remove cluster confirmation (#7602)

Signed-off-by: viktorplakida <plakyda1@gmail.com>
2021-11-02 11:37:59 -07:00
Leonardo Luz Almeida
8a6b759c4a fix: address edge cases with sync windows (#7517)
* fix: address edge cases with sync windows

Signed-off-by: Leonardo Luz Almeida <leoluz@users.noreply.github.com>

* trigger build

Signed-off-by: Leonardo Luz Almeida <leoluz@users.noreply.github.com>

* trigger build

Signed-off-by: Leonardo Luz Almeida <leoluz@users.noreply.github.com>
2021-11-02 08:48:00 -07:00
Saumeya Katyal
c2b3e74089 feat: autocompletion for resource shortnames (#7466)
* feat: autocompletion for resource shortnames

Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2021-11-02 08:33:51 -07:00
John Keates
8b10b64dfa Update USERS.md (#7589)
Add Wehkamp as a argocd user.
2021-11-01 11:31:57 -07:00
jphelton
e5c34f472e fix: argocd-dex now merges existing dex.config.oauth2 block instead of overwriting (#7583)
* fix: argocd-dex now merges existing dex.config.oauth2 block with autogenerated block

Signed-off-by: Joshua Helton <jdoghelton@gmail.com>
Signed-off-by: jphelton <jdoghelton@gmail.com>

* simplified statement based on PR feedback

Signed-off-by: Joshua Helton <jdoghelton@gmail.com>
2021-11-01 11:30:42 -07:00
Ben Ye
49b71522c4 feat: support pprof endpoints (#7533)
Signed-off-by: Ben Ye <ben.ye@bytedance.com>
2021-11-01 10:49:43 -07:00
Alexander Matyushentsev
7a6b2ffe56 fix: controller fails to connect to cluster using exec auth provider (#7586)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-11-01 10:02:57 +01:00
jannfis
c7792522c5 fix: Improve user experience for update-password CLI command (#7581)
* fix: Improve user experience for update-password CLI command

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

* Regenerate CLI docs

Signed-off-by: jannfis <jann@mistrust.net>
2021-10-30 10:30:58 +02:00
Simon Ninon
f4fd836a1b fix: return a codes.NotFound error when trying to get a non-existent repository (#7548)
* fix: return a codes.NotFound error when trying to get a non-existent repository

Signed-off-by: Simon Ninon <simon.ninon@gmail.com>

* move s.db.RepositoryExists call after the permission check

Signed-off-by: Simon Ninon <simon.ninon@gmail.com>

* update ArgoDB mock and add unit tests

Signed-off-by: Simon Ninon <simon.ninon@gmail.com>
2021-10-30 10:11:19 +02:00
Mathieu Parent
2770c690a5 Update to Helm v3.7.1, allow to pass credentials and new OCI support (#7249)
* chore: Update Helm to v3.7.1

Signed-off-by: Mathieu Parent <math.parent@gmail.com>
2021-10-29 17:48:27 -07:00
Nills Franssens
5b914750a4 docs: remove mention of ksonnet in basics (#7567)
Signed-off-by: Nills Franssens <nills.franssens@gmail.com>
2021-10-29 10:46:05 -07:00
Yuan Tang
43cba9cc0b docs: Remove misleading minus sign after version number (#7559)
* docs: Remove unnecessary version numbers in high_availability.md

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Fix

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-10-28 15:49:32 -07:00
Alex Stockinger
0dbffb8557 Clarify key/cert encoding in cluster credentials (#7545)
Fixes #7544

Signed-off-by: Alex Stockinger <mail@alexstockinger.de>
2021-10-28 13:02:19 -07:00
pasha-codefresh
7b0cf773cc feat: Replace option in cli, sync command (#7526)
feat: Replace option in cli, sync command (#7526)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-28 13:01:32 -07:00
Denis Lavrushko
d3bec0faaa docs: Added iits-consulting to the Users.md (#7566)
* added IITS organizations to the USERS.md file

Signed-off-by: Denis Lavrushko <denis.lavrushko@iits-consulting.de>
2021-10-28 12:21:09 -07:00
Saumeya Katyal
7750f579bb docs: toolchain doc minor command update (#7568)
Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2021-10-28 12:16:54 -07:00
Jeff Maaks
5aeb113968 Update private-repositories.md -- add Azure Repos (#7040)
Added a link to the documentation for creating an access token on Azure Repos
2021-10-28 12:11:40 -07:00
Engin Diri
4522a88289 feat: Show "Open application" link in Application details list view (#7455)
Signed-off-by: Engin Diri <engin.diri@mail.schwarz>
2021-10-28 12:04:29 -07:00
Ben Ye
5f4ecf1ef2 feat: improve cluster info fetch from secret by reducing unnecessary unmarshalling (#7530)
Signed-off-by: Ben Ye <ben.ye@bytedance.com>
2021-10-28 11:11:25 -07:00
Masakinpo
7ced59f346 chore: fix typo in docs/operator-manual/high_availability.md (#7551)
* fix typo in docs/operator-manual/high_availability.md

Signed-off-by: Masakinpo <masakinpo.jp@gmail.com>

* chore: fix typo in docs/operator-manual/high_availability.md

Signed-off-by: Masakinpo <masakinpo.jp@gmail.com>
2021-10-27 10:44:43 -07:00
Omer Kahani
a912611b7a Adding Snyk (#7537)
Signed-off-by: Omer Kahani <kahaniomer@gmail.com>
2021-10-25 18:19:21 -07:00
Alexander Matyushentsev
a21b0363e3 fix: Argo CD should provide apiversion and kinds to 'helm template' command (#7519)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-10-25 16:52:19 -07:00
Viktor Farcic
07b8a1f63c docs: Video about Image Updater (#7547)
Signed-off-by: Viktor Farcic <viktor@farcic.com>
2021-10-25 20:23:57 +02:00
Keith Chong
1804d771c7 feat: Add banner position option #7313 (#7462)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2021-10-23 11:09:17 -07:00
kiran
7fe8e5ff37 Added paytmlabs argocd blog in readme (#7529)
Signed-off-by: kiran <kiran.sundaravarathan@paytm.com>

Co-authored-by: kiran <kiran.sundaravarathan@paytm.com>
2021-10-22 17:26:47 -07:00
pasha-codefresh
b8510f35f1 fix: mkdocs doesnt work with 3.10.0 python (#7518)
fix: mkdocs doesnt work with 3.10.0 python (#7518)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-21 15:46:31 -07:00
pasha-codefresh
aa6aed3c04 feat: max cookie length (#7515)
feat: max cookie length (#7515)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-21 14:37:39 -07:00
Snyk bot
d6d620e98c fix: upgrade @types/react-helmet from 5.0.8 to 5.0.17 (#7473)
Snyk has created this PR to upgrade @types/react-helmet from 5.0.8 to 5.0.17.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/argoproj/project/e257be49-1bf5-455e-a11b-cdab3dbef067?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-10-21 11:13:23 -07:00
Michael Crenshaw
3e17a69df3 chore: default to no gpg for Procfile - avoids missing temp dir failure (#7506)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

Co-authored-by: Michael Crenshaw <michael_crenshaw@intuit.com>
2021-10-21 11:12:47 -07:00
Alexander Matyushentsev
da63fb26d1 fix: don't use revision caching during app creation (#7508)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-10-20 20:24:14 -07:00
Mohammad Yosefpor
401b266235 fix: supporting OCI dependencies. Fixes #6062 (#6994)
* fix: supporting OCI dependencies

Signed-off-by: Mohammad Yosefpor <myusefpur@gmail.com>

* chore: add org to USERS.md

Signed-off-by: Mohammad Yosefpor <myusefpur@gmail.com>

* fix(tests): remove invalid TestRepoPermission e2e test

Signed-off-by: Mohammad Yosefpor <myusefpur@gmail.com>
2021-10-20 18:22:37 -07:00
Alexander Matyushentsev
f46ac844b8 chore: add pasha-codefresh to reviewers list (#7503)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-10-20 13:09:13 -07:00
May Zhang
046840dcf7 fix: docker image for ui-test (#7461)
fix: docker image for ui-test (#7461)

Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-10-20 11:34:28 -07:00
Atsushin
d460f844a4 fix: Fix Color Support in Logs (#7476)
Signed-off-by: Atsushi Neki <nekiaiken@gmail.com>
2021-10-20 11:31:24 -07:00
Leonardo Luz Almeida
970bb80b28 feat: add new sync option to fail if finds shared resources (#7444)
* feat: add new sync option to fail if finds shared resources

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

* docs: add docs for FailOnSharedResource sync option

Signed-off-by: Leonardo Luz Almeida <leoluz@users.noreply.github.com>
2021-10-20 08:06:41 -07:00
Alexander Matyushentsev
81e801d8ee fix: Invalid memory address or nil pointer dereference in processRequestedAppOperation (#7501)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-10-20 08:03:55 -07:00
Alexander Matyushentsev
872eff292b fix: Operation has completed with phase: Running (#7482)
* fix: Operation has completed with phase: Running

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-10-19 17:16:31 -07:00
Julian Strobl
00874af5f2 fix: client certificate ignored during (re)login (#7423)
fix: client certificate ignored during (re)login (#7423)

Signed-off-by: Julian Strobl <julian.strobl@telekom.de>

Co-authored-by: Julian Strobl <julian.strobl@telekom.de>
2021-10-19 13:12:35 -07:00
Hritik Gupta
ad97ed52d5 doc: fixed content in toolchain guide (#7470)
doc: fixed content in toolchain guide (#7470)

Signed-off-by: hgupta3 <hritik_gupta@intuit.com>
2021-10-19 13:08:41 -07:00
Alexander Matyushentsev
7ea35924c9 fix: Application status panel shows Syncing instead of Deleting (#7486)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-10-19 10:30:09 -07:00
Byungjin Park (Claud)
c7074fe67a docs: Add KarrotPay to Users (#7467)
Signed-off-by: Byungjin Park <posquit0.bj@gmail.com>
2021-10-19 10:13:27 -07:00
jannfis
9a11790df2 fix: Allow plugins to lock repository at top-level to prevent git races (#6223)
* fix: Allow plugins to lock complete repository

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

* Add some documentation

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

* Adapt documentation

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

* Codegen

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

* Update codegen

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

* Update codegen

Signed-off-by: jannfis <jann@mistrust.net>
2021-10-19 18:51:59 +02:00
Yuan Tang
695699d08e docs: Add Akuity to the list of users (#7480)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-10-19 08:20:32 -07:00
Álvaro González
374965a606 docs: add a google warning and fix some formats (#7340)
Signed-off-by: alvarogonzalez-packlink <alvarogonzalez@packlink.com>
2021-10-19 01:36:59 -07:00
pasha-codefresh
ddc9f56d05 feat: Cluster name as part of sync (#7394)
feat: Cluster name as part of sync (#7394)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-18 18:44:54 -07:00
pasha-codefresh
3312dc0037 feat: Resource id tracking method doc (#7468)
feat: Resource id tracking method doc (#7468)
Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-18 18:44:08 -07:00
pasha-codefresh
67dd012b87 feat: add cluster name UI (#7409)
* group diff should set resource id use new interface

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

* add cluster destination should support name

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-18 13:03:49 -07:00
Leonardo Luz Almeida
10bb1c4e1f docs: add remaining metric docs (#7469)
Signed-off-by: Leonardo Luz Almeida <leoluz@users.noreply.github.com>
2021-10-18 10:10:34 -07:00
ChangZhuo Chen (陳昌倬)
f3730da01e fix: Fix typo in SparkApplication health check script (#7433) (#7434)
Closes: #7433

Signed-off-by: ChangZhuo Chen (陳昌倬) <czchen@czchen.org>
2021-10-17 22:24:42 -07:00
Snyk bot
d8f6ee2d72 fix: upgrade @types/react-dom from 16.8.5 to 16.9.14 (#7400)
Snyk has created this PR to upgrade @types/react-dom from 16.8.5 to 16.9.14.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/argoproj/project/e257be49-1bf5-455e-a11b-cdab3dbef067?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-10-17 20:35:07 -07:00
Leonardo Luz Almeida
b5d1433a1f Fix argocd_cluster_connection_status metric (#7419)
* bug: fix argocd_cluster_connection_status metric + docs

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2021-10-17 19:58:02 -07:00
Vaibhav Thakur
83ff035df7 Add Tigera to USERS.md (#7435)
Signed-off-by: Vaibhav Thakur <vaibhav@tigera.io>

Co-authored-by: Vaibhav Thakur <vaibhav@tigera.io>
2021-10-17 11:50:02 -07:00
jiraguha
1d4b91efa2 Add Rise the money app for teens to USERS.md (#7465)
Signed-off-by: jpiraguha <jiraguha@gmail.com>
2021-10-17 11:39:43 -07:00
May Zhang
43bcbfb093 fix: makeslice: cap out of range (#7463)
Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-10-17 10:43:14 -07:00
May Zhang
f0cd21a9f3 fix: invalid memory address or nil pointer dereference during cluster… (#7445)
Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-10-16 21:57:39 -07:00
Guy Elia
d7d8fe3da2 Add BigPanda to USERS.md (#7416)
Add BigPanda as an ArgoCD user
2021-10-12 10:00:51 -07:00
Assel Meher
c80c1d4f95 fix: fix parameter name when the value is a list (#7360) (#7362)
* fix: #7360

Signed-off-by: Assel Meher <asselmeher@gmail.com>

* fix assert in tests

Signed-off-by: Assel Meher <asselmeher@gmail.com>
2021-10-12 09:50:50 -07:00
Alexander Krantz
6644cbe452 fix: prevent displayed namespace from being undefined (#7401)
Signed-off-by: Alex Krantz <alex@krantz.dev>
2021-10-12 08:28:24 -07:00
Regina Scott
ae02bc27fc feat: add hide toggle for health status bar (#7153)
Signed-off-by: Regina Scott <rescott@redhat.com>
2021-10-11 14:41:48 -07:00
Mustafa
5faea8f339 docs: Append echo to kubectl in getting_started.md (#7403)
Add echo to the end of the kubectl command to fetch initial admin secrets so that '%' new line character is not printed at the end of the secret.

Signed-off-by: mustafa89 <mustafa.mujahid@outlook.com>

Co-authored-by: Mustafa Mujahid <mustafa.mujahid@tradebyte.com>
2021-10-11 22:49:06 +02:00
pasha-codefresh
678d35d850 feat: project destination cli (#7407)
feat: project destination cli (#7407)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-11 06:42:47 -07:00
c1_zh
363e1d2d49 feat: Make Casbin matcher configurable on runtime(globMatch(default) or RegexMatch) (#7165)
* feat: Make Casbin matcher configurable on runtime(globMatch(default) or RegexMatch)

Signed-off-by: cezhang <c1zhang.dev@gmail.com>
2021-10-09 12:01:09 -07:00
Alexander Matyushentsev
b2c70df619 docs: update v2.3+ roadmap (#7353)
* docs: update v2.3+ roadmap

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

* Address reviewer notes: Add 'Merge Argo CD Image Updater into Argo CD' and 'Multi-tenancy improvements'

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-10-08 15:46:15 -07:00
May Zhang
3c874ae065 fix: Utilize a backoff for git retried operations (#7395)
* fix: git retry duration

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

* fix: adjust default values

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

* fix: adjust default values

Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-10-08 14:00:09 -07:00
Jan-Otto Kröpke
4dd570eb11 docs: Kustomize load_restrictor -> load-restrictor (#7358)
Signed-off-by: Jan-Otto Kröpke <joe@adorsys.de>
2021-10-08 11:56:05 -07:00
Chetan Banavikalmutt
1bc231dd99 fix: failing automated UI smoke tests (#7392)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2021-10-08 11:49:00 -07:00
Hritik Gupta
8a8373faba feat(ui): Ability to view previous container logs in log viewer (#7393)
feat(ui): Ability to view previous container logs in log viewer (#7393)

Signed-off-by: hgupta3 <hritik_gupta@intuit.com>
2021-10-08 11:33:26 -07:00
Leonardo Luz Almeida
384f5b2bae Expose Application labels in prometheus metric (#7374)
Expose Application labels in prometheus metric (#7374)

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2021-10-08 10:15:51 -07:00
pasha-codefresh
b0736219b6 feat: Resources should be normalized in order to prevent our of sync during migration (#7388)
feat: Resources should be normalized in order to prevent our of sync during migration (#7388)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-07 09:51:29 -07:00
Hrittik Roy
4399348ae5 docs: Add p3r to Users.md (#7346)
docs: Add p3r to Users.md (#7346)

* Update USERS.md

* Add p3r to Users.md

Signed-off-by: GitHub <noreply@github.com>

* Update USERS.md

Signed-off-by: GitHub <noreply@github.com>
2021-10-07 09:49:39 -07:00
Chetan Banavikalmutt
df5cce866f fix: unable to read jqPathExpressions (#7375)
The commit introduces the following changes:
1. Update the admin settings resource-overrides CLI to work with jqPathExpressions
2. Allow jqPathExpressions to be set from the UI

Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2021-10-06 09:59:09 -07:00
pasha-codefresh
07eeddf5f1 feat: group diff should set resource id use new interface (#7381)
feat: group diff should set resource id use new interface (#7381)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-06 09:08:20 -07:00
Chetan Banavikalmutt
0c757534ed fix: remove misleading Helm labels from Redis resources in HA mode (#7368)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2021-10-05 13:00:26 +02:00
Chetan Banavikalmutt
d8d7b30f58 fix: username is required with access token (#7359)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2021-10-04 14:58:16 -07:00
Alexander Matyushentsev
9d88e614cd fix: creating JWT token fails (#7366)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-10-04 14:43:49 -07:00
Fabiano Arruda
4e025838c0 Update USERS.md (#7348) 2021-10-04 09:49:15 -07:00
pasha-codefresh
d0c6280d38 feat: change annotation format (#7345)
* change annotation format

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-04 09:48:51 -07:00
Keith Chong
e084a110e4 feat: Allow Banner to be non-closable #7261 (#7312)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2021-10-04 09:45:13 -07:00
pasha-codefresh
df7e5ffd96 feat: annotation-label tracking method (#7342)
feat: annotation-label tracking method (#7342)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-03 16:08:51 -07:00
Oleksandr Saulyak
6f8b10c324 fix: updated argo-ui package with fixes for #7192 / #7262 (#7344)
Signed-off-by: oleksandr-codefresh <oleksandr.saulyak@codefresh.io>
2021-10-02 10:50:32 -07:00
Jille Timmermans
eb70a1e3fa docs: Add an example for setting up Helm charts with GitOps (#7060)
Took me embarrassingly long to figure out.

Signed-off-by: Jille Timmermans <jille@quis.cx>
2021-10-01 11:18:30 -07:00
plakyda-codefresh
35bd9e1ed6 fix: retry options in app details modal (#7329)
fix: retry options in app details modal (#7329)

Signed-off-by: viktorplakida <plakyda1@gmail.com>
2021-10-01 10:24:46 -07:00
Matt Pursley
778be231b9 fix: a few typos in kustomize.md (#7334)
Signed-off-by: Matt Pursley <mattpursley@improbable.io>
2021-10-01 10:17:47 -07:00
Abhishek Veeramalla
d790e96aa9 fix: Retry with exponential backoff result in time to wait of zero(#7173) (#7339)
* fix: Retry with exponential backoff result in time to wait of zero(#7173)

Signed-off-by: iam-veeramalla <abhishek.veeramalla@gmail.com>

* fix issue reported by golintci

Signed-off-by: iam-veeramalla <abhishek.veeramalla@gmail.com>
2021-10-01 10:02:44 -07:00
Saumeya Katyal
a6039e1be9 fix: add url check and wrapping for commit msg field (#7218)
* fix: add url check and wrapping for commit msg field

Signed-off-by: saumeya <saumeyakatyal@gmail.com>

* move url regex to util

lint check

Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2021-10-01 09:23:49 -07:00
pasha-codefresh
3d4deeb4f0 fix: compare app state (#7341)
* fix compare app state

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-10-01 09:18:01 -07:00
pasha-codefresh
ebd87b77ed feat: improve sync logic (#7328)
feat: improve sync logic (#7328)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-30 14:49:29 -07:00
Yuan Tang
31b2cbee70 chore: More informative error message when redirect URL is invalid (#7331)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-09-30 13:29:12 -07:00
pasha-codefresh
a2677f5537 fix: Rm browser history (#7327)
fix: Rm browser history (#7327)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-30 13:25:46 -07:00
Álvaro González
65d669565b docs: configuring Google OIDC and Google groups for RBAC (#7308)
Signed-off-by: alvarogonzalez-packlink <alvarogonzalez@packlink.com>
2021-09-30 02:02:19 -07:00
Ishita Sequeira
07f4034aaa feat: lua script for pause/resume action for Deployments (#7293)
Signed-off-by: ishitasequeira <isequeir@redhat.com>
2021-09-29 17:58:35 -07:00
Yi Cai
459833d7c3 fix: default schedule options are cropped #5261 (#7289)
* fix: default schedule options are cropped #5261

Signed-off-by: ciiay <yicai@redhat.com>
2021-09-29 14:53:49 -07:00
Andrii Shaforostov
bbdbf81108 feat: update argo-ui (#7323)
* use merged argo-ui, align dependencies with argo-ui

Signed-off-by: andrii-codefresh <andrii@codefresh.io>

* use merged argo-ui, align dependencies with argo-ui

Signed-off-by: andrii-codefresh <andrii@codefresh.io>
2021-09-29 14:51:42 -07:00
Alexander Matyushentsev
1842c98374 fix: core-install.yaml always refers to latest argocd image (#7321)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-29 14:05:18 -07:00
Chetan Banavikalmutt
94372adcd4 fix: handle applicationset backup forbidden error (#7306)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2021-09-29 12:33:58 -07:00
plakyda-codefresh
e3df023310 fix: Move orphaned filter to Filters block (#7082)
fix: Move orphaned filter to Filters block (#7082)

Signed-off-by: viktorplakida <plakyda1@gmail.com>
2021-09-29 12:29:21 -07:00
Duy Le
6f5f7ffeee fix: tooltip zindex overwrite toolbar (#7220)
Signed-off-by: Duy Le <duyngoc834@gmail.com>
2021-09-29 12:24:41 -07:00
chandu484
97302103d9 Add Keeeb User to userlist (#7288) 2021-09-29 11:03:29 -07:00
Regina Scott
380037b63d fix: preventOverflow console warnings (#7298)
Signed-off-by: Regina Scott <rescott@redhat.com>
2021-09-29 10:27:25 -07:00
pasha-codefresh
0d68194205 feat: tracking method for annotations should be in another format (#7316)
feat: tracking method for annotations should be in another format (#7316)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-29 10:14:49 -07:00
Abhishek Veeramalla
20313adbe2 docs: minor formatting change in the docs (#7305)
Signed-off-by: iam-veeramalla <abhishek.veeramalla@gmail.com>
2021-09-29 11:43:57 +02:00
pasha-codefresh
a731997c59 feat: tracking method e2e (#7310)
feat: tracking method e2e (#7310)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-28 12:46:01 -07:00
pasha-codefresh
bb88a1c975 feat: rename app identifier (#7251)
feat: rename app identifier (#7251)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-28 08:35:17 -07:00
Alexander Matyushentsev
917d0797fa fix: deploy CI task should start docker using current user id to avoid permission denied error (#7300)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-27 19:01:55 -07:00
plakyda-codefresh
993cb838a9 feat: Project autocomplete (Connect repo SSH) (#7286)
feat: Project autocomplete (Connect repo SSH) (#7286)

Signed-off-by: viktorplakida <plakyda1@gmail.com>
2021-09-27 17:19:00 -07:00
Regina Scott
eb2c69d45e fix: long banner messages get cut off (#7264)
Signed-off-by: Regina Scott <rescott@redhat.com>
2021-09-27 13:31:14 -07:00
Alexander Matyushentsev
65012f502b chore: use kustomize verison bundled into argocd to upgrade argocd manifests in argoproj/argoproj-deployments (#7299)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-27 12:58:15 -07:00
ml
2f6e91ad22 chore: fix typo in directory name (#7248)
Signed-off-by: ml <ml@visu.li>
2021-09-27 11:33:00 -07:00
shivjm
b264729bfb docs: fix example ServiceMonitor for argocd-repo-server (#7254)
Signed-off-by: Shiv Jha-Mathur <shivjm@users.noreply.github.com>
2021-09-23 12:46:19 -07:00
pasha-codefresh
3952f66fc7 fix: remove not existing repo (#7280)
* remove not existing repo

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

* fix test

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-22 14:27:07 +02:00
plakyda-codefresh
b1f979aad6 feat: retry option app creation (#7252)
feat: retry option app creation (#7252)

Signed-off-by: viktorplakida <plakyda1@gmail.com>
2021-09-21 15:42:26 -07:00
Yuan Tang
2a579a6c05 docs: Add missing links to 1.8-2.1 upgrading guides (#7263)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-09-21 15:02:26 -07:00
dependabot[bot]
9e234b9dec chore(deps): bump tmpl from 1.0.4 to 1.0.5 in /ui (#7266)
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-21 15:02:14 -07:00
John Chen
4f69e93802 docs: add comment about current-user-password (#7258)
It is not immediately clear what the `<current-user-password>` should be as shown by this issue: https://github.com/argoproj/argo-cd/issues/4096.
This comment should make it more clear that when users are setting passwords as the default `admin` user, they should be using the `admin` password here.

Signed-off-by: John Chen <johnchen456@gmail.com>
2021-09-21 14:34:13 -07:00
Alexander Matyushentsev
3799d706df refactor: cache virtual project calculation to improve performance (#7274)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-21 12:20:49 -07:00
yyyyyy888
344353cb16 docs: Add Sutpc company into the user list. (#7267)
Signed-off-by: yangtian9999 <yangtian9999@163.com>
2021-09-21 12:20:08 -07:00
dependabot[bot]
d698e5d68a chore(deps): bump prismjs from 1.24.1 to 1.25.0 in /ui (#7265)
Bumps [prismjs](https://github.com/PrismJS/prism) from 1.24.1 to 1.25.0.
- [Release notes](https://github.com/PrismJS/prism/releases)
- [Changelog](https://github.com/PrismJS/prism/blob/master/CHANGELOG.md)
- [Commits](https://github.com/PrismJS/prism/compare/v1.24.1...v1.25.0)

---
updated-dependencies:
- dependency-name: prismjs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-21 11:32:50 -07:00
dependabot[bot]
5f9993a75b chore(deps): bump nth-check from 2.0.0 to 2.0.1 in /ui (#7270)
Bumps [nth-check](https://github.com/fb55/nth-check) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/fb55/nth-check/releases)
- [Commits](https://github.com/fb55/nth-check/compare/v2.0.0...v2.0.1)

---
updated-dependencies:
- dependency-name: nth-check
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-21 09:43:13 -07:00
Alexander Matyushentsev
f613fab6f3 refactor: stop using @beyonk/google-fonts-webpack-plugin to download google fonts (#7253)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-18 08:22:53 +02:00
Alexander Matyushentsev
183d729d40 fix: Argo CD should not use cached git/helm revision during app creation/update validation (#7244)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-16 18:35:15 -07:00
Regina Scott
b26e92873f fix: typo causing docs to not render properly (#7242)
Signed-off-by: Regina Scott <rescott@redhat.com>
2021-09-16 13:00:02 -07:00
Alexander Matyushentsev
36ab4dadda fix: Argo CD server address unspecified with Argo CD CLI v2.1.x (#7238)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-16 11:23:29 -07:00
pasha-codefresh
91fea1470f feat: add test to redis_hook.go (#7233)
* add test to redis_hook.go

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

* restart action

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-16 08:06:29 -07:00
pasha-codefresh
17e6ebdce1 feat: show difference in repos that exist and that should be changed (#7224)
* show difference in repos that exist and that should be changed

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-16 08:02:50 -07:00
pasha-codefresh
6f794d0dc9 fix: Redis should reconnect on connectivity issue (#7207)
fix: Redis should reconnect on connectivity issue (#7207)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-15 09:05:48 -07:00
Miguel Ángel Cabrera Miñagorri
9cf71bef90 fix: support gpg keys generation in centos-7 distros (#7221)
Signed-off-by: Miguel A. Cabrera Minagorri <mcabrera@vmware.com>
2021-09-15 08:26:46 -07:00
gin
25db5038c7 docs(users): add mixi in users.md (#7210)
Signed-off-by: gin <10017674+lirlia@users.noreply.github.com>
2021-09-14 12:52:19 -07:00
Remington Breeze
b6c458e8f4 fix(ui): Add Error Boundary around Extensions and comply with new Extensions API (#7215)
* fix: Add error boundary around Extensions and change path where UI looks for extensions

Signed-off-by: Remington Breeze <remington@breeze.software>

* Add error message to error boundary

Signed-off-by: Remington Breeze <remington@breeze.software>
2021-09-14 12:51:37 -07:00
Alexander Matyushentsev
2147ed3aea fix: cluster API should not drop system labels and annotations (#7212)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-14 10:37:57 -07:00
Remington Breeze
3df6be73e7 fix(ui): More tab was displayed for resources that did not have extensions installed (#7209)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-09-13 22:18:38 -07:00
jannfis
d823efee5d proposal: Change application identifier to allow app names longer than 63 chars (#6425)
proposal: Change application identifier to allow app names longer than 63 chars (#6425)

Signed-off-by: jannfis <jann@mistrust.net>
2021-09-13 08:49:15 -07:00
pasha-codefresh
1817b6b4d4 Scoped resources doc (#7206)
* add doc about scoped resources

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

* docs: explain project scoped resources

Signed-off-by: Kostis Kapelonis <kostis@codefresh.io>

Co-authored-by: Kostis Kapelonis <kostis@codefresh.io>
2021-09-13 08:47:39 -07:00
pasha-codefresh
7ed06cc9f6 feat: Scoped resources cluster e2e (#7199)
feat: Scoped resources cluster e2e (#7199)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-12 19:05:49 -07:00
Yuan Tang
49378a95c4 chore: Update Ingress apiVersion to networking.k8s.io/v1beta1 (#7188)
* chore: Update Ingress apiVersion to networking.k8s.io/v1beta1

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* Revert changes in  controller/cache/info_test.go

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-09-10 10:04:52 -07:00
jannfis
a38f3176e2 chore: Update haproxy for redis-ha to 2.0.25 (#7194)
Signed-off-by: jannfis <jann@mistrust.net>
2021-09-10 09:13:27 -07:00
pasha-codefresh
08d1cf0e55 feat: Ability to test rbac and implement it with scoped repos (#7187)
feat: Ability to test rbac and implement it with scoped repos (#7187)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-09 21:42:32 -07:00
Thomas
85c45ca76e fix: use selected helm-values (#7166)
Signed-off-by: Thomas Münzl <thomasmuenzl@icloud.com>
2021-09-09 20:48:32 -07:00
Yi Cai
626c963b1c docs: minor update on dependencies.md (#7190)
Signed-off-by: ciiay <yicai@redhat.com>
2021-09-09 15:28:49 -07:00
Suraj Bodade
fc49eb2e46 fixed small typos in github credentials types (#7161)
Signed-off-by: suraj-zemoso <suraj.bodade@zemosolabs.com>
2021-09-09 11:40:06 -07:00
irizzant
e0c07b8027 #7144 fix: add custom volume as Helm working dir (#7162)
#7144 fix: add custom volume as Helm working dir (#7162)

Signed-off-by: irizzant <i.rizzante@gmail.com>
2021-09-09 10:31:03 -07:00
Chetan Banavikalmutt
7122b83fc3 feat: support adding labels and annotations to cluster secret (#7139)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2021-09-09 09:03:32 -07:00
pasha-codefresh
c64e8df84c feat: ability to switch user during test execution (#7164)
feat: ability to switch user during test execution (#7164)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-09-09 08:58:46 -07:00
Ben Ye
be884d2172 feat: Support delete-resource command in cli (#7093)
* feat: support delete-resource command in argocd cli

Signed-off-by: Ben Ye <ben.ye@bytedance.com>

* add E2E test and fix documents

Signed-off-by: Ben Ye <ben.ye@bytedance.com>

* sync app

Signed-off-by: Ben Ye <ben.ye@bytedance.com>
2021-09-06 09:11:06 -07:00
Ijeh Onyeka
d2100a30a0 add youverify to companies actively using argocd (#7163) 2021-09-04 15:09:51 -07:00
ThoTischner
9559613c8f feat: Closes #6956 - Adding confluent health checks (#6957)
* Issue argoproj#6956 - Adding confluent health checks

Signed-off-by: ThoTischner <thomas-schwaig@web.de>

* Issue argoproj#6956 - Change Unknown to Progressing

Signed-off-by: ThoTischner <thomas-schwaig@web.de>
2021-09-03 21:51:00 +02:00
dependabot[bot]
bd7f8c8eda chore(deps): bump tar from 6.1.3 to 6.1.11 in /ui (#7123)
Bumps [tar](https://github.com/npm/node-tar) from 6.1.3 to 6.1.11.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v6.1.3...v6.1.11)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-03 19:32:33 +02:00
jannfis
a90ab1a2e1 chore: Upgrade github.com/bradleyfalzon/ghinstallation to v2.0.2 (#7151)
Signed-off-by: jannfis <jann@mistrust.net>
2021-09-03 10:28:10 -07:00
Thomas
a5126648e1 fix: use basehref as cookie-path (#7105)
Signed-off-by: Thomas Münzl <thomasmuenzl@icloud.com>
2021-09-03 19:21:31 +02:00
Petr Drastil
d9e8a0fc31 chore: Upgrade dex server image to 2.30.0 (#7102)
* chore: Upgrade dex server to 2.30.0

Signed-off-by: Petr Drastil <petr.drastil@gmail.com>

* Revert dex server probes

Signed-off-by: Petr Drastil <petr.drastil@gmail.com>
2021-09-03 19:20:01 +02:00
Ishita Sequeira
b559bf88d1 feat: Add health checks for route.openshift.io (#7112)
* feat: Add health checks for route.openshift.io

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* Addressed PR comments

Signed-off-by: ishitasequeira <isequeir@redhat.com>
2021-09-03 17:27:16 +02:00
Ishita Sequeira
c0f2bf55a7 feat: health check for openshift DeploymentConfig (#7114)
* feat: health check for openshift DeploymentConfig

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* Address PR comments

Signed-off-by: ishitasequeira <isequeir@redhat.com>
2021-09-03 17:26:31 +02:00
Ishita Sequeira
4b92f96034 feat: Add health checks for olm operators (#7126)
* feat: Add health checks for olm operators

Signed-off-by: ishitasequeira <isequeir@redhat.com>

* Addressed the PR comments

Signed-off-by: ishitasequeira <isequeir@redhat.com>
2021-09-03 17:25:42 +02:00
smartbit
24054820da docs: update url of External Secrets Operator (#7120)
has moved from ContainerSolutions' github account to it's own github project
2021-09-03 11:10:58 +02:00
Alexander Matyushentsev
22600228c2 fix: Correct this attempt to modify const 'store' variable (#7145)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-02 11:37:20 -07:00
renjikari
9025318adf docs: Add freee as a user (#7140)
Signed-off-by: Shunki Fujiwara <shunki-fujiwara@freee.co.jp>
2021-09-02 03:43:13 -07:00
Alexander Matyushentsev
5d9aa989f3 fix: gracefully shutdown metrics server when dex config changes (#7138)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-01 18:55:05 -07:00
Alexander Matyushentsev
9613b240fb fix: upgrade gitops engine (fix #7088) (#7137)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-01 17:45:42 -07:00
Alexander Matyushentsev
8fbcc1c7fc fix: cluster filter popping out of box (#7135)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-09-01 15:33:27 -07:00
Remington Breeze
d2ff65ae39 feat(ui): Display event timestamps in human readable format (#7132)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-09-01 15:08:40 -07:00
c1_zh
dd26a48f8a fix: Network view is confusing if same ingress is targeting two services #2338 (#7113)
Signed-off-by: cezhang <c1zhang.dev@gmail.com>
2021-09-01 14:46:40 -07:00
Chetan Banavikalmutt
8c19c7864d docs: add a section about banners (#7109)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2021-09-01 12:52:59 -07:00
pasha-codefresh
a9f009cb10 feat: e2e for clusters (#7118)
feat: e2e for clusters (#7118)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-31 10:32:54 -07:00
May Zhang
ce1d8031ae fix: repository name already exists when multiple helm dependencies f… (#7096)
* fix: repository name already exists when multiple helm dependencies from same private repo server

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

* fix: add test cases

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

* fix: clean up

Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-08-31 08:30:03 -07:00
pasha-codefresh
dd2900eaeb feat: scoped repo e2e tests (#7110)
feat: scoped repo e2e tests (#7110)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-30 10:10:32 -07:00
pasha-codefresh
c0bcd6b255 feat: repo list and repo get command + e2e tests (#7108)
feat: repo list and repo get command + e2e tests (#7108)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-30 10:08:33 -07:00
Álvaro González
6897aa4ed2 docs: add configuration guide for using Google Load Balancers with GKE (#6747)
* docs: add configuration guide for using Google Load Balancers with GKE

Signed-off-by: alvarogonzalez-packlink <alvarogonzalez@packlink.com>

* docs: fix format on notes and warnings

Signed-off-by: alvarogonzalez-packlink <alvarogonzalez@packlink.com>
2021-08-30 15:58:49 +02:00
Yi Cai
42903044f3 fix: Summary Colors don't match key and numbers don't match colors #5200 (#7042)
Signed-off-by: ciiay <yicai@redhat.com>
2021-08-27 12:41:09 -07:00
Thomas
700806f408 fix: reset token-cookie on logout (oidc) (#7092)
fix: reset token-cookie on logout (oidc) (#7092)

Signed-off-by: jimtoniq <thomasmuenzl@icloud.com>
2021-08-27 11:09:19 -07:00
pasha-codefresh
b271d6ac5c feat: Test create repository with project ( part of scoped resources e2e tests ) (#7103)
feat: Test create repository with project ( part of scoped resources e2e tests ) (#7103)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-27 10:29:31 -07:00
Jonah Back
a940cb5914 fix(ui): calculate service info correctly for networking.k8s.io/v1 ingress (#6923)
Signed-off-by: Jonah Back <jonah@jonahback.com>
2021-08-26 14:47:26 -07:00
Alexander Matyushentsev
87de4edd15 fix: document IP addresses logging (#7094)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-26 13:01:40 -07:00
Alexander Matyushentsev
abba8dddce docs: update VERSION file and CHANGELOG (#7083)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-26 11:28:51 -07:00
plakyda-codefresh
44520ea479 feat: resource name filter + filter block for resource table view (#7081)
feat: resource name filter + filter block for resource table view (#7081)

Signed-off-by: viktorplakida <plakyda1@gmail.com>
2021-08-26 10:32:36 -07:00
pasha-codefresh
ae803a2f1e feat: goreman option to exclude (#7080)
feat: goreman option to exclude (#7080)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-25 12:40:55 -07:00
pasha-codefresh
49a854a738 feat: Scoped clusters (#7039)
feat: Scoped clusters (#7039)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-25 09:53:58 -07:00
Benjamin Manifold
81155ccb0c feat: Cassandra Health Check. Closes #6843 (#7017)
Signed-off-by: benmanifold <benmanifold@gmail.com>
2021-08-25 11:27:07 +02:00
Josh Gavant
18057fa5ee docs: clarify new repo, port-forward flags (#6937)
The instructions for telling the CLI how to automatically use
port-forward were intertwined with the instructions for registering a
repo; this separates them.

This also moves the port-forward flags instructions to the first place
in the doc a user would need them.

Signed-off-by: Josh Gavant <joshgavant@gmail.com>
2021-08-25 11:26:44 +02:00
May Zhang
ca5003f3ba fix: password reset requirements (#7071)
* fix: password reset meet requirement

Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-08-24 23:21:03 -07:00
Alexander Matyushentsev
1d3d03f5d3 fix: Custom Styles feature is broken (#7067)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-24 15:08:12 -07:00
Remington Breeze
a894d4b128 fix(ui): Unschedulable button changed widths on click (#7030)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-08-24 11:29:45 -07:00
Remington Breeze
440e4dc5d9 fix(ui): Add State to props passed to Extensions (#7045)
Signed-off-by: Remington Breeze <remington@breeze.software>
Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-24 11:23:56 -07:00
Alexander Matyushentsev
d6973c7b8a fix: fix building remote container (#7062)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-24 09:48:14 -07:00
pasha-codefresh
34e904dd7b fix: make codegen (#7059)
fix: make codegen

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-24 09:02:44 -07:00
Omar De Donato
c7e532941f docs: added Technacy in USERS.md (#7051)
We at Technacy love using Argo CD

Signed-off-by: Omar <omar.dedonato@technacy.it>
2021-08-23 13:23:28 +02:00
Alexander Matyushentsev
613db278a7 fix: keep uid_entrypoint.sh for backward compatibility (#7047)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-23 08:38:29 +02:00
pasha-codefresh
91c883668e feat: Scoped repo unit tests (#7026)
feat: Scoped repo unit tests

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-22 18:01:36 -07:00
Yi Cai
d12eafa826 fix: Truncated synchronize check-boxes should have tooltips #4233 (#6954)
Signed-off-by: ciiay <yicai@redhat.com>
2021-08-20 12:41:25 -07:00
Alexander Matyushentsev
0dcac9a8d9 fix: reload extension when selected resource node changes (#7034)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-19 22:14:00 -07:00
Jesse Suen
0078a4d9ee docs: add @wanghong230 as a reviewer (#7029)
Signed-off-by: Jesse Suen <jessesuen@gmail.com>
2021-08-19 17:02:51 -07:00
Jesse Suen
8ceceb8b55 docs: add @rbreeze as an approver (#7028)
Signed-off-by: Jesse Suen <jessesuen@gmail.com>
2021-08-19 13:56:47 -07:00
Remington Breeze
2e3405134b fix(ui): Resource details crashed due to extensions (#7025)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-08-19 09:55:16 -07:00
pasha-codefresh
5b1906d2a7 feat: Cover grpc crud rbac (#7008)
feat: Cover grpc crud rbac (#7008)

Signed-off-by: Victor Plakyda <plakyda1@gmail.com>
Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-19 08:43:48 -07:00
pasha-codefresh
0093bddc39 fix(ui): user account list yaml (#7021)
fix(ui): user account list yaml (#7021)

Signed-off-by: Victor Plakyda <plakyda1@gmail.com>
2021-08-19 08:40:20 -07:00
Alexander Matyushentsev
788613cb14 feat: support loading extensions in Argo CD UI (#7019)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-19 08:39:51 -07:00
pasha-codefresh
53dd0da8c3 fix(ui): applications table view, Closes #6733 (#6995)
Co-authored-by: Victor Plakyda <plakyda1@gmail.com>
2021-08-18 12:23:34 -07:00
Guido Zockoll
8f21138d54 docs: added type:git to secret examples (fixes #6984) (#7013)
* Update declarative-setup.md

added `type: git` to the secrets

* warning about labels getting lost

when using sealed-secrets the labels will get lost and has to be readded
2021-08-18 20:18:28 +02:00
Saumeya Katyal
676a8714bf fix: Unschedulable button style (#7003)
Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2021-08-18 09:24:03 -07:00
Philipp Dallig
4ae1d876fd fix: Running on Openshift 4.x with readOnlyRootFilesystem (#6998)
Signed-off-by: Philipp Dallig <philipp.dallig@gmail.com>
2021-08-18 12:18:01 +02:00
Chris Sinjakli
efc8ec1d78 chore: Log application name for invalid application spec (#6991)
When creating an application directly through the CLI or a `kubectl
apply`, it's relatively obvious which application is invalid (provided
you aren't applying several at once) as you're there creating it
interactively.

It's less clear when applications are generated by the application set
controller. When that happens, you need to go looking in the controller
logs, where you'll find something like:

> time="2021-08-10T11:36:02Z" level=error msg="application spec is
> invalid: InvalidSpecError: application destination
> {https://kubernetes.default.svc default} is not permitted in project
> 'my-project'"

which doesn't have any connection back to the application being
generated. This is particularly tricky to track down if you're searching
your logs via some sort of aggregator rather than watching `kubectl logs
-f`.

After this change, the log produced would be:

> time="2021-08-10T11:36:02Z" level=error msg="application spec for
> guestbook is invalid: InvalidSpecError: application destination
> {https://kubernetes.default.svc default} is not permitted in project
> 'my-project'"

There's probably fancier ways this information could be presented (e.g.
if application sets were represented in the UI and knew about failures
to apply their generated applications), but this logging change seems
like a cheap way to make this situation more debuggable.

Signed-off-by: Chris Sinjakli <chris@sinjakli.co.uk>
2021-08-18 11:10:52 +02:00
Alexander Matyushentsev
e3b7a2be13 fix: resouce health filter should include node if node or node's root health matches filter (#7002)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-17 14:34:27 -07:00
Alexander Matyushentsev
44ec4e0a82 fix: upgrade argo-ui version (#7010)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-17 12:50:07 -07:00
pasha-codefresh
24ad4618c2 fix: Git errors to grpc (#7005)
fix: Git errors to grpc (#7005)

Signed-off-by: olegz-codefresh <olegz@codefresh.io>
2021-08-17 12:27:44 -07:00
Yuan Tang
d3fb6fb7db chore: Update to use NewSharedInformerFactoryWithOptions due to deprecation (#7009)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-08-17 21:23:13 +02:00
RoCha
95d9016ed4 feat: healtcheck for iam.cnrm.cloud.google.com/IAMPolicyMember (#6783)
Signed-off-by: Romain Chalumeau <rchalumeau@magicleap.com>
2021-08-17 21:20:30 +02:00
Alexander Matyushentsev
e195995790 docs: update obsolete resource customization docs (#7000)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-16 10:49:34 -07:00
Spiros Economakis
124995c275 feat: Add a metric to express connection status to each cluster (#6862)
The cluster collector includes one more metric for kubernetes cluster connection
which rely on `SyncError`.

Ticket: #6855
Signed-off-by: Spiros Economakis <spiros.oikonomakis@gmail.com>
2021-08-16 09:52:47 -07:00
pasha-codefresh
7b89c4e53c feat: Project scoped repo (#6943)
feat: Project scoped repo (#6943)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-16 09:38:37 -07:00
David Collom
1ab85de378 fix: Disable generating of CA Certificates (#6987)
Signed-off-by: David Collom <david.collom@jetstack.io>
2021-08-14 10:04:41 +02:00
Remington Breeze
eb76649ef5 chore(ui): Relocate CheckboxRow component to Filters instead of argo-ui (#6990)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-08-13 15:33:36 -07:00
Remington Breeze
3887289090 fix(ui): Migrate to keyhook helpers in argo-ui, update keybindings accordingly (#6953)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-08-13 14:26:11 -07:00
Yi Cai
d842e8333a feat: Allow collapsing of individual diff sections in diff view #3608 (#6978)
Signed-off-by: ciiay <yicai@redhat.com>
2021-08-13 08:31:37 -07:00
Alexander Matyushentsev
311926b8c9 fix: argocd core commands should not drop existing persistent flags (#6981)
* fix: argocd core commands should not drop existing persistent flags

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

* run cli codegen

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-12 23:10:59 -07:00
Yuan Tang
63d809614c docs: Fix links to subsections in roadmap (#6986)
* docs: Fix links to completed subsections in roadmap

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>

* One more link

Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-08-12 22:50:15 -07:00
Yuan Tang
741329afb6 docs: Add cluster URL when creating an app to be consistent with the screenshot (#6731)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2021-08-12 22:23:00 -07:00
Nico Schottelius
d36cf3e2bb Update USERS.md - added ungleich.ch (#6979)
Signed-off-by: Nico Schottelius <nico.schottelius@ungleich.ch>

Co-authored-by: Nico Schottelius <nico@nico-notebook.schottelius.org>
2021-08-12 22:17:54 -07:00
Alexander Matyushentsev
53bbb8ecf4 docs: update roadmap and release checklist (#6980)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-12 16:59:39 -07:00
dependabot[bot]
86ca66b2d6 chore(deps): bump jszip from 3.5.0 to 3.7.1 in /ui-test (#6952)
Bumps [jszip](https://github.com/Stuk/jszip) from 3.5.0 to 3.7.1.
- [Release notes](https://github.com/Stuk/jszip/releases)
- [Changelog](https://github.com/Stuk/jszip/blob/master/CHANGES.md)
- [Commits](https://github.com/Stuk/jszip/compare/v3.5.0...v3.7.1)

---
updated-dependencies:
- dependency-name: jszip
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-12 13:19:20 -07:00
pasha-codefresh
6ac9753b63 feat: support ability get cluster by name from cli, Closes #6865 (#6972)
feat: support ability get cluster by name from cli, Closes #6865 (#6972)

Support get cluster cmd by name
https://github.com/argoproj/argo-cd/issues/6865

Signed-off-by: olegz-codefresh <olegz@codefresh.io>
2021-08-12 13:18:18 -07:00
pasha-codefresh
afb1c8b210 feat(ui): add top value for large breakpoint Closes #6944 (#6975)
feat(ui): add `top` value for `large` breakpoint Closes #6944 (#6975)

Signed-off-by: andrii-codefresh <andrii@codefresh.io>
2021-08-12 12:35:20 -07:00
dependabot[bot]
117eadaceb chore(deps): bump path-parse from 1.0.6 to 1.0.7 in /ui-test (#6950)
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-12 12:33:41 -07:00
dependabot[bot]
10b4e44c42 chore(deps): bump path-parse from 1.0.6 to 1.0.7 in /ui (#6949)
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-12 12:33:18 -07:00
dependabot[bot]
8cf8a8cf81 chore(deps): bump url-parse from 1.5.1 to 1.5.3 in /ui (#6951)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-12 12:33:10 -07:00
pasha-codefresh
8a29cf8fbf fix(ui): Fix checkbox style in Delete pod modal Closes #6947 (#6961)
* Fix checkbox style in Delete pod modal

Signed-off-by: Victor Plakyda <plakyda1@gmail.com>

* Fix checkbox

Signed-off-by: Victor Plakyda <plakyda1@gmail.com>

Co-authored-by: Victor Plakyda <plakyda1@gmail.com>
2021-08-12 12:05:17 -07:00
ritchiekng
4a3dd76f19 Create USERS.md (#6973)
Fixing issue where link not working
2021-08-12 12:02:30 -07:00
Jesse Suen
b91732a8eb fix: rollout v1.0 'Paused' status.phase should map to Argo CD 'Suspended' (#6967)
Signed-off-by: Jesse Suen <jessesuen@gmail.com>
2021-08-12 11:37:08 -07:00
ritchiekng
97e8c7d00d Update USERS.md - added MeDirect (#6955)
* Update USERS.md

Signed-off-by: Steve Ritchie <steve.ritchie@medirect.com.mt>

* Update USERS.md

Updating website for Medirect
2021-08-11 16:28:51 -07:00
Alexander Matyushentsev
e5ee00f4d0 fix: basehref not set correctly (#6962)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-11 15:22:33 -07:00
Alexander Matyushentsev
aab0b173d5 fix: update deprecated helm2 installation URL (#6960)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-11 12:33:59 -07:00
Alexander Matyushentsev
50993206a5 fix: make sure repo server discard cached empty response (#6948)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-10 19:25:07 -07:00
Alexander Matyushentsev
4164db88f5 fix: applications/resources filter improvement and bug fixes (#6931)
* fix: applications/resources filter improvement and bug fixes

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-10 17:10:24 -07:00
May Zhang
c5eb25ceba fix: use secure way to generate initial password (#6938)
* fix: use secure way to generate initial password

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

* fix: use secure way to generate initial password

Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-08-09 19:22:10 -07:00
pasha-codefresh
685b07ed34 feat(ui): Retry strategy, Application + Applications, #5318 (#6864)
feat(ui): Retry strategy, Application + Applications, #5318 (#6864)

Signed-off-by: Victor Plakyda <plakyda1@gmail.com>
2021-08-09 17:26:31 -07:00
jannfis
3091bc5b6f docs: Update contributor docs (#6615)
* Sync

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

* docs: Update contributor docs

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

* New paragraph about code submission

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

* Update

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

* Update code submissions before triage paragraph

Signed-off-by: jannfis <jann@mistrust.net>
2021-08-09 12:15:21 +02:00
Saravanan Arumugam (Aswath)
810a977846 Added RightRev As the user's list. (#6929)
Added RightRev As the user's list.

Signed-off-by: Saravanan Arumugam (Aswath) <saravanan.a@rightrev.com>
2021-08-08 08:55:39 -07:00
jannfis
adade448a8 docs: Update security considerations (#6930)
* docs: Update security considerations

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

* docs: Update security considerations

Signed-off-by: jannfis <jann@mistrust.net>
2021-08-08 08:55:01 -07:00
jannfis
c22d8321cc docs: Update security contacts in security policy (#6928)
* docs: Update security contact

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

* docs: Update security contact

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

* docs: Update security contact

Signed-off-by: jannfis <jann@mistrust.net>
2021-08-07 17:58:21 -07:00
Daisuke Taniwaki
819225c709 fix: Set header to OIDC requests (#6869)
Signed-off-by: Daisuke Taniwaki <daisuketaniwaki@gmail.com>
2021-08-05 12:02:22 +02:00
Connor
dd50b88cd1 docs: Add documentation on using OIDC with Dex (#6904)
* docs: Add documentation on using OIDC with Dex

Signed-off-by: Connor Kelly <connor.r.kelly@gmail.com>

* docs: Add documentation on using OIDC with Dex -- fix typo

Signed-off-by: Connor Kelly <connor.r.kelly@gmail.com>

* Fix warning box for Dex OIDC group configuration knob

Signed-off-by: Connor Kelly <connor.r.kelly@gmail.com>
2021-08-05 11:57:18 +02:00
Alexander Matyushentsev
8b1c364f58 fix: application sync panel crashes if app has no sync options (#6914)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-04 16:56:08 -07:00
Yi Cai
d74ce38c8c fix: Reword Generate new token dialog (#6913)
Signed-off-by: ciiay <yicai@redhat.com>
2021-08-04 16:48:27 -07:00
Alexander Matyushentsev
826288f861 fix: assume ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS, ARGOCD_SERVER_REPO_SERVER_TIMEOUT_SECONDS env vars have seconds (#6912)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-04 13:51:16 -07:00
Yi Cai
e86c5ea17c fix: UI 6337 cluster filter improvement for issue #6337 (#6856)
* fix: when cluster field is bge-dev1, the applications with cluster dev1 is selected #6337

Signed-off-by: ciiay <yicai@redhat.com>
2021-08-04 13:05:49 -07:00
Noam Gal
f7614e0c4e fixed max to use MaxInt64 value (#6911)
Signed-off-by: Noam Gal <noam.gal@codefresh.io>
2021-08-04 11:07:54 -07:00
Chetan Banavikalmutt
2130c8a949 fix: unset command should remove env vars when there's no error (#6908)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2021-08-04 10:54:16 -07:00
pasha-codefresh
9d6ccee305 feat: rollback should work without id passed #6825. (#6877)
feat: rollback should work without id passed #6825. (#6877)

Signed-off-by: pashavictorovich <pavel@codefresh.io>
2021-08-04 10:51:54 -07:00
Remington Breeze
9c0495d9a3 fix: Add https prefix to ingress URLs if hosts field is present (#6901)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-08-04 09:33:41 -07:00
woshicai
ef653cac57 fix: client input arguments with equal sign (#6885)
Signed-off-by: Charles Cai <charles.cai@sap.com>

Co-authored-by: Charles Cai <charles.cai@sap.com>
2021-08-04 14:20:18 +02:00
Bob Claerhout
9099d0ba83 docs: Add replace description on individual resource level (#6905)
Signed-off-by: Bob Claerhout <claerhout.bob@gmail.com>
2021-08-04 14:14:21 +02:00
May Zhang
50b0010470 fix: logout redirect URL (#6903)
Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-08-03 17:05:58 -07:00
Alexander Matyushentsev
6b0d449997 refactor: update resources install order according to helm implementation (#6902)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-03 16:53:39 -07:00
Alexander Matyushentsev
c607a3b294 fix: controller should not create orphaned resources warning by default (#6898)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-03 16:05:19 -07:00
Alexander Matyushentsev
4fef2114fe feat: Improve Replace sync option description in UI (#6899)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-03 16:05:08 -07:00
dependabot[bot]
8c216ed7a8 chore(deps): bump tar from 6.1.0 to 6.1.3 in /ui (#6900)
Bumps [tar](https://github.com/npm/node-tar) from 6.1.0 to 6.1.3.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v6.1.0...v6.1.3)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-03 13:50:29 -07:00
Joseph Michael Casey
d404f0e425 docs(users): add Capital One (#6897) 2021-08-03 10:51:49 -07:00
Yi Cai
c5ebc584d0 fix: menu for application loses text when title area buttons collapse #6474 (#6887)
Signed-off-by: ciiay <yicai@redhat.com>
2021-08-03 10:06:12 -07:00
Remington Breeze
241a6fb1ba fix(ui): Bump argo-ui to hide filter suggestions on enter and show on typing (#6891)
* fix(ui): Bump argo-ui to hide filter suggestions on enter and show on typing

Signed-off-by: Remington Breeze <remington@breeze.software>

* remove unneccessary yarn.lock changes

Signed-off-by: Remington Breeze <remington@breeze.software>
2021-08-03 09:34:07 -07:00
Remington Breeze
93e624d590 fix(ui): Add View Details option to resource actions menu (#6893)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-08-03 09:33:25 -07:00
Jan-Otto Kröpke
8f4e002ae4 fix: upgrade to kustomize 4.2.0 (#6861)
Signed-off-by: Jan-Otto Kröpke <joe@adorsys.de>
2021-08-03 09:24:22 -07:00
May Zhang
3abf8c6735 fix: add documentation for using argocd repocreds with --enable-coi and --type helm (#6890)
Signed-off-by: May Zhang <may_zhang@intuit.com>
2021-08-03 10:48:20 +02:00
Jun
3ff8481694 feat: Rollback command support omit history id (#6863)
Signed-off-by: junnplus <junnplus@gmail.com>
2021-08-02 22:32:09 -07:00
Remington Breeze
0d23207c59 fix(ui): Incorrect path for non-namespaced resources (#6895)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-08-02 17:56:12 -07:00
balchua
fcd28b6eb1 docs: rename credit agricole to credit agricole CIB. (#6871)
* rename credit agricole to credit agricole CIB.

Signed-off-by: balchua <balchua@yahoo.com>

* fix semantic pr.

Signed-off-by: balchua <balchua@yahoo.com>
2021-08-02 12:29:54 -07:00
Remington Breeze
7e27d1072f fix(ui): Page navigation no longer visible with status bar (#6888)
Signed-off-by: Remington Breeze <remington@breeze.software>
2021-08-02 12:29:37 -07:00
Alexander Matyushentsev
1e5c763d6f fix: make sure orphaned filter checkbox is clickable (#6886)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-08-02 11:51:40 -07:00
woshicai
7fbf50493b fix: docs about custom image user #6851 (#6872)
* fix: docs about custom image user, change it from argocd to 999

Signed-off-by: Charles Cai <charles.cai@sap.com>

* update: docs for upgrading version

Signed-off-by: Charles Cai <charles.cai@sap.com>

Co-authored-by: Charles Cai <charles.cai@sap.com>
2021-08-02 11:43:01 -07:00
Geoffrey Huntley
f170d24ed1 docs(users): add gitpod (#6879)
Signed-off-by: Geoffrey Huntley <ghuntley@ghuntley.com>
2021-08-02 11:39:08 -07:00
Joe Bowbeer
bcfc112d82 docs: installation.md (#6860)
Signed-off-by: Joe Bowbeer <joe.bowbeer@gmail.com>
2021-07-30 15:57:17 -07:00
Yi Cai
66acd16bce fix: Project filter selector does not get unset upon clear filters #6750 (#6866)
Signed-off-by: ciiay <yicai@redhat.com>
2021-07-30 15:47:00 -07:00
Remington Breeze
bee20c2154 fix(ui): Prevent UI crash if app status or resources is empty (#6858) 2021-07-30 08:48:05 -07:00
Alexander Matyushentsev
17bef1c2c6 fix: util.cli.SetLogLevel should update global log level (#6852)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-07-29 13:01:38 -07:00
Alexander Matyushentsev
2abf284f81 fix: include cluster level RBAC into argocd-core manifests (#6854)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-07-29 12:49:06 -07:00
David Maciel
221d0c048d Fix #6567 Admin token now expires (#6846) 2021-07-29 11:19:53 -07:00
dependabot[bot]
cd9dcecccd chore(deps): bump glob-parent from 5.1.1 to 5.1.2 in /ui-test (#6848)
Bumps [glob-parent](https://github.com/gulpjs/glob-parent) from 5.1.1 to 5.1.2.
- [Release notes](https://github.com/gulpjs/glob-parent/releases)
- [Changelog](https://github.com/gulpjs/glob-parent/blob/main/CHANGELOG.md)
- [Commits](https://github.com/gulpjs/glob-parent/compare/v5.1.1...v5.1.2)

---
updated-dependencies:
- dependency-name: glob-parent
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-29 11:18:57 -07:00
dependabot[bot]
52090425c6 chore(deps): bump ws from 7.4.1 to 7.5.3 in /ui-test (#6849)
Bumps [ws](https://github.com/websockets/ws) from 7.4.1 to 7.5.3.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.4.1...7.5.3)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-29 11:18:19 -07:00
Klaus Dorninger
228c465393 fix: #6844 multiple global projects can be configured (#6845)
Signed-off-by: Klaus Dorninger <github@dornimaug.org>
2021-07-29 11:01:52 -07:00
Keith Chong
4a69cce7b1 test: Add initial automated UI smoke tests (#4393) (#4694)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2021-07-29 10:11:11 -07:00
Alexander Matyushentsev
c7738a0cae fix: core installation must include CRD definitions (#6841)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2021-07-28 16:30:11 -07:00
961 changed files with 85548 additions and 8676 deletions

View File

@@ -6,7 +6,7 @@ labels: 'bug'
assignees: ''
---
If you are trying to resolve an environment-specific issue or have a one-off question about the edge case that does not require a feature then please consider asking a question in argocd slack [channel](https://argoproj.github.io/community/join-slack).
<!-- If you are trying to resolve an environment-specific issue or have a one-off question about the edge case that does not require a feature then please consider asking a question in argocd slack [channel](https://argoproj.github.io/community/join-slack). -->
Checklist:
@@ -16,19 +16,19 @@ Checklist:
**Describe the bug**
A clear and concise description of what the bug is.
<!-- A clear and concise description of what the bug is. -->
**To Reproduce**
A list of the steps required to reproduce the issue. Best of all, give us the URL to a repository that exhibits this issue.
<!-- A list of the steps required to reproduce the issue. Best of all, give us the URL to a repository that exhibits this issue. -->
**Expected behavior**
A clear and concise description of what you expected to happen.
<!-- A clear and concise description of what you expected to happen. -->
**Screenshots**
If applicable, add screenshots to help explain your problem.
<!-- If applicable, add screenshots to help explain your problem. -->
**Version**

View File

@@ -12,19 +12,9 @@ on:
env:
# Golang version to use across CI steps
GOLANG_VERSION: '1.16.5'
GOLANG_VERSION: '1.17'
jobs:
build-docker:
name: Build Docker image
runs-on: ubuntu-latest
if: github.head_ref != ''
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build Docker image
run: |
make image
check-go:
name: Ensure Go modules synchronicity
runs-on: ubuntu-latest
@@ -264,6 +254,7 @@ jobs:
env:
NODE_ENV: production
NODE_ONLINE_ENV: online
HOST_ARCH: amd64
working-directory: ui/
- name: Run ESLint
run: yarn lint
@@ -340,7 +331,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
k3s-version: [v1.21.2, v1.20.2, v1.19.2, v1.18.9, v1.17.11]
k3s-version: [v1.23.3, v1.22.6, v1.21.2]
needs:
- build-go
env:
@@ -385,10 +376,13 @@ jobs:
- name: Add /usr/local/bin to PATH
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Add ./dist to PATH
run: |
echo "$(pwd)/dist" >> $GITHUB_PATH
- name: Download Go dependencies
run: |
go mod download
go get github.com/mattn/goreman
go install github.com/mattn/goreman@latest
- name: Install all tools required for building & testing
run: |
make install-test-tools-local
@@ -400,7 +394,7 @@ jobs:
run: |
docker pull quay.io/dexidp/dex:v2.25.0
docker pull argoproj/argo-cd-ci-builder:v1.0.0
docker pull redis:6.2.4-alpine
docker pull redis:6.2.6-alpine
- name: Create target directory for binaries in the build-process
run: |
mkdir -p dist

View File

@@ -8,6 +8,7 @@ on:
jobs:
CodeQL-Build:
if: github.repository == 'argoproj/argo-cd'
# CodeQL runs on ubuntu-latest and windows-latest
runs-on: ubuntu-latest

View File

@@ -1,23 +0,0 @@
name: Deploy
on:
push:
branches:
- master
pull_request:
branches:
- 'master'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: 3.x
- name: build
run: |
pip install -r docs/requirements.txt
mkdocs build

View File

@@ -4,12 +4,17 @@ on:
push:
branches:
- master
pull_request:
branches:
- master
types: [ labeled, unlabeled, opened, synchronize, reopened ]
env:
GOLANG_VERSION: '1.16.5'
GOLANG_VERSION: '1.17'
jobs:
publish:
if: github.repository == 'argoproj/argo-cd'
runs-on: ubuntu-latest
env:
GOPATH: /home/runner/work/argo-cd/argo-cd
@@ -26,34 +31,43 @@ jobs:
working-directory: ./src/github.com/argoproj/argo-cd
id: image
# build
- run: |
docker images -a --format "{{.ID}}" | xargs -I {} docker rmi {}
make image DEV_IMAGE=true DOCKER_PUSH=false IMAGE_NAMESPACE=ghcr.io/argoproj IMAGE_TAG=${{ steps.image.outputs.tag }}
working-directory: ./src/github.com/argoproj/argo-cd
# publish
# login
- run: |
docker login ghcr.io --username $USERNAME --password $PASSWORD
docker push ghcr.io/argoproj/argocd:${{ steps.image.outputs.tag }}
docker login --username "${DOCKER_USERNAME}" --password "${DOCKER_TOKEN}"
docker tag ghcr.io/argoproj/argocd:${{ steps.image.outputs.tag }} argoproj/argocd:latest
docker push argoproj/argocd:latest
docker login quay.io --username "${DOCKER_USERNAME}" --password "${DOCKER_TOKEN}"
if: github.event_name == 'push'
env:
USERNAME: ${{ secrets.USERNAME }}
PASSWORD: ${{ secrets.TOKEN }}
DOCKER_USERNAME: ${{ secrets.RELEASE_DOCKERHUB_USERNAME }}
DOCKER_TOKEN: ${{ secrets.RELEASE_DOCKERHUB_TOKEN }}
DOCKER_USERNAME: ${{ secrets.RELEASE_QUAY_USERNAME }}
DOCKER_TOKEN: ${{ secrets.RELEASE_QUAY_TOKEN }}
# build
- uses: docker/setup-qemu-action@v1
- uses: docker/setup-buildx-action@v1
- run: |
IMAGE_PLATFORMS=linux/amd64
if [[ "${{ github.event_name }}" == "push" || "${{ contains(github.event.pull_request.labels.*.name, 'test-arm-image') }}" == "true" ]]
then
IMAGE_PLATFORMS=linux/amd64,linux/arm64
fi
echo "Building image for platforms: $IMAGE_PLATFORMS"
docker buildx build --platform $IMAGE_PLATFORMS --push="${{ github.event_name == 'push' }}" \
-t ghcr.io/argoproj/argocd:${{ steps.image.outputs.tag }} \
-t quay.io/argoproj/argocd:latest .
working-directory: ./src/github.com/argoproj/argo-cd
# deploy
- run: git clone "https://$TOKEN@github.com/argoproj/argoproj-deployments"
if: github.event_name == 'push'
env:
TOKEN: ${{ secrets.TOKEN }}
- run: |
docker run -v $(pwd):/src -w /src --rm -t lyft/kustomizer:v3.3.0 kustomize edit set image quay.io/argoproj/argocd=ghcr.io/argoproj/argocd:${{ steps.image.outputs.tag }}
docker run -u $(id -u):$(id -g) -v $(pwd):/src -w /src --rm -t ghcr.io/argoproj/argocd:${{ steps.image.outputs.tag }} kustomize edit set image quay.io/argoproj/argocd=ghcr.io/argoproj/argocd:${{ steps.image.outputs.tag }}
git config --global user.email 'ci@argoproj.com'
git config --global user.name 'CI'
git diff --exit-code && echo 'Already deployed' || (git commit -am 'Upgrade argocd to ${{ steps.image.outputs.tag }}' && git push)
if: github.event_name == 'push'
working-directory: argoproj-deployments/argocd
# TODO: clean up old images once github supports it: https://github.community/t5/How-to-use-Git-and-GitHub/Deleting-images-from-GitHub-Package-Registry/m-p/41202/thread-id/9811

View File

@@ -12,11 +12,12 @@ on:
- '!release-v0*'
env:
GOLANG_VERSION: '1.16.5'
GOLANG_VERSION: '1.17'
jobs:
prepare-release:
name: Perform automatic release on trigger ${{ github.ref }}
if: github.repository == 'argoproj/argo-cd'
runs-on: ubuntu-latest
env:
# The name of the tag as supplied by the GitHub event
@@ -94,7 +95,7 @@ jobs:
echo "=========== BEGIN COMMIT MESSAGE ============="
git show ${SOURCE_TAG}
echo "============ END COMMIT MESSAGE =============="
# Quite dirty hack to get the release notes from the annotated tag
# into a temporary file.
RELEASE_NOTES=$(mktemp -p /tmp release-notes.XXXXXX)
@@ -141,7 +142,7 @@ jobs:
echo "RELEASE_NOTES=${RELEASE_NOTES}" >> $GITHUB_ENV
- name: Setup Golang
uses: actions/setup-go@v1
uses: actions/setup-go@v2
with:
go-version: ${{ env.GOLANG_VERSION }}
@@ -182,18 +183,7 @@ jobs:
echo "Creating release ${RELEASE_TAG}"
git tag ${RELEASE_TAG}
- name: Build Docker image for release
run: |
set -ue
git clean -fd
mkdir -p dist/
make image IMAGE_TAG="${TARGET_VERSION}" DOCKER_PUSH=false
make release-cli
chmod +x ./dist/argocd-linux-amd64
./dist/argocd-linux-amd64 version --client
if: ${{ env.DRY_RUN != 'true' }}
- name: Push docker image to repository
- name: Login to docker repositories
env:
DOCKER_USERNAME: ${{ secrets.RELEASE_DOCKERHUB_USERNAME }}
DOCKER_TOKEN: ${{ secrets.RELEASE_DOCKERHUB_TOKEN }}
@@ -202,11 +192,22 @@ jobs:
run: |
set -ue
docker login quay.io --username "${QUAY_USERNAME}" --password "${QUAY_TOKEN}"
docker push ${IMAGE_NAMESPACE}/argocd:v${TARGET_VERSION}
# Remove the following when Docker Hub is gone
docker login --username "${DOCKER_USERNAME}" --password "${DOCKER_TOKEN}"
docker tag ${IMAGE_NAMESPACE}/argocd:v${TARGET_VERSION} argoproj/argocd:v${TARGET_VERSION}
docker push argoproj/argocd:v${TARGET_VERSION}
if: ${{ env.DRY_RUN != 'true' }}
- uses: docker/setup-qemu-action@v1
- uses: docker/setup-buildx-action@v1
- name: Build and push Docker image for release
run: |
set -ue
git clean -fd
mkdir -p dist/
docker buildx build --platform linux/amd64,linux/arm64 --push -t ${IMAGE_NAMESPACE}/argocd:v${TARGET_VERSION} -t argoproj/argocd:v${TARGET_VERSION} .
make release-cli
chmod +x ./dist/argocd-linux-amd64
./dist/argocd-linux-amd64 version --client
if: ${{ env.DRY_RUN != 'true' }}
- name: Read release notes file
@@ -244,6 +245,17 @@ jobs:
asset_content_type: application/octet-stream
if: ${{ env.DRY_RUN != 'true' }}
- name: Upload argocd-linux-arm64 binary to release assets
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./dist/argocd-linux-arm64
asset_name: argocd-linux-arm64
asset_content_type: application/octet-stream
if: ${{ env.DRY_RUN != 'true' }}
- name: Upload argocd-darwin-amd64 binary to release assets
uses: actions/upload-release-asset@v1
env:
@@ -255,6 +267,17 @@ jobs:
asset_content_type: application/octet-stream
if: ${{ env.DRY_RUN != 'true' }}
- name: Upload argocd-darwin-arm64 binary to release assets
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./dist/argocd-darwin-arm64
asset_name: argocd-darwin-arm64
asset_content_type: application/octet-stream
if: ${{ env.DRY_RUN != 'true' }}
- name: Upload argocd-windows-amd64 binary to release assets
uses: actions/upload-release-asset@v1
env:
@@ -266,6 +289,48 @@ jobs:
asset_content_type: application/octet-stream
if: ${{ env.DRY_RUN != 'true' }}
- name: Generate SBOM (spdx)
id: spdx-builder
env:
# defines the spdx/spdx-sbom-generator version to use.
SPDX_GEN_VERSION: v0.0.13
# defines the sigs.k8s.io/bom version to use.
SIGS_BOM_VERSION: v0.2.1
# comma delimited list of project relative folders to inspect for package
# managers (gomod, yarn, npm).
PROJECT_FOLDERS: ".,./ui"
# full qualified name of the docker image to be inspected
DOCKER_IMAGE: ${{env.IMAGE_NAMESPACE}}/argocd:v${{env.TARGET_VERSION}}
run: |
yarn install --cwd ./ui
go install github.com/spdx/spdx-sbom-generator/cmd/generator@$SPDX_GEN_VERSION
go install sigs.k8s.io/bom/cmd/bom@$SIGS_BOM_VERSION
# Generate SPDX for project dependencies analyzing package managers
for folder in $(echo $PROJECT_FOLDERS | sed "s/,/ /g")
do
generator -p $folder -o /tmp
done
# Generate SPDX for binaries analyzing the docker image
if [[ ! -z $DOCKER_IMAGE ]]; then
bom generate -o /tmp/bom-docker-image.spdx -i $DOCKER_IMAGE
fi
cd /tmp && tar -zcf sbom.tar.gz *.spdx
if: ${{ env.DRY_RUN != 'true' }}
- name: Upload SBOM to release assets
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: /tmp/sbom.tar.gz
asset_name: sbom.tar.gz
asset_content_type: application/octet-stream
if: ${{ env.DRY_RUN != 'true' }}
- name: Update homebrew formula
env:
HOMEBREW_TOKEN: ${{ secrets.RELEASE_HOMEBREW_TOKEN }}
@@ -280,3 +345,4 @@ jobs:
set -ue
git push --delete origin ${SOURCE_TAG}
if: ${{ always() }}

2
.gitpod.Dockerfile vendored
View File

@@ -9,7 +9,7 @@ RUN curl -L https://go.kubebuilder.io/dl/2.3.1/$(go env GOOS)/$(go env GOARCH) |
tar -xz -C /tmp/ && mv /tmp/kubebuilder_2.3.1_$(go env GOOS)_$(go env GOARCH) /usr/local/kubebuilder
RUN apt-get install redis-server -y
RUN go get github.com/mattn/goreman
RUN go install github.com/mattn/goreman@latest
USER gitpod

View File

@@ -2,5 +2,5 @@ image:
file: .gitpod.Dockerfile
tasks:
- init: make mod-download-local dep-ui-local && GO111MODULE=off go get github.com/mattn/goreman
- init: make mod-download-local dep-ui-local && GO111MODULE=off go install github.com/mattn/goreman@latest
command: make start-test-k8s

View File

@@ -1,6 +1,234 @@
# Changelog
## v2.1.0 (Unreleased)
## v2.3.0 (Unreleased)
### Argo CD ApplicationSet and Notifications are now part of Argo CD
Two popular [Argoproj Labs](https://github.com/argoproj-labs) projects [Argo CD ApplicationSet](https://github.com/argoproj/applicationset) and
[Argo CD Notifications](https://github.com/argoproj-labs/argocd-notifications) are now part of Argo CD! The default Argo CD installation manifests now
bundle both projects out of the box. Going forward you can expect more tightened integration of these projects into Argo CD.
### New sync and diff strategies
Users can now configure the Application resource to instruct Argo CD to consider the ignore difference setup during the sync process.
In order to do so, add the new sync option RespectIgnoreDifferences=true in the Application resource. Once the sync option is added,
Argo CD won't change ignored fields during the syncing process.
Configuring ignored fields is also easier now. Instead of listing fields one by one users can now leverage the
managedFields metadata to instruct Argo CD about trusted managers and automatically ignore any fields owned by them. A new diff customization
(managedFieldsManagers) is now available allowing users to specify managers the application should trust and to ignore all fields owned by those managers.
Read more about these changes at [New sync and diff strategies in ArgoCD](https://blog.argoproj.io/new-sync-and-diff-strategies-in-argocd-44195d3f8b8c) blog post.
### ARM Images
An officially supported ARM 64 image is now available. Enjoy running Argo CD on your Raspberry Pi! Additionally, the image size was reduced by nearly ~50%
and is only 200MB now. The ARM version of `argocd` CLI is also available and published as a Github release artifact.
### Compact Tree View And Click Application Navigation
The application details page now supports compact application resources tree visualization. Using the "Group Nodes" button, you can collapse the similar resources
into a single group node to remove the clutter and make it easier to understand the state of application resources. You still can get detailed information about the collapsed resources by clicking on the group node. The list of collapsed resources will be available in a sliding panel. Compact resource tree is still too big?
You can use the zoom in and zoom out feature to make it smaller - or even larger!
You no longer need to move back and forth between the application details page and the application list page. Instead you can navigate directly to the required application by clicking the search icon in the application details page title.
### Upgraded Config Management Tools
Both bundled Helm and Kustomize binaries have been upgraded to the latest versions. Kustomize has been upgraded from 4.2.0 to 4.4.1 and Helm has been upgraded from 3.7.1 to 3.8.0.
### Bug Fixes and Performance Enhancements
* Config management tools enhancements:
* The skipCrds flag and ability to ignore missing values files for Helm (#8012, #8003)
* Additional environment variables for Kustomize (#8096)
* Argo CD CLI follows the XDG Base directory standard (#7638)
* Redis is no longer used during SSO login (#8241)
### Features
- feat: Add app list and details page views to navigation history (#7776) (#7937)
- feat: Add skipCrds flag for helm charts (#8012)
- feat: Add visual indicator for newly created pods (#8006)
- feat: Added a new Helm option ignoreMissingValueFiles (#7767) (#8003)
- feat: Allow configuring system wide ignore differences for all resources (#8224)
- feat: Allow escaping dollar in Envsubst (#7961)
- feat: Allow external links on Application (#3487) (#8231)
- feat: Allow selecting application on detail page (#8176)
- feat: Bundle applicationset-controller with argocd (#8148)
- feat: Enable specifying root ca for oidc (#6712)
- feat: Expose ARGOCD_APP_NAME to the `kustomize build` command (#8096)
- feat: Ignore differences owned by trusted managers from managedFields (#7869)
- feat: New sync option to use ignore diff configs during sync (#8078)
- feat: Provide address flag for admin dashboard command (#8095)
- feat: Store "Group Nodes" button state in application details preferences (#8036)
- feat: Support specifying cluster by name in addition to API server URL in Cluster API (#8077)
- feat: Support XDG Base directory standard (#7638) (#7791)
- feat: Use encrypted cookie to store OAuth2 state nonce (instead of redis) (#8241)
- feat: Build images on PR and conditionally build arm64 image on push (#8108)
### Bug Fixes
- fix: Add "Restarting MinIO" status to MiniO Tenant health check (#8191)
- fix: Add all resources in list view (#7295)
- fix: Adding pagination to grouped nodes sliding panel#7837 (#7915)
- fix: Allow all resources to add external links (#7923)
- fix: Always call ValidateDestination (#7976)
- fix: Application exist panic when execute api call (#8188)
- fix: Application-icons-alignment (#8054)
- fix: Controller panics if resource manifest has incorrect annotation (#8022)
- fix: Correctly handle project field during partial cluster update (#7994)
- fix: Default value for retry validation #8055 (#8064)
- fix: Fix a possible crash when parsing RBAC (#8165)
- fix: Grouped node list missing resources on Compact resources view #8014 (#8018)
- fix: Issue with headless installation (#7958)
- fix: Issue with project scoped resources (#8048)
- fix: Kubernetes labels normalization for Prometheus (#7925)
- fix: Nested Refresh dropdown does not work on Application Details page #1524 (#7950)
- fix: Network line colors and menu icon alignment (#8059)
- fix: Opening app details shows UI error on some apps (#8016) (#8019)
- fix: Parse to correct uint32 type (#8177)
- fix: Prevent possible nil-pointer deref in normalizer (#8185)
- fix: Prevent possible out-of-bounds access when loading policies (#8186)
- fix: Provide a semantic version parsed version for KUBE_VERSION (#8250)
- fix: Refreshing label toast (#7979)
- fix: Resource details page crashes when resource is not deployed and hide managed fields is selected (#7971)
- fix: Retry disabled text (#8004)
- fix: Route health check stuck in 'Progressing' (#8170)
- fix: Sync window panel is crashed if resource name not contain letters (#8053)
- fix: Targetervision compatible without prefix refs/heads or refs/tags (#7939)
- fix: Trailing line in Filter Dropdown Menus #7821 (#8001)
- fix: Webhook URL matching edge cases (#7981)
- fix(ui): Use consistent case for diff modes (#7945)
- fix: Use gRPC timeout for sidecar CMPs (#8131) (#8236)
### Other
- chore: Bump go-jsonnet to v0.18.0 (#8011)
- chore: Escape proj in regex (#7985)
- chore: Exclude argocd-server rbac for core-install (#8234)
- chore: Log out the resource triggering reconciliation (#8192)
- chore: Migrate to use golang-jwt/jwt v4.2.0 (#8136)
- chore: Move resolveRevision from api-server to repo-server (#7966)
- chore: Update notifications version (#8267)
- chore: Update slack version (#8299)
- chore: Update to Redis 6.2.4 (#8157)
- chore: Upgrade awscli to 2.4.6 and remove python deps (#7947)
- chore: Upgrade base image to ubuntu:21.10 (#8230)
- chore: Upgrade dex to v2.30.2 (https://github.com/dexidp/dex/issues/2326) (#8237)
- chore: Upgrade gitops engine (#8288)
- chore: Upgrade golang to 1.17.6 (#8229)
- chore: Upgrade helm to most recent version (v3.7.2) (#8226)
- chore: Upgrade k8s client to v1.23 (#8213)
- chore: Upgrade kustomize to most recent version (v4.4.1) (#8227)
- refactor: Introduce 'byClusterName' secret index to speedup cluster server URL lookup (#8133)
- refactor: Move project filtering to server side (#8102)
## v2.2.3 (2022-01-18)
- fix: Application exist panic when execute api call (#8188)
- fix: Route health check stuck in 'Progressing' (#8170)
- refactor: Introduce 'byClusterName' secret index to speedup cluster server URL lookup (#8133)
- chore: Update to Redis 6.2.4 (#8157) (#8158)
## v2.2.2 (2021-12-31)
- fix: Issue with project scoped resources (#8048)
- fix: Escape proj in regex (#7985)
- fix: Default value for retry validation #8055 (#8064)
- fix: Sync window panel is crashed if resource name not contain letters (#8053)
- fix: Upgrade github.com/argoproj/gitops-engine to v0.5.2
- fix: Retry disabled text (#8004)
- fix: Opening app details shows UI error on some apps (#8016) (#8019)
- fix: Correctly handle project field during partial cluster update (#7994)
- fix: Cluster API does not support updating labels and annotations (#7901)
## v2.2.1 (2021-12-16)
- fix: Resource details page crashes when resource is not deployed and hide managed fields is selected (#7971)
- fix: Issue with headless installation (#7958)
- fix: Nil pointer (#7905)
## v2.2.0 (2021-12-14)
> [Upgrade instructions](./docs/operator-manual/upgrading/2.1-2.2.md)
### Project Scoped repositories and clusters
The project scoped repositories and clusters is a feature that simplifies registering the repositories and cluster credentials.
Instead of requiring operators to set up in advance all clusters and git repositories that can be used, developers can now do
this on their own in a self-service manner.
### Config Management Plugins V2
The Config Management Plugins V2 is set of enhancement of the existing config management plugins feature.
The list includes improved installation experience, ability to package plugin into a separate image and
improved plugin manifests discovery.
### Resource tracking
Argo CD has traditionally tracked the resources it manages by the well-known "app.kubernetes.io/instance" property.
While using this property works ok in simple scenarios, it also has several limitations. ArgoCD now allows you to use
a new annotation (argocd.argoproj.io/tracking-id) for tracking your resources. Using this annotation is a much more flexible approach
as there are no conflicts with other Kubernetes tools, and you can easily install multiple Argo CD instances on the same clusters.
### Bug Fixes and Performance Enhancements
* Argo CD API server caches RBAC checks that significantly improves the GET /api/v1/applications API performance (#7587)
* Argo CD RBAC supports regex matches (#7165)
* Health check support for KubeVirt (#7176), Cassandra (#7017), Openshift Route (#7112), DeploymentConfig (#7114), Confluent (#6957) and SparkApplication (#7434) CRDs.
* Persistent banner (#7312) with custom positioning (#7462)
* Cluster name support in project destinations (#7198)
* around 30 more features and a total of 84 bug fixes
## v2.1.7 (2021-12-14)
- fix: issue with keepalive (#7861)
- fix nil pointer dereference error (#7905)
- fix: env vars to tune cluster cache were broken (#7779)
- fix: upgraded gitops engine to v0.4.2 (fixes #7561)
## v2.1.6 (2021-11-16)
- fix: don't use revision caching during app creation (#7508)
- fix: supporting OCI dependencies. Fixes #6062 (#6994)
## v2.1.5 (2021-11-16)
- fix: Invalid memory address or nil pointer dereference in processRequestedAppOperation (#7501)
## v2.1.4 (2021-11-15)
- fix: Operation has completed with phase: Running (#7482)
- fix: Application status panel shows Syncing instead of Deleting (#7486)
- fix(ui): Add Error Boundary around Extensions and comply with new Extensions API (#7215)
## v2.1.3 (2021-10-29)
- fix: core-install.yaml always refers to latest argocd image (#7321)
- fix: handle applicationset backup forbidden error (#7306)
- fix: Argo CD should not use cached git/helm revision during app creation/update validation (#7244)
## v2.1.2 (2021-10-02)
- fix: cluster filter popping out of box (#7135)
- fix: gracefully shutdown metrics server when dex config changes (#7138)
- fix: upgrade gitops engine version to v0.4.1 (#7088)
- fix: repository name already exists when multiple helm dependencies (#7096)
## v2.1.1 (2021-08-25)
### Bug Fixes
- fix: password reset requirements (#7071)
- fix: Custom Styles feature is broken (#7067)
- fix(ui): Add State to props passed to Extensions (#7045)
- fix: keep uid_entrypoint.sh for backward compatibility (#7047)
## v2.1.0 (2021-08-20)
> [Upgrade instructions](./docs/operator-manual/upgrading/2.0-2.1.md)
@@ -744,7 +972,7 @@ More documentation and tools are coming in patch releases.
The Argo CD deletes all **in-flight** hooks if you terminate running sync operation. The hook state assessment change implemented in this release the Argo CD enables detection of
an in-flight state for all Kubernetes resources including `Deployment`, `PVC`, `StatefulSet`, `ReplicaSet` etc. So if you terminate the sync operation that has, for example,
`StatefulSet` hook that is `Progressing` it will be deleted. The long-running jobs are not supposed to be used as a sync hook and you should consider using
[Sync Waves](https://argoproj.github.io/argo-cd/user-guide/sync-waves/) instead.
[Sync Waves](https://argo-cd.readthedocs.io/en/stable/user-guide/sync-waves/) instead.
#### Enhancements
* feat: Add custom health checks for cert-manager v0.11.0 (#2689)

View File

@@ -1,10 +1,10 @@
ARG BASE_IMAGE=docker.io/library/ubuntu:21.04
ARG BASE_IMAGE=docker.io/library/ubuntu:21.10
####################################################################################################
# Builder image
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
# Also used as the image in CI jobs so needs all dependencies
####################################################################################################
FROM docker.io/library/golang:1.16.5 as builder
FROM docker.io/library/golang:1.17 as builder
RUN echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
@@ -32,6 +32,7 @@ RUN ./install.sh ksonnet-linux
RUN ./install.sh helm2-linux
RUN ./install.sh helm-linux
RUN ./install.sh kustomize-linux
RUN ./install.sh awscli-linux
####################################################################################################
# Argo CD Base - used as the base for both the release and dev argocd images
@@ -47,24 +48,23 @@ RUN groupadd -g 999 argocd && \
mkdir -p /home/argocd && \
chown argocd:0 /home/argocd && \
chmod g=u /home/argocd && \
chmod g=u /etc/passwd && \
apt-get update && \
apt-get dist-upgrade -y && \
apt-get install -y git git-lfs python3-pip tini gpg tzdata && \
apt-get install -y git git-lfs tini gpg tzdata && \
apt-get clean && \
pip3 install awscli==1.18.80 && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY hack/git-ask-pass.sh /usr/local/bin/git-ask-pass.sh
COPY hack/gpg-wrapper.sh /usr/local/bin/gpg-wrapper.sh
COPY hack/git-verify-wrapper.sh /usr/local/bin/git-verify-wrapper.sh
COPY --from=builder /usr/local/bin/ks /usr/local/bin/ks
COPY --from=builder /usr/local/bin/helm2 /usr/local/bin/helm2
COPY --from=builder /usr/local/bin/helm /usr/local/bin/helm
COPY --from=builder /usr/local/bin/kustomize /usr/local/bin/kustomize
# script to add current (possibly arbitrary) user to /etc/passwd at runtime
# (if it's not already there, to be openshift friendly)
COPY uid_entrypoint.sh /usr/local/bin/uid_entrypoint.sh
COPY --from=builder /usr/local/aws-cli/v2/current/dist /usr/local/aws-cli/v2/current/dist
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
# keep uid_entrypoint.sh for backward compatibility
RUN ln -s /usr/local/bin/entrypoint.sh /usr/local/bin/uid_entrypoint.sh
RUN ln -s /usr/local/aws-cli/v2/current/dist/aws /usr/local/bin/aws
# support for mounting configuration from a configmap
RUN mkdir -p /app/config/ssh && \
@@ -91,18 +91,18 @@ FROM docker.io/library/node:12.18.4 as argocd-ui
WORKDIR /src
ADD ["ui/package.json", "ui/yarn.lock", "./"]
RUN yarn install
RUN yarn install --network-timeout 200000
ADD ["ui/", "."]
ARG ARGO_VERSION=latest
ENV ARGO_VERSION=$ARGO_VERSION
RUN NODE_ENV='production' NODE_ONLINE_ENV='online' yarn build
RUN HOST_ARCH='amd64' NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OPTIONS=--max_old_space_size=8192 yarn build
####################################################################################################
# Argo CD Build stage which performs the actual build of Argo CD binaries
####################################################################################################
FROM golang:1.16.5 as argocd-build
FROM docker.io/library/golang:1.17 as argocd-build
WORKDIR /go/src/github.com/argoproj/argo-cd
@@ -116,12 +116,6 @@ COPY . .
COPY --from=argocd-ui /src/dist/app /go/src/github.com/argoproj/argo-cd/ui/dist/app
RUN make argocd-all
ARG BUILD_ALL_CLIS=true
RUN if [ "$BUILD_ALL_CLIS" = "true" ] ; then \
make BIN_NAME=argocd-darwin-amd64 GOOS=darwin argocd-all && \
make BIN_NAME=argocd-windows-amd64.exe GOOS=windows argocd-all \
; fi
####################################################################################################
# Final image
####################################################################################################
@@ -131,7 +125,9 @@ COPY --from=argocd-build /go/src/github.com/argoproj/argo-cd/dist/argocd* /usr/l
USER root
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-repo-server
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-cmp-server
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-application-controller
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-dex
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-notifications
USER 999

View File

@@ -3,12 +3,11 @@
####################################################################################################
FROM argocd-base
COPY argocd /usr/local/bin/
COPY argocd-darwin-amd64 /usr/local/bin/
COPY argocd-windows-amd64.exe /usr/local/bin/
USER root
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-repo-server
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-application-controller
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-dex
RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-notifications
USER 999

View File

@@ -4,6 +4,8 @@ DIST_DIR=${CURRENT_DIR}/dist
CLI_NAME=argocd
BIN_NAME=argocd
GEN_RESOURCES_CLI_NAME=argocd-resources-gen
HOST_OS:=$(shell go env GOOS)
HOST_ARCH:=$(shell go env GOARCH)
@@ -13,7 +15,7 @@ GIT_COMMIT=$(shell git rev-parse HEAD)
GIT_TAG=$(shell if [ -z "`git status --porcelain`" ]; then git describe --exact-match --tags HEAD 2>/dev/null; fi)
GIT_TREE_STATE=$(shell if [ -z "`git status --porcelain`" ]; then echo "clean" ; else echo "dirty"; fi)
VOLUME_MOUNT=$(shell if test "$(go env GOOS)" = "darwin"; then echo ":delegated"; elif test selinuxenabled; then echo ":delegated"; else echo ""; fi)
KUBECTL_VERSION=$(shell go list -m all | grep k8s.io/client-go | cut -d ' ' -f5)
KUBECTL_VERSION=$(shell go list -m k8s.io/client-go | head -n 1 | rev | cut -d' ' -f1 | rev)
GOPATH?=$(shell if test -x `which go`; then go env GOPATH; else echo "$(HOME)/go"; fi)
GOCACHE?=$(HOME)/.cache/go-build
@@ -45,7 +47,7 @@ ARGOCD_E2E_DEX_PORT?=5556
ARGOCD_E2E_YARN_HOST?=localhost
ARGOCD_E2E_DISABLE_AUTH?=
ARGOCD_E2E_TEST_TIMEOUT?=20m
ARGOCD_E2E_TEST_TIMEOUT?=30m
ARGOCD_IN_CI?=false
ARGOCD_TEST_E2E?=true
@@ -177,7 +179,7 @@ gogen: ensure-gopath
go generate ./util/argo/...
.PHONY: protogen
protogen: ensure-gopath
protogen: ensure-gopath mod-vendor-local
export GO111MODULE=off
./hack/generate-proto.sh
@@ -186,6 +188,16 @@ openapigen: ensure-gopath
export GO111MODULE=off
./hack/update-openapi.sh
.PHONY: notification-catalog
notification-catalog:
go run ./hack/gen-catalog catalog
.PHONY: notification-docs
notification-docs:
go run ./hack/gen-docs
go run ./hack/gen-catalog docs
.PHONY: clientgen
clientgen: ensure-gopath
export GO111MODULE=off
@@ -195,8 +207,9 @@ clientgen: ensure-gopath
clidocsgen: ensure-gopath
go run tools/cmd-docs/main.go
.PHONY: codegen-local
codegen-local: ensure-gopath mod-vendor-local gogen protogen clientgen openapigen clidocsgen manifests-local
codegen-local: ensure-gopath mod-vendor-local notification-docs notification-catalog gogen protogen clientgen openapigen clidocsgen manifests-local
rm -rf vendor/
.PHONY: codegen
@@ -211,13 +224,17 @@ cli: test-tools-image
cli-local: clean-debug
CGO_ENABLED=0 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${CLI_NAME} ./cmd
.PHONY: gen-resources-cli-local
gen-resources-cli-local: clean-debug
CGO_ENABLED=0 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${GEN_RESOURCES_CLI_NAME} ./hack/gen-resources/cmd
.PHONY: release-cli
release-cli: clean-debug image
docker create --name tmp-argocd-linux $(IMAGE_PREFIX)argocd:$(IMAGE_TAG)
docker cp tmp-argocd-linux:/usr/local/bin/argocd ${DIST_DIR}/argocd-linux-amd64
docker cp tmp-argocd-linux:/usr/local/bin/argocd-darwin-amd64 ${DIST_DIR}/argocd-darwin-amd64
docker cp tmp-argocd-linux:/usr/local/bin/argocd-windows-amd64.exe ${DIST_DIR}/argocd-windows-amd64.exe
docker rm tmp-argocd-linux
release-cli: clean-debug build-ui
make BIN_NAME=argocd-darwin-amd64 GOOS=darwin argocd-all
make BIN_NAME=argocd-darwin-arm64 GOOS=darwin GOARCH=arm64 argocd-all
make BIN_NAME=argocd-linux-amd64 GOOS=linux argocd-all
make BIN_NAME=argocd-linux-arm64 GOOS=linux GOARCH=arm64 argocd-all
make BIN_NAME=argocd-windows-amd64.exe GOOS=windows argocd-all
.PHONY: test-tools-image
test-tools-image:
@@ -235,7 +252,7 @@ manifests: test-tools-image
# consolidated binary for cli, util, server, repo-server, controller
.PHONY: argocd-all
argocd-all: clean-debug
CGO_ENABLED=0 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${BIN_NAME} ./cmd
CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${BIN_NAME} ./cmd
.PHONY: server
server: clean-debug
@@ -249,23 +266,25 @@ repo-server:
controller:
CGO_ENABLED=0 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd-application-controller ./cmd
.PHONY: build-ui
build-ui:
docker build -t argocd-ui --target argocd-ui .
find ./ui/dist -type f -not -name gitkeep -delete
docker run -v ${CURRENT_DIR}/ui/dist/app:/tmp/app --rm -t argocd-ui sh -c 'cp -r ./dist/app/* /tmp/app/'
.PHONY: image
ifeq ($(DEV_IMAGE), true)
# The "dev" image builds the binaries from the users desktop environment (instead of in Docker)
# which speeds up builds. Dockerfile.dev needs to be copied into dist to perform the build, since
# the dist directory is under .dockerignore.
IMAGE_TAG="dev-$(shell git describe --always --dirty)"
image:
image: build-ui
docker build -t argocd-base --target argocd-base .
docker build -t argocd-ui --target argocd-ui .
find ./ui/dist -type f -not -name gitkeep -delete
docker run -v ${CURRENT_DIR}/ui/dist/app:/tmp/app --rm -t argocd-ui sh -c 'cp -r ./dist/app/* /tmp/app/'
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd ./cmd
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd-darwin-amd64 ./cmd
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd-windows-amd64.exe ./cmd
ln -sfn ${DIST_DIR}/argocd ${DIST_DIR}/argocd-server
ln -sfn ${DIST_DIR}/argocd ${DIST_DIR}/argocd-application-controller
ln -sfn ${DIST_DIR}/argocd ${DIST_DIR}/argocd-repo-server
ln -sfn ${DIST_DIR}/argocd ${DIST_DIR}/argocd-cmp-server
ln -sfn ${DIST_DIR}/argocd ${DIST_DIR}/argocd-dex
cp Dockerfile.dev dist
docker build -t $(IMAGE_PREFIX)argocd:$(IMAGE_TAG) -f dist/Dockerfile.dev dist
@@ -276,10 +295,8 @@ endif
@if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)argocd:$(IMAGE_TAG) ; fi
.PHONY: armimage
# The "BUILD_ALL_CLIS" argument is to skip building the CLIs for darwin and windows
# which would take a really long time.
armimage:
docker build -t $(IMAGE_PREFIX)argocd:$(IMAGE_TAG)-arm . --build-arg BUILD_ALL_CLIS="false"
docker build -t $(IMAGE_PREFIX)argocd:$(IMAGE_TAG)-arm .
.PHONY: builder-image
builder-image:
@@ -409,12 +426,14 @@ start-e2e-local:
if test -d /tmp/argo-e2e/app/config/gpg; then rm -rf /tmp/argo-e2e/app/config/gpg/*; fi
mkdir -p /tmp/argo-e2e/app/config/gpg/keys && chmod 0700 /tmp/argo-e2e/app/config/gpg/keys
mkdir -p /tmp/argo-e2e/app/config/gpg/source && chmod 0700 /tmp/argo-e2e/app/config/gpg/source
mkdir -p /tmp/argo-e2e/app/config/plugin && chmod 0700 /tmp/argo-e2e/app/config/plugin
# set paths for locally managed ssh known hosts and tls certs data
ARGOCD_SSH_DATA_PATH=/tmp/argo-e2e/app/config/ssh \
ARGOCD_TLS_DATA_PATH=/tmp/argo-e2e/app/config/tls \
ARGOCD_GPG_DATA_PATH=/tmp/argo-e2e/app/config/gpg/source \
ARGOCD_GNUPGHOME=/tmp/argo-e2e/app/config/gpg/keys \
ARGOCD_GPG_ENABLED=$(ARGOCD_GPG_ENABLED) \
ARGOCD_PLUGINCONFIGFILEPATH=/tmp/argo-e2e/app/config/plugin \
ARGOCD_E2E_DISABLE_AUTH=false \
ARGOCD_ZJWT_FEATURE_FLAG=always \
ARGOCD_IN_CI=$(ARGOCD_IN_CI) \
@@ -451,6 +470,12 @@ start-local: mod-vendor-local dep-ui-local
ARGOCD_E2E_TEST=false \
goreman -f $(ARGOCD_PROCFILE) start ${ARGOCD_START}
# Run goreman start with exclude option , provide exclude env variable with list of services
.PHONY: run
run:
bash ./hack/goreman-start.sh
# Runs pre-commit validation with the virtualized toolchain
.PHONY: pre-commit
pre-commit: codegen build lint test
@@ -484,10 +509,6 @@ serve-docs-local:
serve-docs:
docker run ${MKDOCS_RUN_ARGS} --rm -it -p 8000:8000 -v ${CURRENT_DIR}:/docs ${MKDOCS_DOCKER_IMAGE} serve -a 0.0.0.0:8000
.PHONY: lint-docs
lint-docs:
# https://github.com/dkhamsing/awesome_bot
find docs -name '*.md' -exec grep -l http {} + | xargs docker run --rm -v $(PWD):/mnt:ro dkhamsing/awesome_bot -t 3 --allow-dupe --allow-redirect --white-list `cat white-list | grep -v "#" | tr "\n" ','` --skip-save-results --
# Verify that kubectl can connect to your K8s cluster from Docker
.PHONY: verify-kube-connect
@@ -533,3 +554,7 @@ dep-ui-local:
start-test-k8s:
go run ./hack/k8s
.PHONY: list
list:
@LC_ALL=C $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'

7
OWNERS
View File

@@ -9,6 +9,7 @@ approvers:
- jessesuen
- jgwest
- mayzhang2000
- rbreeze
reviewers:
- dthomson25
@@ -18,3 +19,9 @@ reviewers:
- reginapizza
- hblixt
- chetan-rns
- wanghong230
- pasha-codefresh
- ciiay
- leoluz
- crenshaw-dev
- saumeya

View File

@@ -1,8 +1,8 @@
controller: 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 go run ./cmd/main.go --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081}"
api-server: 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-server go run ./cmd/main.go --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} "
dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v2/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.27.0 serve /dex.yaml"
redis: bash -c "if [ $ARGOCD_REDIS_LOCAL == 'true' ]; then redis-server --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; else docker run --rm --name argocd-redis -i -p ${ARGOCD_E2E_REDIS_PORT:-6379}:${ARGOCD_E2E_REDIS_PORT:-6379} redis:6.2.4-alpine --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; fi"
repo-server: sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_GNUPGHOME=${ARGOCD_GNUPGHOME:-/tmp/argocd-local/gpg/keys} ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-repo-server go run ./cmd/main.go --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379}"
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}"
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_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-server $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} "
dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v2/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.30.2 dex serve /dex.yaml"
redis: bash -c "if [ \"$ARGOCD_REDIS_LOCAL\" == 'true' ]; then redis-server --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; else docker run --rm --name argocd-redis -i -p ${ARGOCD_E2E_REDIS_PORT:-6379}:${ARGOCD_E2E_REDIS_PORT:-6379} redis:6.2.6-alpine --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; fi"
repo-server: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_GNUPGHOME=${ARGOCD_GNUPGHOME:-/tmp/argocd-local/gpg/keys} ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-/tmp/argo-e2e/app/config/plugin} ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-repo-server ARGOCD_GPG_ENABLED=${ARGOCD_GPG_ENABLED:-false} $COMMAND --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379}"
ui: sh -c 'cd ui && ${ARGOCD_E2E_YARN_CMD:-yarn} start'
git-server: test/fixture/testrepos/start-git.sh
helm-registry: test/fixture/testrepos/start-helm-registry.sh

View File

@@ -45,6 +45,9 @@ Participation in the Argo CD project is governed by the [CNCF Code of Conduct](h
### Blogs and Presentations
1. [Awesome-Argo: A Curated List of Awesome Projects and Resources Related to Argo](https://github.com/terrytangyuan/awesome-argo)
1. [Unveil the Secret Ingredients of Continuous Delivery at Enterprise Scale with Argo CD](https://blog.akuity.io/unveil-the-secret-ingredients-of-continuous-delivery-at-enterprise-scale-with-argo-cd-7c5b4057ee49)
1. [GitOps Without Pipelines With ArgoCD Image Updater](https://youtu.be/avPUQin9kzU)
1. [Combining Argo CD (GitOps), Crossplane (Control Plane), And KubeVela (OAM)](https://youtu.be/eEcgn_gU3SM)
1. [How to Apply GitOps to Everything - Combining Argo CD and Crossplane](https://youtu.be/yrj4lmScKHQ)
1. [Couchbase - How To Run a Database Cluster in Kubernetes Using Argo CD](https://youtu.be/nkPoPaVzExY)
@@ -69,3 +72,4 @@ Participation in the Argo CD project is governed by the [CNCF Code of Conduct](h
1. [Applied GitOps with Argo CD](https://thenewstack.io/applied-gitops-with-argocd/)
1. [Solving configuration drift using GitOps with Argo CD](https://www.cncf.io/blog/2020/12/17/solving-configuration-drift-using-gitops-with-argo-cd/)
1. [Decentralized GitOps over environments](https://blogs.sap.com/2021/05/06/decentralized-gitops-over-environments/)
1. [How GitOps and Operators mark the rise of Infrastructure-As-Software](https://paytmlabs.com/blog/2021/10/how-to-improve-operational-work-with-operators-and-gitops/)

View File

@@ -1,6 +1,6 @@
# Security Policy for Argo CD
Version: **v1.1 (2020-06-29)**
Version: **v1.4 (2022-01-23)**
## Preface
@@ -26,8 +26,12 @@ are well aware of the issues that may affect Argo CD and are constantly
working on the remediation of those that affect Argo CD and our users.
If you believe that we might have missed an issue that we should take a look
at (that can happen), then please discuss it with us. But please, do validate
that assumption before at least roughly.
at (that can happen), then please discuss it with us. If there is a CVE
assigned to the issue, please do open an issue on our GitHub tracker instead
of writing to the security contact e-mail, since things reported by scanners
are public already and the discussion that might emerge is of benefit to the
general community. However, please validate your scanner results and its
impact on Argo CD before opening an issue at least roughly.
## Supported Versions
@@ -56,13 +60,17 @@ We will do our best to react quickly on your inquiry, and to coordinate a fix
and disclosure with you. Sometimes, it might take a little longer for us to
react (e.g. out of office conditions), so please bear with us in these cases.
We will publish security advisiories using the Git Hub SA feature to keep our
community well informed, and will credit you for your findings (unless you
prefer to stay anonymous, of course).
We will publish security advisiories using the
[Git Hub Security Advisories](https://github.com/argoproj/argo-cd/security/advisories)
feature to keep our community well informed, and will credit you for your
findings (unless you prefer to stay anonymous, of course).
Please report vulnerabilities by e-mail to all of the following people:
Please report vulnerabilities by e-mail to the following address:
* jfischer@redhat.com
* Jesse_Suen@intuit.com
* Alexander_Matyushentsev@intuit.com
* Edward_Lee@intuit.com
* cncf-argo-security@lists.cncf.io
## Securing your Argo CD Instance
See the [operator manual security page](docs/operator-manual/security.md) for
additional information about Argo CD's security features and how to make your
Argo CD production ready.

View File

@@ -9,7 +9,9 @@ Currently, the following organizations are **officially** using Argo CD:
1. [7shifts](https://www.7shifts.com/)
1. [Adevinta](https://www.adevinta.com/)
1. [Adventure](https://jp.adventurekk.com/)
1. [Akuity](https://akuity.io/)
1. [Alibaba Group](https://www.alibabagroup.com/)
1. [Allianz Direct](https://www.allianzdirect.de/)
1. [Ambassador Labs](https://www.getambassador.io/)
1. [Ant Group](https://www.antgroup.com/)
1. [ANSTO - Australian Synchrotron](https://www.synchrotron.org.au/)
@@ -22,20 +24,24 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Beat](https://thebeat.co/en/)
1. [Beez Innovation Labs](https://www.beezlabs.com/)
1. [BioBox Analytics](https://biobox.io)
1. [BigPanda](https://bigpanda.io)
1. [BMW Group](https://www.bmwgroup.com/)
1. [Camptocamp](https://camptocamp.com)
1. [Capital One](https://www.capitalone.com)
1. [CARFAX](https://www.carfax.com)
1. [Celonis](https://www.celonis.com/)
1. [Chime](https://www.chime.com)
1. [Cisco ET&I](https://eti.cisco.com/)
1. [Codefresh](https://www.codefresh.io/)
1. [Codility](https://www.codility.com/)
1. [Commonbond](https://commonbond.co/)
1. [Crédit Agricole](https://www.ca-cib.com)
1. [Crédit Agricole CIB](https://www.ca-cib.com)
1. [CROZ d.o.o.](https://croz.net/)
1. [CyberAgent](https://www.cyberagent.co.jp/en/)
1. [Cybozu](https://cybozu-global.com)
1. [Chargetrip](https://chargetrip.com)
1. [D2iQ](https://www.d2iq.com)
1. [Deloitte](https://www.deloitte.com/)
1. [Devtron Labs](https://github.com/devtron-labs/devtron)
1. [EDF Renewables](https://www.edf-re.com/)
1. [edX](https://edx.org)
@@ -44,26 +50,34 @@ Currently, the following organizations are **officially** using Argo CD:
1. [END.](https://www.endclothing.com/)
1. [Energisme](https://energisme.com/)
1. [Fave](https://myfave.com)
1. [Flip](https://flip.id)
1. [Fonoa](https://www.fonoa.com/)
1. [Future PLC](https://www.futureplc.com/)
1. [Garner](https://www.garnercorp.com)
1. [G DATA CyberDefense AG](https://www.gdata-software.com/)
1. [Generali Deutschland AG](https://www.generali.de/)
1. [Gitpod](https://www.gitpod.io)
1. [Glovo](https://www.glovoapp.com)
1. [Gllue](https://gllue.com)
1. [GMETRI](https://gmetri.com/)
1. [Gojek](https://www.gojek.io/)
1. [Greenpass](https://www.greenpass.com.br/)
1. [Handelsbanken](https://www.handelsbanken.se)
1. [Healy](https://www.healyworld.net)
1. [Helio](https://helio.exchange)
1. [hipages](https://hipages.com.au/)
1. [Hiya](https://hiya.com)
1. [Honestbank](https://honestbank.com)
1. [IBM](https://www.ibm.com/)
1. [Ibotta](https://home.ibotta.com)
1. [IITS-Consulting](https://iits-consulting.de)
1. [Index Exchange](https://www.indexexchange.com/)
1. [InsideBoard](https://www.insideboard.com)
1. [Intuit](https://www.intuit.com/)
1. [Joblift](https://joblift.com/)
1. [JovianX](https://www.jovianx.com/)
1. [Karrot](https://www.daangn.com/)
1. [KarrotPay](https://www.daangnpay.com/)
1. [Kasa](https://kasa.co.kr/)
1. [Keptn](https://keptn.sh)
1. [Kinguin](https://www.kinguin.net/)
@@ -74,9 +88,11 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Lytt](https://www.lytt.co/)
1. [Major League Baseball](https://mlb.com)
1. [Mambu](https://www.mambu.com/)
1. [Mattermost](https://www.mattermost.com)
1. [Max Kelsen](https://www.maxkelsen.com/)
1. [MindSpore](https://mindspore.cn)
1. [Mirantis](https://mirantis.com/)
1. [mixi Group](https://mixi.co.jp/)
1. [Moengage](https://www.moengage.com/)
1. [Money Forward](https://corp.moneyforward.com/en/)
1. [MOO Print](https://www.moo.com/)
@@ -85,7 +101,9 @@ Currently, the following organizations are **officially** using Argo CD:
1. [New Relic](https://newrelic.com/)
1. [Nextdoor](https://nextdoor.com/)
1. [Nikkei](https://www.nikkei.co.jp/nikkeiinfo/en/)
1. [Nitro](https://gonitro.com)
1. [Octadesk](https://octadesk.com)
1. [omegaUp](https://omegaUp.com)
1. [openEuler](https://openeuler.org)
1. [openGauss](https://opengauss.org/)
1. [openLooKeng](https://openlookeng.io)
@@ -93,6 +111,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Opensurvey](https://www.opensurvey.co.kr/)
1. [Optoro](https://www.optoro.com/)
1. [Orbital Insight](https://orbitalinsight.com/)
1. [Packlink](https://www.packlink.com/)
1. [PayPay](https://paypay.ne.jp/)
1. [Peloton Interactive](https://www.onepeloton.com/)
1. [Pipefy](https://www.pipefy.com/)
@@ -110,9 +129,13 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Saildrone](https://www.saildrone.com/)
1. [Saloodo! GmbH](https://www.saloodo.com)
1. [Schwarz IT](https://jobs.schwarz/it-mission)
1. [Skit](https://skit.ai/)
1. [Snyk](https://snyk.io/)
1. [Speee](https://speee.jp/)
1. [Spendesk](https://spendesk.com/)
1. [Sumo Logic](https://sumologic.com/)
1. [Sutpc](http://www.sutpc.com/)
1. [Swiss Post](https://github.com/swisspost)
1. [Swisscom](https://www.swisscom.ch)
1. [Swissquote](https://github.com/swissquote)
1. [Syncier](https://syncier.com/)
@@ -122,10 +145,12 @@ Currently, the following organizations are **officially** using Argo CD:
1. [ThousandEyes](https://www.thousandeyes.com/)
1. [Ticketmaster](https://ticketmaster.com)
1. [Tiger Analytics](https://www.tigeranalytics.com/)
1. [Tigera](https://www.tigera.io/)
1. [Toss](https://toss.im/en)
1. [tru.ID](https://tru.id)
1. [Twilio SendGrid](https://sendgrid.com)
1. [tZERO](https://www.tzero.com/)
1. [ungleich.ch](https://ungleich.ch/)
1. [UBIO](https://ub.io/)
1. [UFirstGroup](https://www.ufirstgroup.com/en/)
1. [Universidad Mesoamericana](https://www.umes.edu.gt/)
@@ -135,6 +160,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Volvo Cars](https://www.volvocars.com/)
1. [VSHN - The DevOps Company](https://vshn.ch/)
1. [Walkbase](https://www.walkbase.com/)
1. [Wehkamp](https://www.wehkamp.nl/)
1. [WeMo Scooter](https://www.wemoscooter.com/)
1. [Webstores](https://www.webstores.nl)
1. [Whitehat Berlin](https://whitehat.berlin) by Guido Maria Serra +Fenaroli
@@ -154,3 +180,18 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Beleza Na Web](https://www.belezanaweb.com.br/)
1. [MariaDB](https://mariadb.com)
1. [Lightricks](https://www.lightricks.com/)
1. [RightRev](https://rightrev.com/)
1. [MeDirect](https://medirect.com.mt/)
1. [Snapp](https://snapp.ir/)
1. [Technacy](https://www.technacy.it/)
1. [freee](https://corp.freee.co.jp/en/company/)
1. [Youverify](https://youverify.co/)
1. [Keeeb](https://www.keeeb.com/)
1. [p3r](https://www.p3r.one/)
1. [Faro](https://www.faro.com/)
1. [Rise](https://www.risecard.eu/)
1. [Devopsi - Poland Software/DevOps Consulting](https://devopsi.pl/)
1. [Skyscanner](https://www.skyscanner.net/)
1. [Casavo](https://casavo.com)
1. [Majid Al Futtaim](https://www.majidalfuttaim.com/)
1. [ZOZO](https://corp.zozo.com/)

View File

@@ -1 +1 @@
2.1.0
2.3.4

View File

@@ -11,4 +11,4 @@ g = _, _
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
[matchers]
m = g(r.sub, p.sub) && globMatch(r.res, p.res) && globMatch(r.act, p.act) && globMatch(r.obj, p.obj)
m = g(r.sub, p.sub) && globOrRegexMatch(r.res, p.res) && globOrRegexMatch(r.act, p.act) && globOrRegexMatch(r.obj, p.obj)

View File

@@ -256,7 +256,7 @@
},
{
"type": "string",
"description": "the selector to to restrict returned list to applications only with matched labels.",
"description": "the selector to restrict returned list to applications only with matched labels.",
"name": "selector",
"in": "query"
},
@@ -520,7 +520,7 @@
},
{
"type": "string",
"description": "the selector to to restrict returned list to applications only with matched labels.",
"description": "the selector to restrict returned list to applications only with matched labels.",
"name": "selector",
"in": "query"
},
@@ -753,6 +753,11 @@
"type": "string",
"name": "resourceName",
"in": "query"
},
{
"type": "boolean",
"name": "previous",
"in": "query"
}
],
"responses": {
@@ -932,6 +937,11 @@
"type": "string",
"name": "resourceName",
"in": "query"
},
{
"type": "boolean",
"name": "previous",
"in": "query"
}
],
"responses": {
@@ -1595,6 +1605,18 @@
"type": "string",
"name": "name",
"in": "query"
},
{
"type": "string",
"description": "type is the type of the specified cluster identifier ( \"server\" - default, \"name\" ).",
"name": "id.type",
"in": "query"
},
{
"type": "string",
"description": "value holds the cluster server URL or cluster name.",
"name": "id.value",
"in": "query"
}
],
"responses": {
@@ -1649,7 +1671,53 @@
}
}
},
"/api/v1/clusters/{cluster.server}": {
"/api/v1/clusters/{id.value}": {
"get": {
"tags": [
"ClusterService"
],
"summary": "Get returns a cluster by server address",
"operationId": "ClusterService_Get",
"parameters": [
{
"type": "string",
"description": "value holds the cluster server URL or cluster name",
"name": "id.value",
"in": "path",
"required": true
},
{
"type": "string",
"name": "server",
"in": "query"
},
{
"type": "string",
"name": "name",
"in": "query"
},
{
"type": "string",
"description": "type is the type of the specified cluster identifier ( \"server\" - default, \"name\" ).",
"name": "id.type",
"in": "query"
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1alpha1Cluster"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
}
},
"put": {
"tags": [
"ClusterService"
@@ -1659,8 +1727,8 @@
"parameters": [
{
"type": "string",
"description": "Server is the API server URL of the Kubernetes cluster",
"name": "cluster.server",
"description": "value holds the cluster server URL or cluster name",
"name": "id.value",
"in": "path",
"required": true
},
@@ -1680,41 +1748,11 @@
"collectionFormat": "multi",
"name": "updatedFields",
"in": "query"
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1alpha1Cluster"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
}
}
},
"/api/v1/clusters/{server}": {
"get": {
"tags": [
"ClusterService"
],
"summary": "Get returns a cluster by server address",
"operationId": "ClusterService_Get",
"parameters": [
{
"type": "string",
"name": "server",
"in": "path",
"required": true
},
{
"type": "string",
"name": "name",
"description": "type is the type of the specified cluster identifier ( \"server\" - default, \"name\" ).",
"name": "id.type",
"in": "query"
}
],
@@ -1742,14 +1780,26 @@
"parameters": [
{
"type": "string",
"name": "server",
"description": "value holds the cluster server URL or cluster name",
"name": "id.value",
"in": "path",
"required": true
},
{
"type": "string",
"name": "server",
"in": "query"
},
{
"type": "string",
"name": "name",
"in": "query"
},
{
"type": "string",
"description": "type is the type of the specified cluster identifier ( \"server\" - default, \"name\" ).",
"name": "id.type",
"in": "query"
}
],
"responses": {
@@ -1768,7 +1818,7 @@
}
}
},
"/api/v1/clusters/{server}/invalidate-cache": {
"/api/v1/clusters/{id.value}/invalidate-cache": {
"post": {
"tags": [
"ClusterService"
@@ -1778,7 +1828,8 @@
"parameters": [
{
"type": "string",
"name": "server",
"description": "value holds the cluster server URL or cluster name",
"name": "id.value",
"in": "path",
"required": true
}
@@ -1799,7 +1850,7 @@
}
}
},
"/api/v1/clusters/{server}/rotate-auth": {
"/api/v1/clusters/{id.value}/rotate-auth": {
"post": {
"tags": [
"ClusterService"
@@ -1809,7 +1860,8 @@
"parameters": [
{
"type": "string",
"name": "server",
"description": "value holds the cluster server URL or cluster name",
"name": "id.value",
"in": "path",
"required": true
}
@@ -2081,6 +2133,37 @@
}
}
},
"/api/v1/projects/{name}/detailed": {
"get": {
"tags": [
"ProjectService"
],
"summary": "GetDetailedProject returns a project that include project, global project and scoped resources by name",
"operationId": "ProjectService_GetDetailedProject",
"parameters": [
{
"type": "string",
"name": "name",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/projectDetailedProjectsResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
}
}
},
"/api/v1/projects/{name}/events": {
"get": {
"tags": [
@@ -2661,6 +2744,16 @@
"type": "string",
"name": "revision",
"in": "query"
},
{
"type": "string",
"name": "appName",
"in": "query"
},
{
"type": "string",
"name": "appProject",
"in": "query"
}
],
"responses": {
@@ -2863,6 +2956,12 @@
"description": "HTTP/HTTPS proxy to access the repository.",
"name": "proxy",
"in": "query"
},
{
"type": "string",
"description": "Reference between project and repository that allow you automatically to be added as item inside SourceRepos project entity.",
"name": "project",
"in": "query"
}
],
"responses": {
@@ -3059,7 +3158,7 @@
},
{
"type": "string",
"description": "the selector to to restrict returned list to applications only with matched labels.",
"description": "the selector to restrict returned list to applications only with matched labels.",
"name": "selector",
"in": "query"
},
@@ -3483,6 +3582,20 @@
}
}
},
"clusterClusterID": {
"type": "object",
"title": "ClusterID holds a cluster server URL or cluster name",
"properties": {
"type": {
"type": "string",
"title": "type is the type of the specified cluster identifier ( \"server\" - default, \"name\" )"
},
"value": {
"type": "string",
"title": "value holds the cluster server URL or cluster name"
}
}
},
"clusterClusterResponse": {
"type": "object"
},
@@ -3523,6 +3636,13 @@
"type": "object",
"title": "Help settings",
"properties": {
"binaryUrls": {
"type": "object",
"title": "the URLs for downloading argocd binaries",
"additionalProperties": {
"type": "string"
}
},
"chatText": {
"type": "string",
"title": "the text for getting chat help, defaults to \"Chat now!\""
@@ -3605,6 +3725,9 @@
"oidcConfig": {
"$ref": "#/definitions/clusterOIDCConfig"
},
"passwordPattern": {
"type": "string"
},
"plugins": {
"type": "array",
"items": {
@@ -3620,9 +3743,18 @@
"statusBadgeEnabled": {
"type": "boolean"
},
"trackingMethod": {
"type": "string"
},
"uiBannerContent": {
"type": "string"
},
"uiBannerPermanent": {
"type": "boolean"
},
"uiBannerPosition": {
"type": "string"
},
"uiBannerURL": {
"type": "string"
},
@@ -3674,6 +3806,32 @@
}
}
},
"projectDetailedProjectsResponse": {
"type": "object",
"properties": {
"clusters": {
"type": "array",
"items": {
"$ref": "#/definitions/v1alpha1Cluster"
}
},
"globalProjects": {
"type": "array",
"items": {
"$ref": "#/definitions/v1alpha1AppProject"
}
},
"project": {
"$ref": "#/definitions/v1alpha1AppProject"
},
"repositories": {
"type": "array",
"items": {
"$ref": "#/definitions/v1alpha1Repository"
}
}
}
},
"projectEmptyResponse": {
"type": "object"
},
@@ -3957,6 +4115,9 @@
"appName": {
"type": "string"
},
"appProject": {
"type": "string"
},
"source": {
"$ref": "#/definitions/v1alpha1ApplicationSource"
}
@@ -4283,6 +4444,10 @@
"description": "Operation is the type of operation which lead to this ManagedFieldsEntry being created.\nThe only valid values for this field are 'Apply' and 'Update'.",
"type": "string"
},
"subresource": {
"description": "Subresource is the name of the subresource used to update that object, or\nempty string if the object was updated through the main resource. The\nvalue of this field is used to distinguish between managers, even if they\nshare the same name. For example, a status update will be distinct from a\nregular update using the same manager name.\nNote that the APIVersion field is not related to the Subresource field and\nit always corresponds to the version of the main resource.",
"type": "string"
},
"time": {
"$ref": "#/definitions/v1Time"
}
@@ -4437,7 +4602,7 @@
},
"v1ObjectReference": {
"type": "object",
"title": "ObjectReference contains enough information to let you inspect or modify the referred object.\n---\nNew uses of this type are discouraged because of difficulty describing its usage when embedded in APIs.\n 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage.\n 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular\n restrictions like, \"must refer only to types A and B\" or \"UID not honored\" or \"name must be restricted\".\n Those cannot be well described when embedded.\n 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen.\n 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity\n during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple\n and the version of the actual struct is irrelevant.\n 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type\n will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control.\nInstead of using this type, create a locally provided and used type that is well-focused on your reference.\nFor example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 .\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object",
"title": "ObjectReference contains enough information to let you inspect or modify the referred object.\n---\nNew uses of this type are discouraged because of difficulty describing its usage when embedded in APIs.\n 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage.\n 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular\n restrictions like, \"must refer only to types A and B\" or \"UID not honored\" or \"name must be restricted\".\n Those cannot be well described when embedded.\n 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen.\n 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity\n during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple\n and the version of the actual struct is irrelevant.\n 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type\n will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control.\nInstead of using this type, create a locally provided and used type that is well-focused on your reference.\nFor example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 .\n+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n+structType=atomic",
"properties": {
"apiVersion": {
"type": "string",
@@ -4470,8 +4635,8 @@
}
},
"v1OwnerReference": {
"description": "OwnerReference contains enough information to let you identify an owning\nobject. An owning object must be in the same namespace as the dependent, or\nbe cluster-scoped, so there is no namespace field.",
"type": "object",
"title": "OwnerReference contains enough information to let you identify an owning\nobject. An owning object must be in the same namespace as the dependent, or\nbe cluster-scoped, so there is no namespace field.\n+structType=atomic",
"properties": {
"apiVersion": {
"description": "API version of the referent.",
@@ -4803,6 +4968,10 @@
"$ref": "#/definitions/v1alpha1HelmFileParameter"
}
},
"ignoreMissingValueFiles": {
"type": "boolean",
"title": "IgnoreMissingValueFiles prevents helm template from failing when valueFiles do not exist locally by not appending them to helm template --values"
},
"parameters": {
"type": "array",
"title": "Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation",
@@ -4810,10 +4979,18 @@
"$ref": "#/definitions/v1alpha1HelmParameter"
}
},
"passCredentials": {
"type": "boolean",
"title": "PassCredentials pass credentials to all domains (Helm's --pass-credentials)"
},
"releaseName": {
"type": "string",
"title": "ReleaseName is the Helm release name to use. If omitted it will use the application name"
},
"skipCrds": {
"type": "boolean",
"title": "SkipCrds skips custom resource definition installation step (Helm's --skip-crds)"
},
"valueFiles": {
"type": "array",
"title": "ValuesFiles is a list of Helm value files to use when generating a template",
@@ -5106,6 +5283,13 @@
"type": "object",
"title": "Cluster is the definition of a cluster resource",
"properties": {
"annotations": {
"type": "object",
"title": "Annotations for cluster secret metadata",
"additionalProperties": {
"type": "string"
}
},
"clusterResources": {
"description": "Indicates if cluster level resources should be managed. This setting is used only if cluster is connected in a namespaced mode.",
"type": "boolean"
@@ -5119,6 +5303,13 @@
"info": {
"$ref": "#/definitions/v1alpha1ClusterInfo"
},
"labels": {
"type": "object",
"title": "Labels for cluster secret metadata",
"additionalProperties": {
"type": "string"
}
},
"name": {
"type": "string",
"title": "Name of the cluster. If omitted, will use the server address"
@@ -5130,6 +5321,10 @@
"type": "string"
}
},
"project": {
"type": "string",
"title": "Reference between project and cluster that allow you automatically to be added as item inside Destinations project entity"
},
"refreshRequestedAt": {
"$ref": "#/definitions/v1Time"
},
@@ -5276,6 +5471,9 @@
"init": {
"$ref": "#/definitions/v1alpha1Command"
},
"lockRepo": {
"type": "boolean"
},
"name": {
"type": "string"
}
@@ -5671,16 +5869,25 @@
},
"v1alpha1OverrideIgnoreDiff": {
"type": "object",
"title": "TODO: describe this type",
"title": "OverrideIgnoreDiff contains configurations about how fields should be ignored during diffs between\nthe desired state and live state",
"properties": {
"jSONPointers": {
"type": "array",
"title": "JSONPointers is a JSON path list following the format defined in RFC4627 (https://datatracker.ietf.org/doc/html/rfc6902#section-3)",
"items": {
"type": "string"
}
},
"jqPathExpressions": {
"type": "array",
"title": "JQPathExpressions is a JQ path list that will be evaludated during the diff process",
"items": {
"type": "string"
}
},
"managedFieldsManagers": {
"type": "array",
"title": "ManagedFieldsManagers is a list of trusted managers. Fields mutated by those managers will take precedence over the\ndesired state defined in the SCM and won't be displayed in diffs",
"items": {
"type": "string"
}
@@ -5846,6 +6053,10 @@
"type": "string",
"title": "Password contains the password or PAT used for authenticating at the remote repository"
},
"project": {
"type": "string",
"title": "Reference between project and repository that allow you automatically to be added as item inside SourceRepos project entity"
},
"proxy": {
"type": "string",
"title": "Proxy specifies the HTTP/HTTPS proxy used to access the repo"
@@ -6039,6 +6250,13 @@
"kind": {
"type": "string"
},
"managedFieldsManagers": {
"type": "array",
"title": "ManagedFieldsManagers is a list of trusted managers. Fields mutated by those managers will take precedence over the\ndesired state defined in the SCM and won't be displayed in diffs",
"items": {
"type": "string"
}
},
"name": {
"type": "string"
},
@@ -6534,6 +6752,10 @@
"schedule": {
"type": "string",
"title": "Schedule is the time the window will begin, specified in cron format"
},
"timeZone": {
"type": "string",
"title": "TimeZone of the sync that will be applied to the schedule"
}
}
},

View File

@@ -49,6 +49,7 @@ func NewCommand() *cobra.Command {
glogLevel int
metricsPort int
metricsCacheExpiration time.Duration
metricsAplicationLabels []string
kubectlParallelismLimit int64
cacheSrc func() (*appstatecache.Cache, error)
redisClient *redis.Client
@@ -110,10 +111,14 @@ func NewCommand() *cobra.Command {
errors.CheckError(err)
cache.Cache.SetClient(cacheutil.NewTwoLevelClient(cache.Cache.GetClient(), 10*time.Minute))
settingsMgr := settings.NewSettingsManager(ctx, kubeClient, namespace)
var appController *controller.ApplicationController
settingsMgr := settings.NewSettingsManager(ctx, kubeClient, namespace, settings.WithRepoOrClusterChangedHandler(func() {
appController.InvalidateProjectsCache()
}))
kubectl := kubeutil.NewKubectl()
clusterFilter := getClusterFilter()
appController, err := controller.NewApplicationController(
appController, err = controller.NewApplicationController(
namespace,
settingsMgr,
kubeClient,
@@ -125,6 +130,7 @@ func NewCommand() *cobra.Command {
time.Duration(selfHealTimeoutSeconds)*time.Second,
metricsPort,
metricsCacheExpiration,
metricsAplicationLabels,
kubectlParallelismLimit,
clusterFilter)
errors.CheckError(err)
@@ -144,20 +150,21 @@ func NewCommand() *cobra.Command {
}
clientConfig = cli.AddKubectlFlagsToCmd(&command)
command.Flags().Int64Var(&appResyncPeriod, "app-resync", int64(env.ParseDurationFromEnv("ARGOCD_RECONCILIATION_TIMEOUT", defaultAppResyncPeriod*time.Second, 0, math.MaxInt32).Seconds()), "Time period in seconds for application resync.")
command.Flags().Int64Var(&appResyncPeriod, "app-resync", int64(env.ParseDurationFromEnv("ARGOCD_RECONCILIATION_TIMEOUT", defaultAppResyncPeriod*time.Second, 0, math.MaxInt64).Seconds()), "Time period in seconds for application resync.")
command.Flags().StringVar(&repoServerAddress, "repo-server", env.StringFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER", common.DefaultRepoServerAddr), "Repo server address.")
command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", int(env.ParseDurationFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS", 60*time.Second, 0, math.MaxInt32).Seconds()), "Repo server RPC call timeout seconds.")
command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS", 60, 0, math.MaxInt64), "Repo server RPC call timeout seconds.")
command.Flags().IntVar(&statusProcessors, "status-processors", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_STATUS_PROCESSORS", 20, 0, math.MaxInt32), "Number of application status processors")
command.Flags().IntVar(&operationProcessors, "operation-processors", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_OPERATION_PROCESSORS", 10, 0, math.MaxInt32), "Number of application operation processors")
command.Flags().StringVar(&cmdutil.LogFormat, "logformat", env.StringFromEnv("ARGOCD_APPLICATION_CONTROLLER_LOGFORMAT", "text"), "Set the logging format. One of: text|json")
command.Flags().StringVar(&cmdutil.LogLevel, "loglevel", env.StringFromEnv("ARGOCD_APPLICATION_CONTROLLER_LOGLEVEL", "info"), "Set the logging level. One of: debug|info|warn|error")
command.Flags().IntVar(&glogLevel, "gloglevel", 0, "Set the glog logging level")
command.Flags().IntVar(&metricsPort, "metrics-port", common.DefaultPortArgoCDMetrics, "Start metrics server on given port")
command.Flags().DurationVar(&metricsCacheExpiration, "metrics-cache-expiration", env.ParseDurationFromEnv("ARGOCD_APPLICATION_CONTROLLER_METRICS_CACHE_EXPIRATION", 0*time.Second, 0, math.MaxInt32), "Prometheus metrics cache expiration (disabled by default. e.g. 24h0m0s)")
command.Flags().DurationVar(&metricsCacheExpiration, "metrics-cache-expiration", env.ParseDurationFromEnv("ARGOCD_APPLICATION_CONTROLLER_METRICS_CACHE_EXPIRATION", 0*time.Second, 0, math.MaxInt64), "Prometheus metrics cache expiration (disabled by default. e.g. 24h0m0s)")
command.Flags().IntVar(&selfHealTimeoutSeconds, "self-heal-timeout-seconds", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_TIMEOUT_SECONDS", 5, 0, math.MaxInt32), "Specifies timeout between application self heal attempts")
command.Flags().Int64Var(&kubectlParallelismLimit, "kubectl-parallelism-limit", 20, "Number of allowed concurrent kubectl fork/execs. Any value less the 1 means no limit.")
command.Flags().BoolVar(&repoServerPlaintext, "repo-server-plaintext", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_PLAINTEXT", false), "Disable TLS on connections to repo server")
command.Flags().BoolVar(&repoServerStrictTLS, "repo-server-strict-tls", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_STRICT_TLS", false), "Whether to use strict validation of the TLS cert presented by the repo server")
command.Flags().StringSliceVar(&metricsAplicationLabels, "metrics-application-labels", []string{}, "List of Application labels that will be added to the argocd_application_labels metric")
cacheSrc = appstatecache.AddCacheFlagsToCmd(&command, func(client *redis.Client) {
redisClient = client
})

View File

@@ -0,0 +1,58 @@
package commands
import (
"time"
"github.com/argoproj/pkg/stats"
"github.com/spf13/cobra"
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
"github.com/argoproj/argo-cd/v2/cmpserver"
"github.com/argoproj/argo-cd/v2/cmpserver/plugin"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/util/errors"
)
const (
// CLIName is the name of the CLI
cliName = "argocd-cmp-server"
)
func NewCommand() *cobra.Command {
var (
configFilePath string
)
var command = cobra.Command{
Use: cliName,
Short: "Run ArgoCD ConfigManagementPlugin Server",
Long: "ArgoCD ConfigManagementPlugin Server is an internal service which runs as sidecar container in reposerver deployment. It can be configured by following options.",
DisableAutoGenTag: true,
RunE: func(c *cobra.Command, args []string) error {
cli.SetLogFormat(cmdutil.LogFormat)
cli.SetLogLevel(cmdutil.LogLevel)
config, err := plugin.ReadPluginConfig(configFilePath)
errors.CheckError(err)
server, err := cmpserver.NewServer(plugin.CMPServerInitConstants{
PluginConfig: *config,
})
errors.CheckError(err)
// register dumper
stats.RegisterStackDumper()
stats.StartStatsTicker(10 * time.Minute)
stats.RegisterHeapDumper("memprofile")
// run argocd-cmp-server server
server.Run()
return nil
},
}
command.Flags().StringVar(&cmdutil.LogFormat, "logformat", "text", "Set the logging format. One of: text|json")
command.Flags().StringVar(&cmdutil.LogLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")
command.Flags().StringVar(&configFilePath, "config-dir-path", common.DefaultPluginConfigFilePath, "Config management plugin configuration file location, Default is '/home/argocd/cmp-server/config/'")
return &command
}

View File

@@ -0,0 +1,57 @@
package commands
import (
"context"
"fmt"
"os"
"strings"
"github.com/argoproj/argo-cd/v2/util/git"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"github.com/argoproj/argo-cd/v2/reposerver/askpass"
"github.com/argoproj/argo-cd/v2/util/errors"
grpc_util "github.com/argoproj/argo-cd/v2/util/grpc"
"github.com/argoproj/argo-cd/v2/util/io"
)
const (
// cliName is the name of the CLI
cliName = "argocd-git-ask-pass"
)
func NewCommand() *cobra.Command {
var command = cobra.Command{
Use: cliName,
Short: "Argo CD git credential helper",
DisableAutoGenTag: true,
Run: func(c *cobra.Command, args []string) {
if len(os.Args) != 2 {
errors.CheckError(fmt.Errorf("expected 1 argument, got %d", len(os.Args)-1))
}
nonce := os.Getenv(git.ASKPASS_NONCE_ENV)
if nonce == "" {
errors.CheckError(fmt.Errorf("%s is not set", git.ASKPASS_NONCE_ENV))
}
conn, err := grpc_util.BlockingDial(context.Background(), "unix", askpass.SocketPath, nil, grpc.WithInsecure())
errors.CheckError(err)
defer io.Close(conn)
client := askpass.NewAskPassServiceClient(conn)
creds, err := client.GetCredentials(context.Background(), &askpass.CredentialsRequest{Nonce: nonce})
errors.CheckError(err)
switch {
case strings.HasPrefix(os.Args[1], "Username"):
fmt.Println(creds.Username)
case strings.HasPrefix(os.Args[1], "Password"):
fmt.Println(creds.Password)
default:
errors.CheckError(fmt.Errorf("unknown credential type '%s'", os.Args[1]))
}
},
}
return &command
}

View File

@@ -0,0 +1,132 @@
package commands
import (
"context"
"fmt"
"net/http"
"os"
"strings"
service "github.com/argoproj/argo-cd/v2/util/notification/argocd"
notificationscontroller "github.com/argoproj/argo-cd/v2/notification_controller/controller"
controller "github.com/argoproj/notifications-engine/pkg/controller"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/tools/clientcmd"
)
const (
defaultMetricsPort = 9001
)
func addK8SFlagsToCmd(cmd *cobra.Command) clientcmd.ClientConfig {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig
overrides := clientcmd.ConfigOverrides{}
kflags := clientcmd.RecommendedConfigOverrideFlags("")
cmd.PersistentFlags().StringVar(&loadingRules.ExplicitPath, "kubeconfig", "", "Path to a kube config. Only required if out-of-cluster")
clientcmd.BindOverrideFlags(&overrides, cmd.PersistentFlags(), kflags)
return clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, &overrides, os.Stdin)
}
func NewCommand() *cobra.Command {
var (
clientConfig clientcmd.ClientConfig
processorsCount int
namespace string
appLabelSelector string
logLevel string
logFormat string
metricsPort int
argocdRepoServer string
argocdRepoServerPlaintext bool
argocdRepoServerStrictTLS bool
configMapName string
secretName string
)
var command = cobra.Command{
Use: "controller",
Short: "Starts Argo CD Notifications controller",
RunE: func(c *cobra.Command, args []string) error {
restConfig, err := clientConfig.ClientConfig()
if err != nil {
return err
}
dynamicClient, err := dynamic.NewForConfig(restConfig)
if err != nil {
return err
}
k8sClient, err := kubernetes.NewForConfig(restConfig)
if err != nil {
return err
}
if namespace == "" {
namespace, _, err = clientConfig.Namespace()
if err != nil {
return err
}
}
level, err := log.ParseLevel(logLevel)
if err != nil {
return err
}
log.SetLevel(level)
switch strings.ToLower(logFormat) {
case "json":
log.SetFormatter(&log.JSONFormatter{})
case "text":
if os.Getenv("FORCE_LOG_COLORS") == "1" {
log.SetFormatter(&log.TextFormatter{ForceColors: true})
}
default:
return fmt.Errorf("Unknown log format '%s'", logFormat)
}
argocdService, err := service.NewArgoCDService(k8sClient, namespace, argocdRepoServer, argocdRepoServerPlaintext, argocdRepoServerStrictTLS)
if err != nil {
return err
}
defer argocdService.Close()
registry := controller.NewMetricsRegistry("argocd")
http.Handle("/metrics", promhttp.HandlerFor(prometheus.Gatherers{registry, prometheus.DefaultGatherer}, promhttp.HandlerOpts{}))
go func() {
log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", metricsPort), http.DefaultServeMux))
}()
log.Infof("serving metrics on port %d", metricsPort)
log.Infof("loading configuration %d", metricsPort)
ctrl := notificationscontroller.NewController(k8sClient, dynamicClient, argocdService, namespace, appLabelSelector, registry, secretName, configMapName)
err = ctrl.Init(context.Background())
if err != nil {
return err
}
go ctrl.Run(context.Background(), processorsCount)
<-context.Background().Done()
return nil
},
}
clientConfig = addK8SFlagsToCmd(&command)
command.Flags().IntVar(&processorsCount, "processors-count", 1, "Processors count.")
command.Flags().StringVar(&appLabelSelector, "app-label-selector", "", "App label selector.")
command.Flags().StringVar(&namespace, "namespace", "", "Namespace which controller handles. Current namespace if empty.")
command.Flags().StringVar(&logLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")
command.Flags().StringVar(&logFormat, "logformat", "text", "Set the logging format. One of: text|json")
command.Flags().IntVar(&metricsPort, "metrics-port", defaultMetricsPort, "Metrics port")
command.Flags().StringVar(&argocdRepoServer, "argocd-repo-server", "argocd-repo-server:8081", "Argo CD repo server address")
command.Flags().BoolVar(&argocdRepoServerPlaintext, "argocd-repo-server-plaintext", false, "Use a plaintext client (non-TLS) to connect to repository server")
command.Flags().BoolVar(&argocdRepoServerStrictTLS, "argocd-repo-server-strict-tls", false, "Perform strict validation of TLS certificates when connecting to repo server")
command.Flags().StringVar(&configMapName, "config-map-name", "argocd-notifications-cm", "Set notifications ConfigMap name")
command.Flags().StringVar(&secretName, "secret-name", "argocd-notifications-secret", "Set notifications Secret name")
return &command
}

View File

@@ -18,6 +18,7 @@ import (
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/reposerver"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/reposerver/askpass"
reposervercache "github.com/argoproj/argo-cd/v2/reposerver/cache"
"github.com/argoproj/argo-cd/v2/reposerver/metrics"
"github.com/argoproj/argo-cd/v2/reposerver/repository"
@@ -61,6 +62,10 @@ func getPauseGenerationOnFailureForRequests() int {
return env.ParseNumFromEnv(common.EnvPauseGenerationRequests, defaultPauseGenerationOnFailureForRequests, 0, math.MaxInt32)
}
func getSubmoduleEnabled() bool {
return env.ParseBoolFromEnv(common.EnvGitSubmoduleEnabled, true)
}
func NewCommand() *cobra.Command {
var (
parallelismLimit int64
@@ -90,6 +95,7 @@ func NewCommand() *cobra.Command {
cache, err := cacheSrc()
errors.CheckError(err)
askPassServer := askpass.NewServer()
metricsServer := metrics.NewMetricsServer()
cacheutil.CollectMetrics(redisClient, metricsServer)
server, err := reposerver.NewServer(metricsServer, cache, tlsConfigCustomizer, repository.RepoServerInitConstants{
@@ -97,7 +103,8 @@ func NewCommand() *cobra.Command {
PauseGenerationAfterFailedGenerationAttempts: getPauseGenerationAfterFailedGenerationAttempts(),
PauseGenerationOnFailureForMinutes: getPauseGenerationOnFailureForMinutes(),
PauseGenerationOnFailureForRequests: getPauseGenerationOnFailureForRequests(),
})
SubmoduleEnabled: getSubmoduleEnabled(),
}, askPassServer)
errors.CheckError(err)
grpc := server.CreateGRPC()
@@ -128,6 +135,7 @@ func NewCommand() *cobra.Command {
})
http.Handle("/metrics", metricsServer.GetHandler())
go func() { errors.CheckError(http.ListenAndServe(fmt.Sprintf(":%d", metricsPort), nil)) }()
go func() { errors.CheckError(askPassServer.Run(askpass.SocketPath)) }()
if gpg.IsGPGEnabled() {
log.Infof("Initializing GnuPG keyring at %s", common.GetGnuPGHomePath())

View File

@@ -63,6 +63,7 @@ func NewCommand() *cobra.Command {
frameOptions string
repoServerPlaintext bool
repoServerStrictTLS bool
staticAssetsDir string
)
var command = &cobra.Command{
Use: cliName,
@@ -139,6 +140,7 @@ func NewCommand() *cobra.Command {
Cache: cache,
XFrameOptions: frameOptions,
RedisClient: redisClient,
StaticAssetsDir: staticAssetsDir,
}
stats.RegisterStackDumper()
@@ -157,9 +159,7 @@ func NewCommand() *cobra.Command {
clientConfig = cli.AddKubectlFlagsToCmd(command)
command.Flags().BoolVar(&insecure, "insecure", env.ParseBoolFromEnv("ARGOCD_SERVER_INSECURE", false), "Run server without TLS")
var staticAssetsDir string
command.Flags().StringVar(&staticAssetsDir, "staticassets", "", "Static assets directory path")
_ = command.Flags().MarkDeprecated("staticassets", "The --staticassets flag is not longer supported. Static assets are embedded into binary.")
command.Flags().StringVar(&staticAssetsDir, "staticassets", env.StringFromEnv("ARGOCD_SERVER_STATIC_ASSETS", "/shared/app"), "Directory path that contains additional static assets")
command.Flags().StringVar(&baseHRef, "basehref", env.StringFromEnv("ARGOCD_SERVER_BASEHREF", "/"), "Value for base href in index.html. Used if Argo CD is running behind reverse proxy under subpath different from /")
command.Flags().StringVar(&rootPath, "rootpath", env.StringFromEnv("ARGOCD_SERVER_ROOTPATH", ""), "Used if Argo CD is running behind reverse proxy under subpath different from /")
command.Flags().StringVar(&cmdutil.LogFormat, "logformat", env.StringFromEnv("ARGOCD_SERVER_LOGFORMAT", "text"), "Set the logging format. One of: text|json")
@@ -172,7 +172,7 @@ func NewCommand() *cobra.Command {
command.AddCommand(cli.NewVersionCmd(cliName))
command.Flags().IntVar(&listenPort, "port", common.DefaultPortAPIServer, "Listen on given port")
command.Flags().IntVar(&metricsPort, "metrics-port", common.DefaultPortArgoCDAPIServerMetrics, "Start metrics on given port")
command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", int(env.ParseDurationFromEnv("ARGOCD_SERVER_REPO_SERVER_TIMEOUT_SECONDS", 60*time.Second, 0, math.MaxInt32).Seconds()), "Repo server RPC call timeout seconds.")
command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", env.ParseNumFromEnv("ARGOCD_SERVER_REPO_SERVER_TIMEOUT_SECONDS", 60, 0, math.MaxInt64), "Repo server RPC call timeout seconds.")
command.Flags().StringVar(&frameOptions, "x-frame-options", env.StringFromEnv("ARGOCD_SERVER_X_FRAME_OPTIONS", "sameorigin"), "Set X-Frame-Options header in HTTP responses to `value`. To disable, set to \"\".")
command.Flags().BoolVar(&repoServerPlaintext, "repo-server-plaintext", env.ParseBoolFromEnv("ARGOCD_SERVER_REPO_SERVER_PLAINTEXT", false), "Use a plaintext client (non-TLS) to connect to repository server")
command.Flags().BoolVar(&repoServerStrictTLS, "repo-server-strict-tls", env.ParseBoolFromEnv("ARGOCD_SERVER_REPO_SERVER_STRICT_TLS", false), "Perform strict validation of TLS certificates when connecting to repo server")

View File

@@ -54,7 +54,19 @@ func NewAccountUpdatePasswordCommand(clientOpts *argocdclient.ClientOptions) *co
)
var command = &cobra.Command{
Use: "update-password",
Short: "Update password",
Short: "Update an account's password",
Long: `
This command can be used to update the password of the currently logged on
user, or an arbitrary local user account when the currently logged on user
has appropriate RBAC permissions to change other accounts.
`,
Example: `
# Update the current user's password
argocd account update-password
# Update the password for user foobar
argocd account update-password --account foobar
`,
Run: func(c *cobra.Command, args []string) {
if len(args) != 0 {
c.HelpFunc()(c, args)
@@ -67,16 +79,20 @@ func NewAccountUpdatePasswordCommand(clientOpts *argocdclient.ClientOptions) *co
userInfo := getCurrentAccount(acdClient)
if userInfo.Iss == sessionutil.SessionManagerClaimsIssuer && currentPassword == "" {
fmt.Print("*** Enter current password: ")
fmt.Printf("*** Enter password of currently logged in user (%s): ", userInfo.Username)
password, err := term.ReadPassword(int(os.Stdin.Fd()))
errors.CheckError(err)
currentPassword = string(password)
fmt.Print("\n")
}
if account == "" {
account = userInfo.Username
}
if newPassword == "" {
var err error
newPassword, err = cli.ReadAndConfirmPassword()
newPassword, err = cli.ReadAndConfirmPassword(account)
errors.CheckError(err)
}
@@ -111,7 +127,7 @@ func NewAccountUpdatePasswordCommand(clientOpts *argocdclient.ClientOptions) *co
},
}
command.Flags().StringVar(&currentPassword, "current-password", "", "current password you wish to change")
command.Flags().StringVar(&currentPassword, "current-password", "", "password of the currently logged on user")
command.Flags().StringVar(&newPassword, "new-password", "", "new password you want to update to")
command.Flags().StringVar(&account, "account", "", "an account name that should be updated. Defaults to current user account")
return command

View File

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

View File

@@ -10,6 +10,8 @@ import (
"sort"
"time"
"github.com/argoproj/argo-cd/v2/util/argo"
"github.com/ghodss/yaml"
"github.com/spf13/cobra"
apiv1 "k8s.io/api/core/v1"
@@ -88,9 +90,12 @@ func NewGenAppSpecCommand() *cobra.Command {
argocd admin app generate-spec ksane --repo https://github.com/argoproj/argocd-example-apps.git --path plugins/kasane --dest-namespace default --dest-server https://kubernetes.default.svc --config-management-plugin kasane
`,
Run: func(c *cobra.Command, args []string) {
app, err := cmdutil.ConstructApp(fileURL, appName, labels, annotations, args, appOpts, c.Flags())
apps, err := cmdutil.ConstructApps(fileURL, appName, labels, annotations, args, appOpts, c.Flags())
errors.CheckError(err)
if len(apps) > 1 {
errors.CheckError(fmt.Errorf("failed to generate spec, more than one application is not supported"))
}
app := apps[0]
if app.Name == "" {
c.HelpFunc()(c, args)
os.Exit(1)
@@ -329,11 +334,11 @@ func reconcileApplications(
settingsMgr := settings.NewSettingsManager(context.Background(), kubeClientset, namespace)
argoDB := db.NewDB(namespace, settingsMgr, kubeClientset)
appInformerFactory := appinformers.NewFilteredSharedInformerFactory(
appInformerFactory := appinformers.NewSharedInformerFactoryWithOptions(
appClientset,
1*time.Hour,
namespace,
func(options *v1.ListOptions) {},
appinformers.WithNamespace(namespace),
appinformers.WithTweakListOptions(func(options *v1.ListOptions) {}),
)
appInformer := appInformerFactory.Argoproj().V1alpha1().Applications().Informer()
@@ -350,7 +355,7 @@ func reconcileApplications(
return true
}, func(r *http.Request) error {
return nil
})
}, []string{})
if err != nil {
return nil, err
@@ -366,7 +371,7 @@ func reconcileApplications(
)
appStateManager := controller.NewAppStateManager(
argoDB, appClientset, repoServerClient, namespace, kubeutil.NewKubectl(), settingsMgr, stateCache, projInformer, server, cache, time.Second)
argoDB, appClientset, repoServerClient, namespace, kubeutil.NewKubectl(), settingsMgr, stateCache, projInformer, server, cache, time.Second, argo.NewResourceTracking())
appsList, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(context.Background(), v1.ListOptions{LabelSelector: selector})
if err != nil {
@@ -408,5 +413,5 @@ func reconcileApplications(
}
func newLiveStateCache(argoDB db.ArgoDB, appInformer kubecache.SharedIndexInformer, settingsMgr *settings.SettingsManager, server *metrics.MetricsServer) cache.LiveStateCache {
return cache.NewLiveStateCache(argoDB, appInformer, settingsMgr, kubeutil.NewKubectl(), server, func(managedByApp map[string]bool, ref apiv1.ObjectReference) {}, nil)
return cache.NewLiveStateCache(argoDB, appInformer, settingsMgr, kubeutil.NewKubectl(), server, func(managedByApp map[string]bool, ref apiv1.ObjectReference) {}, nil, argo.NewResourceTracking())
}

View File

@@ -10,7 +10,7 @@ import (
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/ghodss/yaml"
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
apierr "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -88,7 +88,11 @@ func NewExportCommand() *cobra.Command {
}
applicationSets, err := acdClients.applicationSets.List(context.Background(), v1.ListOptions{})
if err != nil && !apierr.IsNotFound(err) {
errors.CheckError(err)
if apierr.IsForbidden(err) {
log.Warn(err)
} else {
errors.CheckError(err)
}
}
if applicationSets != nil {
for _, appSet := range applicationSets.Items {
@@ -107,10 +111,11 @@ func NewExportCommand() *cobra.Command {
// NewImportCommand defines a new command for exporting Kubernetes and Argo CD resources.
func NewImportCommand() *cobra.Command {
var (
clientConfig clientcmd.ClientConfig
prune bool
dryRun bool
verbose bool
clientConfig clientcmd.ClientConfig
prune bool
dryRun bool
verbose bool
stopOperation bool
)
var command = cobra.Command{
Use: "import SOURCE",
@@ -176,6 +181,17 @@ func NewImportCommand() *cobra.Command {
for _, proj := range projects.Items {
pruneObjects[kube.ResourceKey{Group: "argoproj.io", Kind: "AppProject", Name: proj.GetName()}] = proj
}
applicationSets, err := acdClients.applicationSets.List(context.Background(), v1.ListOptions{})
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
log.Warnf("argoproj.io/ApplicationSet: %v\n", err)
} else {
errors.CheckError(err)
}
if applicationSets != nil {
for _, appSet := range applicationSets.Items {
pruneObjects[kube.ResourceKey{Group: "argoproj.io", Kind: "ApplicationSet", Name: appSet.GetName()}] = appSet
}
}
// Create or replace existing object
backupObjects, err := kube.SplitYAML(input)
@@ -199,22 +215,39 @@ func NewImportCommand() *cobra.Command {
dynClient = acdClients.applicationSets
}
if !exists {
isForbidden := false
if !dryRun {
_, err = dynClient.Create(context.Background(), bakObj, v1.CreateOptions{})
errors.CheckError(err)
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
isForbidden = true
log.Warnf("%s/%s %s: %v", gvk.Group, gvk.Kind, bakObj.GetName(), err)
} else {
errors.CheckError(err)
}
}
fmt.Printf("%s/%s %s created%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
} else if specsEqual(*bakObj, liveObj) {
if !isForbidden {
fmt.Printf("%s/%s %s created%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
}
} else if specsEqual(*bakObj, liveObj) && checkAppHasNoNeedToStopOperation(liveObj, stopOperation) {
if verbose {
fmt.Printf("%s/%s %s unchanged%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
}
} else {
isForbidden := false
if !dryRun {
newLive := updateLive(bakObj, &liveObj)
newLive := updateLive(bakObj, &liveObj, stopOperation)
_, err = dynClient.Update(context.Background(), newLive, v1.UpdateOptions{})
errors.CheckError(err)
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
isForbidden = true
log.Warnf("%s/%s %s: %v", gvk.Group, gvk.Kind, bakObj.GetName(), err)
} else {
errors.CheckError(err)
}
}
if !isForbidden {
fmt.Printf("%s/%s %s updated%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
}
fmt.Printf("%s/%s %s updated%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
}
}
@@ -239,16 +272,24 @@ func NewImportCommand() *cobra.Command {
}
}
}
case "ApplicationSet":
dynClient = acdClients.applicationSets
default:
logrus.Fatalf("Unexpected kind '%s' in prune list", key.Kind)
log.Fatalf("Unexpected kind '%s' in prune list", key.Kind)
}
isForbidden := false
if !dryRun {
err = dynClient.Delete(context.Background(), key.Name, v1.DeleteOptions{})
if err != nil && !apierr.IsNotFound(err) {
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
isForbidden = true
log.Warnf("%s/%s %s: %v\n", key.Group, key.Kind, key.Name, err)
} else {
errors.CheckError(err)
}
}
fmt.Printf("%s/%s %s pruned%s\n", key.Group, key.Kind, key.Name, dryRunMsg)
if !isForbidden {
fmt.Printf("%s/%s %s pruned%s\n", key.Group, key.Kind, key.Name, dryRunMsg)
}
} else {
fmt.Printf("%s/%s %s needs pruning\n", key.Group, key.Kind, key.Name)
}
@@ -260,10 +301,23 @@ func NewImportCommand() *cobra.Command {
command.Flags().BoolVar(&dryRun, "dry-run", false, "Print what will be performed")
command.Flags().BoolVar(&prune, "prune", false, "Prune secrets, applications and projects which do not appear in the backup")
command.Flags().BoolVar(&verbose, "verbose", false, "Verbose output (versus only changed output)")
command.Flags().BoolVar(&stopOperation, "stop-operation", false, "Stop any existing operations")
return &command
}
// check app has no need to stop operation.
func checkAppHasNoNeedToStopOperation(liveObj unstructured.Unstructured, stopOperation bool) bool {
if !stopOperation {
return true
}
switch liveObj.GetKind() {
case "Application":
return liveObj.Object["operation"] == nil
}
return true
}
// export writes the unstructured object and removes extraneous cruft from output before writing
func export(w io.Writer, un unstructured.Unstructured) {
name := un.GetName()
@@ -289,7 +343,7 @@ func export(w io.Writer, un unstructured.Unstructured) {
// updateLive replaces the live object's finalizers, spec, annotations, labels, and data from the
// backup object but leaves all other fields intact (status, other metadata, etc...)
func updateLive(bak, live *unstructured.Unstructured) *unstructured.Unstructured {
func updateLive(bak, live *unstructured.Unstructured, stopOperation bool) *unstructured.Unstructured {
newLive := live.DeepCopy()
newLive.SetAnnotations(bak.GetAnnotations())
newLive.SetLabels(bak.GetLabels())
@@ -304,6 +358,12 @@ func updateLive(bak, live *unstructured.Unstructured) *unstructured.Unstructured
if _, ok := bak.Object["status"]; ok {
newLive.Object["status"] = bak.Object["status"]
}
if stopOperation {
newLive.Object["operation"] = nil
}
case "ApplicationSet":
newLive.Object["spec"] = bak.Object["spec"]
}
return newLive
}

View File

@@ -35,6 +35,7 @@ import (
"github.com/argoproj/argo-cd/v2/util/glob"
kubeutil "github.com/argoproj/argo-cd/v2/util/kube"
"github.com/argoproj/argo-cd/v2/util/settings"
"github.com/argoproj/argo-cd/v2/util/text/label"
)
func NewClusterCommand(pathOpts *clientcmd.PathOptions) *cobra.Command {
@@ -508,6 +509,8 @@ func NewGenClusterConfigCommand(pathOpts *clientcmd.PathOptions) *cobra.Command
bearerToken string
generateToken bool
outputFormat string
labels []string
annotations []string
)
var command = &cobra.Command{
Use: "generate-spec CONTEXT",
@@ -561,7 +564,13 @@ func NewGenClusterConfigCommand(pathOpts *clientcmd.PathOptions) *cobra.Command
if clusterOpts.Name != "" {
contextName = clusterOpts.Name
}
clst := cmdutil.NewCluster(contextName, clusterOpts.Namespaces, clusterOpts.ClusterResources, conf, bearerToken, awsAuthConf, execProviderConf)
labelsMap, err := label.Parse(labels)
errors.CheckError(err)
annotationsMap, err := label.Parse(annotations)
errors.CheckError(err)
clst := cmdutil.NewCluster(contextName, clusterOpts.Namespaces, clusterOpts.ClusterResources, conf, bearerToken, awsAuthConf, execProviderConf, labelsMap, annotationsMap)
if clusterOpts.InCluster {
clst.Server = argoappv1.KubernetesInternalAPIServerAddr
}
@@ -590,6 +599,8 @@ func NewGenClusterConfigCommand(pathOpts *clientcmd.PathOptions) *cobra.Command
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "argocd-manager", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default \"%s\" SA will be used", clusterauth.ArgoCDManagerServiceAccount))
command.Flags().StringVar(&clusterOpts.SystemNamespace, "system-namespace", common.DefaultSystemNamespace, "Use different system namespace")
command.Flags().StringVarP(&outputFormat, "output", "o", "yaml", "Output format. One of: json|yaml")
command.Flags().StringArrayVar(&labels, "label", nil, "Set metadata labels (e.g. --label key=value)")
command.Flags().StringArrayVar(&annotations, "annotation", nil, "Set metadata annotations (e.g. --annotation key=value)")
cmdutil.AddClusterFlags(command, &clusterOpts)
return command
}

View File

@@ -13,18 +13,20 @@ import (
func NewDashboardCommand() *cobra.Command {
var (
port int
port int
address string
)
cmd := &cobra.Command{
Use: "dashboard",
Short: "Starts Argo CD Web UI locally",
Run: func(cmd *cobra.Command, args []string) {
println(fmt.Sprintf("Argo CD UI is available at http://localhost:%d", port))
println(fmt.Sprintf("Argo CD UI is available at http://%s:%d", address, port))
<-context.Background().Done()
},
}
clientOpts := &apiclient.ClientOptions{Core: true}
headless.InitCommand(cmd, clientOpts, &port)
headless.InitCommand(cmd, clientOpts, &port, &address)
cmd.Flags().IntVar(&port, "port", common.DefaultPortAPIServer, "Listen on given port")
cmd.Flags().StringVar(&address, "address", common.DefaultAddressAPIServer, "Listen on given address")
return cmd
}

View File

@@ -0,0 +1,51 @@
package admin
import (
"log"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
service "github.com/argoproj/argo-cd/v2/util/notification/argocd"
settings "github.com/argoproj/argo-cd/v2/util/notification/settings"
"github.com/argoproj/notifications-engine/pkg/cmd"
"github.com/spf13/cobra"
)
var (
applications = schema.GroupVersionResource{Group: "argoproj.io", Version: "v1alpha1", Resource: "applications"}
)
func NewNotificationsCommand() *cobra.Command {
var (
argocdRepoServer string
argocdRepoServerPlaintext bool
argocdRepoServerStrictTLS bool
)
var argocdService service.Service
toolsCommand := cmd.NewToolsCommand(
"notifications",
"notifications",
applications,
settings.GetFactorySettings(argocdService, "argocd-notifications-secret", "argocd-notifications-cm"), func(clientConfig clientcmd.ClientConfig) {
k8sCfg, err := clientConfig.ClientConfig()
if err != nil {
log.Fatalf("Failed to parse k8s config: %v", err)
}
ns, _, err := clientConfig.Namespace()
if err != nil {
log.Fatalf("Failed to parse k8s config: %v", err)
}
argocdService, err = service.NewArgoCDService(kubernetes.NewForConfigOrDie(k8sCfg), ns, argocdRepoServer, argocdRepoServerPlaintext, argocdRepoServerStrictTLS)
if err != nil {
log.Fatalf("Failed to initalize Argo CD service: %v", err)
}
})
toolsCommand.PersistentFlags().StringVar(&argocdRepoServer, "argocd-repo-server", "argocd-repo-server:8081", "Argo CD repo server address")
toolsCommand.PersistentFlags().BoolVar(&argocdRepoServerPlaintext, "argocd-repo-server-plaintext", false, "Use a plaintext client (non-TLS) to connect to repository server")
toolsCommand.PersistentFlags().BoolVar(&argocdRepoServerStrictTLS, "argocd-repo-server-strict-tls", false, "Perform strict validation of TLS certificates when connecting to repo server")
return toolsCommand
}

View File

@@ -401,11 +401,15 @@ argocd admin settings resource-overrides ignore-differences ./deploy.yaml --argo
executeResourceOverrideCommand(cmdCtx, args, func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride) {
gvk := res.GroupVersionKind()
if len(override.IgnoreDifferences.JSONPointers) == 0 {
if len(override.IgnoreDifferences.JSONPointers) == 0 && len(override.IgnoreDifferences.JQPathExpressions) == 0 {
_, _ = fmt.Printf("Ignore differences are not configured for '%s/%s'\n", gvk.Group, gvk.Kind)
return
}
// This normalizer won't verify 'managedFieldsManagers' ignore difference
// configurations. This requires access to live resources which is not the
// purpose of this command. This will just apply jsonPointers and
// jqPathExpressions configurations.
normalizer, err := normalizers.NewIgnoreNormalizer(nil, overrides)
errors.CheckError(err)

View File

@@ -14,7 +14,8 @@ import (
"time"
"unicode/utf8"
"github.com/argoproj/gitops-engine/pkg/diff"
"github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/sync/hook"
"github.com/argoproj/gitops-engine/pkg/sync/ignore"
@@ -44,11 +45,11 @@ import (
repoapiclient "github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/reposerver/repository"
"github.com/argoproj/argo-cd/v2/util/argo"
argodiff "github.com/argoproj/argo-cd/v2/util/argo/diff"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/util/errors"
"github.com/argoproj/argo-cd/v2/util/git"
argoio "github.com/argoproj/argo-cd/v2/util/io"
argokube "github.com/argoproj/argo-cd/v2/util/kube"
"github.com/argoproj/argo-cd/v2/util/templates"
"github.com/argoproj/argo-cd/v2/util/text/label"
)
@@ -92,6 +93,7 @@ func NewApplicationCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman
command.AddCommand(NewApplicationEditCommand(clientOpts))
command.AddCommand(NewApplicationPatchCommand(clientOpts))
command.AddCommand(NewApplicationPatchResourceCommand(clientOpts))
command.AddCommand(NewApplicationDeleteResourceCommand(clientOpts))
command.AddCommand(NewApplicationResourceActionsCommand(clientOpts))
command.AddCommand(NewApplicationListResourcesCommand(clientOpts))
command.AddCommand(NewApplicationLogsCommand(clientOpts))
@@ -133,24 +135,27 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.
Run: func(c *cobra.Command, args []string) {
argocdClient := argocdclient.NewClientOrDie(clientOpts)
app, err := cmdutil.ConstructApp(fileURL, appName, labels, annotations, args, appOpts, c.Flags())
apps, err := cmdutil.ConstructApps(fileURL, appName, labels, annotations, args, appOpts, c.Flags())
errors.CheckError(err)
if app.Name == "" {
c.HelpFunc()(c, args)
os.Exit(1)
for _, app := range apps {
if app.Name == "" {
c.HelpFunc()(c, args)
os.Exit(1)
}
conn, appIf := argocdClient.NewApplicationClientOrDie()
defer argoio.Close(conn)
appCreateRequest := applicationpkg.ApplicationCreateRequest{
Application: *app,
Upsert: &upsert,
Validate: &appOpts.Validate,
}
created, err := appIf.Create(context.Background(), &appCreateRequest)
errors.CheckError(err)
fmt.Printf("application '%s' created\n", created.ObjectMeta.Name)
}
conn, appIf := argocdClient.NewApplicationClientOrDie()
defer argoio.Close(conn)
appCreateRequest := applicationpkg.ApplicationCreateRequest{
Application: *app,
Upsert: &upsert,
Validate: &appOpts.Validate,
}
created, err := appIf.Create(context.Background(), &appCreateRequest)
errors.CheckError(err)
fmt.Printf("application '%s' created\n", created.ObjectMeta.Name)
},
}
command.Flags().StringVar(&appName, "name", "", "A name for the app, ignored if a file is set (DEPRECATED)")
@@ -278,6 +283,7 @@ func NewApplicationLogsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
untilTime string
filter string
container string
previous bool
)
var command = &cobra.Command{
Use: "logs APPNAME",
@@ -307,6 +313,7 @@ func NewApplicationLogsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
UntilTime: &untilTime,
Filter: &filter,
Container: container,
Previous: previous,
})
if err != nil {
log.Fatalf("failed to get pod logs: %v", err)
@@ -348,6 +355,7 @@ func NewApplicationLogsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
command.Flags().StringVar(&untilTime, "until-time", "", "Show logs until this time")
command.Flags().StringVar(&filter, "filter", "", "Show logs contain this string")
command.Flags().StringVar(&container, "container", "", "Optional container name")
command.Flags().BoolVarP(&previous, "previous", "p", false, "Specify if the previously terminated container logs should be returned")
return command
}
@@ -553,15 +561,16 @@ func NewApplicationSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
// NewApplicationUnsetCommand returns a new instance of an `argocd app unset` command
func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
parameters []string
valuesLiteral bool
valuesFiles []string
nameSuffix bool
namePrefix bool
kustomizeVersion bool
kustomizeImages []string
pluginEnvs []string
appOpts cmdutil.AppOptions
parameters []string
valuesLiteral bool
valuesFiles []string
ignoreMissingValueFiles bool
nameSuffix bool
namePrefix bool
kustomizeVersion bool
kustomizeImages []string
pluginEnvs []string
appOpts cmdutil.AppOptions
)
var command = &cobra.Command{
Use: "unset APPNAME parameters",
@@ -638,7 +647,7 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
}
}
if app.Spec.Source.Helm != nil {
if len(parameters) == 0 && len(valuesFiles) == 0 && !valuesLiteral {
if len(parameters) == 0 && len(valuesFiles) == 0 && !valuesLiteral && !ignoreMissingValueFiles {
c.HelpFunc()(c, args)
os.Exit(1)
}
@@ -666,6 +675,14 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
}
}
}
if ignoreMissingValueFiles {
app.Spec.Source.Helm.IgnoreMissingValueFiles = false
updated = true
}
if app.Spec.Source.Helm.PassCredentials {
app.Spec.Source.Helm.PassCredentials = false
updated = true
}
}
if app.Spec.Source.Plugin != nil {
@@ -675,7 +692,7 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
}
for _, env := range pluginEnvs {
err = app.Spec.Source.Plugin.RemoveEnvEntry(env)
if err != nil {
if err == nil {
updated = true
}
}
@@ -697,6 +714,7 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
command.Flags().StringArrayVarP(&parameters, "parameter", "p", []string{}, "Unset a parameter override (e.g. -p guestbook=image)")
command.Flags().StringArrayVar(&valuesFiles, "values", []string{}, "Unset one or more Helm values files")
command.Flags().BoolVar(&valuesLiteral, "values-literal", false, "Unset literal Helm values block")
command.Flags().BoolVar(&ignoreMissingValueFiles, "ignore-missing-value-files", false, "Unset the helm ignore-missing-value-files option (revert to false)")
command.Flags().BoolVar(&nameSuffix, "namesuffix", false, "Kustomize namesuffix")
command.Flags().BoolVar(&namePrefix, "nameprefix", false, "Kustomize nameprefix")
command.Flags().BoolVar(&kustomizeVersion, "kustomize-version", false, "Kustomize version")
@@ -731,9 +749,9 @@ func liveObjects(resources []*argoappv1.ResourceDiff) ([]*unstructured.Unstructu
return objs, nil
}
func getLocalObjects(app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, kustomizeOptions *argoappv1.KustomizeOptions,
configManagementPlugins []*argoappv1.ConfigManagementPlugin) []*unstructured.Unstructured {
manifestStrings := getLocalObjectsString(app, local, localRepoRoot, appLabelKey, kubeVersion, kustomizeOptions, configManagementPlugins)
func getLocalObjects(app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions,
configManagementPlugins []*argoappv1.ConfigManagementPlugin, trackingMethod string) []*unstructured.Unstructured {
manifestStrings := getLocalObjectsString(app, local, localRepoRoot, appLabelKey, kubeVersion, apiVersions, kustomizeOptions, configManagementPlugins, trackingMethod)
objs := make([]*unstructured.Unstructured, len(manifestStrings))
for i := range manifestStrings {
obj := unstructured.Unstructured{}
@@ -744,10 +762,10 @@ func getLocalObjects(app *argoappv1.Application, local, localRepoRoot, appLabelK
return objs
}
func getLocalObjectsString(app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, kustomizeOptions *argoappv1.KustomizeOptions,
configManagementPlugins []*argoappv1.ConfigManagementPlugin) []string {
func getLocalObjectsString(app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions,
configManagementPlugins []*argoappv1.ConfigManagementPlugin, trackingMethod string) []string {
res, err := repository.GenerateManifests(local, localRepoRoot, app.Spec.Source.TargetRevision, &repoapiclient.ManifestRequest{
res, err := repository.GenerateManifests(context.Background(), local, localRepoRoot, app.Spec.Source.TargetRevision, &repoapiclient.ManifestRequest{
Repo: &argoappv1.Repository{Repo: app.Spec.Source.RepoURL},
AppLabelKey: appLabelKey,
AppName: app.Name,
@@ -755,8 +773,10 @@ func getLocalObjectsString(app *argoappv1.Application, local, localRepoRoot, app
ApplicationSource: &app.Spec.Source,
KustomizeOptions: kustomizeOptions,
KubeVersion: kubeVersion,
ApiVersions: apiVersions,
Plugins: configManagementPlugins,
}, true)
TrackingMethod: trackingMethod,
}, true, &git.NoopCredsStore{})
errors.CheckError(err)
return res.Manifests
@@ -841,7 +861,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
defer argoio.Close(conn)
cluster, err := clusterIf.Get(context.Background(), &clusterpkg.ClusterQuery{Name: app.Spec.Destination.Name, Server: app.Spec.Destination.Server})
errors.CheckError(err)
localObjs := groupObjsByKey(getLocalObjects(app, local, localRepoRoot, argoSettings.AppLabelKey, cluster.ServerVersion, argoSettings.KustomizeOptions, argoSettings.ConfigManagementPlugins), liveObjs, app.Spec.Destination.Namespace)
localObjs := groupObjsByKey(getLocalObjects(app, local, localRepoRoot, argoSettings.AppLabelKey, cluster.Info.ServerVersion, cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.ConfigManagementPlugins, argoSettings.TrackingMethod), liveObjs, app.Spec.Destination.Namespace)
items = groupObjsForDiff(resources, localObjs, items, argoSettings, appName)
} else if revision != "" {
var unstructureds []*unstructured.Unstructured
@@ -883,10 +903,18 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
val := argoSettings.ResourceOverrides[k]
overrides[k] = *val
}
normalizer, err := argo.NewDiffNormalizer(app.Spec.IgnoreDifferences, overrides)
// TODO remove hardcoded IgnoreAggregatedRoles and retrieve the
// compareOptions in the protobuf
ignoreAggregatedRoles := false
diffConfig, err := argodiff.NewDiffConfigBuilder().
WithDiffSettings(app.Spec.IgnoreDifferences, overrides, ignoreAggregatedRoles).
WithTracking(argoSettings.AppLabelKey, argoSettings.TrackingMethod).
WithNoCache().
Build()
errors.CheckError(err)
diffRes, err := diff.Diff(item.target, item.live, diff.WithNormalizer(normalizer))
diffRes, err := argodiff.StateDiff(item.live, item.target, diffConfig)
errors.CheckError(err)
if diffRes.Modified || item.target == nil || item.live == nil {
@@ -923,6 +951,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
}
func groupObjsForDiff(resources *application.ManagedResourcesResponse, objs map[kube.ResourceKey]*unstructured.Unstructured, items []objKeyLiveTarget, argoSettings *settings.Settings, appName string) []objKeyLiveTarget {
resourceTracking := argo.NewResourceTracking()
for _, res := range resources.Items {
var live = &unstructured.Unstructured{}
err := json.Unmarshal([]byte(res.NormalizedLiveState), &live)
@@ -936,7 +965,7 @@ func groupObjsForDiff(resources *application.ManagedResourcesResponse, objs map[
}
if local, ok := objs[key]; ok || live != nil {
if local != nil && !kube.IsCRD(local) {
err = argokube.SetAppInstanceLabel(local, argoSettings.AppLabelKey, appName)
err = resourceTracking.SetAppInstance(local, argoSettings.AppLabelKey, appName, "", argoappv1.TrackingMethod(argoSettings.GetTrackingMethod()))
errors.CheckError(err)
}
@@ -1269,6 +1298,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
timeout uint
strategy string
force bool
replace bool
async bool
retryLimit int64
retryBackoffDuration time.Duration
@@ -1376,18 +1406,35 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
cluster, err := clusterIf.Get(context.Background(), &clusterpkg.ClusterQuery{Name: app.Spec.Destination.Name, Server: app.Spec.Destination.Server})
errors.CheckError(err)
argoio.Close(conn)
localObjsStrings = getLocalObjectsString(app, local, localRepoRoot, argoSettings.AppLabelKey, cluster.ServerVersion, argoSettings.KustomizeOptions, argoSettings.ConfigManagementPlugins)
localObjsStrings = getLocalObjectsString(app, local, localRepoRoot, argoSettings.AppLabelKey, cluster.Info.ServerVersion, cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.ConfigManagementPlugins, argoSettings.TrackingMethod)
}
syncOptionsFactory := func() *applicationpkg.SyncOptions {
syncOptions := applicationpkg.SyncOptions{}
items := make([]string, 0)
if replace {
items = append(items, common.SyncOptionReplace)
}
if len(items) == 0 {
// for prevent send even empty array if not need
return nil
}
syncOptions.Items = items
return &syncOptions
}
syncReq := applicationpkg.ApplicationSyncRequest{
Name: &appName,
DryRun: dryRun,
Revision: revision,
Resources: selectedResources,
Prune: prune,
Manifests: localObjsStrings,
Infos: getInfos(infos),
Name: &appName,
DryRun: dryRun,
Revision: revision,
Resources: selectedResources,
Prune: prune,
Manifests: localObjsStrings,
Infos: getInfos(infos),
SyncOptions: syncOptionsFactory(),
}
switch strategy {
case "apply":
syncReq.Strategy = &argoappv1.SyncStrategy{Apply: &argoappv1.SyncStrategyApply{}}
@@ -1444,6 +1491,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
command.Flags().Int64Var(&retryBackoffFactor, "retry-backoff-factor", argoappv1.DefaultSyncRetryFactor, "Factor multiplies the base duration after each failed retry")
command.Flags().StringVar(&strategy, "strategy", "", "Sync strategy (one of: apply|hook)")
command.Flags().BoolVar(&force, "force", false, "Use a force apply")
command.Flags().BoolVar(&replace, "replace", false, "Use a kubectl create/replace instead apply")
command.Flags().BoolVar(&async, "async", false, "Do not wait for application to sync before continuing")
command.Flags().StringVar(&local, "local", "", "Path to a local directory. When this flag is present no git queries will be made")
command.Flags().StringVar(&localRepoRoot, "local-repo-root", "/", "Path to the repository root. Used together with --local allows setting the repository root")
@@ -1814,6 +1862,23 @@ func NewApplicationHistoryCommand(clientOpts *argocdclient.ClientOptions) *cobra
return command
}
func findRevisionHistory(application *argoappv1.Application, historyId int64) (*argoappv1.RevisionHistory, error) {
// in case if history id not passed and need fetch previous history revision
if historyId == -1 {
l := len(application.Status.History)
if l < 2 {
return nil, fmt.Errorf("Application '%s' should have at least two successful deployments", application.ObjectMeta.Name)
}
return &application.Status.History[l-2], nil
}
for _, di := range application.Status.History {
if di.ID == historyId {
return &di, nil
}
}
return nil, fmt.Errorf("Application '%s' does not have deployment id '%d' in history\n", application.ObjectMeta.Name, historyId)
}
// NewApplicationRollbackCommand returns a new instance of an `argocd app rollback` command
func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
@@ -1821,36 +1886,33 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr
timeout uint
)
var command = &cobra.Command{
Use: "rollback APPNAME ID",
Short: "Rollback application to a previous deployed version by History ID",
Use: "rollback APPNAME [ID]",
Short: "Rollback application to a previous deployed version by History ID, omitted will Rollback to the previous version",
Run: func(c *cobra.Command, args []string) {
if len(args) != 2 {
if len(args) == 0 {
c.HelpFunc()(c, args)
os.Exit(1)
}
appName := args[0]
depID, err := strconv.Atoi(args[1])
errors.CheckError(err)
var err error
depID := -1
if len(args) > 1 {
depID, err = strconv.Atoi(args[1])
errors.CheckError(err)
}
acdClient := argocdclient.NewClientOrDie(clientOpts)
conn, appIf := acdClient.NewApplicationClientOrDie()
defer argoio.Close(conn)
ctx := context.Background()
app, err := appIf.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName})
errors.CheckError(err)
var depInfo *argoappv1.RevisionHistory
for _, di := range app.Status.History {
if di.ID == int64(depID) {
depInfo = &di
break
}
}
if depInfo == nil {
log.Fatalf("Application '%s' does not have deployment id '%d' in history\n", app.ObjectMeta.Name, depID)
}
depInfo, err := findRevisionHistory(app, int64(depID))
errors.CheckError(err)
_, err = appIf.Rollback(ctx, &applicationpkg.ApplicationRollbackRequest{
Name: &appName,
ID: int64(depID),
ID: depInfo.ID,
Prune: prune,
})
errors.CheckError(err)
@@ -2188,3 +2250,59 @@ func NewApplicationPatchResourceCommand(clientOpts *argocdclient.ClientOptions)
return command
}
func NewApplicationDeleteResourceCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var resourceName string
var namespace string
var kind string
var group string
var force bool
var orphan bool
var all bool
command := &cobra.Command{
Use: "delete-resource APPNAME",
Short: "Delete resource in an application",
}
command.Flags().StringVar(&resourceName, "resource-name", "", "Name of resource")
command.Flags().StringVar(&kind, "kind", "", "Kind")
err := command.MarkFlagRequired("kind")
errors.CheckError(err)
command.Flags().StringVar(&group, "group", "", "Group")
command.Flags().StringVar(&namespace, "namespace", "", "Namespace")
command.Flags().BoolVar(&force, "force", false, "Indicates whether to orphan the dependents of the deleted resource")
command.Flags().BoolVar(&orphan, "orphan", false, "Indicates whether to force delete the resource")
command.Flags().BoolVar(&all, "all", false, "Indicates whether to patch multiple matching of resources")
command.Run = func(c *cobra.Command, args []string) {
if len(args) != 1 {
c.HelpFunc()(c, args)
os.Exit(1)
}
appName := args[0]
conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie()
defer argoio.Close(conn)
ctx := context.Background()
resources, err := appIf.ManagedResources(ctx, &applicationpkg.ResourcesQuery{ApplicationName: &appName})
errors.CheckError(err)
objectsToDelete := filterResources(command, resources.Items, group, kind, namespace, resourceName, all)
for i := range objectsToDelete {
obj := objectsToDelete[i]
gvk := obj.GroupVersionKind()
_, err = appIf.DeleteResource(ctx, &applicationpkg.ApplicationResourceDeleteRequest{
Name: &appName,
Namespace: obj.GetNamespace(),
ResourceName: obj.GetName(),
Version: gvk.Version,
Group: gvk.Group,
Kind: gvk.Kind,
Force: &force,
Orphan: &orphan,
})
errors.CheckError(err)
log.Infof("Resource '%s' deleted", obj.GetName())
}
}
return command
}

View File

@@ -0,0 +1,163 @@
package commands
import (
"testing"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
func TestFindRevisionHistoryWithoutPassedId(t *testing.T) {
histories := v1alpha1.RevisionHistories{}
histories = append(histories, v1alpha1.RevisionHistory{ID: 1})
histories = append(histories, v1alpha1.RevisionHistory{ID: 2})
histories = append(histories, v1alpha1.RevisionHistory{ID: 3})
status := v1alpha1.ApplicationStatus{
Resources: nil,
Sync: v1alpha1.SyncStatus{},
Health: v1alpha1.HealthStatus{},
History: histories,
Conditions: nil,
ReconciledAt: nil,
OperationState: nil,
ObservedAt: nil,
SourceType: "",
Summary: v1alpha1.ApplicationSummary{},
}
application := v1alpha1.Application{
Status: status,
}
history, err := findRevisionHistory(&application, -1)
if err != nil {
t.Fatal("Find revision history should fail without errors")
}
if history == nil {
t.Fatal("History should be found")
}
}
func TestFindRevisionHistoryWithoutPassedIdAndEmptyHistoryList(t *testing.T) {
histories := v1alpha1.RevisionHistories{}
status := v1alpha1.ApplicationStatus{
Resources: nil,
Sync: v1alpha1.SyncStatus{},
Health: v1alpha1.HealthStatus{},
History: histories,
Conditions: nil,
ReconciledAt: nil,
OperationState: nil,
ObservedAt: nil,
SourceType: "",
Summary: v1alpha1.ApplicationSummary{},
}
application := v1alpha1.Application{
Status: status,
}
history, err := findRevisionHistory(&application, -1)
if err == nil {
t.Fatal("Find revision history should fail with errors")
}
if history != nil {
t.Fatal("History should be empty")
}
if err.Error() != "Application '' should have at least two successful deployments" {
t.Fatal("Find revision history should fail with correct error message")
}
}
func TestFindRevisionHistoryWithPassedId(t *testing.T) {
histories := v1alpha1.RevisionHistories{}
histories = append(histories, v1alpha1.RevisionHistory{ID: 1})
histories = append(histories, v1alpha1.RevisionHistory{ID: 2})
histories = append(histories, v1alpha1.RevisionHistory{ID: 3, Revision: "123"})
status := v1alpha1.ApplicationStatus{
Resources: nil,
Sync: v1alpha1.SyncStatus{},
Health: v1alpha1.HealthStatus{},
History: histories,
Conditions: nil,
ReconciledAt: nil,
OperationState: nil,
ObservedAt: nil,
SourceType: "",
Summary: v1alpha1.ApplicationSummary{},
}
application := v1alpha1.Application{
Status: status,
}
history, err := findRevisionHistory(&application, 3)
if err != nil {
t.Fatal("Find revision history should fail without errors")
}
if history == nil {
t.Fatal("History should be found")
}
if history.Revision != "123" {
t.Fatal("Failed to find correct history with correct revision")
}
}
func TestFindRevisionHistoryWithPassedIdThatNotExist(t *testing.T) {
histories := v1alpha1.RevisionHistories{}
histories = append(histories, v1alpha1.RevisionHistory{ID: 1})
histories = append(histories, v1alpha1.RevisionHistory{ID: 2})
histories = append(histories, v1alpha1.RevisionHistory{ID: 3, Revision: "123"})
status := v1alpha1.ApplicationStatus{
Resources: nil,
Sync: v1alpha1.SyncStatus{},
Health: v1alpha1.HealthStatus{},
History: histories,
Conditions: nil,
ReconciledAt: nil,
OperationState: nil,
ObservedAt: nil,
SourceType: "",
Summary: v1alpha1.ApplicationSummary{},
}
application := v1alpha1.Application{
Status: status,
}
history, err := findRevisionHistory(&application, 4)
if err == nil {
t.Fatal("Find revision history should fail with errors")
}
if history != nil {
t.Fatal("History should be not found")
}
if err.Error() != "Application '' does not have deployment id '4' in history\n" {
t.Fatal("Find revision history should fail with correct error message")
}
}

View File

@@ -4,13 +4,18 @@ import (
"context"
"fmt"
"os"
"regexp"
"strings"
"text/tabwriter"
"github.com/mattn/go-isatty"
"k8s.io/client-go/kubernetes"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/util/text/label"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
@@ -18,7 +23,6 @@ import (
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
clusterpkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/cluster"
argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/util/clusterauth"
"github.com/argoproj/argo-cd/v2/util/errors"
"github.com/argoproj/argo-cd/v2/util/io"
@@ -60,6 +64,8 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
var (
clusterOpts cmdutil.ClusterOptions
skipConfirmation bool
labels []string
annotations []string
)
var command = &cobra.Command{
Use: "add CONTEXT",
@@ -79,15 +85,6 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
log.Fatalf("Context %s does not exist in kubeconfig", contextName)
}
isTerminal := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
if isTerminal && !skipConfirmation {
message := fmt.Sprintf("WARNING: This will create a service account `argocd-manager` on the cluster referenced by context `%s` with full cluster level admin privileges. Do you want to continue [y/N]? ", contextName)
if !cli.AskToProceed(message) {
os.Exit(1)
}
}
overrides := clientcmd.ConfigOverrides{
Context: *clstContext,
}
@@ -118,22 +115,39 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
if clusterOpts.ServiceAccount != "" {
managerBearerToken, err = clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount)
} else {
isTerminal := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
if isTerminal && !skipConfirmation {
message := fmt.Sprintf("WARNING: This will create a service account `argocd-manager` on the cluster referenced by context `%s` with full cluster level admin privileges. Do you want to continue [y/N]? ", contextName)
if !cli.AskToProceed(message) {
os.Exit(1)
}
}
managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, clusterOpts.SystemNamespace, clusterOpts.Namespaces)
}
errors.CheckError(err)
}
labelsMap, err := label.Parse(labels)
errors.CheckError(err)
annotationsMap, err := label.Parse(annotations)
errors.CheckError(err)
conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie()
defer io.Close(conn)
if clusterOpts.Name != "" {
contextName = clusterOpts.Name
}
clst := cmdutil.NewCluster(contextName, clusterOpts.Namespaces, clusterOpts.ClusterResources, conf, managerBearerToken, awsAuthConf, execProviderConf)
clst := cmdutil.NewCluster(contextName, clusterOpts.Namespaces, clusterOpts.ClusterResources, conf, managerBearerToken, awsAuthConf, execProviderConf, labelsMap, annotationsMap)
if clusterOpts.InCluster {
clst.Server = argoappv1.KubernetesInternalAPIServerAddr
}
if clusterOpts.Shard >= 0 {
clst.Shard = &clusterOpts.Shard
}
if clusterOpts.Project != "" {
clst.Project = clusterOpts.Project
}
clstCreateReq := clusterpkg.ClusterCreateRequest{
Cluster: clst,
Upsert: clusterOpts.Upsert,
@@ -148,6 +162,8 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default \"%s\" SA will be created", clusterauth.ArgoCDManagerServiceAccount))
command.Flags().StringVar(&clusterOpts.SystemNamespace, "system-namespace", common.DefaultSystemNamespace, "Use different system namespace")
command.Flags().BoolVarP(&skipConfirmation, "yes", "y", false, "Skip explicit confirmation")
command.Flags().StringArrayVar(&labels, "label", nil, "Set metadata labels (e.g. --label key=value)")
command.Flags().StringArrayVar(&annotations, "annotation", nil, "Set metadata annotations (e.g. --annotation key=value)")
cmdutil.AddClusterFlags(command, &clusterOpts)
return command
}
@@ -158,9 +174,10 @@ func NewClusterGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
output string
)
var command = &cobra.Command{
Use: "get SERVER",
Short: "Get cluster information",
Example: `argocd cluster get https://12.34.567.89`,
Use: "get SERVER/NAME",
Short: "Get cluster information",
Example: `argocd cluster get https://12.34.567.89
argocd cluster get in-cluster`,
Run: func(c *cobra.Command, args []string) {
if len(args) == 0 {
c.HelpFunc()(c, args)
@@ -169,8 +186,8 @@ func NewClusterGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie()
defer io.Close(conn)
clusters := make([]argoappv1.Cluster, 0)
for _, clusterName := range args {
clst, err := clusterIf.Get(context.Background(), &clusterpkg.ClusterQuery{Server: clusterName})
for _, clusterSelector := range args {
clst, err := clusterIf.Get(context.Background(), getQueryBySelector(clusterSelector))
errors.CheckError(err)
clusters = append(clusters, *clst)
}
@@ -257,17 +274,29 @@ func NewClusterRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comm
// Print table of cluster information
func printClusterTable(clusters []argoappv1.Cluster) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
_, _ = fmt.Fprintf(w, "SERVER\tNAME\tVERSION\tSTATUS\tMESSAGE\n")
_, _ = fmt.Fprintf(w, "SERVER\tNAME\tVERSION\tSTATUS\tMESSAGE\tPROJECT\n")
for _, c := range clusters {
server := c.Server
if len(c.Namespaces) > 0 {
server = fmt.Sprintf("%s (%d namespaces)", c.Server, len(c.Namespaces))
}
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", server, c.Name, c.ServerVersion, c.ConnectionState.Status, c.ConnectionState.Message)
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n", server, c.Name, c.ServerVersion, c.ConnectionState.Status, c.ConnectionState.Message, c.Project)
}
_ = w.Flush()
}
// Returns cluster query for getting cluster depending on the cluster selector
func getQueryBySelector(clusterSelector string) *clusterpkg.ClusterQuery {
var query clusterpkg.ClusterQuery
isServer, err := regexp.MatchString(`^https?://`, clusterSelector)
if isServer || err != nil {
query.Server = clusterSelector
} else {
query.Name = clusterSelector
}
return &query
}
// Print list of cluster servers
func printClusterServers(clusters []argoappv1.Cluster) {
for _, c := range clusters {

View File

@@ -6,8 +6,24 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
)
func Test_getQueryBySelector(t *testing.T) {
query := getQueryBySelector("my-cluster")
assert.Equal(t, query.Name, "my-cluster")
assert.Equal(t, query.Server, "")
query = getQueryBySelector("http://my-server")
assert.Equal(t, query.Name, "")
assert.Equal(t, query.Server, "http://my-server")
query = getQueryBySelector("https://my-server")
assert.Equal(t, query.Name, "")
assert.Equal(t, query.Server, "https://my-server")
}
func Test_printClusterTable(t *testing.T) {
printClusterTable([]v1alpha1.Cluster{
{

View File

@@ -18,6 +18,7 @@ import (
type forwardCacheClient struct {
namespace string
context string
init sync.Once
client cache.CacheClient
err error
@@ -25,7 +26,9 @@ type forwardCacheClient struct {
func (c *forwardCacheClient) doLazy(action func(client cache.CacheClient) error) error {
c.init.Do(func() {
overrides := clientcmd.ConfigOverrides{}
overrides := clientcmd.ConfigOverrides{
CurrentContext: c.context,
}
redisPort, err := kubeutil.PortForward(6379, c.namespace, &overrides,
"app.kubernetes.io/name=argocd-redis-ha-haproxy", "app.kubernetes.io/name=argocd-redis")
if err != nil {
@@ -74,6 +77,7 @@ func (c *forwardCacheClient) NotifyUpdated(key string) error {
type forwardRepoClientset struct {
namespace string
context string
init sync.Once
repoClientset repoapiclient.Clientset
err error
@@ -81,7 +85,9 @@ type forwardRepoClientset struct {
func (c *forwardRepoClientset) NewRepoServerClient() (io.Closer, repoapiclient.RepoServerServiceClient, error) {
c.init.Do(func() {
overrides := clientcmd.ConfigOverrides{}
overrides := clientcmd.ConfigOverrides{
CurrentContext: c.context,
}
repoServerPort, err := kubeutil.PortForward(8081, c.namespace, &overrides, "app.kubernetes.io/name=argocd-repo-server")
if err != nil {
c.err = err

View File

@@ -12,10 +12,11 @@ import (
"github.com/golang/protobuf/ptypes/empty"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/utils/pointer"
argoapi "github.com/argoproj/argo-cd/v2/pkg/apiclient"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
@@ -27,6 +28,8 @@ import (
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/util/io"
"github.com/argoproj/argo-cd/v2/util/localconfig"
flag "github.com/spf13/pflag"
)
func testAPI(clientOpts *argoapi.ClientOptions) error {
@@ -43,21 +46,27 @@ func testAPI(clientOpts *argoapi.ClientOptions) error {
return err
}
func addKubectlFlagsToCmd(cmd *cobra.Command) clientcmd.ClientConfig {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig
overrides := clientcmd.ConfigOverrides{}
kflags := clientcmd.RecommendedConfigOverrideFlags("")
cmd.Flags().StringVar(&loadingRules.ExplicitPath, "kubeconfig", "", "Path to a kube config. Only required if out-of-cluster")
clientcmd.BindOverrideFlags(&overrides, cmd.PersistentFlags(), kflags)
return clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, &overrides, os.Stdin)
func retrieveContextIfChanged(contextFlag *flag.Flag) string {
if contextFlag != nil && contextFlag.Changed {
return contextFlag.Value.String()
}
return ""
}
// InitCommand allows executing command in a headless mode: on the fly starts Argo CD API server and
// changes provided client options to use started API server port
func InitCommand(cmd *cobra.Command, clientOpts *argoapi.ClientOptions, port *int) *cobra.Command {
func InitCommand(cmd *cobra.Command, clientOpts *argoapi.ClientOptions, port *int, address *string) *cobra.Command {
ctx, cancel := context.WithCancel(context.Background())
clientConfig := addKubectlFlagsToCmd(cmd)
flags := pflag.NewFlagSet("tmp", pflag.ContinueOnError)
clientConfig := cli.AddKubectlFlagsToSet(flags)
// copy k8s persistent flags into argocd command flags
flags.VisitAll(func(flag *pflag.Flag) {
// skip Kubernetes server flags since argocd has it's own server flag
if flag.Name == "server" {
return
}
cmd.Flags().AddFlag(flag)
})
cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
startInProcessAPI := clientOpts.Core
if !startInProcessAPI {
@@ -82,8 +91,12 @@ func InitCommand(cmd *cobra.Command, clientOpts *argoapi.ClientOptions, port *in
cli.SetLogLevel(log.ErrorLevel.String())
log.SetLevel(log.ErrorLevel)
os.Setenv(v1alpha1.EnvVarFakeInClusterConfig, "true")
if address == nil {
address = pointer.String("localhost")
}
if port == nil || *port == 0 {
ln, err := net.Listen("tcp", "localhost:0")
addr := fmt.Sprintf("%s:0", *address)
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
@@ -109,12 +122,14 @@ func InitCommand(cmd *cobra.Command, clientOpts *argoapi.ClientOptions, port *in
return err
}
context := retrieveContextIfChanged(cmd.Flag("context"))
mr, err := miniredis.Run()
if err != nil {
return err
}
appstateCache := appstatecache.NewCache(cacheutil.NewCache(&forwardCacheClient{namespace: namespace}), time.Hour)
appstateCache := appstatecache.NewCache(cacheutil.NewCache(&forwardCacheClient{namespace: namespace, context: context}), time.Hour)
srv := server.NewServer(ctx, server.ArgoCDServerOpts{
EnableGZip: false,
Namespace: namespace,
@@ -125,12 +140,12 @@ func InitCommand(cmd *cobra.Command, clientOpts *argoapi.ClientOptions, port *in
Cache: servercache.NewCache(appstateCache, 0, 0, 0),
KubeClientset: kubeClientset,
Insecure: true,
ListenHost: "localhost",
RepoClientset: &forwardRepoClientset{namespace: namespace},
ListenHost: *address,
RepoClientset: &forwardRepoClientset{namespace: namespace, context: context},
})
go srv.Run(ctx, *port, 0)
clientOpts.ServerAddr = fmt.Sprintf("localhost:%d", *port)
clientOpts.ServerAddr = fmt.Sprintf("%s:%d", *address, *port)
clientOpts.PlainText = true
if !cache.WaitForCacheSync(ctx.Done(), srv.Initialized) {
log.Fatal("Timed out waiting for project cache to sync")

View File

@@ -0,0 +1,80 @@
package headless
import (
"testing"
flag "github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
)
type StringFlag struct {
// The exact value provided on the flag
value string
}
func (f StringFlag) String() string {
return f.value
}
func (f *StringFlag) Set(value string) error {
f.value = value
return nil
}
func (f *StringFlag) Type() string {
return "string"
}
func Test_FlagContextNotChanged(t *testing.T) {
res := retrieveContextIfChanged(&flag.Flag{
Name: "",
Shorthand: "",
Usage: "",
Value: &StringFlag{value: "test"},
DefValue: "",
Changed: false,
NoOptDefVal: "",
Deprecated: "",
Hidden: false,
ShorthandDeprecated: "",
Annotations: nil,
})
assert.Equal(t, "", res)
}
func Test_FlagContextChanged(t *testing.T) {
res := retrieveContextIfChanged(&flag.Flag{
Name: "",
Shorthand: "",
Usage: "",
Value: &StringFlag{value: "test"},
DefValue: "",
Changed: true,
NoOptDefVal: "",
Deprecated: "",
Hidden: false,
ShorthandDeprecated: "",
Annotations: nil,
})
assert.Equal(t, "test", res)
}
func Test_FlagContextNil(t *testing.T) {
res := retrieveContextIfChanged(&flag.Flag{
Name: "",
Shorthand: "",
Usage: "",
Value: nil,
DefValue: "",
Changed: false,
NoOptDefVal: "",
Deprecated: "",
Hidden: false,
ShorthandDeprecated: "",
Annotations: nil,
})
assert.Equal(t, "", res)
}

View File

@@ -13,7 +13,7 @@ import (
"time"
"github.com/coreos/go-oidc"
"github.com/dgrijalva/jwt-go/v4"
"github.com/golang-jwt/jwt/v4"
log "github.com/sirupsen/logrus"
"github.com/skratchdot/open-golang/open"
"github.com/spf13/cobra"
@@ -90,6 +90,8 @@ argocd login cd.argoproj.io --core`,
ServerAddr: server,
Insecure: globalClientOpts.Insecure,
PlainText: globalClientOpts.PlainText,
ClientCertFile: globalClientOpts.ClientCertFile,
ClientCertKeyFile: globalClientOpts.ClientCertKeyFile,
GRPCWeb: globalClientOpts.GRPCWeb,
GRPCWebRootPath: globalClientOpts.GRPCWebRootPath,
PortForward: globalClientOpts.PortForward,
@@ -125,9 +127,7 @@ argocd login cd.argoproj.io --core`,
errors.CheckError(err)
tokenString, refreshToken = oauth2Login(ctx, ssoPort, acdSet.GetOIDCConfig(), oauth2conf, provider)
}
parser := &jwt.Parser{
ValidationHelper: jwt.NewValidationHelper(jwt.WithoutClaimsValidation(), jwt.WithoutAudienceValidation()),
}
parser := jwt.NewParser(jwt.WithoutClaimsValidation())
claims := jwt.MapClaims{}
_, _, err := parser.ParseUnverified(tokenString, &claims)
errors.CheckError(err)

View File

@@ -3,7 +3,7 @@ package commands
import (
"testing"
"github.com/dgrijalva/jwt-go/v4"
"github.com/golang-jwt/jwt/v4"
"github.com/stretchr/testify/assert"
)

View File

@@ -219,8 +219,17 @@ func NewProjectRemoveSignatureKeyCommand(clientOpts *argocdclient.ClientOptions)
// NewProjectAddDestinationCommand returns a new instance of an `argocd proj add-destination` command
func NewProjectAddDestinationCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var nameInsteadServer bool
buildApplicationDestination := func(destination string, namespace string, nameInsteadServer bool) v1alpha1.ApplicationDestination {
if nameInsteadServer {
return v1alpha1.ApplicationDestination{Name: destination, Namespace: namespace}
}
return v1alpha1.ApplicationDestination{Server: destination, Namespace: namespace}
}
var command = &cobra.Command{
Use: "add-destination PROJECT SERVER NAMESPACE",
Use: "add-destination PROJECT SERVER/NAME NAMESPACE",
Short: "Add project destination",
Run: func(c *cobra.Command, args []string) {
if len(args) != 3 {
@@ -228,8 +237,8 @@ func NewProjectAddDestinationCommand(clientOpts *argocdclient.ClientOptions) *co
os.Exit(1)
}
projName := args[0]
server := args[1]
namespace := args[2]
destination := buildApplicationDestination(args[1], namespace, nameInsteadServer)
conn, projIf := argocdclient.NewClientOrDie(clientOpts).NewProjectClientOrDie()
defer argoio.Close(conn)
@@ -237,15 +246,18 @@ func NewProjectAddDestinationCommand(clientOpts *argocdclient.ClientOptions) *co
errors.CheckError(err)
for _, dest := range proj.Spec.Destinations {
if dest.Namespace == namespace && dest.Server == server {
dstServerExist := destination.Server != "" && dest.Server == destination.Server
dstNameExist := destination.Name != "" && dest.Name == destination.Name
if dest.Namespace == namespace && (dstServerExist || dstNameExist) {
log.Fatal("Specified destination is already defined in project")
}
}
proj.Spec.Destinations = append(proj.Spec.Destinations, v1alpha1.ApplicationDestination{Server: server, Namespace: namespace})
proj.Spec.Destinations = append(proj.Spec.Destinations, destination)
_, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj})
errors.CheckError(err)
},
}
command.Flags().BoolVar(&nameInsteadServer, "name", false, "Use name as destination instead server")
return command
}

View File

@@ -9,7 +9,7 @@ import (
"time"
timeutil "github.com/argoproj/pkg/time"
jwtgo "github.com/dgrijalva/jwt-go/v4"
jwtgo "github.com/golang-jwt/jwt/v4"
"github.com/spf13/cobra"
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"

View File

@@ -116,6 +116,7 @@ func NewProjectWindowsAddWindowCommand(clientOpts *argocdclient.ClientOptions) *
namespaces []string
clusters []string
manualSync bool
timeZone string
)
var command = &cobra.Command{
Use: "add PROJECT",
@@ -132,7 +133,7 @@ func NewProjectWindowsAddWindowCommand(clientOpts *argocdclient.ClientOptions) *
proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName})
errors.CheckError(err)
err = proj.Spec.AddWindow(kind, schedule, duration, applications, namespaces, clusters, manualSync)
err = proj.Spec.AddWindow(kind, schedule, duration, applications, namespaces, clusters, manualSync, timeZone)
errors.CheckError(err)
_, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj})
@@ -146,6 +147,7 @@ func NewProjectWindowsAddWindowCommand(clientOpts *argocdclient.ClientOptions) *
command.Flags().StringSliceVar(&namespaces, "namespaces", []string{}, "Namespaces that the schedule will be applied to. Comma separated, wildcards supported (e.g. --namespaces default,\\*-prod)")
command.Flags().StringSliceVar(&clusters, "clusters", []string{}, "Clusters that the schedule will be applied to. Comma separated, wildcards supported (e.g. --clusters prod,staging)")
command.Flags().BoolVar(&manualSync, "manual-sync", false, "Allow manual syncs for both deny and allow windows")
command.Flags().StringVar(&timeZone, "time-zone", "UTC", "Time zone of the sync window")
return command
}
@@ -189,6 +191,7 @@ func NewProjectWindowsUpdateCommand(clientOpts *argocdclient.ClientOptions) *cob
applications []string
namespaces []string
clusters []string
timeZone string
)
var command = &cobra.Command{
Use: "update PROJECT ID",
@@ -212,7 +215,7 @@ func NewProjectWindowsUpdateCommand(clientOpts *argocdclient.ClientOptions) *cob
for i, window := range proj.Spec.SyncWindows {
if id == i {
err := window.Update(schedule, duration, applications, namespaces, clusters)
err := window.Update(schedule, duration, applications, namespaces, clusters, timeZone)
if err != nil {
errors.CheckError(err)
}
@@ -228,6 +231,7 @@ func NewProjectWindowsUpdateCommand(clientOpts *argocdclient.ClientOptions) *cob
command.Flags().StringSliceVar(&applications, "applications", []string{}, "Applications that the schedule will be applied to. Comma separated, wildcards supported (e.g. --applications prod-\\*,website)")
command.Flags().StringSliceVar(&namespaces, "namespaces", []string{}, "Namespaces that the schedule will be applied to. Comma separated, wildcards supported (e.g. --namespaces default,\\*-prod)")
command.Flags().StringSliceVar(&clusters, "clusters", []string{}, "Clusters that the schedule will be applied to. Comma separated, wildcards supported (e.g. --clusters prod,staging)")
command.Flags().StringVar(&timeZone, "time-zone", "UTC", "Time zone of the sync window. (e.g. --time-zone \"America/New_York\")")
return command
}

View File

@@ -43,13 +43,15 @@ func NewReloginCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Comm
var tokenString string
var refreshToken string
clientOpts := argocdclient.ClientOptions{
ConfigPath: "",
ServerAddr: configCtx.Server.Server,
Insecure: configCtx.Server.Insecure,
GRPCWeb: globalClientOpts.GRPCWeb,
GRPCWebRootPath: globalClientOpts.GRPCWebRootPath,
PlainText: configCtx.Server.PlainText,
Headers: globalClientOpts.Headers,
ConfigPath: "",
ServerAddr: configCtx.Server.Server,
Insecure: configCtx.Server.Insecure,
ClientCertFile: globalClientOpts.ClientCertFile,
ClientCertKeyFile: globalClientOpts.ClientCertKeyFile,
GRPCWeb: globalClientOpts.GRPCWeb,
GRPCWebRootPath: globalClientOpts.GRPCWebRootPath,
PlainText: configCtx.Server.PlainText,
Headers: globalClientOpts.Headers,
}
acdClient := argocdclient.NewClientOrDie(&clientOpts)
claims, err := configCtx.User.Claims()

View File

@@ -182,6 +182,7 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
GithubAppInstallationID: repoOpts.Repo.GithubAppInstallationId,
GithubAppEnterpriseBaseUrl: repoOpts.Repo.GitHubAppEnterpriseBaseURL,
Proxy: repoOpts.Proxy,
Project: repoOpts.Repo.Project,
}
_, err := repoIf.ValidateAccess(context.Background(), &repoAccessReq)
errors.CheckError(err)
@@ -226,7 +227,7 @@ func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
// Print table of repo info
func printRepoTable(repos appsv1.Repositories) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
_, _ = fmt.Fprintf(w, "TYPE\tNAME\tREPO\tINSECURE\tOCI\tLFS\tCREDS\tSTATUS\tMESSAGE\n")
_, _ = fmt.Fprintf(w, "TYPE\tNAME\tREPO\tINSECURE\tOCI\tLFS\tCREDS\tSTATUS\tMESSAGE\tPROJECT\n")
for _, r := range repos {
var hasCreds string
if !r.HasCredentials() {
@@ -238,7 +239,7 @@ func printRepoTable(repos appsv1.Repositories) {
hasCreds = "true"
}
}
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%v\t%v\t%s\t%s\t%s\n", r.Type, r.Name, r.Repo, r.IsInsecure(), r.EnableOCI, r.EnableLFS, hasCreds, r.ConnectionState.Status, r.ConnectionState.Message)
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%v\t%v\t%s\t%s\t%s\t%s\n", r.Type, r.Name, r.Repo, r.IsInsecure(), r.EnableOCI, r.EnableLFS, hasCreds, r.ConnectionState.Status, r.ConnectionState.Message, r.Project)
}
_ = w.Flush()
}

View File

@@ -60,6 +60,9 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma
# Add credentials with GitHub App authentication to use for all repositories under https://ghe.example.com/repos
argocd repocreds add https://ghe.example.com/repos/ --github-app-id 1 --github-app-installation-id 2 --github-app-private-key-path test.private-key.pem --github-app-enterprise-base-url https://ghe.example.com/api/v3
# Add credentials with helm oci registry so that these oci registry urls do not need to be added as repos individually.
argocd repocreds add localhost:5000/myrepo --enable-oci --type helm
`
var command = &cobra.Command{

View File

@@ -40,19 +40,19 @@ func NewCommand() *cobra.Command {
}
command.AddCommand(NewCompletionCommand())
command.AddCommand(headless.InitCommand(NewVersionCmd(&clientOpts), &clientOpts, nil))
command.AddCommand(headless.InitCommand(NewClusterCommand(&clientOpts, pathOpts), &clientOpts, nil))
command.AddCommand(headless.InitCommand(NewApplicationCommand(&clientOpts), &clientOpts, nil))
command.AddCommand(headless.InitCommand(NewVersionCmd(&clientOpts), &clientOpts, nil, nil))
command.AddCommand(headless.InitCommand(NewClusterCommand(&clientOpts, pathOpts), &clientOpts, nil, nil))
command.AddCommand(headless.InitCommand(NewApplicationCommand(&clientOpts), &clientOpts, nil, nil))
command.AddCommand(NewLoginCommand(&clientOpts))
command.AddCommand(NewReloginCommand(&clientOpts))
command.AddCommand(headless.InitCommand(NewRepoCommand(&clientOpts), &clientOpts, nil))
command.AddCommand(headless.InitCommand(NewRepoCredsCommand(&clientOpts), &clientOpts, nil))
command.AddCommand(headless.InitCommand(NewRepoCommand(&clientOpts), &clientOpts, nil, nil))
command.AddCommand(headless.InitCommand(NewRepoCredsCommand(&clientOpts), &clientOpts, nil, nil))
command.AddCommand(NewContextCommand(&clientOpts))
command.AddCommand(headless.InitCommand(NewProjectCommand(&clientOpts), &clientOpts, nil))
command.AddCommand(headless.InitCommand(NewAccountCommand(&clientOpts), &clientOpts, nil))
command.AddCommand(headless.InitCommand(NewProjectCommand(&clientOpts), &clientOpts, nil, nil))
command.AddCommand(headless.InitCommand(NewAccountCommand(&clientOpts), &clientOpts, nil, nil))
command.AddCommand(NewLogoutCommand(&clientOpts))
command.AddCommand(headless.InitCommand(NewCertCommand(&clientOpts), &clientOpts, nil))
command.AddCommand(headless.InitCommand(NewGPGCommand(&clientOpts), &clientOpts, nil))
command.AddCommand(headless.InitCommand(NewCertCommand(&clientOpts), &clientOpts, nil, nil))
command.AddCommand(headless.InitCommand(NewGPGCommand(&clientOpts), &clientOpts, nil, nil))
command.AddCommand(admin.NewAdminCommand())
defaultLocalConfigPath, err := localconfig.DefaultLocalConfigPath()

View File

@@ -8,7 +8,10 @@ import (
"github.com/spf13/cobra"
appcontroller "github.com/argoproj/argo-cd/v2/cmd/argocd-application-controller/commands"
cmpserver "github.com/argoproj/argo-cd/v2/cmd/argocd-cmp-server/commands"
dex "github.com/argoproj/argo-cd/v2/cmd/argocd-dex/commands"
gitaskpass "github.com/argoproj/argo-cd/v2/cmd/argocd-git-ask-pass/commands"
notification "github.com/argoproj/argo-cd/v2/cmd/argocd-notification/commands"
reposerver "github.com/argoproj/argo-cd/v2/cmd/argocd-repo-server/commands"
apiserver "github.com/argoproj/argo-cd/v2/cmd/argocd-server/commands"
cli "github.com/argoproj/argo-cd/v2/cmd/argocd/commands"
@@ -34,8 +37,14 @@ func main() {
command = appcontroller.NewCommand()
case "argocd-repo-server":
command = reposerver.NewCommand()
case "argocd-cmp-server":
command = cmpserver.NewCommand()
case "argocd-dex":
command = dex.NewCommand()
case "argocd-notifications":
command = notification.NewCommand()
case "argocd-git-ask-pass":
command = gitaskpass.NewCommand()
default:
command = cli.NewCommand()
}

View File

@@ -9,6 +9,8 @@ import (
"strings"
"time"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
@@ -34,12 +36,15 @@ type AppOptions struct {
destNamespace string
Parameters []string
valuesFiles []string
ignoreMissingValueFiles bool
values string
releaseName string
helmSets []string
helmSetStrings []string
helmSetFiles []string
helmVersion string
helmPassCredentials bool
helmSkipCrds bool
project string
syncPolicy string
syncOptions []string
@@ -83,12 +88,15 @@ func AddAppFlags(command *cobra.Command, opts *AppOptions) {
command.Flags().StringVar(&opts.destNamespace, "dest-namespace", "", "K8s target namespace (overrides the namespace specified in the ksonnet app.yaml)")
command.Flags().StringArrayVarP(&opts.Parameters, "parameter", "p", []string{}, "set a parameter override (e.g. -p guestbook=image=example/guestbook:latest)")
command.Flags().StringArrayVar(&opts.valuesFiles, "values", []string{}, "Helm values file(s) to use")
command.Flags().BoolVar(&opts.ignoreMissingValueFiles, "ignore-missing-value-files", false, "Ignore locally missing valueFiles when setting helm template --values")
command.Flags().StringVar(&opts.values, "values-literal-file", "", "Filename or URL to import as a literal Helm values block")
command.Flags().StringVar(&opts.releaseName, "release-name", "", "Helm release-name")
command.Flags().StringVar(&opts.helmVersion, "helm-version", "", "Helm version")
command.Flags().BoolVar(&opts.helmPassCredentials, "helm-pass-credentials", false, "Pass credentials to all domain")
command.Flags().StringArrayVar(&opts.helmSets, "helm-set", []string{}, "Helm set values on the command line (can be repeated to set several values: --helm-set key1=val1 --helm-set key2=val2)")
command.Flags().StringArrayVar(&opts.helmSetStrings, "helm-set-string", []string{}, "Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2)")
command.Flags().StringArrayVar(&opts.helmSetFiles, "helm-set-file", []string{}, "Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2)")
command.Flags().BoolVar(&opts.helmSkipCrds, "helm-skip-crds", false, "Skip helm crd installation step")
command.Flags().StringVar(&opts.project, "project", "", "Application project name")
command.Flags().StringVar(&opts.syncPolicy, "sync-policy", "", "Set the sync policy (one of: none, automated (aliases of automated: auto, automatic))")
command.Flags().StringArrayVar(&opts.syncOptions, "sync-option", []string{}, "Add or remove a sync option, e.g add `Prune=false`. Remove using `!` prefix, e.g. `!Prune=false`")
@@ -122,6 +130,9 @@ func AddAppFlags(command *cobra.Command, opts *AppOptions) {
func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, appOpts *AppOptions) int {
visited := 0
if flags == nil {
return visited
}
flags.Visit(func(f *pflag.Flag) {
visited++
switch f.Name {
@@ -140,6 +151,8 @@ func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, ap
spec.RevisionHistoryLimit = &i
case "values":
setHelmOpt(&spec.Source, helmOpts{valueFiles: appOpts.valuesFiles})
case "ignore-missing-value-files":
setHelmOpt(&spec.Source, helmOpts{ignoreMissingValueFiles: appOpts.ignoreMissingValueFiles})
case "values-literal-file":
var data []byte
@@ -156,12 +169,16 @@ func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, ap
setHelmOpt(&spec.Source, helmOpts{releaseName: appOpts.releaseName})
case "helm-version":
setHelmOpt(&spec.Source, helmOpts{version: appOpts.helmVersion})
case "helm-pass-credentials":
setHelmOpt(&spec.Source, helmOpts{passCredentials: appOpts.helmPassCredentials})
case "helm-set":
setHelmOpt(&spec.Source, helmOpts{helmSets: appOpts.helmSets})
case "helm-set-string":
setHelmOpt(&spec.Source, helmOpts{helmSetStrings: appOpts.helmSetStrings})
case "helm-set-file":
setHelmOpt(&spec.Source, helmOpts{helmSetFiles: appOpts.helmSetFiles})
case "helm-skip-crds":
setHelmOpt(&spec.Source, helmOpts{skipCrds: appOpts.helmSkipCrds})
case "directory-recurse":
if spec.Source.Directory != nil {
spec.Source.Directory.Recurse = appOpts.directoryRecurse
@@ -372,13 +389,16 @@ func setPluginOptEnvs(src *argoappv1.ApplicationSource, envs []string) {
}
type helmOpts struct {
valueFiles []string
values string
releaseName string
version string
helmSets []string
helmSetStrings []string
helmSetFiles []string
valueFiles []string
ignoreMissingValueFiles bool
values string
releaseName string
version string
helmSets []string
helmSetStrings []string
helmSetFiles []string
passCredentials bool
skipCrds bool
}
func setHelmOpt(src *argoappv1.ApplicationSource, opts helmOpts) {
@@ -388,6 +408,9 @@ func setHelmOpt(src *argoappv1.ApplicationSource, opts helmOpts) {
if len(opts.valueFiles) > 0 {
src.Helm.ValueFiles = opts.valueFiles
}
if opts.ignoreMissingValueFiles {
src.Helm.IgnoreMissingValueFiles = opts.ignoreMissingValueFiles
}
if len(opts.values) > 0 {
src.Helm.Values = opts.values
}
@@ -397,6 +420,12 @@ func setHelmOpt(src *argoappv1.ApplicationSource, opts helmOpts) {
if opts.version != "" {
src.Helm.Version = opts.version
}
if opts.passCredentials {
src.Helm.PassCredentials = opts.passCredentials
}
if opts.skipCrds {
src.Helm.SkipCrds = opts.skipCrds
}
for _, text := range opts.helmSets {
p, err := argoappv1.NewHelmParameter(text, false)
if err != nil {
@@ -518,39 +547,99 @@ func SetParameterOverrides(app *argoappv1.Application, parameters []string) {
}
}
func readAppFromStdin(app *argoappv1.Application) error {
func readApps(yml []byte, apps *[]*argoappv1.Application) error {
yamls, _ := kube.SplitYAMLToString(yml)
var err error
for _, yml := range yamls {
var app argoappv1.Application
err = config.Unmarshal([]byte(yml), &app)
*apps = append(*apps, &app)
if err != nil {
return err
}
}
return err
}
func readAppsFromStdin(apps *[]*argoappv1.Application) error {
reader := bufio.NewReader(os.Stdin)
err := config.UnmarshalReader(reader, &app)
data, err := ioutil.ReadAll(reader)
if err != nil {
return err
}
err = readApps(data, apps)
if err != nil {
return fmt.Errorf("unable to read manifest from stdin: %v", err)
}
return nil
}
func readAppFromURI(fileURL string, app *argoappv1.Application) error {
parsedURL, err := url.ParseRequestURI(fileURL)
if err != nil || !(parsedURL.Scheme == "http" || parsedURL.Scheme == "https") {
err = config.UnmarshalLocalFile(fileURL, &app)
} else {
err = config.UnmarshalRemoteFile(fileURL, &app)
func readAppsFromURI(fileURL string, apps *[]*argoappv1.Application) error {
readFilePayload := func() ([]byte, error) {
parsedURL, err := url.ParseRequestURI(fileURL)
if err != nil || !(parsedURL.Scheme == "http" || parsedURL.Scheme == "https") {
return ioutil.ReadFile(fileURL)
}
return config.ReadRemoteFile(fileURL)
}
return err
yml, err := readFilePayload()
if err != nil {
return err
}
return readApps(yml, apps)
}
func ConstructApp(fileURL, appName string, labels, annotations, args []string, appOpts AppOptions, flags *pflag.FlagSet) (*argoappv1.Application, error) {
var app argoappv1.Application
if fileURL == "-" {
// read stdin
err := readAppFromStdin(&app)
if err != nil {
return nil, err
}
} else if fileURL != "" {
// read uri
err := readAppFromURI(fileURL, &app)
if err != nil {
return nil, err
func constructAppsFromStdin() ([]*argoappv1.Application, error) {
apps := make([]*argoappv1.Application, 0)
// read stdin
err := readAppsFromStdin(&apps)
if err != nil {
return nil, err
}
return apps, nil
}
func constructAppsBaseOnName(appName string, labels, annotations, args []string, appOpts AppOptions, flags *pflag.FlagSet) ([]*argoappv1.Application, error) {
var app *argoappv1.Application
// read arguments
if len(args) == 1 {
if appName != "" && appName != args[0] {
return nil, fmt.Errorf("--name argument '%s' does not match app name %s", appName, args[0])
}
appName = args[0]
}
app = &argoappv1.Application{
TypeMeta: v1.TypeMeta{
Kind: application.ApplicationKind,
APIVersion: application.Group + "/v1alpha1",
},
ObjectMeta: v1.ObjectMeta{
Name: appName,
},
}
SetAppSpecOptions(flags, &app.Spec, &appOpts)
SetParameterOverrides(app, appOpts.Parameters)
mergeLabels(app, labels)
setAnnotations(app, annotations)
return []*argoappv1.Application{
app,
}, nil
}
func constructAppsFromFileUrl(fileURL, appName string, labels, annotations, args []string, appOpts AppOptions, flags *pflag.FlagSet) ([]*argoappv1.Application, error) {
apps := make([]*argoappv1.Application, 0)
// read uri
err := readAppsFromURI(fileURL, &apps)
if err != nil {
return nil, err
}
for _, app := range apps {
if len(args) == 1 && args[0] != app.Name {
return nil, fmt.Errorf("app name '%s' does not match app spec metadata.name '%s'", args[0], app.Name)
}
@@ -561,32 +650,20 @@ func ConstructApp(fileURL, appName string, labels, annotations, args []string, a
return nil, fmt.Errorf("app.Name is empty. --name argument can be used to provide app.Name")
}
SetAppSpecOptions(flags, &app.Spec, &appOpts)
SetParameterOverrides(&app, appOpts.Parameters)
mergeLabels(&app, labels)
setAnnotations(&app, annotations)
} else {
// read arguments
if len(args) == 1 {
if appName != "" && appName != args[0] {
return nil, fmt.Errorf("--name argument '%s' does not match app name %s", appName, args[0])
}
appName = args[0]
}
app = argoappv1.Application{
TypeMeta: v1.TypeMeta{
Kind: application.ApplicationKind,
APIVersion: application.Group + "/v1alpha1",
},
ObjectMeta: v1.ObjectMeta{
Name: appName,
},
}
SetAppSpecOptions(flags, &app.Spec, &appOpts)
SetParameterOverrides(&app, appOpts.Parameters)
mergeLabels(&app, labels)
setAnnotations(&app, annotations)
SetParameterOverrides(app, appOpts.Parameters)
mergeLabels(app, labels)
setAnnotations(app, annotations)
}
return &app, nil
return apps, nil
}
func ConstructApps(fileURL, appName string, labels, annotations, args []string, appOpts AppOptions, flags *pflag.FlagSet) ([]*argoappv1.Application, error) {
if fileURL == "-" {
return constructAppsFromStdin()
} else if fileURL != "" {
return constructAppsFromFileUrl(fileURL, appName, labels, annotations, args, appOpts, flags)
}
return constructAppsBaseOnName(appName, labels, annotations, args, appOpts, flags)
}
func mergeLabels(app *argoappv1.Application, labels []string) {

View File

@@ -1,12 +1,16 @@
package util
import (
"io/ioutil"
"os"
"testing"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
func Test_setHelmOpt(t *testing.T) {
@@ -20,6 +24,11 @@ func Test_setHelmOpt(t *testing.T) {
setHelmOpt(&src, helmOpts{valueFiles: []string{"foo"}})
assert.Equal(t, []string{"foo"}, src.Helm.ValueFiles)
})
t.Run("IgnoreMissingValueFiles", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setHelmOpt(&src, helmOpts{ignoreMissingValueFiles: true})
assert.Equal(t, true, src.Helm.IgnoreMissingValueFiles)
})
t.Run("ReleaseName", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setHelmOpt(&src, helmOpts{releaseName: "foo"})
@@ -45,6 +54,16 @@ func Test_setHelmOpt(t *testing.T) {
setHelmOpt(&src, helmOpts{version: "v3"})
assert.Equal(t, "v3", src.Helm.Version)
})
t.Run("HelmPassCredentials", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setHelmOpt(&src, helmOpts{passCredentials: true})
assert.Equal(t, true, src.Helm.PassCredentials)
})
t.Run("HelmSkipCrds", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setHelmOpt(&src, helmOpts{skipCrds: true})
assert.Equal(t, true, src.Helm.SkipCrds)
})
}
func Test_setKustomizeOpt(t *testing.T) {
@@ -190,3 +209,106 @@ func Test_setAnnotations(t *testing.T) {
assert.Equal(t, map[string]string{"hoge": ""}, app.Annotations)
})
}
const appsYaml = `---
# Source: apps/templates/helm.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sth1
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
namespace: sth
server: 'https://kubernetes.default.svc'
project: default
source:
repoURL: 'https://github.com/pasha-codefresh/argocd-example-apps'
targetRevision: HEAD
path: apps
helm:
valueFiles:
- values.yaml
---
# Source: apps/templates/helm.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sth2
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
namespace: sth
server: 'https://kubernetes.default.svc'
project: default
source:
repoURL: 'https://github.com/pasha-codefresh/argocd-example-apps'
targetRevision: HEAD
path: apps
helm:
valueFiles:
- values.yaml`
func TestReadAppsFromURI(t *testing.T) {
file, err := ioutil.TempFile(os.TempDir(), "")
if err != nil {
panic(err)
}
defer func() {
_ = os.Remove(file.Name())
}()
_, _ = file.WriteString(appsYaml)
_ = file.Sync()
apps := make([]*argoappv1.Application, 0)
err = readAppsFromURI(file.Name(), &apps)
assert.NoError(t, err)
assert.Equal(t, 2, len(apps))
assert.Equal(t, "sth1", apps[0].Name)
assert.Equal(t, "sth2", apps[1].Name)
}
func TestConstructAppFromStdin(t *testing.T) {
file, err := ioutil.TempFile(os.TempDir(), "")
if err != nil {
panic(err)
}
defer func() {
_ = os.Remove(file.Name())
}()
_, _ = file.WriteString(appsYaml)
_ = file.Sync()
if _, err := file.Seek(0, 0); err != nil {
log.Fatal(err)
}
os.Stdin = file
apps, err := ConstructApps("-", "test", []string{}, []string{}, []string{}, AppOptions{}, nil)
if err := file.Close(); err != nil {
log.Fatal(err)
}
assert.NoError(t, err)
assert.Equal(t, 2, len(apps))
assert.Equal(t, "sth1", apps[0].Name)
assert.Equal(t, "sth2", apps[1].Name)
}
func TestConstructBasedOnName(t *testing.T) {
apps, err := ConstructApps("", "test", []string{}, []string{}, []string{}, AppOptions{}, nil)
assert.NoError(t, err)
assert.Equal(t, 1, len(apps))
assert.Equal(t, "test", apps[0].Name)
}

View File

@@ -55,7 +55,7 @@ func PrintKubeContexts(ca clientcmd.ConfigAccess) {
}
}
func NewCluster(name string, namespaces []string, clusterResources bool, conf *rest.Config, managerBearerToken string, awsAuthConf *argoappv1.AWSAuthConfig, execProviderConf *argoappv1.ExecProviderConfig) *argoappv1.Cluster {
func NewCluster(name string, namespaces []string, clusterResources bool, conf *rest.Config, managerBearerToken string, awsAuthConf *argoappv1.AWSAuthConfig, execProviderConf *argoappv1.ExecProviderConfig, labels, annotations map[string]string) *argoappv1.Cluster {
tlsClientConfig := argoappv1.TLSClientConfig{
Insecure: conf.TLSClientConfig.Insecure,
ServerName: conf.TLSClientConfig.ServerName,
@@ -89,6 +89,8 @@ func NewCluster(name string, namespaces []string, clusterResources bool, conf *r
AWSAuthConfig: awsAuthConf,
ExecProviderConfig: execProviderConf,
},
Labels: labels,
Annotations: annotations,
}
// Bearer token will preferentially be used for auth if present,
@@ -111,6 +113,7 @@ type ClusterOptions struct {
Namespaces []string
ClusterResources bool
Name string
Project string
Shard int64
ExecProviderCommand string
ExecProviderArgs []string
@@ -126,6 +129,7 @@ func AddClusterFlags(command *cobra.Command, opts *ClusterOptions) {
command.Flags().StringArrayVar(&opts.Namespaces, "namespace", nil, "List of namespaces which are allowed to manage")
command.Flags().BoolVar(&opts.ClusterResources, "cluster-resources", false, "Indicates if cluster level resources should be managed. The setting is used only if list of managed namespaces is not empty.")
command.Flags().StringVar(&opts.Name, "name", "", "Overwrite the cluster name")
command.Flags().StringVar(&opts.Project, "project", "", "project of the cluster")
command.Flags().Int64Var(&opts.Shard, "shard", -1, "Cluster shard number; inferred from hostname if not set")
command.Flags().StringVar(&opts.ExecProviderCommand, "exec-command", "", "Command to run to provide client credentials to the cluster. You may need to build a custom ArgoCD image to ensure the command is available at runtime.")
command.Flags().StringArrayVar(&opts.ExecProviderArgs, "exec-command-args", nil, "Arguments to supply to the --exec-command executable")

View File

@@ -11,6 +11,8 @@ import (
)
func Test_newCluster(t *testing.T) {
labels := map[string]string{"key1": "val1"}
annotations := map[string]string{"key2": "val2"}
clusterWithData := NewCluster("test-cluster", []string{"test-namespace"}, false, &rest.Config{
TLSClientConfig: rest.TLSClientConfig{
Insecure: false,
@@ -23,11 +25,13 @@ func Test_newCluster(t *testing.T) {
},
"test-bearer-token",
&v1alpha1.AWSAuthConfig{},
&v1alpha1.ExecProviderConfig{})
&v1alpha1.ExecProviderConfig{}, labels, annotations)
assert.Equal(t, "test-cert-data", string(clusterWithData.Config.CertData))
assert.Equal(t, "test-key-data", string(clusterWithData.Config.KeyData))
assert.Equal(t, "", clusterWithData.Config.BearerToken)
assert.Equal(t, labels, clusterWithData.Labels)
assert.Equal(t, annotations, clusterWithData.Annotations)
clusterWithFiles := NewCluster("test-cluster", []string{"test-namespace"}, false, &rest.Config{
TLSClientConfig: rest.TLSClientConfig{
@@ -41,11 +45,13 @@ func Test_newCluster(t *testing.T) {
},
"test-bearer-token",
&v1alpha1.AWSAuthConfig{},
&v1alpha1.ExecProviderConfig{})
&v1alpha1.ExecProviderConfig{}, labels, nil)
assert.True(t, strings.Contains(string(clusterWithFiles.Config.CertData), "test-cert-data"))
assert.True(t, strings.Contains(string(clusterWithFiles.Config.KeyData), "test-key-data"))
assert.Equal(t, "", clusterWithFiles.Config.BearerToken)
assert.Equal(t, labels, clusterWithFiles.Labels)
assert.Nil(t, clusterWithFiles.Annotations)
clusterWithBearerToken := NewCluster("test-cluster", []string{"test-namespace"}, false, &rest.Config{
TLSClientConfig: rest.TLSClientConfig{
@@ -57,7 +63,9 @@ func Test_newCluster(t *testing.T) {
},
"test-bearer-token",
&v1alpha1.AWSAuthConfig{},
&v1alpha1.ExecProviderConfig{})
&v1alpha1.ExecProviderConfig{}, nil, nil)
assert.Equal(t, "test-bearer-token", clusterWithBearerToken.Config.BearerToken)
assert.Nil(t, clusterWithBearerToken.Labels)
assert.Nil(t, clusterWithBearerToken.Annotations)
}

View File

@@ -27,6 +27,7 @@ type RepoOptions struct {
func AddRepoFlags(command *cobra.Command, opts *RepoOptions) {
command.Flags().StringVar(&opts.Repo.Type, "type", common.DefaultRepoType, "type of the repository, \"git\" or \"helm\"")
command.Flags().StringVar(&opts.Repo.Name, "name", "", "name of the repository, mandatory for repositories of type helm")
command.Flags().StringVar(&opts.Repo.Project, "project", "", "project of the repository")
command.Flags().StringVar(&opts.Repo.Username, "username", "", "username to the repository")
command.Flags().StringVar(&opts.Repo.Password, "password", "", "password to the repository")
command.Flags().StringVar(&opts.SshPrivateKeyPath, "ssh-private-key-path", "", "path to the private ssh key (e.g. ~/.ssh/id_rsa)")

View File

@@ -0,0 +1,62 @@
package apiclient
import (
"context"
"time"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
grpc_util "github.com/argoproj/argo-cd/v2/util/grpc"
"github.com/argoproj/argo-cd/v2/util/io"
)
const (
// MaxGRPCMessageSize contains max grpc message size
MaxGRPCMessageSize = 100 * 1024 * 1024
)
// Clientset represents config management plugin server api clients
type Clientset interface {
NewConfigManagementPluginClient() (io.Closer, ConfigManagementPluginServiceClient, error)
}
type clientSet struct {
address string
}
func (c *clientSet) NewConfigManagementPluginClient() (io.Closer, ConfigManagementPluginServiceClient, error) {
conn, err := NewConnection(c.address)
if err != nil {
return nil, nil, err
}
return conn, NewConfigManagementPluginServiceClient(conn), nil
}
func NewConnection(address string) (*grpc.ClientConn, error) {
retryOpts := []grpc_retry.CallOption{
grpc_retry.WithMax(3),
grpc_retry.WithBackoff(grpc_retry.BackoffLinear(1000 * time.Millisecond)),
}
unaryInterceptors := []grpc.UnaryClientInterceptor{grpc_retry.UnaryClientInterceptor(retryOpts...)}
dialOpts := []grpc.DialOption{
grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor(retryOpts...)),
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(unaryInterceptors...)),
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(MaxGRPCMessageSize), grpc.MaxCallSendMsgSize(MaxGRPCMessageSize)),
}
dialOpts = append(dialOpts, grpc.WithInsecure())
conn, err := grpc_util.BlockingDial(context.Background(), "unix", address, nil, dialOpts...)
if err != nil {
log.Errorf("Unable to connect to config management plugin service with address %s", address)
return nil, err
}
return conn, nil
}
// NewConfigManagementPluginClientSet creates new instance of config management plugin server Clientset
func NewConfigManagementPluginClientSet(address string) Clientset {
return &clientSet{address: address}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,91 @@
package plugin
import (
"fmt"
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/argoproj/argo-cd/v2/common"
configUtil "github.com/argoproj/argo-cd/v2/util/config"
)
const (
ConfigManagementPluginKind string = "ConfigManagementPlugin"
)
type PluginConfig struct {
metav1.TypeMeta `json:",inline"`
Metadata metav1.ObjectMeta `json:"metadata"`
Spec PluginConfigSpec `json:"spec"`
}
type PluginConfigSpec struct {
Version string `json:"version"`
Init Command `json:"init,omitempty"`
Generate Command `json:"generate"`
Discover Discover `json:"discover"`
AllowConcurrency bool `json:"allowConcurrency"`
LockRepo bool `json:"lockRepo"`
}
//Discover holds find and fileName
type Discover struct {
Find Find `json:"find"`
FileName string `json:"fileName"`
}
// Command holds binary path and arguments list
type Command struct {
Command []string `json:"command,omitempty"`
Args []string `json:"args,omitempty"`
}
// Find holds find command or glob pattern
type Find struct {
Command
Glob string `json:"glob"`
}
func ReadPluginConfig(filePath string) (*PluginConfig, error) {
path := fmt.Sprintf("%s/%s", strings.TrimRight(filePath, "/"), common.PluginConfigFileName)
var config PluginConfig
err := configUtil.UnmarshalLocalFile(path, &config)
if err != nil {
return nil, err
}
if err = ValidatePluginConfig(config); err != nil {
return nil, err
}
return &config, nil
}
func ValidatePluginConfig(config PluginConfig) error {
if config.Metadata.Name == "" {
return fmt.Errorf("invalid plugin configuration file. metadata.name should be non-empty.")
}
if config.TypeMeta.Kind != ConfigManagementPluginKind {
return fmt.Errorf("invalid plugin configuration file. kind should be %s, found %s", ConfigManagementPluginKind, config.TypeMeta.Kind)
}
if len(config.Spec.Generate.Command) == 0 {
return fmt.Errorf("invalid plugin configuration file. spec.generate command should be non-empty")
}
if config.Spec.Discover.Find.Glob == "" && len(config.Spec.Discover.Find.Command.Command) == 0 && config.Spec.Discover.FileName == "" {
return fmt.Errorf("invalid plugin configuration file. atleast one of discover.find.command or discover.find.glob or discover.fineName should be non-empty")
}
return nil
}
func (cfg *PluginConfig) Address() string {
var address string
pluginSockFilePath := common.GetPluginSockFilePath()
if cfg.Spec.Version != "" {
address = fmt.Sprintf("%s/%s-%s.sock", pluginSockFilePath, cfg.Metadata.Name, cfg.Spec.Version)
} else {
address = fmt.Sprintf("%s/%s.sock", pluginSockFilePath, cfg.Metadata.Name)
}
return address
}

223
cmpserver/plugin/plugin.go Normal file
View File

@@ -0,0 +1,223 @@
package plugin
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/argoproj/pkg/rand"
"github.com/argoproj/argo-cd/v2/util/buffered_context"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/mattn/go-zglob"
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/v2/cmpserver/apiclient"
)
// cmpTimeoutBuffer is the amount of time before the request deadline to timeout server-side work. It makes sure there's
// enough time before the client times out to send a meaningful error message.
const cmpTimeoutBuffer = 100 * time.Millisecond
// Service implements ConfigManagementPluginService interface
type Service struct {
initConstants CMPServerInitConstants
}
type CMPServerInitConstants struct {
PluginConfig PluginConfig
}
// NewService returns a new instance of the ConfigManagementPluginService
func NewService(initConstants CMPServerInitConstants) *Service {
return &Service{
initConstants: initConstants,
}
}
func runCommand(ctx context.Context, command Command, path string, env []string) (string, error) {
if len(command.Command) == 0 {
return "", fmt.Errorf("Command is empty")
}
cmd := exec.CommandContext(ctx, command.Command[0], append(command.Command[1:], command.Args...)...)
cmd.Env = env
cmd.Dir = path
execId, err := rand.RandString(5)
if err != nil {
return "", err
}
logCtx := log.WithFields(log.Fields{"execID": execId})
// log in a way we can copy-and-paste into a terminal
args := strings.Join(cmd.Args, " ")
logCtx.WithFields(log.Fields{"dir": cmd.Dir}).Info(args)
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
// Make sure the command is killed immediately on timeout. https://stackoverflow.com/a/38133948/684776
cmd.SysProcAttr = newSysProcAttr(true)
start := time.Now()
err = cmd.Start()
if err != nil {
return "", err
}
go func() {
<-ctx.Done()
// Kill by group ID to make sure child processes are killed. The - tells `kill` that it's a group ID.
// Since we didn't set Pgid in SysProcAttr, the group ID is the same as the process ID. https://pkg.go.dev/syscall#SysProcAttr
_ = sysCallKill(-cmd.Process.Pid)
}()
err = cmd.Wait()
duration := time.Since(start)
output := stdout.String()
logCtx.WithFields(log.Fields{"duration": duration}).Debug(output)
if err != nil {
err := newCmdError(args, errors.New(err.Error()), strings.TrimSpace(stderr.String()))
logCtx.Error(err.Error())
return strings.TrimSuffix(output, "\n"), err
}
return strings.TrimSuffix(output, "\n"), nil
}
type CmdError struct {
Args string
Stderr string
Cause error
}
func (ce *CmdError) Error() string {
res := fmt.Sprintf("`%v` failed %v", ce.Args, ce.Cause)
if ce.Stderr != "" {
res = fmt.Sprintf("%s: %s", res, ce.Stderr)
}
return res
}
func newCmdError(args string, cause error, stderr string) *CmdError {
return &CmdError{Args: args, Stderr: stderr, Cause: cause}
}
// Environ returns a list of environment variables in name=value format from a list of variables
func environ(envVars []*apiclient.EnvEntry) []string {
var environ []string
for _, item := range envVars {
if item != nil && item.Name != "" && item.Value != "" {
environ = append(environ, fmt.Sprintf("%s=%s", item.Name, item.Value))
}
}
return environ
}
// GenerateManifest runs generate command from plugin config file and returns generated manifest files
func (s *Service) GenerateManifest(ctx context.Context, q *apiclient.ManifestRequest) (*apiclient.ManifestResponse, error) {
bufferedCtx, cancel := buffered_context.WithEarlierDeadline(ctx, cmpTimeoutBuffer)
defer cancel()
if deadline, ok := bufferedCtx.Deadline(); ok {
log.Infof("Generating manifests with deadline %v from now", time.Until(deadline))
} else {
log.Info("Generating manifests with no request-level timeout")
}
config := s.initConstants.PluginConfig
env := append(os.Environ(), environ(q.Env)...)
if len(config.Spec.Init.Command) > 0 {
_, err := runCommand(bufferedCtx, config.Spec.Init, q.AppPath, env)
if err != nil {
return &apiclient.ManifestResponse{}, err
}
}
out, err := runCommand(bufferedCtx, config.Spec.Generate, q.AppPath, env)
if err != nil {
return &apiclient.ManifestResponse{}, err
}
manifests, err := kube.SplitYAMLToString([]byte(out))
if err != nil {
return &apiclient.ManifestResponse{}, err
}
return &apiclient.ManifestResponse{
Manifests: manifests,
}, err
}
// MatchRepository checks whether the application repository type is supported by config management plugin server
func (s *Service) MatchRepository(ctx context.Context, q *apiclient.RepositoryRequest) (*apiclient.RepositoryResponse, error) {
bufferedCtx, cancel := buffered_context.WithEarlierDeadline(ctx, cmpTimeoutBuffer)
defer cancel()
var repoResponse apiclient.RepositoryResponse
config := s.initConstants.PluginConfig
if config.Spec.Discover.FileName != "" {
log.Debugf("config.Spec.Discover.FileName is provided")
pattern := strings.TrimSuffix(q.Path, "/") + "/" + strings.TrimPrefix(config.Spec.Discover.FileName, "/")
matches, err := filepath.Glob(pattern)
if err != nil || len(matches) == 0 {
log.Debugf("Could not find match for pattern %s. Error is %v.", pattern, err)
return &repoResponse, err
} else if len(matches) > 0 {
repoResponse.IsSupported = true
return &repoResponse, nil
}
}
if config.Spec.Discover.Find.Glob != "" {
log.Debugf("config.Spec.Discover.Find.Glob is provided")
pattern := strings.TrimSuffix(q.Path, "/") + "/" + strings.TrimPrefix(config.Spec.Discover.Find.Glob, "/")
// filepath.Glob doesn't have '**' support hence selecting third-party lib
// https://github.com/golang/go/issues/11862
matches, err := zglob.Glob(pattern)
if err != nil || len(matches) == 0 {
log.Debugf("Could not find match for pattern %s. Error is %v.", pattern, err)
return &repoResponse, err
} else if len(matches) > 0 {
repoResponse.IsSupported = true
return &repoResponse, nil
}
}
log.Debugf("Going to try runCommand.")
find, err := runCommand(bufferedCtx, config.Spec.Discover.Find.Command, q.Path, os.Environ())
if err != nil {
return &repoResponse, err
}
var isSupported bool
if find != "" {
isSupported = true
}
return &apiclient.RepositoryResponse{
IsSupported: isSupported,
}, nil
}
// GetPluginConfig returns plugin config
func (s *Service) GetPluginConfig(ctx context.Context, q *apiclient.ConfigRequest) (*apiclient.ConfigResponse, error) {
config := s.initConstants.PluginConfig
return &apiclient.ConfigResponse{
AllowConcurrency: config.Spec.AllowConcurrency,
LockRepo: config.Spec.LockRepo,
}, nil
}

View File

@@ -0,0 +1,61 @@
syntax = "proto3";
option go_package = "github.com/argoproj/argo-cd/v2/cmpserver/apiclient";
package plugin;
import "k8s.io/api/core/v1/generated.proto";
// ManifestRequest is a query for manifest generation.
message ManifestRequest {
// Name of the application for which the request is triggered
string appName = 1;
string appPath = 2;
string repoPath = 3;
bool noCache = 4;
repeated EnvEntry env = 5;
}
// EnvEntry represents an entry in the application's environment
message EnvEntry {
// Name is the name of the variable, usually expressed in uppercase
string name = 1;
// Value is the value of the variable
string value = 2;
}
message ManifestResponse {
repeated string manifests = 1;
string sourceType = 2;
}
message RepositoryRequest {
string path = 1;
repeated EnvEntry env = 2;
}
message RepositoryResponse {
bool isSupported = 1;
}
message ConfigRequest {
}
message ConfigResponse {
bool allowConcurrency = 1;
bool lockRepo = 2;
}
// ConfigManagementPlugin Service
service ConfigManagementPluginService {
// GenerateManifest generates manifest for application in specified repo name and revision
rpc GenerateManifest(ManifestRequest) returns (ManifestResponse) {
}
// MatchRepository returns whether or not the given path is supported by the plugin
rpc MatchRepository(RepositoryRequest) returns (RepositoryResponse) {
}
// Get configuration of the plugin
rpc GetPluginConfig(ConfigRequest) returns (ConfigResponse) {
}
}

View File

@@ -0,0 +1,83 @@
package plugin
import (
"context"
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/argoproj/argo-cd/v2/cmpserver/apiclient"
)
func newService(configFilePath string) (*Service, error) {
config, err := ReadPluginConfig(configFilePath)
if err != nil {
return nil, err
}
initConstants := CMPServerInitConstants{
PluginConfig: *config,
}
service := &Service{
initConstants: initConstants,
}
return service, nil
}
func TestMatchRepository(t *testing.T) {
configFilePath := "./testdata/ksonnet/config"
service, err := newService(configFilePath)
require.NoError(t, err)
q := apiclient.RepositoryRequest{}
path, err := os.Getwd()
require.NoError(t, err)
q.Path = path
res1, err := service.MatchRepository(context.Background(), &q)
require.NoError(t, err)
require.True(t, res1.IsSupported)
}
func Test_Negative_ConfigFile_DoesnotExist(t *testing.T) {
configFilePath := "./testdata/kustomize-neg/config"
service, err := newService(configFilePath)
require.Error(t, err)
require.Nil(t, service)
}
func TestGenerateManifest(t *testing.T) {
configFilePath := "./testdata/kustomize/config"
service, err := newService(configFilePath)
require.NoError(t, err)
q := apiclient.ManifestRequest{}
res1, err := service.GenerateManifest(context.Background(), &q)
require.NoError(t, err)
require.NotNil(t, res1)
expectedOutput := "{\"apiVersion\":\"v1\",\"data\":{\"foo\":\"bar\"},\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"my-map\"}}"
if res1 != nil {
require.Equal(t, expectedOutput, res1.Manifests[0])
}
}
// TestRunCommandContextTimeout makes sure the command dies at timeout rather than sleeping past the timeout.
func TestRunCommandContextTimeout(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 990*time.Millisecond)
defer cancel()
// Use a subshell so there's a child command.
command := Command{
Command: []string{"sh", "-c"},
Args: []string{"sleep 5"},
}
before := time.Now()
_, err := runCommand(ctx, command, "", []string{})
after := time.Now()
assert.Error(t, err) // The command should time out, causing an error.
assert.Less(t, after.Sub(before), 1*time.Second)
}

View File

@@ -0,0 +1,16 @@
//go:build !windows
// +build !windows
package plugin
import (
"syscall"
)
func newSysProcAttr(setpgid bool) *syscall.SysProcAttr {
return &syscall.SysProcAttr{Setpgid: setpgid}
}
func sysCallKill(pid int) error {
return syscall.Kill(pid, syscall.SIGKILL)
}

View File

@@ -0,0 +1,16 @@
//go:build windows
// +build windows
package plugin
import (
"syscall"
)
func newSysProcAttr(setpgid bool) *syscall.SysProcAttr {
return &syscall.SysProcAttr{}
}
func sysCallKill(pid int) error {
return nil
}

View File

@@ -0,0 +1,15 @@
apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
name: ksonnet
spec:
version: v1.0
init:
command: [ks, version]
generate:
command: [sh, -c, "ks show $ARGOCD_APP_ENV"]
discover:
find:
glob: "**/*/main.jsonnet"
allowConcurrency: false
lockRepo: false

View File

View File

@@ -0,0 +1,16 @@
apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
name: kustomize
spec:
version: v1.0
init:
command: [kustomize, version]
generate:
command: [sh, -c, "cd testdata/kustomize && kustomize build"]
discover:
find:
command: [sh, -c, find . -name kustomization.yaml]
glob: "**/*/kustomization.yaml"
allowConcurrency: true
lockRepo: false

View File

@@ -0,0 +1,6 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: my-map
data:
foo: bar

View File

@@ -0,0 +1,16 @@
apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
name: kustomize
spec:
version: v1.0
init:
command: [kustomize, version]
generate:
command: [sh, -c, "cd testdata/kustomize && kustomize build"]
discover:
find:
command: [sh, -c, find . -name kustomization.yaml]
glob: "**/*/kustomization.yaml"
allowConcurrency: true
lockRepo: false

View File

@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./cm.yaml

107
cmpserver/server.go Normal file
View File

@@ -0,0 +1,107 @@
package cmpserver
import (
"net"
"os"
"os/signal"
"syscall"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/reflection"
"github.com/argoproj/argo-cd/v2/cmpserver/apiclient"
"github.com/argoproj/argo-cd/v2/cmpserver/plugin"
"github.com/argoproj/argo-cd/v2/common"
versionpkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/version"
"github.com/argoproj/argo-cd/v2/server/version"
"github.com/argoproj/argo-cd/v2/util/errors"
grpc_util "github.com/argoproj/argo-cd/v2/util/grpc"
)
// ArgoCDCMPServer is the config management plugin server implementation
type ArgoCDCMPServer struct {
log *log.Entry
opts []grpc.ServerOption
initConstants plugin.CMPServerInitConstants
stopCh chan os.Signal
doneCh chan interface{}
sig os.Signal
}
// NewServer returns a new instance of the Argo CD config management plugin server
func NewServer(initConstants plugin.CMPServerInitConstants) (*ArgoCDCMPServer, error) {
if os.Getenv(common.EnvEnableGRPCTimeHistogramEnv) == "true" {
grpc_prometheus.EnableHandlingTimeHistogram()
}
serverLog := log.NewEntry(log.StandardLogger())
streamInterceptors := []grpc.StreamServerInterceptor{grpc_logrus.StreamServerInterceptor(serverLog), grpc_prometheus.StreamServerInterceptor, grpc_util.PanicLoggerStreamServerInterceptor(serverLog)}
unaryInterceptors := []grpc.UnaryServerInterceptor{grpc_logrus.UnaryServerInterceptor(serverLog), grpc_prometheus.UnaryServerInterceptor, grpc_util.PanicLoggerUnaryServerInterceptor(serverLog)}
serverOpts := []grpc.ServerOption{
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(unaryInterceptors...)),
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(streamInterceptors...)),
grpc.MaxRecvMsgSize(apiclient.MaxGRPCMessageSize),
grpc.MaxSendMsgSize(apiclient.MaxGRPCMessageSize),
}
return &ArgoCDCMPServer{
log: serverLog,
opts: serverOpts,
stopCh: make(chan os.Signal),
doneCh: make(chan interface{}),
initConstants: initConstants,
}, nil
}
func (a *ArgoCDCMPServer) Run() {
config := a.initConstants.PluginConfig
// Listen on the socket address
_ = os.Remove(config.Address())
listener, err := net.Listen("unix", config.Address())
errors.CheckError(err)
log.Infof("argocd-cmp-server %s serving on %s", common.GetVersion(), listener.Addr())
signal.Notify(a.stopCh, syscall.SIGINT, syscall.SIGTERM)
go a.Shutdown(config.Address())
grpcServer := a.CreateGRPC()
err = grpcServer.Serve(listener)
errors.CheckError(err)
if a.sig != nil {
<-a.doneCh
}
}
// CreateGRPC creates new configured grpc server
func (a *ArgoCDCMPServer) CreateGRPC() *grpc.Server {
server := grpc.NewServer(a.opts...)
versionpkg.RegisterVersionServiceServer(server, version.NewServer(nil, func() (bool, error) {
return true, nil
}))
pluginService := plugin.NewService(a.initConstants)
apiclient.RegisterConfigManagementPluginServiceServer(server, pluginService)
healthService := health.NewServer()
grpc_health_v1.RegisterHealthServer(server, healthService)
// Register reflection service on gRPC server.
reflection.Register(server)
return server
}
func (a *ArgoCDCMPServer) Shutdown(address string) {
defer signal.Stop(a.stopCh)
a.sig = <-a.stopCh
_ = os.Remove(address)
close(a.doneCh)
}

View File

@@ -42,6 +42,11 @@ const (
DefaultPortRepoServerMetrics = 8084
)
// Default listener address for ArgoCD components
const (
DefaultAddressAPIServer = "localhost"
)
// Default paths on the pod's file system
const (
// The default path where TLS certificates for repositories are located
@@ -54,6 +59,12 @@ const (
DefaultGnuPgHomePath = "/app/config/gpg/keys"
// Default path to repo server TLS endpoint config
DefaultAppConfigPath = "/app/config"
// Default path to cmp server plugin socket file
DefaultPluginSockFilePath = "/home/argocd/cmp-server/plugins"
// Default path to cmp server plugin configuration file
DefaultPluginConfigFilePath = "/home/argocd/cmp-server/config"
// Plugin Config File is a ConfigManagementPlugin manifest located inside the plugin container
PluginConfigFileName = "plugin.yaml"
)
// Argo CD application related constants
@@ -65,11 +76,18 @@ const (
ArgoCDUserAgentName = "argocd-client"
// AuthCookieName is the HTTP cookie name where we store our auth token
AuthCookieName = "argocd.token"
// StateCookieName is the HTTP cookie name that holds temporary nonce tokens for CSRF protection
StateCookieName = "argocd.oauthstate"
// StateCookieMaxAge is the maximum age of the oauth state cookie
StateCookieMaxAge = time.Minute * 5
// ChangePasswordSSOTokenMaxAge is the max token age for password change operation
ChangePasswordSSOTokenMaxAge = time.Minute * 5
// GithubAppCredsExpirationDuration is the default time used to cache the GitHub app credentials
GithubAppCredsExpirationDuration = time.Minute * 60
// PasswordPatten is the default password patten
PasswordPatten = `^.{8,32}$`
)
// Dex related constants
@@ -110,6 +128,9 @@ const (
// LabelValueSecretTypeRepoCreds indicates a secret type of repository credentials
LabelValueSecretTypeRepoCreds = "repo-creds"
// The Argo CD application name is used as the instance name
AnnotationKeyAppInstance = "argocd.argoproj.io/tracking-id"
// AnnotationCompareOptions is a comma-separated list of options for comparison
AnnotationCompareOptions = "argocd.argoproj.io/compare-options"
@@ -141,6 +162,12 @@ const (
EnvVarTLSDataPath = "ARGOCD_TLS_DATA_PATH"
// Specifies number of git remote operations attempts count
EnvGitAttemptsCount = "ARGOCD_GIT_ATTEMPTS_COUNT"
// Specifices max duration of git remote operation retry
EnvGitRetryMaxDuration = "ARGOCD_GIT_RETRY_MAX_DURATION"
// Specifies duration of git remote operation retry
EnvGitRetryDuration = "ARGOCD_GIT_RETRY_DURATION"
// Specifies fator of git remote operation retry
EnvGitRetryFactor = "ARGOCD_GIT_RETRY_FACTOR"
// Overrides git submodule support, true by default
EnvGitSubmoduleEnabled = "ARGOCD_GIT_MODULES_ENABLED"
// EnvGnuPGHome is the path to ArgoCD's GnuPG keyring for signature verification
@@ -169,6 +196,10 @@ const (
EnvLogFormat = "ARGOCD_LOG_FORMAT"
// EnvLogLevel log level that is defined by `--loglevel` option
EnvLogLevel = "ARGOCD_LOG_LEVEL"
// EnvMaxCookieNumber max number of chunks a cookie can be broken into
EnvMaxCookieNumber = "ARGOCD_MAX_COOKIE_NUMBER"
// EnvPluginSockFilePath allows to override the pluginSockFilePath for repo server and cmp server
EnvPluginSockFilePath = "ARGOCD_PLUGINSOCKFILEPATH"
)
const (
@@ -181,6 +212,12 @@ const (
CacheVersion = "1.8.3"
)
const (
DefaultGitRetryMaxDuration time.Duration = time.Second * 5 // 5s
DefaultGitRetryDuration time.Duration = time.Millisecond * 250 // 0.25s
DefaultGitRetryFactor = int64(2)
)
// GetGnuPGHomePath retrieves the path to use for GnuPG home directory, which is either taken from GNUPGHOME environment or a default value
func GetGnuPGHomePath() string {
if gnuPgHome := os.Getenv(EnvGnuPGHome); gnuPgHome == "" {
@@ -189,3 +226,12 @@ func GetGnuPGHomePath() string {
return gnuPgHome
}
}
// GetPluginSockFilePath retrieves the path of plugin sock file, which is either taken from PluginSockFilePath environment or a default value
func GetPluginSockFilePath() string {
if pluginSockFilePath := os.Getenv(EnvPluginSockFilePath); pluginSockFilePath == "" {
return DefaultPluginSockFilePath
} else {
return pluginSockFilePath
}
}

View File

@@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
apiruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
@@ -36,9 +37,6 @@ import (
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
// make sure to register workqueue prometheus metrics
_ "k8s.io/component-base/metrics/prometheus/workqueue"
statecache "github.com/argoproj/argo-cd/v2/controller/cache"
"github.com/argoproj/argo-cd/v2/controller/metrics"
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
@@ -48,6 +46,7 @@ import (
applisters "github.com/argoproj/argo-cd/v2/pkg/client/listers/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/util/argo"
argodiff "github.com/argoproj/argo-cd/v2/util/argo/diff"
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/errors"
@@ -112,6 +111,7 @@ type ApplicationController struct {
metricsServer *metrics.MetricsServer
kubectlSemaphore *semaphore.Weighted
clusterFilter func(cluster *appv1.Cluster) bool
projByNameCache sync.Map
}
// NewApplicationController creates new instance of ApplicationController.
@@ -127,6 +127,7 @@ func NewApplicationController(
selfHealTimeout time.Duration,
metricsPort int,
metricsCacheExpiration time.Duration,
metricsApplicationLabels []string,
kubectlParallelismLimit int64,
clusterFilter func(cluster *appv1.Cluster) bool,
) (*ApplicationController, error) {
@@ -151,6 +152,7 @@ func NewApplicationController(
settingsMgr: settingsMgr,
selfHealTimeout: selfHealTimeout,
clusterFilter: clusterFilter,
projByNameCache: sync.Map{},
}
if kubectlParallelismLimit > 0 {
ctrl.kubectlSemaphore = semaphore.NewWeighted(kubectlParallelismLimit)
@@ -163,16 +165,26 @@ func NewApplicationController(
AddFunc: func(obj interface{}) {
if key, err := cache.MetaNamespaceKeyFunc(obj); err == nil {
ctrl.projectRefreshQueue.Add(key)
if projMeta, ok := obj.(metav1.Object); ok {
ctrl.InvalidateProjectsCache(projMeta.GetName())
}
}
},
UpdateFunc: func(old, new interface{}) {
if key, err := cache.MetaNamespaceKeyFunc(new); err == nil {
ctrl.projectRefreshQueue.Add(key)
if projMeta, ok := new.(metav1.Object); ok {
ctrl.InvalidateProjectsCache(projMeta.GetName())
}
}
},
DeleteFunc: func(obj interface{}) {
if key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj); err == nil {
ctrl.projectRefreshQueue.Add(key)
if projMeta, ok := obj.(metav1.Object); ok {
ctrl.InvalidateProjectsCache(projMeta.GetName())
}
}
},
})
@@ -180,7 +192,7 @@ func NewApplicationController(
var err error
ctrl.metricsServer, err = metrics.NewMetricsServer(metricsAddr, appLister, ctrl.canProcessApp, func(r *http.Request) error {
return nil
})
}, metricsApplicationLabels)
if err != nil {
return nil, err
}
@@ -190,8 +202,8 @@ func NewApplicationController(
return nil, err
}
}
stateCache := statecache.NewLiveStateCache(db, appInformer, ctrl.settingsMgr, kubectl, ctrl.metricsServer, ctrl.handleObjectUpdated, clusterFilter)
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectl, ctrl.settingsMgr, stateCache, projInformer, ctrl.metricsServer, argoCache, ctrl.statusRefreshTimeout)
stateCache := statecache.NewLiveStateCache(db, appInformer, ctrl.settingsMgr, kubectl, ctrl.metricsServer, ctrl.handleObjectUpdated, clusterFilter, argo.NewResourceTracking())
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectl, ctrl.settingsMgr, stateCache, projInformer, ctrl.metricsServer, argoCache, ctrl.statusRefreshTimeout, argo.NewResourceTracking())
ctrl.appInformer = appInformer
ctrl.appLister = appLister
ctrl.projInformer = projInformer
@@ -201,6 +213,19 @@ func NewApplicationController(
return &ctrl, nil
}
func (ctrl *ApplicationController) InvalidateProjectsCache(names ...string) {
if len(names) > 0 {
for _, name := range names {
ctrl.projByNameCache.Delete(name)
}
} else {
ctrl.projByNameCache.Range(func(key, _ interface{}) bool {
ctrl.projByNameCache.Delete(key)
return true
})
}
}
func (ctrl *ApplicationController) GetMetricsServer() *metrics.MetricsServer {
return ctrl.metricsServer
}
@@ -230,8 +255,35 @@ func isSelfReferencedApp(app *appv1.Application, ref v1.ObjectReference) bool {
gvk.Kind == application.ApplicationKind
}
func (ctrl *ApplicationController) newAppProjCache(name string) *appProjCache {
return &appProjCache{name: name, ctrl: ctrl}
}
type appProjCache struct {
name string
ctrl *ApplicationController
lock sync.Mutex
appProj *appv1.AppProject
}
func (projCache *appProjCache) GetAppProject(ctx context.Context) (*appv1.AppProject, error) {
projCache.lock.Lock()
defer projCache.lock.Unlock()
if projCache.appProj != nil {
return projCache.appProj, nil
}
proj, err := argo.GetAppProjectByName(projCache.name, applisters.NewAppProjectLister(projCache.ctrl.projInformer.GetIndexer()), projCache.ctrl.namespace, projCache.ctrl.settingsMgr, projCache.ctrl.db, ctx)
if err != nil {
return nil, err
}
projCache.appProj = proj
return projCache.appProj, nil
}
func (ctrl *ApplicationController) getAppProj(app *appv1.Application) (*appv1.AppProject, error) {
return argo.GetAppProject(&app.Spec, applisters.NewAppProjectLister(ctrl.projInformer.GetIndexer()), ctrl.namespace, ctrl.settingsMgr)
projCache, _ := ctrl.projByNameCache.LoadOrStore(app.Spec.GetProject(), ctrl.newAppProjCache(app.Spec.GetProject()))
return projCache.(*appProjCache).GetAppProject(context.TODO())
}
func (ctrl *ApplicationController) handleObjectUpdated(managedByApp map[string]bool, ref v1.ObjectReference) {
@@ -244,12 +296,8 @@ func (ctrl *ApplicationController) handleObjectUpdated(managedByApp map[string]b
if !ok {
continue
}
// exclude resource unless it is permitted in the app project. If project is not permitted then it is not controlled by the user and there is no point showing the warning.
if proj, err := ctrl.getAppProj(app); err == nil && proj.IsGroupKindPermitted(ref.GroupVersionKind().GroupKind(), true) &&
!isKnownOrphanedResourceExclusion(kube.NewResourceKey(ref.GroupVersionKind().Group, ref.GroupVersionKind().Kind, ref.Namespace, ref.Name), proj) {
managedByApp[app.Name] = false
}
managedByApp[app.Name] = true
}
}
}
@@ -269,24 +317,43 @@ func (ctrl *ApplicationController) handleObjectUpdated(managedByApp map[string]b
if isManagedResource {
level = CompareWithRecent
}
// Additional check for debug level so we don't need to evaluate the
// format string in case of non-debug scenarios
if log.GetLevel() >= log.DebugLevel {
var resKey string
if ref.Namespace != "" {
resKey = ref.Namespace + "/" + ref.Name
} else {
resKey = "(cluster-scoped)/" + ref.Name
}
log.Debugf("Refreshing app %s for change in cluster of object %s of type %s/%s", appName, resKey, ref.APIVersion, ref.Kind)
}
ctrl.requestAppRefresh(appName, &level, nil)
}
}
// setAppManagedResources will build a list of ResourceDiff based on the provided comparisonResult
// and persist app resources related data in the cache. Will return the persisted ApplicationTree.
func (ctrl *ApplicationController) setAppManagedResources(a *appv1.Application, comparisonResult *comparisonResult) (*appv1.ApplicationTree, error) {
managedResources, err := ctrl.managedResources(comparisonResult)
managedResources, err := ctrl.hideSecretData(a, comparisonResult)
if err != nil {
return nil, err
return nil, fmt.Errorf("error getting managed resources: %s", err)
}
tree, err := ctrl.getResourceTree(a, managedResources)
if err != nil {
return nil, err
return nil, fmt.Errorf("error getting resource tree: %s", err)
}
err = ctrl.cache.SetAppResourcesTree(a.Name, tree)
if err != nil {
return nil, err
return nil, fmt.Errorf("error setting app resource tree: %s", err)
}
return tree, ctrl.cache.SetAppManagedResources(a.Name, managedResources)
err = ctrl.cache.SetAppManagedResources(a.Name, managedResources)
if err != nil {
return nil, fmt.Errorf("error setting app managed resources: %s", err)
}
return tree, nil
}
// returns true of given resources exist in the namespace by default and not managed by the user
@@ -316,7 +383,7 @@ func isKnownOrphanedResourceExclusion(key kube.ResourceKey, proj *appv1.AppProje
func (ctrl *ApplicationController) getResourceTree(a *appv1.Application, managedResources []*appv1.ResourceDiff) (*appv1.ApplicationTree, error) {
nodes := make([]appv1.ResourceNode, 0)
proj, err := argo.GetAppProject(&a.Spec, applisters.NewAppProjectLister(ctrl.projInformer.GetIndexer()), ctrl.namespace, ctrl.settingsMgr)
proj, err := ctrl.getAppProj(a)
if err != nil {
return nil, err
}
@@ -355,8 +422,12 @@ func (ctrl *ApplicationController) getResourceTree(a *appv1.Application, managed
},
})
} else {
err := ctrl.stateCache.IterateHierarchy(a.Spec.Destination.Server, kube.GetResourceKey(live), func(child appv1.ResourceNode, appName string) {
err := ctrl.stateCache.IterateHierarchy(a.Spec.Destination.Server, kube.GetResourceKey(live), func(child appv1.ResourceNode, appName string) bool {
if !proj.IsResourcePermitted(schema.GroupKind{Group: child.ResourceRef.Group, Kind: child.ResourceRef.Kind}, child.Namespace, a.Spec.Destination) {
return false
}
nodes = append(nodes, child)
return true
})
if err != nil {
return nil, err
@@ -366,16 +437,18 @@ func (ctrl *ApplicationController) getResourceTree(a *appv1.Application, managed
orphanedNodes := make([]appv1.ResourceNode, 0)
for k := range orphanedNodesMap {
if k.Namespace != "" && proj.IsGroupKindPermitted(k.GroupKind(), true) && !isKnownOrphanedResourceExclusion(k, proj) {
err := ctrl.stateCache.IterateHierarchy(a.Spec.Destination.Server, k, func(child appv1.ResourceNode, appName string) {
err := ctrl.stateCache.IterateHierarchy(a.Spec.Destination.Server, k, func(child appv1.ResourceNode, appName string) bool {
belongToAnotherApp := false
if appName != "" {
if _, exists, err := ctrl.appInformer.GetIndexer().GetByKey(ctrl.namespace + "/" + appName); exists && err == nil {
belongToAnotherApp = true
}
}
if !belongToAnotherApp {
orphanedNodes = append(orphanedNodes, child)
if belongToAnotherApp || !proj.IsResourcePermitted(schema.GroupKind{Group: child.ResourceRef.Group, Kind: child.ResourceRef.Kind}, child.Namespace, a.Spec.Destination) {
return false
}
orphanedNodes = append(orphanedNodes, child)
return true
})
if err != nil {
return nil, err
@@ -490,7 +563,7 @@ func (ctrl *ApplicationController) getAppHosts(a *appv1.Application, appNodes []
return hosts, nil
}
func (ctrl *ApplicationController) managedResources(comparisonResult *comparisonResult) ([]*appv1.ResourceDiff, error) {
func (ctrl *ApplicationController) hideSecretData(app *appv1.Application, comparisonResult *comparisonResult) ([]*appv1.ResourceDiff, error) {
items := make([]*appv1.ResourceDiff, len(comparisonResult.managedResources))
for i := range comparisonResult.managedResources {
res := comparisonResult.managedResources[i]
@@ -510,26 +583,46 @@ func (ctrl *ApplicationController) managedResources(comparisonResult *comparison
var err error
target, live, err = diff.HideSecretData(res.Target, res.Live)
if err != nil {
return nil, err
return nil, fmt.Errorf("error hiding secret data: %s", err)
}
compareOptions, err := ctrl.settingsMgr.GetResourceCompareOptions()
if err != nil {
return nil, err
return nil, fmt.Errorf("error getting resource compare options: %s", err)
}
resDiffPtr, err := diff.Diff(target, live,
diff.WithNormalizer(comparisonResult.diffNormalizer),
diff.WithLogr(logutils.NewLogrusLogger(logutils.NewWithCurrentConfig())),
diff.IgnoreAggregatedRoles(compareOptions.IgnoreAggregatedRoles))
resourceOverrides, err := ctrl.settingsMgr.GetResourceOverrides()
if err != nil {
return nil, err
return nil, fmt.Errorf("error getting resource overrides: %s", err)
}
resDiff = *resDiffPtr
appLabelKey, err := ctrl.settingsMgr.GetAppInstanceLabelKey()
if err != nil {
return nil, fmt.Errorf("error getting app instance label key: %s", err)
}
trackingMethod, err := ctrl.settingsMgr.GetTrackingMethod()
if err != nil {
return nil, fmt.Errorf("error getting tracking method: %s", err)
}
diffConfig, err := argodiff.NewDiffConfigBuilder().
WithDiffSettings(app.Spec.IgnoreDifferences, resourceOverrides, compareOptions.IgnoreAggregatedRoles).
WithTracking(appLabelKey, trackingMethod).
WithNoCache().
WithLogger(logutils.NewLogrusLogger(logutils.NewWithCurrentConfig())).
Build()
if err != nil {
return nil, fmt.Errorf("appcontroller error building diff config: %s", err)
}
diffResult, err := argodiff.StateDiff(live, target, diffConfig)
if err != nil {
return nil, fmt.Errorf("error applying diff: %s", err)
}
resDiff = diffResult
}
if live != nil {
data, err := json.Marshal(live)
if err != nil {
return nil, err
return nil, fmt.Errorf("error marshaling live json: %s", err)
}
item.LiveState = string(data)
} else {
@@ -539,7 +632,7 @@ func (ctrl *ApplicationController) managedResources(comparisonResult *comparison
if target != nil {
data, err := json.Marshal(target)
if err != nil {
return nil, err
return nil, fmt.Errorf("error marshaling target json: %s", err)
}
item.TargetState = string(data)
} else {
@@ -665,6 +758,18 @@ func (ctrl *ApplicationController) processAppOperationQueueItem() (processNext b
}
app := origApp.DeepCopy()
if app.Operation != nil {
// If we get here, we are about process an operation but we cannot rely on informer since it might has stale data.
// So always retrieve the latest version to ensure it is not stale to avoid unnecessary syncing.
// We cannot rely on informer since applications might be updated by both application controller and api server.
freshApp, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(ctrl.namespace).Get(context.Background(), app.ObjectMeta.Name, metav1.GetOptions{})
if err != nil {
log.Errorf("Failed to retrieve latest application state: %v", err)
return
}
app = freshApp
}
if app.Operation != nil {
ctrl.processRequestedAppOperation(app)
} else if app.DeletionTimestamp != nil && app.CascadedDeletion() {
@@ -789,7 +894,7 @@ func (ctrl *ApplicationController) getPermittedAppLiveObjects(app *appv1.Applica
}
// Don't delete live resources which are not permitted in the app project
for k, v := range objsMap {
if !proj.IsLiveResourcePermitted(v, app.Spec.Destination.Server) {
if !proj.IsLiveResourcePermitted(v, app.Spec.Destination.Server, app.Spec.Destination.Name) {
delete(objsMap, k)
}
}
@@ -1037,7 +1142,7 @@ func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Appli
}
ctrl.setOperationState(app, state)
if state.Phase.Completed() && !app.Operation.Sync.DryRun {
if state.Phase.Completed() && (app.Operation.Sync != nil && !app.Operation.Sync.DryRun) {
// if we just completed an operation, force a refresh so that UI will report up-to-date
// sync/health information
if _, err := cache.MetaNamespaceKeyFunc(app); err == nil {
@@ -1085,7 +1190,7 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
}
appClient := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(ctrl.namespace)
patchedApp, err := appClient.Patch(context.Background(), app.Name, types.MergePatchType, patchJSON, metav1.PatchOptions{})
_, err = appClient.Patch(context.Background(), app.Name, types.MergePatchType, patchJSON, metav1.PatchOptions{})
if err != nil {
// Stop retrying updating deleted application
if apierr.IsNotFound(err) {
@@ -1115,10 +1220,6 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
ctrl.auditLogger.LogAppEvent(app, eventInfo, strings.Join(messages, " "))
ctrl.metricsServer.IncSync(app, state)
}
// write back to informer in order to avoid stale cache
if err := ctrl.appInformer.GetStore().Update(patchedApp); err != nil {
log.Warnf("Fails to update informer: %v", err)
}
return nil
})
}
@@ -1197,6 +1298,13 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
app.Status.Sync.Status = appv1.SyncStatusCodeUnknown
app.Status.Health.Status = health.HealthStatusUnknown
ctrl.persistAppStatus(origApp, &app.Status)
if err := ctrl.cache.SetAppResourcesTree(app.Name, &appv1.ApplicationTree{}); err != nil {
log.Warnf("failed to set app resource tree: %v", err)
}
if err := ctrl.cache.SetAppManagedResources(app.Name, nil); err != nil {
log.Warnf("failed to set app managed resources tree: %v", err)
}
return
}
@@ -1586,7 +1694,7 @@ func (ctrl *ApplicationController) newApplicationInformerAndLister() (cache.Shar
return nil, nil
}
proj, err := ctrl.getAppProj(app)
proj, err := applisters.NewAppProjectLister(ctrl.projInformer.GetIndexer()).AppProjects(ctrl.namespace).Get(app.Spec.GetProject())
if err != nil {
return nil, nil
}

View File

@@ -106,6 +106,7 @@ func newFakeController(data *fakeData) *ApplicationController {
time.Minute,
common.DefaultPortArgoCDMetrics,
data.metricsCacheExpiration,
[]string{},
0,
nil,
)
@@ -135,12 +136,12 @@ func newFakeController(data *fakeData) *ApplicationController {
mockStateCache.On("GetClusterCache", mock.Anything).Return(&clusterCacheMock, nil)
mockStateCache.On("IterateHierarchy", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
key := args[1].(kube.ResourceKey)
action := args[2].(func(child argoappv1.ResourceNode, appName string))
action := args[2].(func(child argoappv1.ResourceNode, appName string) bool)
appName := ""
if res, ok := data.namespacedResources[key]; ok {
appName = res.AppName
}
action(argoappv1.ResourceNode{ResourceRef: argoappv1.ResourceRef{Kind: key.Kind, Group: key.Group, Namespace: key.Namespace, Name: key.Name}}, appName)
_ = action(argoappv1.ResourceNode{ResourceRef: argoappv1.ResourceRef{Kind: key.Kind, Group: key.Group, Namespace: key.Namespace, Name: key.Name}}, appName)
}).Return(nil)
return ctrl
}
@@ -784,11 +785,11 @@ func TestHandleOrphanedResourceUpdated(t *testing.T) {
isRequested, level := ctrl.isRefreshRequested(app1.Name)
assert.True(t, isRequested)
assert.Equal(t, ComparisonWithNothing, level)
assert.Equal(t, CompareWithRecent, level)
isRequested, level = ctrl.isRefreshRequested(app2.Name)
assert.True(t, isRequested)
assert.Equal(t, ComparisonWithNothing, level)
assert.Equal(t, CompareWithRecent, level)
}
func TestGetResourceTree_HasOrphanedResources(t *testing.T) {
@@ -1083,12 +1084,10 @@ func TestProcessRequestedAppOperation_FailedNoRetries(t *testing.T) {
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
receivedPatch := map[string]interface{}{}
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patchedApp := &v1alpha1.Application{}
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
}
return true, patchedApp, nil
return true, nil, nil
})
ctrl.processRequestedAppOperation(app)
@@ -1110,12 +1109,10 @@ func TestProcessRequestedAppOperation_InvalidDestination(t *testing.T) {
fakeAppCs.Lock()
defer fakeAppCs.Unlock()
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patchedApp := &v1alpha1.Application{}
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
}
return true, patchedApp, nil
return true, nil, nil
})
}()
@@ -1138,12 +1135,10 @@ func TestProcessRequestedAppOperation_FailedHasRetries(t *testing.T) {
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
receivedPatch := map[string]interface{}{}
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patchedApp := &v1alpha1.Application{}
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
}
return true, patchedApp, nil
return true, nil, nil
})
ctrl.processRequestedAppOperation(app)
@@ -1183,12 +1178,10 @@ func TestProcessRequestedAppOperation_RunningPreviouslyFailed(t *testing.T) {
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
receivedPatch := map[string]interface{}{}
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patchedApp := &v1alpha1.Application{}
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
}
return true, patchedApp, nil
return true, nil, nil
})
ctrl.processRequestedAppOperation(app)
@@ -1218,12 +1211,10 @@ func TestProcessRequestedAppOperation_HasRetriesTerminated(t *testing.T) {
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
receivedPatch := map[string]interface{}{}
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patchedApp := &v1alpha1.Application{}
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
}
return true, patchedApp, nil
return true, nil, nil
})
ctrl.processRequestedAppOperation(app)

View File

@@ -2,10 +2,12 @@ package cache
import (
"context"
"errors"
"fmt"
"os"
"math"
"reflect"
"sync"
"syscall"
"time"
clustercache "github.com/argoproj/gitops-engine/pkg/cache"
@@ -14,6 +16,7 @@ import (
log "github.com/sirupsen/logrus"
"golang.org/x/sync/semaphore"
v1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -24,6 +27,7 @@ import (
appv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/argo"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/env"
logutils "github.com/argoproj/argo-cd/v2/util/log"
"github.com/argoproj/argo-cd/v2/util/lua"
"github.com/argoproj/argo-cd/v2/util/settings"
@@ -32,31 +36,75 @@ import (
const (
// EnvClusterCacheResyncDuration is the env variable that holds cluster cache re-sync duration
EnvClusterCacheResyncDuration = "ARGOCD_CLUSTER_CACHE_RESYNC_DURATION"
// EnvClusterCacheWatchResyncDuration is the env variable that holds cluster cache watch re-sync duration
EnvClusterCacheWatchResyncDuration = "ARGOCD_CLUSTER_CACHE_WATCH_RESYNC_DURATION"
// EnvClusterRetryTimeoutDuration is the env variable that holds cluster retry duration when sync error happens
EnvClusterSyncRetryTimeoutDuration = "ARGOCD_CLUSTER_SYNC_RETRY_TIMEOUT_DURATION"
// EnvClusterCacheListPageSize is the env variable to control size of the list page size when making K8s queries
EnvClusterCacheListPageSize = "ARGOCD_CLUSTER_CACHE_LIST_PAGE_SIZE"
// EnvClusterCacheListSemaphore is the env variable to control size of the list semaphore
// This is used to limit the number of concurrent memory consuming operations on the
// k8s list queries results across all clusters to avoid memory spikes during cache initialization.
EnvClusterCacheListSemaphore = "ARGOCD_CLUSTER_CACHE_LIST_SEMAPHORE"
// EnvClusterCacheRetryLimit is the env variable to control the retry limit for listing resources during cluster cache sync
EnvClusterCacheAttemptLimit = "ARGOCD_CLUSTER_CACHE_ATTEMPT_LIMIT"
// EnvClusterCacheRetryUseBackoff is the env variable to control whether to use a backoff strategy with the retry during cluster cache sync
EnvClusterCacheRetryUseBackoff = "ARGOCD_CLUSTER_CACHE_RETRY_USE_BACKOFF"
)
// GitOps engine cluster cache tuning options
var (
// K8SClusterResyncDuration controls the duration of cluster cache refresh
K8SClusterResyncDuration = 12 * time.Hour
// clusterCacheResyncDuration controls the duration of cluster cache refresh.
// NOTE: this differs from gitops-engine default of 24h
clusterCacheResyncDuration = 12 * time.Hour
// clusterCacheWatchResyncDuration controls the maximum duration that group/kind watches are allowed to run
// for before relisting & restarting the watch
clusterCacheWatchResyncDuration = 10 * time.Minute
// clusterSyncRetryTimeoutDuration controls the sync retry duration when cluster sync error happens
clusterSyncRetryTimeoutDuration = 10 * time.Second
// The default limit of 50 is chosen based on experiments.
clusterCacheListSemaphoreSize int64 = 50
// clusterCacheListPageSize is the page size when performing K8s list requests.
// 500 is equal to kubectl's size
clusterCacheListPageSize int64 = 500
// clusterCacheRetryLimit sets a retry limit for failed requests during cluster cache sync
// If set to 1, retries are disabled.
clusterCacheAttemptLimit int32 = 1
// clusterCacheRetryUseBackoff specifies whether to use a backoff strategy on cluster cache sync, if retry is enabled
clusterCacheRetryUseBackoff bool = false
)
func init() {
if clusterResyncDurationStr := os.Getenv(EnvClusterCacheResyncDuration); clusterResyncDurationStr != "" {
if duration, err := time.ParseDuration(clusterResyncDurationStr); err == nil {
K8SClusterResyncDuration = duration
}
}
clusterCacheResyncDuration = env.ParseDurationFromEnv(EnvClusterCacheResyncDuration, clusterCacheResyncDuration, 0, math.MaxInt64)
clusterCacheWatchResyncDuration = env.ParseDurationFromEnv(EnvClusterCacheWatchResyncDuration, clusterCacheWatchResyncDuration, 0, math.MaxInt64)
clusterSyncRetryTimeoutDuration = env.ParseDurationFromEnv(EnvClusterSyncRetryTimeoutDuration, clusterSyncRetryTimeoutDuration, 0, math.MaxInt64)
clusterCacheListPageSize = env.ParseInt64FromEnv(EnvClusterCacheListPageSize, clusterCacheListPageSize, 0, math.MaxInt64)
clusterCacheListSemaphoreSize = env.ParseInt64FromEnv(EnvClusterCacheListSemaphore, clusterCacheListSemaphoreSize, 0, math.MaxInt64)
clusterCacheAttemptLimit = int32(env.ParseInt64FromEnv(EnvClusterCacheAttemptLimit, 1, 1, math.MaxInt32))
clusterCacheRetryUseBackoff = env.ParseBoolFromEnv(EnvClusterCacheRetryUseBackoff, false)
}
type LiveStateCache interface {
// Returns k8s server version
GetVersionsInfo(serverURL string) (string, []metav1.APIGroup, error)
GetVersionsInfo(serverURL string) (string, []kube.APIResourceInfo, error)
// Returns true of given group kind is a namespaced resource
IsNamespaced(server string, gk schema.GroupKind) (bool, error)
// Returns synced cluster cache
GetClusterCache(server string) (clustercache.ClusterCache, error)
// Executes give callback against resource specified by the key and all its children
IterateHierarchy(server string, key kube.ResourceKey, action func(child appv1.ResourceNode, appName string)) error
IterateHierarchy(server string, key kube.ResourceKey, action func(child appv1.ResourceNode, appName string) bool) error
// Returns state of live nodes which correspond for target nodes of specified application.
GetManagedLiveObjs(a *appv1.Application, targetObjs []*unstructured.Unstructured) (map[kube.ResourceKey]*unstructured.Unstructured, error)
// IterateResources iterates all resource stored in cache
@@ -105,19 +153,19 @@ func NewLiveStateCache(
kubectl kube.Kubectl,
metricsServer *metrics.MetricsServer,
onObjectUpdated ObjectUpdatedHandler,
clusterFilter func(cluster *appv1.Cluster) bool) LiveStateCache {
clusterFilter func(cluster *appv1.Cluster) bool,
resourceTracking argo.ResourceTracking) LiveStateCache {
return &liveStateCache{
appInformer: appInformer,
db: db,
clusters: make(map[string]clustercache.ClusterCache),
onObjectUpdated: onObjectUpdated,
kubectl: kubectl,
settingsMgr: settingsMgr,
metricsServer: metricsServer,
// The default limit of 50 is chosen based on experiments.
listSemaphore: semaphore.NewWeighted(50),
clusterFilter: clusterFilter,
appInformer: appInformer,
db: db,
clusters: make(map[string]clustercache.ClusterCache),
onObjectUpdated: onObjectUpdated,
kubectl: kubectl,
settingsMgr: settingsMgr,
metricsServer: metricsServer,
clusterFilter: clusterFilter,
resourceTracking: resourceTracking,
}
}
@@ -127,17 +175,14 @@ type cacheSettings struct {
}
type liveStateCache struct {
db db.ArgoDB
appInformer cache.SharedIndexInformer
onObjectUpdated ObjectUpdatedHandler
kubectl kube.Kubectl
settingsMgr *settings.SettingsManager
metricsServer *metrics.MetricsServer
clusterFilter func(cluster *appv1.Cluster) bool
// listSemaphore is used to limit the number of concurrent memory consuming operations on the
// k8s list queries results across all clusters to avoid memory spikes during cache initialization.
listSemaphore *semaphore.Weighted
db db.ArgoDB
appInformer cache.SharedIndexInformer
onObjectUpdated ObjectUpdatedHandler
kubectl kube.Kubectl
settingsMgr *settings.SettingsManager
metricsServer *metrics.MetricsServer
clusterFilter func(cluster *appv1.Cluster) bool
resourceTracking argo.ResourceTracking
clusters map[string]clustercache.ClusterCache
cacheSettings cacheSettings
@@ -258,6 +303,19 @@ func skipAppRequeuing(key kube.ResourceKey) bool {
return ignoredRefreshResources[key.Group+"/"+key.Kind]
}
// isRetryableError is a helper method to see whether an error
// returned from the dynamic client is potentially retryable.
func isRetryableError(err error) bool {
return kerrors.IsInternalError(err) ||
kerrors.IsInvalid(err) ||
kerrors.IsServerTimeout(err) ||
kerrors.IsServiceUnavailable(err) ||
kerrors.IsTimeout(err) ||
kerrors.IsUnexpectedObjectError(err) ||
kerrors.IsUnexpectedServerError(err) ||
errors.Is(err, syscall.ECONNRESET)
}
func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, error) {
c.lock.RLock()
clusterCache, ok := c.clusters[server]
@@ -285,9 +343,13 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
return nil, fmt.Errorf("controller is configured to ignore cluster %s", cluster.Server)
}
clusterCache = clustercache.NewClusterCache(cluster.RESTConfig(),
clustercache.SetListSemaphore(c.listSemaphore),
clustercache.SetResyncTimeout(K8SClusterResyncDuration),
trackingMethod := argo.GetTrackingMethod(c.settingsMgr)
clusterCacheOpts := []clustercache.UpdateSettingsFunc{
clustercache.SetListSemaphore(semaphore.NewWeighted(clusterCacheListSemaphoreSize)),
clustercache.SetListPageSize(clusterCacheListPageSize),
clustercache.SetWatchResyncTimeout(clusterCacheWatchResyncDuration),
clustercache.SetClusterSyncRetryTimeout(clusterSyncRetryTimeoutDuration),
clustercache.SetResyncTimeout(clusterCacheResyncDuration),
clustercache.SetSettings(cacheSettings.clusterSettings),
clustercache.SetNamespaces(cluster.Namespaces),
clustercache.SetClusterResources(cluster.ClusterResources),
@@ -295,7 +357,8 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
res := &ResourceInfo{}
populateNodeInfo(un, res)
res.Health, _ = health.GetResourceHealth(un, cacheSettings.clusterSettings.ResourceHealthOverride)
appName := kube.GetAppInstanceLabel(un, cacheSettings.appInstanceLabelKey)
appName := c.resourceTracking.GetAppName(un, cacheSettings.appInstanceLabelKey, trackingMethod)
if isRoot && appName != "" {
res.AppName = appName
}
@@ -306,7 +369,10 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
return res, res.AppName != "" || gvk.Kind == kube.CustomResourceDefinitionKind
}),
clustercache.SetLogr(logutils.NewLogrusLogger(log.WithField("server", cluster.Server))),
)
clustercache.SetRetryOptions(clusterCacheAttemptLimit, clusterCacheRetryUseBackoff, isRetryableError),
}
clusterCache = clustercache.NewClusterCache(cluster.RESTConfig(), clusterCacheOpts...)
_ = clusterCache.OnResourceUpdated(func(newRes *clustercache.Resource, oldRes *clustercache.Resource, namespaceResources map[kube.ResourceKey]*clustercache.Resource) {
toNotify := make(map[string]bool)
@@ -371,13 +437,13 @@ func (c *liveStateCache) IsNamespaced(server string, gk schema.GroupKind) (bool,
return clusterInfo.IsNamespaced(gk)
}
func (c *liveStateCache) IterateHierarchy(server string, key kube.ResourceKey, action func(child appv1.ResourceNode, appName string)) error {
func (c *liveStateCache) IterateHierarchy(server string, key kube.ResourceKey, action func(child appv1.ResourceNode, appName string) bool) error {
clusterInfo, err := c.getSyncedCluster(server)
if err != nil {
return err
}
clusterInfo.IterateHierarchy(key, func(resource *clustercache.Resource, namespaceResources map[kube.ResourceKey]*clustercache.Resource) {
action(asResourceNode(resource), getApp(resource, namespaceResources))
clusterInfo.IterateHierarchy(key, func(resource *clustercache.Resource, namespaceResources map[kube.ResourceKey]*clustercache.Resource) bool {
return action(asResourceNode(resource), getApp(resource, namespaceResources))
})
return nil
}
@@ -419,12 +485,12 @@ func (c *liveStateCache) GetManagedLiveObjs(a *appv1.Application, targetObjs []*
})
}
func (c *liveStateCache) GetVersionsInfo(serverURL string) (string, []metav1.APIGroup, error) {
func (c *liveStateCache) GetVersionsInfo(serverURL string) (string, []kube.APIResourceInfo, error) {
clusterInfo, err := c.getSyncedCluster(serverURL)
if err != nil {
return "", nil, err
}
return clusterInfo.GetServerVersion(), clusterInfo.GetAPIGroups(), nil
return clusterInfo.GetServerVersion(), clusterInfo.GetAPIResources(), nil
}
func (c *liveStateCache) isClusterHasApps(apps []interface{}, cluster *appv1.Cluster) bool {

View File

@@ -1,9 +1,12 @@
package cache
import (
"errors"
"fmt"
"strings"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/gitops-engine/pkg/utils/text"
v1 "k8s.io/api/core/v1"
@@ -27,25 +30,20 @@ func populateNodeInfo(un *unstructured.Unstructured, res *ResourceInfo) {
switch gvk.Kind {
case kube.PodKind:
populatePodInfo(un, res)
return
case kube.ServiceKind:
populateServiceInfo(un, res)
return
case "Node":
populateHostNodeInfo(un, res)
return
}
case "extensions", "networking.k8s.io":
switch gvk.Kind {
case kube.IngressKind:
populateIngressInfo(un, res)
return
}
case "networking.istio.io":
switch gvk.Kind {
case "VirtualService":
populateIstioVirtualServiceInfo(un, res)
return
}
}
@@ -86,16 +84,36 @@ func populateServiceInfo(un *unstructured.Unstructured, res *ResourceInfo) {
res.NetworkingInfo = &v1alpha1.ResourceNetworkingInfo{TargetLabels: targetLabels, Ingress: ingress}
}
func getServiceName(backend map[string]interface{}, gvk schema.GroupVersionKind) (string, error) {
switch gvk.Group {
case "extensions":
return fmt.Sprintf("%s", backend["serviceName"]), nil
case "networking.k8s.io":
switch gvk.Version {
case "v1beta1":
return fmt.Sprintf("%s", backend["serviceName"]), nil
case "v1":
if service, ok, err := unstructured.NestedMap(backend, "service"); ok && err == nil {
return fmt.Sprintf("%s", service["name"]), nil
}
}
}
return "", errors.New("unable to resolve string")
}
func populateIngressInfo(un *unstructured.Unstructured, res *ResourceInfo) {
ingress := getIngress(un)
targetsMap := make(map[v1alpha1.ResourceRef]bool)
gvk := un.GroupVersionKind()
if backend, ok, err := unstructured.NestedMap(un.Object, "spec", "backend"); ok && err == nil {
targetsMap[v1alpha1.ResourceRef{
Group: "",
Kind: kube.ServiceKind,
Namespace: un.GetNamespace(),
Name: fmt.Sprintf("%s", backend["serviceName"]),
}] = true
if serviceName, err := getServiceName(backend, gvk); err == nil {
targetsMap[v1alpha1.ResourceRef{
Group: "",
Kind: kube.ServiceKind,
Namespace: un.GetNamespace(),
Name: serviceName,
}] = true
}
}
urlsSet := make(map[string]bool)
if rules, ok, err := unstructured.NestedSlice(un.Object, "spec", "rules"); ok && err == nil {
@@ -123,13 +141,15 @@ func populateIngressInfo(un *unstructured.Unstructured, res *ResourceInfo) {
continue
}
if serviceName, ok, err := unstructured.NestedString(path, "backend", "serviceName"); ok && err == nil {
targetsMap[v1alpha1.ResourceRef{
Group: "",
Kind: kube.ServiceKind,
Namespace: un.GetNamespace(),
Name: serviceName,
}] = true
if backend, ok, err := unstructured.NestedMap(path, "backend"); ok && err == nil {
if serviceName, err := getServiceName(backend, gvk); err == nil {
targetsMap[v1alpha1.ResourceRef{
Group: "",
Kind: kube.ServiceKind,
Namespace: un.GetNamespace(),
Name: serviceName,
}] = true
}
}
if host == nil || host == "" {
@@ -146,6 +166,17 @@ func populateIngressInfo(un *unstructured.Unstructured, res *ResourceInfo) {
tlshost := tlsline["host"]
if tlshost == host {
stringPort = "https"
continue
}
if hosts := tlsline["hosts"]; hosts != nil {
tlshosts, ok := tlsline["hosts"].(map[string]interface{})
if ok {
for j := range tlshosts {
if tlshosts[j] == host {
stringPort = "https"
}
}
}
}
}
}

View File

@@ -43,6 +43,25 @@ var (
ingress:
- hostname: localhost`)
testLinkAnnotatedService = strToUnstructured(`
apiVersion: v1
kind: Service
metadata:
name: helm-guestbook
namespace: default
resourceVersion: "123"
uid: "4"
annotations:
link.argocd.argoproj.io/external-link: http://my-grafana.com/pre-generated-link
spec:
selector:
app: guestbook
type: LoadBalancer
status:
loadBalancer:
ingress:
- hostname: localhost`)
testIngress = strToUnstructured(`
apiVersion: extensions/v1beta1
kind: Ingress
@@ -74,6 +93,39 @@ var (
ingress:
- ip: 107.178.210.11`)
testLinkAnnotatedIngress = strToUnstructured(`
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: helm-guestbook
namespace: default
uid: "4"
annotations:
link.argocd.argoproj.io/external-link: http://my-grafana.com/ingress-link
spec:
backend:
serviceName: not-found-service
servicePort: 443
rules:
- host: helm-guestbook.com
http:
paths:
- backend:
serviceName: helm-guestbook
servicePort: 443
path: /
- backend:
serviceName: helm-guestbook
servicePort: https
path: /
tls:
- host: helm-guestbook.com
secretName: my-tls-secret
status:
loadBalancer:
ingress:
- ip: 107.178.210.11`)
testIngressWildCardPath = strToUnstructured(`
apiVersion: extensions/v1beta1
kind: Ingress
@@ -133,6 +185,43 @@ var (
ingress:
- ip: 107.178.210.11`)
testIngressNetworkingV1 = strToUnstructured(`
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: helm-guestbook
namespace: default
uid: "4"
spec:
backend:
service:
name: not-found-service
port:
number: 443
rules:
- host: helm-guestbook.com
http:
paths:
- backend:
service:
name: helm-guestbook
port:
number: 443
path: /
- backend:
service:
name: helm-guestbook
port:
name: https
path: /
tls:
- host: helm-guestbook.com
secretName: my-tls-secret
status:
loadBalancer:
ingress:
- ip: 107.178.210.11`)
testIstioVirtualService = strToUnstructured(`
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
@@ -231,6 +320,17 @@ func TestGetServiceInfo(t *testing.T) {
}, info.NetworkingInfo)
}
func TestGetLinkAnnotatedServiceInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testLinkAnnotatedService, info)
assert.Equal(t, 0, len(info.Info))
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
TargetLabels: map[string]string{"app": "guestbook"},
Ingress: []v1.LoadBalancerIngress{{Hostname: "localhost"}},
ExternalURLs: []string{"http://my-grafana.com/pre-generated-link"},
}, info.NetworkingInfo)
}
func TestGetIstioVirtualServiceInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testIstioVirtualService, info)
@@ -255,8 +355,40 @@ func TestGetIstioVirtualServiceInfo(t *testing.T) {
}
func TestGetIngressInfo(t *testing.T) {
var tests = []struct {
Ingress *unstructured.Unstructured
}{
{testIngress},
{testIngressNetworkingV1},
}
for _, tc := range tests {
info := &ResourceInfo{}
populateNodeInfo(tc.Ingress, info)
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
})
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
Ingress: []v1.LoadBalancerIngress{{IP: "107.178.210.11"}},
TargetRefs: []v1alpha1.ResourceRef{{
Namespace: "default",
Group: "",
Kind: kube.ServiceKind,
Name: "not-found-service",
}, {
Namespace: "default",
Group: "",
Kind: kube.ServiceKind,
Name: "helm-guestbook",
}},
ExternalURLs: []string{"https://helm-guestbook.com/"},
}, info.NetworkingInfo)
}
}
func TestGetLinkAnnotatedIngressInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testIngress, info)
populateNodeInfo(testLinkAnnotatedIngress, info)
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
@@ -274,7 +406,7 @@ func TestGetIngressInfo(t *testing.T) {
Kind: kube.ServiceKind,
Name: "helm-guestbook",
}},
ExternalURLs: []string{"https://helm-guestbook.com/"},
ExternalURLs: []string{"https://helm-guestbook.com/", "http://my-grafana.com/ingress-link"},
}, info.NetworkingInfo)
}
@@ -396,7 +528,7 @@ func TestGetIngressInfoNoHost(t *testing.T) {
}
func TestExternalUrlWithSubPath(t *testing.T) {
ingress := strToUnstructured(`
apiVersion: extensions/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: helm-guestbook
@@ -424,7 +556,7 @@ func TestExternalUrlWithSubPath(t *testing.T) {
}
func TestExternalUrlWithMultipleSubPaths(t *testing.T) {
ingress := strToUnstructured(`
apiVersion: extensions/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: helm-guestbook
@@ -463,7 +595,7 @@ func TestExternalUrlWithMultipleSubPaths(t *testing.T) {
}
func TestExternalUrlWithNoSubPath(t *testing.T) {
ingress := strToUnstructured(`
apiVersion: extensions/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: helm-guestbook

View File

@@ -17,8 +17,6 @@ import (
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
@@ -113,7 +111,7 @@ func (_m *LiveStateCache) GetNamespaceTopLevelResources(server string, namespace
}
// GetVersionsInfo provides a mock function with given fields: serverURL
func (_m *LiveStateCache) GetVersionsInfo(serverURL string) (string, []v1.APIGroup, error) {
func (_m *LiveStateCache) GetVersionsInfo(serverURL string) (string, []kube.APIResourceInfo, error) {
ret := _m.Called(serverURL)
var r0 string
@@ -123,12 +121,12 @@ func (_m *LiveStateCache) GetVersionsInfo(serverURL string) (string, []v1.APIGro
r0 = ret.Get(0).(string)
}
var r1 []v1.APIGroup
if rf, ok := ret.Get(1).(func(string) []v1.APIGroup); ok {
var r1 []kube.APIResourceInfo
if rf, ok := ret.Get(1).(func(string) []kube.APIResourceInfo); ok {
r1 = rf(serverURL)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).([]v1.APIGroup)
r1 = ret.Get(1).([]kube.APIResourceInfo)
}
}
@@ -178,11 +176,11 @@ func (_m *LiveStateCache) IsNamespaced(server string, gk schema.GroupKind) (bool
}
// IterateHierarchy provides a mock function with given fields: server, key, action
func (_m *LiveStateCache) IterateHierarchy(server string, key kube.ResourceKey, action func(v1alpha1.ResourceNode, string)) error {
func (_m *LiveStateCache) IterateHierarchy(server string, key kube.ResourceKey, action func(v1alpha1.ResourceNode, string) bool) error {
ret := _m.Called(server, key, action)
var r0 error
if rf, ok := ret.Get(0).(func(string, kube.ResourceKey, func(v1alpha1.ResourceNode, string)) error); ok {
if rf, ok := ret.Get(0).(func(string, kube.ResourceKey, func(v1alpha1.ResourceNode, string) bool) error); ok {
r0 = rf(server, key, action)
} else {
r0 = ret.Error(0)

View File

@@ -64,6 +64,7 @@ func (c *clusterInfoUpdater) updateClusters() {
clusters, err := c.db.ListClusters(context.Background())
if err != nil {
log.Warnf("Failed to save clusters info: %v", err)
return
}
var clustersFiltered []appv1.Cluster
if c.clusterFilter == nil {
@@ -106,7 +107,7 @@ func (c *clusterInfoUpdater) updateClusterInfo(cluster appv1.Cluster, info *cach
}
if info != nil {
clusterInfo.ServerVersion = info.K8SVersion
clusterInfo.APIVersions = argo.APIGroupsToVersions(info.APIGroups)
clusterInfo.APIVersions = argo.APIResourcesToStrings(info.APIResources, false)
if info.LastCacheSyncTime == nil {
clusterInfo.ConnectionState.Status = appv1.ConnectionStatusUnknown
} else if info.SyncError == nil {

View File

@@ -41,6 +41,12 @@ var (
descClusterDefaultLabels,
nil,
)
descClusterConnectionStatus = prometheus.NewDesc(
"argocd_cluster_connection_status",
"The k8s cluster current connection status.",
append(descClusterDefaultLabels, "k8s_version"),
nil,
)
)
type HasClustersInfo interface {
@@ -77,9 +83,11 @@ func (c *clusterCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- descClusterCacheResources
ch <- descClusterAPIs
ch <- descClusterCacheAgeSeconds
ch <- descClusterConnectionStatus
}
func (c *clusterCollector) Collect(ch chan<- prometheus.Metric) {
now := time.Now()
for _, c := range c.info {
defaultValues := []string{c.Server}
@@ -91,5 +99,6 @@ func (c *clusterCollector) Collect(ch chan<- prometheus.Metric) {
cacheAgeSeconds = int(now.Sub(*c.LastCacheSyncTime).Seconds())
}
ch <- prometheus.MustNewConstMetric(descClusterCacheAgeSeconds, prometheus.GaugeValue, float64(cacheAgeSeconds), defaultValues...)
ch <- prometheus.MustNewConstMetric(descClusterConnectionStatus, prometheus.GaugeValue, boolFloat64(c.SyncError == nil), append(defaultValues, c.K8SVersion)...)
}
}

View File

@@ -0,0 +1,104 @@
package metrics
import (
"errors"
"testing"
gitopsCache "github.com/argoproj/gitops-engine/pkg/cache"
)
func TestMetricClusterConnectivity(t *testing.T) {
type testCases struct {
testCombination
skip bool
description string
metricLabels []string
clustersInfo []gitopsCache.ClusterInfo
}
cases := []testCases{
{
description: "metric will have value 1 if connected with the cluster",
skip: false,
metricLabels: []string{"non-existing"},
testCombination: testCombination{
applications: []string{fakeApp},
responseContains: `
# TYPE argocd_cluster_connection_status gauge
argocd_cluster_connection_status{k8s_version="1.21",server="server1"} 1
`,
},
clustersInfo: []gitopsCache.ClusterInfo{
{
Server: "server1",
K8SVersion: "1.21",
SyncError: nil,
},
},
},
{
description: "metric will have value 0 if not connected with the cluster",
skip: false,
metricLabels: []string{"non-existing"},
testCombination: testCombination{
applications: []string{fakeApp},
responseContains: `
# TYPE argocd_cluster_connection_status gauge
argocd_cluster_connection_status{k8s_version="1.21",server="server1"} 0
`,
},
clustersInfo: []gitopsCache.ClusterInfo{
{
Server: "server1",
K8SVersion: "1.21",
SyncError: errors.New("error connecting with cluster"),
},
},
},
{
description: "will have one metric per cluster",
skip: false,
metricLabels: []string{"non-existing"},
testCombination: testCombination{
applications: []string{fakeApp},
responseContains: `
# TYPE argocd_cluster_connection_status gauge
argocd_cluster_connection_status{k8s_version="1.21",server="server1"} 1
argocd_cluster_connection_status{k8s_version="1.21",server="server2"} 1
argocd_cluster_connection_status{k8s_version="1.21",server="server3"} 1
`,
},
clustersInfo: []gitopsCache.ClusterInfo{
{
Server: "server1",
K8SVersion: "1.21",
SyncError: nil,
},
{
Server: "server2",
K8SVersion: "1.21",
SyncError: nil,
},
{
Server: "server3",
K8SVersion: "1.21",
SyncError: nil,
},
},
},
}
for _, c := range cases {
c := c
t.Run(c.description, func(t *testing.T) {
if !c.skip {
cfg := TestMetricServerConfig{
FakeAppYAMLs: c.applications,
ExpectedResponse: c.responseContains,
AppLabels: c.metricLabels,
ClustersInfo: c.clustersInfo,
}
runTest(t, cfg)
}
})
}
}

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"net/http"
"os"
"regexp"
"strconv"
"time"
@@ -20,6 +21,7 @@ import (
applister "github.com/argoproj/argo-cd/v2/pkg/client/listers/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/git"
"github.com/argoproj/argo-cd/v2/util/healthz"
"github.com/argoproj/argo-cd/v2/util/profile"
)
type MetricsServer struct {
@@ -49,6 +51,8 @@ const (
var (
descAppDefaultLabels = []string{"namespace", "name", "project"}
descAppLabels *prometheus.Desc
descAppInfo = prometheus.NewDesc(
"argocd_app_info",
"Information about application.",
@@ -121,7 +125,7 @@ var (
redisRequestCounter = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "argocd_redis_request_total",
Help: "Number of kubernetes requests executed during application reconciliation.",
Help: "Number of redis requests executed during application reconciliation.",
},
[]string{"hostname", "initiator", "failed"},
)
@@ -137,19 +141,32 @@ var (
)
// NewMetricsServer returns a new prometheus server which collects application metrics
func NewMetricsServer(addr string, appLister applister.ApplicationLister, appFilter func(obj interface{}) bool, healthCheck func(r *http.Request) error) (*MetricsServer, error) {
func NewMetricsServer(addr string, appLister applister.ApplicationLister, appFilter func(obj interface{}) bool, healthCheck func(r *http.Request) error, appLabels []string) (*MetricsServer, error) {
hostname, err := os.Hostname()
if err != nil {
return nil, err
}
if len(appLabels) > 0 {
normalizedLabels := normalizeLabels("label", appLabels)
descAppLabels = prometheus.NewDesc(
"argocd_app_labels",
"Argo Application labels converted to Prometheus labels",
append(descAppDefaultLabels, normalizedLabels...),
nil,
)
}
mux := http.NewServeMux()
registry := NewAppRegistry(appLister, appFilter)
registry := NewAppRegistry(appLister, appFilter, appLabels)
registry.MustRegister(depth, adds, latency, workDuration, unfinished, longestRunningProcessor, retries)
mux.Handle(MetricsPath, promhttp.HandlerFor(prometheus.Gatherers{
// contains app controller specific metrics
registry,
// contains process, golang and controller workqueues metrics
prometheus.DefaultGatherer,
}, promhttp.HandlerOpts{}))
profile.RegisterProfiler(mux)
healthz.ServeHealthCheck(mux, healthCheck)
registry.MustRegister(syncCounter)
@@ -180,6 +197,20 @@ func NewMetricsServer(addr string, appLister applister.ApplicationLister, appFil
}, nil
}
// Prometheus invalid labels, more info: https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels.
var invalidPromLabelChars = regexp.MustCompile(`[^a-zA-Z0-9_]`)
func normalizeLabels(prefix string, appLabels []string) []string {
results := []string{}
for _, label := range appLabels {
//prometheus labels don't accept dash in their name
curr := invalidPromLabelChars.ReplaceAllString(label, "_")
result := fmt.Sprintf("%s_%s", prefix, curr)
results = append(results, result)
}
return results
}
func (m *MetricsServer) RegisterClustersInfoSource(ctx context.Context, source HasClustersInfo) {
collector := &clusterCollector{infoSource: source}
go collector.Run(ctx)
@@ -272,25 +303,30 @@ func (m *MetricsServer) SetExpiration(cacheExpiration time.Duration) error {
type appCollector struct {
store applister.ApplicationLister
appFilter func(obj interface{}) bool
appLabels []string
}
// NewAppCollector returns a prometheus collector for application metrics
func NewAppCollector(appLister applister.ApplicationLister, appFilter func(obj interface{}) bool) prometheus.Collector {
func NewAppCollector(appLister applister.ApplicationLister, appFilter func(obj interface{}) bool, appLabels []string) prometheus.Collector {
return &appCollector{
store: appLister,
appFilter: appFilter,
appLabels: appLabels,
}
}
// NewAppRegistry creates a new prometheus registry that collects applications
func NewAppRegistry(appLister applister.ApplicationLister, appFilter func(obj interface{}) bool) *prometheus.Registry {
func NewAppRegistry(appLister applister.ApplicationLister, appFilter func(obj interface{}) bool, appLabels []string) *prometheus.Registry {
registry := prometheus.NewRegistry()
registry.MustRegister(NewAppCollector(appLister, appFilter))
registry.MustRegister(NewAppCollector(appLister, appFilter, appLabels))
return registry
}
// Describe implements the prometheus.Collector interface
func (c *appCollector) Describe(ch chan<- *prometheus.Desc) {
if len(c.appLabels) > 0 {
ch <- descAppLabels
}
ch <- descAppInfo
ch <- descAppSyncStatusCode
ch <- descAppHealthStatus
@@ -305,7 +341,7 @@ func (c *appCollector) Collect(ch chan<- prometheus.Metric) {
}
for _, app := range apps {
if c.appFilter(app) {
collectApps(ch, app)
c.collectApps(ch, app)
}
}
}
@@ -317,7 +353,7 @@ func boolFloat64(b bool) float64 {
return 0
}
func collectApps(ch chan<- prometheus.Metric, app *argoappv1.Application) {
func (c *appCollector) collectApps(ch chan<- prometheus.Metric, app *argoappv1.Application) {
addConstMetric := func(desc *prometheus.Desc, t prometheus.ValueType, v float64, lv ...string) {
project := app.Spec.GetProject()
lv = append([]string{app.Namespace, app.Name, project}, lv...)
@@ -344,6 +380,15 @@ func collectApps(ch chan<- prometheus.Metric, app *argoappv1.Application) {
addGauge(descAppInfo, 1, git.NormalizeGitURL(app.Spec.Source.RepoURL), app.Spec.Destination.Server, app.Spec.Destination.Namespace, string(syncStatus), string(healthStatus), operation)
if len(c.appLabels) > 0 {
labelValues := []string{}
for _, desiredLabel := range c.appLabels {
value := app.GetLabels()[desiredLabel]
labelValues = append(labelValues, value)
}
addGauge(descAppLabels, 1, labelValues...)
}
// Deprecated controller metrics
if os.Getenv(EnvVarLegacyControllerMetrics) == "true" {
addGauge(descAppCreated, float64(app.CreationTimestamp.Unix()))

View File

@@ -10,6 +10,7 @@ import (
"testing"
"time"
gitopsCache "github.com/argoproj/gitops-engine/pkg/cache"
"github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
@@ -29,6 +30,10 @@ kind: Application
metadata:
name: my-app
namespace: argocd
labels:
team-name: my-team
team-bu: bu-id
argoproj.io/cluster: test-cluster
spec:
destination:
namespace: dummy-namespace
@@ -50,6 +55,10 @@ kind: Application
metadata:
name: my-app-2
namespace: argocd
labels:
team-name: my-team
team-bu: bu-id
argoproj.io/cluster: test-cluster
spec:
destination:
namespace: dummy-namespace
@@ -77,6 +86,10 @@ metadata:
name: my-app-3
namespace: argocd
deletionTimestamp: "2020-03-16T09:17:45Z"
labels:
team-name: my-team
team-bu: bu-id
argoproj.io/cluster: test-cluster
spec:
destination:
namespace: dummy-namespace
@@ -138,7 +151,7 @@ func newFakeLister(fakeAppYAMLs ...string) (context.CancelFunc, applister.Applic
fakeApps = append(fakeApps, a)
}
appClientset := appclientset.NewSimpleClientset(fakeApps...)
factory := appinformer.NewFilteredSharedInformerFactory(appClientset, 0, "argocd", func(options *metav1.ListOptions) {})
factory := appinformer.NewSharedInformerFactoryWithOptions(appClientset, 0, appinformer.WithNamespace("argocd"), appinformer.WithTweakListOptions(func(options *metav1.ListOptions) {}))
appInformer := factory.Argoproj().V1alpha1().Applications().Informer()
go appInformer.Run(ctx.Done())
if !cache.WaitForCacheSync(ctx.Done(), appInformer.HasSynced) {
@@ -148,30 +161,71 @@ func newFakeLister(fakeAppYAMLs ...string) (context.CancelFunc, applister.Applic
}
func testApp(t *testing.T, fakeAppYAMLs []string, expectedResponse string) {
cancel, appLister := newFakeLister(fakeAppYAMLs...)
t.Helper()
testMetricServer(t, fakeAppYAMLs, expectedResponse, []string{})
}
type fakeClusterInfo struct {
clustersInfo []gitopsCache.ClusterInfo
}
func (f *fakeClusterInfo) GetClustersInfo() []gitopsCache.ClusterInfo {
return f.clustersInfo
}
type TestMetricServerConfig struct {
FakeAppYAMLs []string
ExpectedResponse string
AppLabels []string
ClustersInfo []gitopsCache.ClusterInfo
}
func testMetricServer(t *testing.T, fakeAppYAMLs []string, expectedResponse string, appLabels []string) {
t.Helper()
cfg := TestMetricServerConfig{
FakeAppYAMLs: fakeAppYAMLs,
ExpectedResponse: expectedResponse,
AppLabels: appLabels,
ClustersInfo: []gitopsCache.ClusterInfo{},
}
runTest(t, cfg)
}
func runTest(t *testing.T, cfg TestMetricServerConfig) {
t.Helper()
cancel, appLister := newFakeLister(cfg.FakeAppYAMLs...)
defer cancel()
metricsServ, err := NewMetricsServer("localhost:8082", appLister, appFilter, noOpHealthCheck)
metricsServ, err := NewMetricsServer("localhost:8082", appLister, appFilter, noOpHealthCheck, cfg.AppLabels)
assert.NoError(t, err)
if len(cfg.ClustersInfo) > 0 {
ci := &fakeClusterInfo{clustersInfo: cfg.ClustersInfo}
collector := &clusterCollector{
infoSource: ci,
info: ci.GetClustersInfo(),
}
metricsServ.registry.MustRegister(collector)
}
req, err := http.NewRequest("GET", "/metrics", nil)
assert.NoError(t, err)
rr := httptest.NewRecorder()
metricsServ.Handler.ServeHTTP(rr, req)
assert.Equal(t, rr.Code, http.StatusOK)
body := rr.Body.String()
log.Println(body)
assertMetricsPrinted(t, expectedResponse, body)
assertMetricsPrinted(t, cfg.ExpectedResponse, body)
}
type testCombination struct {
applications []string
expectedResponse string
responseContains string
}
func TestMetrics(t *testing.T) {
combinations := []testCombination{
{
applications: []string{fakeApp, fakeApp2, fakeApp3},
expectedResponse: `
responseContains: `
# HELP argocd_app_info Information about application.
# TYPE argocd_app_info gauge
argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:6443",health_status="Degraded",name="my-app-3",namespace="argocd",operation="delete",project="important-project",repo="https://github.com/argoproj/argocd-example-apps",sync_status="OutOfSync"} 1
@@ -181,7 +235,7 @@ argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:
},
{
applications: []string{fakeDefaultApp},
expectedResponse: `
responseContains: `
# HELP argocd_app_info Information about application.
# TYPE argocd_app_info gauge
argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:6443",health_status="Healthy",name="my-app",namespace="argocd",operation="",project="default",repo="https://github.com/argoproj/argocd-example-apps",sync_status="Synced"} 1
@@ -190,7 +244,50 @@ argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:
}
for _, combination := range combinations {
testApp(t, combination.applications, combination.expectedResponse)
testApp(t, combination.applications, combination.responseContains)
}
}
func TestMetricLabels(t *testing.T) {
type testCases struct {
testCombination
description string
metricLabels []string
}
cases := []testCases{
{
description: "will return the labels metrics successfully",
metricLabels: []string{"team-name", "team-bu", "argoproj.io/cluster"},
testCombination: testCombination{
applications: []string{fakeApp, fakeApp2, fakeApp3},
responseContains: `
# TYPE argocd_app_labels gauge
argocd_app_labels{label_argoproj_io_cluster="test-cluster",label_team_bu="bu-id",label_team_name="my-team",name="my-app",namespace="argocd",project="important-project"} 1
argocd_app_labels{label_argoproj_io_cluster="test-cluster",label_team_bu="bu-id",label_team_name="my-team",name="my-app-2",namespace="argocd",project="important-project"} 1
argocd_app_labels{label_argoproj_io_cluster="test-cluster",label_team_bu="bu-id",label_team_name="my-team",name="my-app-3",namespace="argocd",project="important-project"} 1
`,
},
},
{
description: "metric will have empty label value if not present in the application",
metricLabels: []string{"non-existing"},
testCombination: testCombination{
applications: []string{fakeApp, fakeApp2, fakeApp3},
responseContains: `
# TYPE argocd_app_labels gauge
argocd_app_labels{label_non_existing="",name="my-app",namespace="argocd",project="important-project"} 1
argocd_app_labels{label_non_existing="",name="my-app-2",namespace="argocd",project="important-project"} 1
argocd_app_labels{label_non_existing="",name="my-app-3",namespace="argocd",project="important-project"} 1
`,
},
},
}
for _, c := range cases {
c := c
t.Run(c.description, func(t *testing.T) {
testMetricServer(t, c.applications, c.responseContains, c.metricLabels)
})
}
}
@@ -222,7 +319,7 @@ argocd_app_sync_status{name="my-app",namespace="argocd",project="important-proje
func TestMetricsSyncCounter(t *testing.T) {
cancel, appLister := newFakeLister()
defer cancel()
metricsServ, err := NewMetricsServer("localhost:8082", appLister, appFilter, noOpHealthCheck)
metricsServ, err := NewMetricsServer("localhost:8082", appLister, appFilter, noOpHealthCheck, []string{})
assert.NoError(t, err)
appSyncTotal := `
@@ -252,11 +349,12 @@ argocd_app_sync_total{dest_server="https://localhost:6443",name="my-app",namespa
// assertMetricsPrinted asserts every line in the expected lines appears in the body
func assertMetricsPrinted(t *testing.T, expectedLines, body string) {
t.Helper()
for _, line := range strings.Split(expectedLines, "\n") {
if line == "" {
continue
}
assert.Contains(t, body, line)
assert.Contains(t, body, line, "expected metrics mismatch")
}
}
@@ -273,7 +371,7 @@ func assertMetricsNotPrinted(t *testing.T, expectedLines, body string) {
func TestReconcileMetrics(t *testing.T) {
cancel, appLister := newFakeLister()
defer cancel()
metricsServ, err := NewMetricsServer("localhost:8082", appLister, appFilter, noOpHealthCheck)
metricsServ, err := NewMetricsServer("localhost:8082", appLister, appFilter, noOpHealthCheck, []string{})
assert.NoError(t, err)
appReconcileMetrics := `
@@ -306,7 +404,7 @@ argocd_app_reconcile_count{dest_server="https://localhost:6443",namespace="argoc
func TestMetricsReset(t *testing.T) {
cancel, appLister := newFakeLister()
defer cancel()
metricsServ, err := NewMetricsServer("localhost:8082", appLister, appFilter, noOpHealthCheck)
metricsServ, err := NewMetricsServer("localhost:8082", appLister, appFilter, noOpHealthCheck, []string{})
assert.NoError(t, err)
appSyncTotal := `

View File

@@ -0,0 +1,101 @@
package metrics
import (
"github.com/prometheus/client_golang/prometheus"
"k8s.io/client-go/util/workqueue"
)
const (
WorkQueueSubsystem = "workqueue"
DepthKey = "depth"
AddsKey = "adds_total"
QueueLatencyKey = "queue_duration_seconds"
WorkDurationKey = "work_duration_seconds"
UnfinishedWorkKey = "unfinished_work_seconds"
LongestRunningProcessorKey = "longest_running_processor_seconds"
RetriesKey = "retries_total"
)
var (
depth = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Subsystem: WorkQueueSubsystem,
Name: DepthKey,
Help: "Current depth of workqueue",
}, []string{"name"})
adds = prometheus.NewCounterVec(prometheus.CounterOpts{
Subsystem: WorkQueueSubsystem,
Name: AddsKey,
Help: "Total number of adds handled by workqueue",
}, []string{"name"})
latency = prometheus.NewHistogramVec(prometheus.HistogramOpts{
Subsystem: WorkQueueSubsystem,
Name: QueueLatencyKey,
Help: "How long in seconds an item stays in workqueue before being requested",
Buckets: []float64{1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1, 5, 10, 15, 30, 60, 120, 180},
}, []string{"name"})
workDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
Subsystem: WorkQueueSubsystem,
Name: WorkDurationKey,
Help: "How long in seconds processing an item from workqueue takes.",
Buckets: []float64{1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1, 5, 10, 15, 30, 60, 120, 180},
}, []string{"name"})
unfinished = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Subsystem: WorkQueueSubsystem,
Name: UnfinishedWorkKey,
Help: "How many seconds of work has been done that " +
"is in progress and hasn't been observed by work_duration. Large " +
"values indicate stuck threads. One can deduce the number of stuck " +
"threads by observing the rate at which this increases.",
}, []string{"name"})
longestRunningProcessor = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Subsystem: WorkQueueSubsystem,
Name: LongestRunningProcessorKey,
Help: "How many seconds has the longest running " +
"processor for workqueue been running.",
}, []string{"name"})
retries = prometheus.NewCounterVec(prometheus.CounterOpts{
Subsystem: WorkQueueSubsystem,
Name: RetriesKey,
Help: "Total number of retries handled by workqueue",
}, []string{"name"})
)
func init() {
workqueue.SetProvider(workqueueMetricsProvider{})
}
type workqueueMetricsProvider struct{}
func (workqueueMetricsProvider) NewDepthMetric(name string) workqueue.GaugeMetric {
return depth.WithLabelValues(name)
}
func (workqueueMetricsProvider) NewAddsMetric(name string) workqueue.CounterMetric {
return adds.WithLabelValues(name)
}
func (workqueueMetricsProvider) NewLatencyMetric(name string) workqueue.HistogramMetric {
return latency.WithLabelValues(name)
}
func (workqueueMetricsProvider) NewWorkDurationMetric(name string) workqueue.HistogramMetric {
return workDuration.WithLabelValues(name)
}
func (workqueueMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) workqueue.SettableGaugeMetric {
return unfinished.WithLabelValues(name)
}
func (workqueueMetricsProvider) NewLongestRunningProcessorSecondsMetric(name string) workqueue.SettableGaugeMetric {
return longestRunningProcessor.WithLabelValues(name)
}
func (workqueueMetricsProvider) NewRetriesMetric(name string) workqueue.CounterMetric {
return retries.WithLabelValues(name)
}

View File

@@ -13,7 +13,6 @@ import (
hookutil "github.com/argoproj/gitops-engine/pkg/sync/hook"
"github.com/argoproj/gitops-engine/pkg/sync/ignore"
resourceutil "github.com/argoproj/gitops-engine/pkg/sync/resource"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
kubeutil "github.com/argoproj/gitops-engine/pkg/utils/kube"
log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -30,6 +29,7 @@ import (
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/util/argo"
argodiff "github.com/argoproj/argo-cd/v2/util/argo/diff"
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/gpg"
@@ -64,13 +64,14 @@ type AppStateManager interface {
SyncAppState(app *v1alpha1.Application, state *v1alpha1.OperationState)
}
// comparisonResult holds the state of an application after the reconciliation
type comparisonResult struct {
syncStatus *v1alpha1.SyncStatus
healthStatus *v1alpha1.HealthStatus
resources []v1alpha1.ResourceStatus
managedResources []managedResource
reconciliationResult sync.ReconciliationResult
diffNormalizer diff.Normalizer
diffConfig argodiff.DiffConfig
appSourceType v1alpha1.ApplicationSourceType
// timings maps phases of comparison to the duration it took to complete (for statistical purposes)
timings map[string]time.Duration
@@ -98,6 +99,7 @@ type appStateManager struct {
cache *appstatecache.Cache
namespace string
statusRefreshTimeout time.Duration
resourceTracking argo.ResourceTracking
}
func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1.ApplicationSource, appLabelKey, revision string, noCache, noRevisionCache, verifySignature bool, proj *v1alpha1.AppProject) ([]*unstructured.Unstructured, *apiclient.ManifestResponse, error) {
@@ -138,6 +140,10 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
if err != nil {
return nil, nil, err
}
enabledSourceTypes, err := m.settingsMgr.GetEnabledSourceTypes()
if err != nil {
return nil, nil, err
}
ts.AddCheckpoint("plugins_ms")
tools := make([]*appv1.ConfigManagementPlugin, len(plugins))
for i := range plugins {
@@ -148,32 +154,41 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
if err != nil {
return nil, nil, err
}
kustomizeOptions, err := kustomizeSettings.GetOptions(app.Spec.Source)
if err != nil {
return nil, nil, err
}
helmOptions, err := m.settingsMgr.GetHelmSettings()
if err != nil {
return nil, nil, err
}
ts.AddCheckpoint("build_options_ms")
serverVersion, apiGroups, err := m.liveStateCache.GetVersionsInfo(app.Spec.Destination.Server)
serverVersion, apiResources, err := m.liveStateCache.GetVersionsInfo(app.Spec.Destination.Server)
if err != nil {
return nil, nil, err
}
ts.AddCheckpoint("version_ms")
manifestInfo, err := repoClient.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
Repo: repo,
Repos: permittedHelmRepos,
Revision: revision,
NoCache: noCache,
NoRevisionCache: noRevisionCache,
AppLabelKey: appLabelKey,
AppName: app.Name,
Namespace: app.Spec.Destination.Namespace,
ApplicationSource: &source,
Plugins: tools,
KustomizeOptions: kustomizeOptions,
KubeVersion: serverVersion,
ApiVersions: argo.APIGroupsToVersions(apiGroups),
VerifySignature: verifySignature,
HelmRepoCreds: permittedHelmCredentials,
Repo: repo,
Repos: permittedHelmRepos,
Revision: revision,
NoCache: noCache,
NoRevisionCache: noRevisionCache,
AppLabelKey: appLabelKey,
AppName: app.Name,
Namespace: app.Spec.Destination.Namespace,
ApplicationSource: &source,
Plugins: tools,
KustomizeOptions: kustomizeOptions,
KubeVersion: serverVersion,
ApiVersions: argo.APIResourcesToStrings(apiResources, true),
VerifySignature: verifySignature,
HelmRepoCreds: permittedHelmCredentials,
TrackingMethod: string(argo.GetTrackingMethod(m.settingsMgr)),
EnabledSourceTypes: enabledSourceTypes,
HelmOptions: helmOptions,
})
if err != nil {
return nil, nil, err
@@ -247,24 +262,22 @@ func DeduplicateTargetObjects(
return result, conditions, nil
}
func (m *appStateManager) getComparisonSettings(app *appv1.Application) (string, map[string]v1alpha1.ResourceOverride, diff.Normalizer, *settings.ResourcesFilter, error) {
// getComparisonSettings will return the system level settings related to the
// diff/normalization process.
func (m *appStateManager) getComparisonSettings() (string, map[string]v1alpha1.ResourceOverride, *settings.ResourcesFilter, error) {
resourceOverrides, err := m.settingsMgr.GetResourceOverrides()
if err != nil {
return "", nil, nil, nil, err
return "", nil, nil, err
}
appLabelKey, err := m.settingsMgr.GetAppInstanceLabelKey()
if err != nil {
return "", nil, nil, nil, err
}
diffNormalizer, err := argo.NewDiffNormalizer(app.Spec.IgnoreDifferences, resourceOverrides)
if err != nil {
return "", nil, nil, nil, err
return "", nil, nil, err
}
resFilter, err := m.settingsMgr.GetResourcesFilter()
if err != nil {
return "", nil, nil, nil, err
return "", nil, nil, err
}
return appLabelKey, resourceOverrides, diffNormalizer, resFilter, nil
return appLabelKey, resourceOverrides, resFilter, nil
}
// verifyGnuPGSignature verifies the result of a GnuPG operation for a given git
@@ -306,64 +319,13 @@ func verifyGnuPGSignature(revision string, project *appv1.AppProject, manifestIn
return conditions
}
func (m *appStateManager) diffArrayCached(configArray []*unstructured.Unstructured, liveArray []*unstructured.Unstructured, cachedDiff []*appv1.ResourceDiff, opts ...diff.Option) (*diff.DiffResultList, error) {
numItems := len(configArray)
if len(liveArray) != numItems {
return nil, fmt.Errorf("left and right arrays have mismatched lengths")
}
diffByKey := map[kube.ResourceKey]*appv1.ResourceDiff{}
for i := range cachedDiff {
res := cachedDiff[i]
diffByKey[kube.NewResourceKey(res.Group, res.Kind, res.Namespace, res.Name)] = cachedDiff[i]
}
diffResultList := diff.DiffResultList{
Diffs: make([]diff.DiffResult, numItems),
}
for i := 0; i < numItems; i++ {
config := configArray[i]
live := liveArray[i]
resourceVersion := ""
var key kube.ResourceKey
if live != nil {
key = kube.GetResourceKey(live)
resourceVersion = live.GetResourceVersion()
} else {
key = kube.GetResourceKey(config)
}
var dr *diff.DiffResult
if cachedDiff, ok := diffByKey[key]; ok && cachedDiff.ResourceVersion == resourceVersion {
dr = &diff.DiffResult{
NormalizedLive: []byte(cachedDiff.NormalizedLiveState),
PredictedLive: []byte(cachedDiff.PredictedLiveState),
Modified: cachedDiff.Modified,
}
} else {
res, err := diff.Diff(configArray[i], liveArray[i], opts...)
if err != nil {
return nil, err
}
dr = res
}
if dr != nil {
diffResultList.Diffs[i] = *dr
if dr.Modified {
diffResultList.Modified = true
}
}
}
return &diffResultList, nil
}
// CompareAppState compares application git state to the live app state, using the specified
// revision and supplied source. If revision or overrides are empty, then compares against
// revision and overrides in the app spec.
func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *appv1.AppProject, revision string, source v1alpha1.ApplicationSource, noCache bool, noRevisionCache bool, localManifests []string) *comparisonResult {
ts := stats.NewTimingStats()
appLabelKey, resourceOverrides, diffNormalizer, resFilter, err := m.getComparisonSettings(app)
appLabelKey, resourceOverrides, resFilter, err := m.getComparisonSettings()
ts.AddCheckpoint("settings_ms")
// return unknown comparison result if basic comparison settings cannot be loaded
@@ -455,14 +417,16 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
// filter out all resources which are not permitted in the application project
for k, v := range liveObjByKey {
if !project.IsLiveResourcePermitted(v, app.Spec.Destination.Server) {
if !project.IsLiveResourcePermitted(v, app.Spec.Destination.Server, app.Spec.Destination.Name) {
delete(liveObjByKey, k)
}
}
trackingMethod := argo.GetTrackingMethod(m.settingsMgr)
for _, liveObj := range liveObjByKey {
if liveObj != nil {
appInstanceName := kubeutil.GetAppInstanceLabel(liveObj, appLabelKey)
appInstanceName := m.resourceTracking.GetAppName(liveObj, appLabelKey, trackingMethod)
if appInstanceName != "" && appInstanceName != app.Name {
conditions = append(conditions, v1alpha1.ApplicationCondition{
Type: v1alpha1.ApplicationConditionSharedResourceWarning,
@@ -482,28 +446,26 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
compareOptions = settings.GetDefaultDiffOptions()
}
logCtx.Debugf("built managed objects list")
var diffResults *diff.DiffResultList
diffOpts := []diff.Option{
diff.WithNormalizer(diffNormalizer),
diff.IgnoreAggregatedRoles(compareOptions.IgnoreAggregatedRoles),
}
cachedDiff := make([]*appv1.ResourceDiff, 0)
// restore comparison using cached diff result if previous comparison was performed for the same revision
revisionChanged := manifestInfo == nil || app.Status.Sync.Revision != manifestInfo.Revision
specChanged := !reflect.DeepEqual(app.Status.Sync.ComparedTo, appv1.ComparedTo{Source: app.Spec.Source, Destination: app.Spec.Destination})
_, refreshRequested := app.IsRefreshRequested()
noCache = noCache || refreshRequested || app.Status.Expired(m.statusRefreshTimeout)
noCache = noCache || refreshRequested || app.Status.Expired(m.statusRefreshTimeout) || specChanged || revisionChanged
if noCache || specChanged || revisionChanged || m.cache.GetAppManagedResources(app.Name, &cachedDiff) != nil {
// (rare) cache miss
diffResults, err = diff.DiffArray(reconciliation.Target, reconciliation.Live, diffOpts...)
diffConfigBuilder := argodiff.NewDiffConfigBuilder().
WithDiffSettings(app.Spec.IgnoreDifferences, resourceOverrides, compareOptions.IgnoreAggregatedRoles).
WithTracking(appLabelKey, string(trackingMethod))
if noCache {
diffConfigBuilder.WithNoCache()
} else {
diffResults, err = m.diffArrayCached(reconciliation.Target, reconciliation.Live, cachedDiff, diffOpts...)
diffConfigBuilder.WithCache(m.cache, app.GetName())
}
// it necessary to ignore the error at this point to avoid creating duplicated
// application conditions as argo.StateDiffs will validate this diffConfig again.
diffConfig, _ := diffConfigBuilder.Build()
diffResults, err := argodiff.StateDiffs(reconciliation.Live, reconciliation.Target, diffConfig)
if err != nil {
diffResults = &diff.DiffResultList{}
failedToLoadObjs = true
@@ -624,7 +586,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
resources: resourceSummaries,
managedResources: managedResources,
reconciliationResult: reconciliation,
diffNormalizer: diffNormalizer,
diffConfig: diffConfig,
diffResultList: diffResults,
}
if manifestInfo != nil {
@@ -681,6 +643,7 @@ func NewAppStateManager(
metricsServer *metrics.MetricsServer,
cache *appstatecache.Cache,
statusRefreshTimeout time.Duration,
resourceTracking argo.ResourceTracking,
) AppStateManager {
return &appStateManager{
liveStateCache: liveStateCache,
@@ -694,5 +657,6 @@ func NewAppStateManager(
projInformer: projInformer,
metricsServer: metricsServer,
statusRefreshTimeout: statusRefreshTimeout,
resourceTracking: resourceTracking,
}
}

View File

@@ -2,6 +2,7 @@ package controller
import (
"context"
"encoding/json"
"fmt"
"os"
"strconv"
@@ -11,6 +12,7 @@ import (
"github.com/argoproj/gitops-engine/pkg/sync"
"github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
jsonpatch "github.com/evanphx/json-patch"
log "github.com/sirupsen/logrus"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -22,6 +24,7 @@ import (
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
listersv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/client/listers/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/argo"
"github.com/argoproj/argo-cd/v2/util/argo/diff"
logutils "github.com/argoproj/argo-cd/v2/util/log"
"github.com/argoproj/argo-cd/v2/util/lua"
"github.com/argoproj/argo-cd/v2/util/rand"
@@ -60,6 +63,16 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
return
}
syncOp = *state.Operation.Sync
// validates if it should fail the sync if it finds shared resources
hasSharedResource, sharedResourceMessage := hasSharedResourceCondition(app)
if syncOp.SyncOptions.HasOption("FailOnSharedResource=true") &&
hasSharedResource {
state.Phase = common.OperationFailed
state.Message = fmt.Sprintf("Shared resouce found: %s", sharedResourceMessage)
return
}
if syncOp.Source == nil {
// normal sync case (where source is taken from app.spec.source)
source = app.Spec.Source
@@ -87,7 +100,7 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
revision = syncOp.Revision
}
proj, err := argo.GetAppProject(&app.Spec, listersv1alpha1.NewAppProjectLister(m.projInformer.GetIndexer()), m.namespace, m.settingsMgr)
proj, err := argo.GetAppProject(&app.Spec, listersv1alpha1.NewAppProjectLister(m.projInformer.GetIndexer()), m.namespace, m.settingsMgr, m.db, context.TODO())
if err != nil {
state.Phase = common.OperationError
state.Message = fmt.Sprintf("Failed to load application project: %v", err)
@@ -162,9 +175,24 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
return
}
reconciliationResult := compareResult.reconciliationResult
// if RespectIgnoreDifferences is enabled, it should normalize the target
// resources which in this case applies the live values in the configured
// ignore differences fields.
if syncOp.SyncOptions.HasOption("RespectIgnoreDifferences=true") {
patchedTargets, err := normalizeTargetResources(compareResult)
if err != nil {
state.Phase = common.OperationError
state.Message = fmt.Sprintf("Failed to normalize target resources: %s", err)
return
}
reconciliationResult.Target = patchedTargets
}
syncCtx, cleanup, err := sync.NewSyncContext(
compareResult.syncStatus.Revision,
compareResult.reconciliationResult,
reconciliationResult,
restConfig,
rawConfig,
m.kubectl,
@@ -176,7 +204,7 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
if !proj.IsGroupKindPermitted(un.GroupVersionKind().GroupKind(), res.Namespaced) {
return fmt.Errorf("Resource %s:%s is not permitted in project %s.", un.GroupVersionKind().Group, un.GroupVersionKind().Kind, proj.Name)
}
if res.Namespaced && !proj.IsDestinationPermitted(v1alpha1.ApplicationDestination{Namespace: un.GetNamespace(), Server: app.Spec.Destination.Server}) {
if res.Namespaced && !proj.IsDestinationPermitted(v1alpha1.ApplicationDestination{Namespace: un.GetNamespace(), Server: app.Spec.Destination.Server, Name: app.Spec.Destination.Name}) {
return fmt.Errorf("namespace %v is not permitted in project '%s'", un.GetNamespace(), proj.Name)
}
return nil
@@ -245,6 +273,159 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
}
}
// normalizeTargetResources will apply the diff normalization in all live and target resources.
// Then it calculates the merge patch between the normalized live and the current live resources.
// Finally it applies the merge patch in the normalized target resources. This is done to ensure
// that target resources have the same ignored diff fields values from live ones to avoid them to
// be applied in the cluster. Returns the list of normalized target resources.
func normalizeTargetResources(cr *comparisonResult) ([]*unstructured.Unstructured, error) {
// normalize live and target resources
normalized, err := diff.Normalize(cr.reconciliationResult.Live, cr.reconciliationResult.Target, cr.diffConfig)
if err != nil {
return nil, err
}
patchedTargets := []*unstructured.Unstructured{}
for idx, live := range cr.reconciliationResult.Live {
normalizedTarget := normalized.Targets[idx]
if normalizedTarget == nil {
patchedTargets = append(patchedTargets, nil)
continue
}
originalTarget := cr.reconciliationResult.Target[idx]
if live == nil {
patchedTargets = append(patchedTargets, originalTarget)
continue
}
// calculate targetPatch between normalized and target resource
targetPatch, err := getMergePatch(normalizedTarget, originalTarget)
if err != nil {
return nil, err
}
// check if there is a patch to apply. An empty patch is identified by a '{}' string.
if len(targetPatch) > 2 {
livePatch, err := getMergePatch(normalized.Lives[idx], live)
if err != nil {
return nil, err
}
// generate a minimal patch that uses the fields from targetPatch (template)
// with livePatch values
patch, err := compilePatch(targetPatch, livePatch)
if err != nil {
return nil, err
}
normalizedTarget, err = applyMergePatch(normalizedTarget, patch)
if err != nil {
return nil, err
}
} else {
// if there is no patch just use the original target
normalizedTarget = originalTarget
}
patchedTargets = append(patchedTargets, normalizedTarget)
}
return patchedTargets, nil
}
// compilePatch will generate a patch using the fields from templatePatch with
// the values from valuePatch.
func compilePatch(templatePatch, valuePatch []byte) ([]byte, error) {
templateMap := make(map[string]interface{})
err := json.Unmarshal(templatePatch, &templateMap)
if err != nil {
return nil, err
}
valueMap := make(map[string]interface{})
err = json.Unmarshal(valuePatch, &valueMap)
if err != nil {
return nil, err
}
resultMap := intersectMap(templateMap, valueMap)
return json.Marshal(resultMap)
}
// intersectMap will return map with the fields intersection from the 2 provided
// maps populated with the valueMap values.
func intersectMap(templateMap, valueMap map[string]interface{}) map[string]interface{} {
result := make(map[string]interface{})
for k, v := range templateMap {
if innerTMap, ok := v.(map[string]interface{}); ok {
if innerVMap, ok := valueMap[k].(map[string]interface{}); ok {
result[k] = intersectMap(innerTMap, innerVMap)
}
} else if innerTSlice, ok := v.([]interface{}); ok {
if innerVSlice, ok := valueMap[k].([]interface{}); ok {
items := []interface{}{}
for idx, innerTSliceValue := range innerTSlice {
if idx < len(innerVSlice) {
if tSliceValueMap, ok := innerTSliceValue.(map[string]interface{}); ok {
if vSliceValueMap, ok := innerVSlice[idx].(map[string]interface{}); ok {
item := intersectMap(tSliceValueMap, vSliceValueMap)
items = append(items, item)
}
} else {
items = append(items, innerVSlice[idx])
}
}
}
if len(items) > 0 {
result[k] = items
}
}
} else {
if _, ok := valueMap[k]; ok {
result[k] = valueMap[k]
}
}
}
return result
}
// getMergePatch calculates and returns the patch between the original and the
// modified unstructures.
func getMergePatch(original, modified *unstructured.Unstructured) ([]byte, error) {
originalJSON, err := original.MarshalJSON()
if err != nil {
return nil, err
}
modifiedJSON, err := modified.MarshalJSON()
if err != nil {
return nil, err
}
return jsonpatch.CreateMergePatch(originalJSON, modifiedJSON)
}
// applyMergePatch will apply the given patch in the obj and return the patched
// unstructure.
func applyMergePatch(obj *unstructured.Unstructured, patch []byte) (*unstructured.Unstructured, error) {
originalJSON, err := obj.MarshalJSON()
if err != nil {
return nil, err
}
patchedJSON, err := jsonpatch.MergePatch(originalJSON, patch)
if err != nil {
return nil, err
}
patchedObj := &unstructured.Unstructured{}
_, _, err = unstructured.UnstructuredJSONScheme.Decode(patchedJSON, nil, patchedObj)
if err != nil {
return nil, err
}
return patchedObj, nil
}
// hasSharedResourceCondition will check if the Application has any resource that has already
// been synced by another Application. If the resource is found in another Application it returns
// true along with a human readable message of which specific resource has this condition.
func hasSharedResourceCondition(app *v1alpha1.Application) (bool, string) {
for _, condition := range app.Status.Conditions {
if condition.Type == v1alpha1.ApplicationConditionSharedResourceWarning {
return true, condition.Message
}
}
return false, ""
}
// delayBetweenSyncWaves is a gitops-engine SyncWaveHook which introduces an artificial delay
// between each sync wave. We introduce an artificial delay in order give other controllers a
// _chance_ to react to the spec change that we just applied. This is important because without

View File

@@ -5,15 +5,20 @@ import (
"os"
"testing"
"github.com/argoproj/gitops-engine/pkg/sync"
"github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"github.com/argoproj/argo-cd/v2/controller/testdata"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/test"
"github.com/argoproj/argo-cd/v2/util/argo/diff"
)
func TestPersistRevisionHistory(t *testing.T) {
@@ -142,3 +147,204 @@ func TestSyncComparisonError(t *testing.T) {
assert.NotEmpty(t, conditions)
assert.Equal(t, "abc123", opState.SyncResult.Revision)
}
func TestAppStateManager_SyncAppState(t *testing.T) {
type fixture struct {
project *v1alpha1.AppProject
application *v1alpha1.Application
controller *ApplicationController
}
setup := func() *fixture {
app := newFakeApp()
app.Status.OperationState = nil
app.Status.History = nil
project := &v1alpha1.AppProject{
ObjectMeta: v1.ObjectMeta{
Namespace: test.FakeArgoCDNamespace,
Name: "default",
},
Spec: v1alpha1.AppProjectSpec{
SignatureKeys: []v1alpha1.SignatureKey{{KeyID: "test"}},
},
}
data := fakeData{
apps: []runtime.Object{app, project},
manifestResponse: &apiclient.ManifestResponse{
Manifests: []string{},
Namespace: test.FakeDestNamespace,
Server: test.FakeClusterURL,
Revision: "abc123",
},
managedLiveObjs: make(map[kube.ResourceKey]*unstructured.Unstructured),
}
ctrl := newFakeController(&data)
return &fixture{
project: project,
application: app,
controller: ctrl,
}
}
t.Run("will fail the sync if finds shared resources", func(t *testing.T) {
// given
t.Parallel()
f := setup()
syncErrorMsg := "deployment already applied by another application"
condition := v1alpha1.ApplicationCondition{
Type: v1alpha1.ApplicationConditionSharedResourceWarning,
Message: syncErrorMsg,
}
f.application.Status.Conditions = append(f.application.Status.Conditions, condition)
// Sync with source unspecified
opState := &v1alpha1.OperationState{Operation: v1alpha1.Operation{
Sync: &v1alpha1.SyncOperation{
Source: &v1alpha1.ApplicationSource{},
SyncOptions: []string{"FailOnSharedResource=true"},
},
}}
// when
f.controller.appStateManager.SyncAppState(f.application, opState)
// then
assert.Equal(t, common.OperationFailed, opState.Phase)
assert.Contains(t, opState.Message, syncErrorMsg)
})
}
func TestNormalizeTargetResources(t *testing.T) {
type fixture struct {
comparisonResult *comparisonResult
}
setup := func(t *testing.T, ignores []v1alpha1.ResourceIgnoreDifferences) *fixture {
t.Helper()
dc, err := diff.NewDiffConfigBuilder().
WithDiffSettings(ignores, nil, true).
WithNoCache().
Build()
require.NoError(t, err)
live := test.YamlToUnstructured(testdata.LiveDeploymentYaml)
target := test.YamlToUnstructured(testdata.TargetDeploymentYaml)
return &fixture{
&comparisonResult{
reconciliationResult: sync.ReconciliationResult{
Live: []*unstructured.Unstructured{live},
Target: []*unstructured.Unstructured{target},
},
diffConfig: dc,
},
}
}
t.Run("will modify target resource adding live state in fields it should ignore", func(t *testing.T) {
// given
ignore := v1alpha1.ResourceIgnoreDifferences{
Group: "*",
Kind: "*",
ManagedFieldsManagers: []string{"janitor"},
}
ignores := []v1alpha1.ResourceIgnoreDifferences{ignore}
f := setup(t, ignores)
// when
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
require.Equal(t, 1, len(targets))
iksmVersion := targets[0].GetAnnotations()["iksm-version"]
assert.Equal(t, "2.0", iksmVersion)
})
t.Run("will not modify target resource if ignore difference is not configured", func(t *testing.T) {
// given
f := setup(t, []v1alpha1.ResourceIgnoreDifferences{})
// when
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
require.Equal(t, 1, len(targets))
iksmVersion := targets[0].GetAnnotations()["iksm-version"]
assert.Equal(t, "1.0", iksmVersion)
})
t.Run("will remove fields from target if not present in live", func(t *testing.T) {
ignore := v1alpha1.ResourceIgnoreDifferences{
Group: "apps",
Kind: "Deployment",
JSONPointers: []string{"/metadata/annotations/iksm-version"},
}
ignores := []v1alpha1.ResourceIgnoreDifferences{ignore}
f := setup(t, ignores)
live := f.comparisonResult.reconciliationResult.Live[0]
unstructured.RemoveNestedField(live.Object, "metadata", "annotations", "iksm-version")
// when
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
require.Equal(t, 1, len(targets))
_, ok := targets[0].GetAnnotations()["iksm-version"]
assert.False(t, ok)
})
t.Run("will correctly normalize with multiple ignore configurations", func(t *testing.T) {
// given
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
Group: "apps",
Kind: "Deployment",
JSONPointers: []string{"/spec/replicas"},
},
{
Group: "*",
Kind: "*",
ManagedFieldsManagers: []string{"janitor"},
},
}
f := setup(t, ignores)
// when
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
require.Equal(t, 1, len(targets))
normalized := targets[0]
iksmVersion, ok := normalized.GetAnnotations()["iksm-version"]
require.True(t, ok)
assert.Equal(t, "2.0", iksmVersion)
replicas, ok, err := unstructured.NestedInt64(normalized.Object, "spec", "replicas")
require.NoError(t, err)
require.True(t, ok)
assert.Equal(t, int64(4), replicas)
})
t.Run("will keep new array entries not found in live state if not ignored", func(t *testing.T) {
t.Skip("limitation in the current implementation")
// given
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
Group: "apps",
Kind: "Deployment",
JQPathExpressions: []string{".spec.template.spec.containers[] | select(.name == \"guestbook-ui\")"},
},
}
f := setup(t, ignores)
target := test.YamlToUnstructured(testdata.TargetDeploymentNewEntries)
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
// when
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
require.Equal(t, 1, len(targets))
containers, ok, err := unstructured.NestedSlice(targets[0].Object, "spec", "template", "spec", "containers")
require.NoError(t, err)
require.True(t, ok)
assert.Equal(t, 2, len(containers))
})
}

14
controller/testdata/data.go vendored Normal file
View File

@@ -0,0 +1,14 @@
package testdata
import _ "embed"
var (
//go:embed live-deployment.yaml
LiveDeploymentYaml string
//go:embed target-deployment.yaml
TargetDeploymentYaml string
//go:embed target-deployment-new-entries.yaml
TargetDeploymentNewEntries string
)

177
controller/testdata/live-deployment.yaml vendored Normal file
View File

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

View File

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

View File

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

View File

@@ -1 +1 @@
Please refer to [the Contribution Guide](https://argo-cd.readthedocs.io/en/latest/developer-guide/contributing/)
Please refer to [the Contribution Guide](https://argo-cd.readthedocs.io/en/latest/developer-guide/code-contributions/)

0
docs/assets/azure-enterprise-claims.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

0
docs/assets/azure-enterprise-saml-urls.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

0
docs/assets/azure-enterprise-users.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

BIN
docs/assets/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -4,6 +4,12 @@ You can download the latest Argo CD version from [the latest release page of thi
## Linux and WSL
### ArchLinux User Repository ([AUR](https://aur.archlinux.org/packages/))
```bash
yay -Sy argocd-bin
```
### Homebrew
```bash

View File

@@ -15,7 +15,7 @@ Since the CI pipeline is triggered on Git commits, there is currently no (known)
If you are absolutely sure that the failure was due to a failure in the pipeline, and not an error within the changes you committed, you can push an empty commit to your branch, thus retriggering the pipeline without any code changes. To do so, issue
```bash
git commit --allow-empty -m "Retrigger CI pipeline"
git commit -s --allow-empty -m "Retrigger CI pipeline"
git push origin <yourbranch>
```
@@ -23,7 +23,9 @@ git push origin <yourbranch>
First, make sure the failing build step succeeds on your machine. Remember the containerized build toolchain is available, too.
If the build is failing at the `Ensuring Gopkg.lock is up-to-date` step, you need to update the dependencies before you push your commits. Run `make dep-ensure` and `make dep` and commit the changes to `Gopkg.lock` to your branch.
If the build is failing at the `Ensure Go modules synchronicity` step, you need to first download all Go dependent modules locally via `go mod download` and then run `go mod tidy` to make sure the dependent Go modules are tidied up. Finally commit and push your changes to `go.mod` and `go.sum` to your branch.
If the build is failing at the `Build & cache Go code`, you need to make sure `make build-local` runs successfully on your local machine.
### Why does the codegen step fail?

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