Compare commits

..

352 Commits

Author SHA1 Message Date
rumstead
ac74bea647 fix: traverse generator tree when getting requeue time (#12407) (#12409)
* add unit test reproducing

Signed-off-by: rumstead <rjumstead@gmail.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

* feat: Begin polishing top bar design (#12327)

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

* chore: add dist to path to use our kustomize version (#12352)

* chore: add dist to path to use our kustomize version

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* correct path

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* missed a spot

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

* fix: when resource does not exist node menu and resource details shou… (#12360)

* fix: when resource does not exist node menu and resource details should still render

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

* Retrigger CI pipeline

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

---------

Signed-off-by: Joshua Helton <jdoghelton@gmail.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

* fix: traverse generator tree when getting requeue time

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

* fix: traverse generator tree when getting requeue time

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

* remove duplicate code

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

* Retrigger CI pipeline

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

* revert gitignore

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

* update from code review

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

---------

Signed-off-by: rumstead <rjumstead@gmail.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: Joshua Helton <jdoghelton@gmail.com>
Co-authored-by: Remington Breeze <remington@breeze.software>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: jphelton <jdoghelton@gmail.com>
2023-02-24 16:31:22 -05:00
Justin Marquis
f102988793 chore: use registry.k8s.io instead of k8s.gcr.io (#12362)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-02-17 15:13:51 -05:00
dependabot[bot]
2c52907304 chore(deps): bump imjasonh/setup-crane from 0.2 to 0.3 (#12504)
Bumps [imjasonh/setup-crane](https://github.com/imjasonh/setup-crane) from 0.2 to 0.3.
- [Release notes](https://github.com/imjasonh/setup-crane/releases)
- [Commits](e82f1b9a80...00c9e93efa)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: imjasonh/setup-crane
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-17 14:40:11 -05:00
Josh Soref
1d6f8b113c docs: FAQ improvements (#12146)
* docs: use more backticks in FAQ

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* docs: add FAQ entry

The order in patch list … doesn't match $setElementOrder list: …

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

---------

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-02-17 14:24:33 -05:00
Dmitriy Mann
5bfcff8631 fix: valid username in webhook URL matching regex (#9055) (#12203)
This commit fixes incorrect regular expression used for URL matching.

Expected behavior: valid user info part is matched => webhook is sent.
Actual behavior: some valid user info is not matched, example: `ssh://user-name@example.com/org/repo` => webhook is not sent.

Context:
 - [RFC 3986 3.2.1 - User Information](https://www.rfc-editor.org/rfc/rfc3986#section-3.2.1)
 - [Username validation regex in shadow Linux package](https://github.com/shadow-maint/shadow/blob/master/libmisc/chkname.c#L36)

Signed-off-by: mdsjip <2284562+mdsjip@users.noreply.github.com>
2023-02-17 14:11:30 -05:00
dependabot[bot]
55289991c6 chore(deps): bump docker/setup-buildx-action from 2.4.0 to 2.4.1 (#12308)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.4.0 to 2.4.1.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](15c905b16b...f03ac48505)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-17 14:01:11 -05:00
atusy
b007073231 docs: fix typo (#12389)
Signed-off-by: atusy <30277794+atusy@users.noreply.github.com>
2023-02-17 13:57:48 -05:00
dependabot[bot]
536d1d0e10 chore(deps): bump actions/cache from 3.2.4 to 3.2.5 (#12433)
Bumps [actions/cache](https://github.com/actions/cache) from 3.2.4 to 3.2.5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](627f0f41f6...6998d139dd)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-17 13:52:50 -05:00
Wojtek Cichoń
dd44083d78 docs: Updated link to Jenkins and added GitHub Actions link (#12465)
Signed-off-by: Wojtek Cichoń <wojtek.cichon@protonmail.com>
2023-02-17 13:36:40 -05:00
Zadkiel Aharonian
db031bbe94 docs: fix typo in health documentation (#12497)
Signed-off-by: Zadkiel Aharonian <hello@zadkiel.fr>
2023-02-17 13:34:38 -05:00
Saumeya Katyal
ac0b3e76c0 fix(security): add url validation for help chat (#9956) (#10417)
* fix: add url validation for help chat

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

* lint check

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

* lint fix

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

* review comments

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

---------

Signed-off-by: saumeya <saumeyakatyal@gmail.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-02-17 13:19:47 -05:00
Michael Chen
a9289d2381 docs: Clarify cascade delete of resource and finalizer (#11064)
* Clarify cascade delete of resource and finalizer.

The wording of this warning was confusing.

Signed-off-by: Michael Chen <4326639+mcgitty@users.noreply.github.com>

* Update docs/operator-manual/declarative-setup.md

Co-authored-by: Nicholas Morey <nicholas@morey.tech>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---------

Signed-off-by: Michael Chen <4326639+mcgitty@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Nicholas Morey <nicholas@morey.tech>
2023-02-17 13:18:06 -05:00
schakrad
4be0ce491d fix: show full event message in pod event view (#12104) (#12267)
* #11602 fix : Object options menu truncated when selected in ApplicationListView.

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* fix for the message to be fully shown under the events section.

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* fixing lint

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

* Update application-resource-list.tsx

Signed-off-by: schakrad <58915923+schakrad@users.noreply.github.com>

* fix for  lint error

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>

---------

Signed-off-by: schakradari <saisindhu_chakradari@intuit.com>
Signed-off-by: schakrad <58915923+schakrad@users.noreply.github.com>
2023-02-17 11:58:14 -05:00
argo-bot
e86cf5d705 Bump version to 2.4.23 2023-02-16 14:40:28 +00:00
argo-bot
8f0d27705e Bump version to 2.4.23 2023-02-16 14:40:22 +00:00
Michael Crenshaw
5831a573aa Merge pull request from GHSA-3jfq-742w-xg8j
fix test name

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-02-16 09:07:57 -05:00
Michael Crenshaw
90869357fb chore: add dist to path to use our kustomize version (#12352)
* chore: add dist to path to use our kustomize version

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* correct path

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* missed a spot

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-02-09 12:18:33 -05:00
Josh Soref
d0551e4c1a docs: Fix heading to not include a v for the second version (#12218)
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-02-03 10:29:27 -05:00
Thomas Decaux
402b38dc7d docs: add destination.name example (#12242)
I had trouble finding the documentation to use the cluster name for destination, instead of the full URL. This is really useful.

Use case: we manage multiple clusters, destination.name is a better way to set destination.

Signed-off-by: Thomas Decaux <ebuildy@gmail.com>
Signed-off-by: ebuildy <ebuildy@gmail.com>
2023-02-02 12:56:27 -05:00
argo-bot
eadd25e7ed Bump version to 2.4.22 2023-02-02 14:58:52 +00:00
argo-bot
3f98ee249b Bump version to 2.4.22 2023-02-02 14:58:37 +00:00
Panagiotis Georgiadis
cafb09a8a5 fix: Upgrade gopkg.in/yaml.v2 to v2.2.4 (#12247)
Signed-off-by: Panagiotis Georgiadis <pgeorgia@redhat.com>
2023-02-01 16:37:50 -05:00
Jaideep Rao
f7b9fa32e4 fix: Upgrade goutils to v1.1.1 [release-2.4] (#12219) (#12222)
* upgrade goutils to v1.1.1

Signed-off-by: Jaideep Rao <jaideep.r97@gmail.com>

* Update go.mod

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---------

Signed-off-by: Jaideep Rao <jaideep.r97@gmail.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-02-01 14:25:55 -05:00
dependabot[bot]
8536a84775 chore(deps): bump docker/setup-buildx-action from 2.2.1 to 2.4.0 (#12227)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.2.1 to 2.4.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](8c0edbc76e...15c905b16b)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-31 16:56:06 -05:00
dependabot[bot]
4bc13fbb25 chore(deps): bump actions/cache from 3.2.3 to 3.2.4 (#12228)
Bumps [actions/cache](https://github.com/actions/cache) from 3.2.3 to 3.2.4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](58c146cc91...627f0f41f6)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-31 16:53:48 -05:00
Adam Jensen
fe6472db05 docs: Fix copy that refers to a different CLI flag (#12236)
Signed-off-by: Adam Jensen <adam@acj.sh>
2023-01-31 16:52:10 -05:00
Kostis (Codefresh)
efb0ceca33 docs: Clarify directory recursion (#12037)
Signed-off-by: Kostis Kapelonis <kostis@codefresh.io>
2023-01-31 16:29:47 -05:00
James Brady
717ac4eec1 docs: Fix list formatting in "Resource Actions" docs page (#12061)
Signed-off-by: James Brady <goodgravy@users.noreply.github.com>
2023-01-31 16:26:46 -05:00
Nobuo Takizawa
6cb2a600b0 chore: Update dex's image tag that is forgotten to be updated (#12234)
Signed-off-by: nobuyo <longzechangsheng@gmail.com>
2023-01-31 15:44:13 -05:00
argo-bot
2eb5656842 Bump version to 2.4.21 2023-01-27 23:14:45 +00:00
argo-bot
5c6f8d5460 Bump version to 2.4.21 2023-01-27 23:14:40 +00:00
Eugen Friedland
45c089b48c fix(health): Handling SparkApplication CRD health status if dynamic allocation is enabled (#7557) (#11522)
Signed-off-by: Yevgeniy Fridland <yevg.mord@gmail.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-27 15:17:27 -05:00
Michael Crenshaw
11ba4834ad fix: add CLI client IDs to default OIDC allowed audiences (#12170) (#12179)
* fix(settings): add CLI client ID in default OAuth2 allowed audiences

Signed-off-by: Yann Soubeyrand <yann.soubeyrand@camptocamp.com>

* fix: add CLI client IDs to default OIDC allowed audiences (#12170)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* docs

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* test

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* handle expired token properly

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---------

Signed-off-by: Yann Soubeyrand <yann.soubeyrand@camptocamp.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Yann Soubeyrand <yann.soubeyrand@camptocamp.com>
2023-01-27 14:43:21 -05:00
Leonardo Luz Almeida
8f4678ee1f chore: Refactor terminal handler to use auth-middleware (#12052)
* chore: Refactor terminal handler to use auth-middleware

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

* remove context key for now

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

* implement unit-tests

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

* remove claim valid check for now

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

* remove unnecessary test

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

* fix lint

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

* don't too much details in http response

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

* Fix error

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

* Fix lint

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

* trigger build

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

* builder pattern in terminal feature-flag middleware

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

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2023-01-27 13:37:02 -05:00
argo-bot
68f58c956a Bump version to 2.4.20 2023-01-25 15:28:44 +00:00
argo-bot
5b3bfc746c Bump version to 2.4.20 2023-01-25 15:28:30 +00:00
Dan Garfield
20c63babca Merge pull request from GHSA-q9hr-j4rf-8fjc
* fix: verify audience claim

Co-Authored-By: Vladimir Pouzanov <farcaller@gmail.com>
Signed-off-by: CI <350466+crenshaw-dev@users.noreply.github.com>

* fix unit tests

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* go mod tidy

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* handle single aud claim marshaled as a string

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: CI <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: CI <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Vladimir Pouzanov <farcaller@gmail.com>
2023-01-25 09:15:04 -05:00
Justin Marquis
0775c6e726 chore: disable docker sbom and attestations (#12059)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2023-01-20 10:04:20 -05:00
argo-bot
0ba9817cc2 Bump version to 2.4.19 2023-01-18 02:08:53 +00:00
argo-bot
cac46bf3a6 Bump version to 2.4.19 2023-01-18 02:08:46 +00:00
Michael Crenshaw
e89bf08452 chore: upgrade github.com/prometheus/client_golang to v1.11.1 to avoid CVE-2022-21698 (#12015)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-17 17:05:12 -05:00
Michael Crenshaw
4fa0627dd8 chore: fix bad merge
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-17 17:00:56 -05:00
Aymen Ben Tanfous
4665f19f9a fix: Fixed matrix requeueAfterSeconds for PR (#10914) (#10915)
* Fixed matrix requeueAfterSeconds for PR

Signed-off-by: Aymen Ben Tanfous <aymen.bentanfous@gmail.com>

* A try to make some tests

Signed-off-by: Aymen Ben Tanfous <aymen.bentanfous@cimpress.com>

* Fixed default test returns the default time

Signed-off-by: Aymen Ben Tanfous <aymenbentanfous@gmail.com>

* Fixed default test returns the default time

Signed-off-by: Aymen Ben Tanfous <aymenbentanfous@gmail.com>

Signed-off-by: Aymen Ben Tanfous <aymen.bentanfous@gmail.com>
Signed-off-by: Aymen Ben Tanfous <aymen.bentanfous@cimpress.com>
Signed-off-by: Aymen Ben Tanfous <aymenbentanfous@gmail.com>
Co-authored-by: Aymen Ben Tanfous <aymen.bentanfous@cimpress.com>
Co-authored-by: Aymen Ben Tanfous <aymenbentanfous@gmail.com>
2023-01-17 16:54:22 -05:00
dependabot[bot]
32ab1d906f chore(deps): bump actions/cache from 3.2.2 to 3.2.3 (#11928)
Bumps [actions/cache](https://github.com/actions/cache) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](4723a57e26...58c146cc91)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-13 09:52:10 -05:00
dependabot[bot]
64b3f0f1f4 chore(deps): bump actions/checkout from 3.2.0 to 3.3.0 (#11895)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](755da8c3cf...ac59398561)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-11 14:07:20 -05:00
Michael Crenshaw
70276136b1 chore: fix codegen
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-11 09:47:07 -05:00
Michael Crenshaw
0051144468 chore: fix codegen
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-10 16:58:51 -05:00
dependabot[bot]
df55641842 chore(deps): bump actions/setup-node from 3.5.1 to 3.6.0 (#11896)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.5.1 to 3.6.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](8c91899e58...64ed1c7eab)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-10 15:25:24 -05:00
dependabot[bot]
7cde38c52f chore(deps): bump actions/upload-artifact from 3.1.1 to 3.1.2 (#11929)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.1 to 3.1.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](83fd05a356...0b7f8abb15)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-10 15:22:04 -05:00
Michael Crenshaw
e9a2102593 Revert "fix: ssa e2e tests failing after updating to kubectl 1.26 (#11753)"
This reverts commit a10a54782a.

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-10 12:19:16 -05:00
Michael Crenshaw
56cba50d69 chore: upgrade redis to 7.0.7 to avoid CVE-2022-3996 (#11925)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-10 10:50:44 -05:00
jannfis
556565f167 chore: Upgrade shipped version of Redis to 7.0.5 to fix CVE-2022-35951 (#10702)
* chore: Upgrade redis to 7.0.5

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

* Also update Redis version in containerized toolchain

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

* Update Redis and Dex in CI

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

* Fix Dex image path

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

Signed-off-by: jannfis <jann@mistrust.net>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-10 10:44:32 -05:00
Michael Crenshaw
f625165b33 fix: upgrade qs to avoid CVE-2022-24999
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-10 10:22:46 -05:00
Alexander Matyushentsev
d11ee714b8 fix: upgrade superagent to resolve potential CVE (#9494)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2023-01-10 10:21:13 -05:00
dependabot[bot]
3aa191d777 chore(deps): bump actions/cache from 3.2.0 to 3.2.2 (#11839)
Bumps [actions/cache](https://github.com/actions/cache) from 3.2.0 to 3.2.2.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](c17f4bf466...4723a57e26)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 17:12:14 -05:00
dependabot[bot]
3487d4789d chore(deps): bump actions/download-artifact from 3.0.1 to 3.0.2 (#11894)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](9782bd6a98...9bc31d5ccc)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 16:52:29 -05:00
Michael Crenshaw
9c9fd9685a docs: note risks of secret-injection plugins (#11617)
* docs: note risks of secret-injection plugins

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* grammar tweaks

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* grammar tweaks

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-01-09 16:31:24 -05:00
dependabot[bot]
bda913c1f2 chore(deps): bump actions/cache from 3.0.11 to 3.2.0 (#11809)
Bumps [actions/cache](https://github.com/actions/cache) from 3.0.11 to 3.2.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](9b0c1fce7a...c17f4bf466)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-22 13:39:04 -05:00
Justin Marquis
e37feab905 chore: fix lint error (#11788)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-12-21 08:14:15 -05:00
Justin Marquis
e380dd1ade chore: get image digest in seperate step (#11778)
* chore: get image digest in seperate step

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

* Retrigger CI pipeline

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-12-20 17:22:40 -05:00
Gaël Jourdan-Weil
6c88a166d8 docs: clarify project destination possibilities (#11706)
Clarify that it's possible to reference clusters by `cluster` or by `name`.

Signed-off-by: Gaël Jourdan-Weil <gjourdanweil@gmail.com>

Signed-off-by: Gaël Jourdan-Weil <gjourdanweil@gmail.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-12-20 12:52:09 -05:00
Matt Clegg
f007ddffc9 docs: correct SSO configuration URL in example configmap (#11720)
Signed-off-by: Matt Clegg <m@cle.gg>

Signed-off-by: Matt Clegg <m@cle.gg>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-12-20 08:58:24 -05:00
Phil Wright- Christie
af7b29d922 docs: Update example dockerfile (#11721)
The latest tag hasn't been updated in almost a year, and as a result, the ubuntu repositories are out of date and are throwing errors. This updates the example to use a fixed version, which are updated much more frequently.

Signed-off-by: Phil Wright- Christie <philwc@gmail.com>

Signed-off-by: Phil Wright- Christie <philwc@gmail.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-12-20 08:55:26 -05:00
Leonardo Luz Almeida
a10a54782a fix: ssa e2e tests failing after updating to kubectl 1.26 (#11753)
* fix: ssa e2e test failing after updating to kubectl 1.26

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

* Remove pinned kubectl version

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

* Cleaner approach to fix e2e test

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

* Fix

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

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-12-20 08:49:49 -05:00
Nicholas Morey
20e4b8806d docs: clarify that all labels must exist (#11693)
It's unclear if all or any of the labels need to exist. This clarifies that all of the labels must exist.

Signed-off-by: Nicholas Morey <nicholas@morey.tech>

Signed-off-by: Nicholas Morey <nicholas@morey.tech>
2022-12-20 08:47:17 -05:00
dependabot[bot]
2626453cfc chore(deps): bump actions/setup-go from 3.4.0 to 3.5.0 (#11697)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](d0a58c1c4d...6edd4406fa)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 08:41:16 -05:00
yanyx
5d6600ed9d doc: correct kustomize demo path (#11762)
Signed-off-by: Yixing Yan <yixingyan@gmail.com>

Signed-off-by: Yixing Yan <yixingyan@gmail.com>
2022-12-20 08:38:17 -05:00
Justin Marquis
0f3f8db000 fix: sign container images by digest (#11151)
* chore: sign container images by digest

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

* use sha hash

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-12-19 20:46:16 -05:00
argo-bot
beef23b7a4 Bump version to 2.4.18 2022-12-16 15:57:45 +00:00
argo-bot
a97db48111 Bump version to 2.4.18 2022-12-16 15:57:36 +00:00
Leonardo Luz Almeida
69939d427a docs: Clarification of the create namespace feature (#11723)
* docs: Clarification of the create namespace feature

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

* Address review suggestion

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

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-12-16 08:33:29 -05:00
Michael Crenshaw
a7d22df297 fix: pin kubectl version (#11726)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-12-16 02:11:59 +01:00
Michael Crenshaw
0f99cdd877 chore: fix flaky e2e test for immutable fields (#11685)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-12-13 15:25:41 -05:00
dependabot[bot]
3c8c8adb37 chore(deps): bump actions/checkout from 3.1.0 to 3.2.0 (#11679)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](93ea575cb5...755da8c3cf)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-13 08:25:37 -05:00
Michael Crenshaw
e0b8b129a5 chore: fix flaky e2e test (#11670)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-12-12 17:45:06 -05:00
Michael Crenshaw
12c6cf3e8c chore: fix flaky e2e test (#11509) (#11654)
* chore: fix flaky e2e test (#11509)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* don't centralize mock response - tests should be independent

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-12-12 12:16:11 -05:00
Nicholas Morey
197e01b834 docs: kustomize has access to build environment (#11643)
Current docs reflect that the build environment is not available to kustomize. Since https://github.com/argoproj/argo-cd/pull/8096 it is now exposed for kustomize. This updates the kustomize section of the docs to reflect that.

Signed-off-by: Nicholas Morey <nicholas@morey.tech>

Signed-off-by: Nicholas Morey <nicholas@morey.tech>
2022-12-11 15:58:51 -05:00
asingh
27ff21643e docs: add warning for user when using replace sync option (#11566)
* docs: adding warning to 'replace' sync option

Signed-off-by: ashutosh16 <11219262+ashutosh16@users.noreply.github.com>

* Update sync-options.md

Signed-off-by: asingh <11219262+ashutosh16@users.noreply.github.com>

Signed-off-by: ashutosh16 <11219262+ashutosh16@users.noreply.github.com>
Signed-off-by: asingh <11219262+ashutosh16@users.noreply.github.com>
2022-12-09 14:23:09 -05:00
Alex Eftimie
ecdea743c2 fix(helm): login OCI Helm dependencies correctly (#8563) (#11327)
Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>

Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>
2022-12-07 12:53:32 -05:00
Alex Eftimie
fca6271d38 fix(helm): helm v3 doesn't have these flags (#11100) (#11540)
* fix: helm v3 doesn't have these flags

Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>

* Revert repoAdd change. Was to greedy, ca-file is needed there

Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>

Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>
2022-12-07 12:43:58 -05:00
Michael Vittrup Larsen
186c4be175 docs: Add skipCrds and ignoreMissingValueFiles to application.yaml example (#11565)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-12-06 09:51:12 -05:00
dependabot[bot]
e46ae882f1 chore(deps): bump decode-uri-component from 0.2.0 to 0.2.2 in /ui (#11533)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-03 22:11:28 -05:00
Michael Crenshaw
30f25ce113 Revert "fix: application stuck in infinite reconciliation loop if using wrong project (#11246)"
This reverts commit 1e53a3adcb.

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-12-02 09:25:13 -05:00
dependabot[bot]
72f8ff370a chore(deps): bump actions/setup-go from 3.3.1 to 3.4.0 (#11535)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3.3.1 to 3.4.0.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](c4a742cab1...d0a58c1c4d)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-02 08:54:45 -05:00
dependabot[bot]
955417ae4f chore(deps): bump softprops/action-gh-release from 0.1.14 to 0.1.15 (#11534)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 0.1.14 to 0.1.15.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](1e07f43987...de2c0eb89a)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-02 08:53:40 -05:00
Michael Merrill
e091a92f6c fix: add missing changes for bitbucket cloud SCM provider (#10143) (#11150)
Signed-off-by: mmerrill3 <jjpaacks@gmail.com>

Signed-off-by: mmerrill3 <jjpaacks@gmail.com>
2022-11-30 21:04:35 -05:00
Alexander Matyushentsev
de7d35b069 fix: expose missing ReactDOM to enable extensions implementation (#11495)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-11-30 11:10:53 -08:00
Michael Crenshaw
b6d33ba162 chore: pin actions (#11360)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-11-29 13:04:57 -05:00
Michael Crenshaw
e3ef547f16 chore: use set-output environment file (#10999)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-11-29 09:48:36 -05:00
dependabot[bot]
2868c5aa0a chore(deps): bump actions/upload-artifact from 2 to 3 (#11365)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-18 22:08:01 -05:00
dependabot[bot]
ba5bab807c chore(deps): bump actions/setup-node from 1 to 3 (#11364)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 1 to 3.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v1...v3)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-18 22:06:32 -05:00
dependabot[bot]
510e3a9557 chore(deps): bump codecov/codecov-action from 1 to 3 (#11362)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 1 to 3.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v1...v3)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-18 22:02:51 -05:00
dependabot[bot]
e52895aead chore(deps): bump actions/download-artifact from 2 to 3 (#11361)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v2...v3)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-18 21:06:33 -05:00
Alexander Matyushentsev
1e53a3adcb fix: application stuck in infinite reconciliation loop if using wrong project (#11246)
* fix: application stuck in infinite reconciliation loop if using wrong project

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

* add missing unit test

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

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-11-18 20:58:54 -05:00
Alex Eftimie
7f4b644231 fix: set HELM_CONFIG_HOME dir for oci registry authentication; fixes: #11284 (#11285)
Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>
2022-11-17 14:27:39 -08:00
Michael Crenshaw
9fc46d2a0f chore: use --password-stdin for docker login (#11331)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-11-17 10:47:07 -05:00
Edmund Rhudy
547f666fb2 fix: UI can now get clusters with slashes in name (#9812) (#9813)
* fix: #9812 UI can now get clusters with slashes in name

Fixes #9812

If a cluster name has a slash in it, the API would not be able
to fetch that cluster and would display "in-cluster (undefined)"
for that application. This fixes that issue by URI-encoding
the cluster name on the UI side and URI-decoding the cluster name
on the API side.

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

* Retrigger CI pipeline

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

Signed-off-by: Edmund Rhudy <erhudy@users.noreply.github.com>
2022-11-17 09:56:12 -05:00
Shuai Zhang
41a2505bf8 fix: allow resolving repo root as jsonnet lib path (#11119)
Signed-off-by: shuai-zh <shuaiz8023@gmail.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-11-15 18:10:14 -05:00
Justin Marquis
b8feaf4db9 fix: use non distroless image for dex (#11219)
* fix: use non distroless image for dex

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

* change image in ci workflow

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-11-09 08:26:14 -05:00
argo-bot
d330967960 Bump version to 2.4.17 2022-11-07 16:28:03 +00:00
argo-bot
158a580df0 Bump version to 2.4.17 2022-11-07 16:27:56 +00:00
Leonardo Luz Almeida
5e8ac1b2d6 fix: handle apiGroup updates in resource-tracking (#11012)
* fix: handle apiGroup updates in resource-tracking

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

* Fix test

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

* change the fix approach by inspecting tracking id from the config

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

* add unit-test to validate the scenario

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

* fix test lint

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

* review fixes

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

* Reword godocs for clarity

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

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-11-03 15:02:45 -04:00
argo-bot
7b5899be33 Bump version to 2.4.16 2022-11-01 21:00:28 +00:00
argo-bot
efa96006cc Bump version to 2.4.16 2022-11-01 21:00:22 +00:00
Michael Crenshaw
b871316bba chore: don't generate release notes (#11141)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-11-01 16:21:34 -04:00
Chromo-residuum-opec
c8a1a8650e docs: fix 'bellow' typos (#11038)
Signed-off-by: backfire-monism-net <development.0extl@simplelogin.com>

Signed-off-by: backfire-monism-net <development.0extl@simplelogin.com>
2022-10-22 20:13:36 -04:00
Michael Crenshaw
27af817afb chore: fix CI (#11022)
* chore: fix CI

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* no more set global

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-21 11:24:10 -04:00
Michael Crenshaw
c7dd9bc6d2 chore: fix e2e (#11005)
* chore: fix e2e

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* more config

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* global

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-21 11:23:14 -04:00
Alex Eftimie
e41612927e docs: mention that OCI helm does not support version ranges (#11026)
* docs: mention that OCI helm does not support version ranges

Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>

* Apply suggestions from code review

Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>

Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>
2022-10-21 11:19:00 -04:00
Allex
5c79556ab6 fix: Update custom health check for kiali.io/Kiali (#10995)
With Kiali v1.57.1 an additional status condition was added:
```
    - lastTransitionTime: '2022-10-14T11:56:24Z'
      message: ''
      reason: ''
      status: 'False'
      type: Failure
```

Based on the discussion in https://github.com/kiali/kiali/issues/5560 this should not lead to a degraded health state.

This will no longer return Degraded as a catch-all and use the `type` and `status` fields of the condition to determine the CR health.

Signed-off-by: Allex Veldman <allexveldman+github@gmail.com>

Signed-off-by: Allex Veldman <allexveldman+github@gmail.com>
2022-10-19 12:17:34 -04:00
Michael Crenshaw
03b2deec02 chore: upgrade actions/checkout to v3, i.e. Node.js 16 (#10947)
* chore: updgrade actions/checkout to v3, i.e. Node.js 16

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* more node 12

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-19 10:42:23 -04:00
34FathomBelow
c0774a0d21 chore: release signature of sbom (#10969)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-10-18 15:39:48 -04:00
Jessie Teng
2a47eafb5a fix: Resource list in sync page msg style#10887 (#10970)
* fix: Resource list in sync page msg style#10887

Signed-off-by: Teng, Jessie <yilin.teng@fmr.com>

* fix: Resource list in sync page msg style#10887

Signed-off-by: Teng, Jessie <yilin.teng@fmr.com>

* fix: Resource list in sync page msg style#10887

Signed-off-by: Teng, Jessie <yilin.teng@fmr.com>

* fix: Resource list in sync page msg style#10887

Signed-off-by: Teng, Jessie <yilin.teng@fmr.com>

Signed-off-by: Teng, Jessie <yilin.teng@fmr.com>
2022-10-18 14:01:55 -04:00
argo-bot
05acf7a52e Bump version to 2.4.15 2022-10-17 20:15:50 +00:00
argo-bot
e290faa6c7 Bump version to 2.4.15 2022-10-17 20:15:42 +00:00
Michael Crenshaw
21a6025d72 chore: add script to generate release notes (#10806)
* chore: add script to generate release notes

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* newlines look bad in the release markdown rendering on GitHub

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* use diff instead of comp

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* use auto-generated docs

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* pre-pended, not appended

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-17 15:47:57 -04:00
34FathomBelow
1a50f7944a chore: sign checksums file for release binaries (#10963)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-10-17 13:03:57 -04:00
34FathomBelow
92df7b877f chore: implement signed images (#10925)
* consolidate checksums into one file

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

* sign container images

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

* sign container images

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

* remove id-token permissions

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-10-17 13:01:10 -04:00
Michael Crenshaw
bca4b1adfc chore: upgrade dex to v2.35.3 to avoid CVE-2022-27665 (#10939)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-17 12:32:47 -04:00
Aiman Fatima
3f4b12ce0d fix: Display pointer on labels for resource names in sync panel (#10959)
Signed-off-by: Aiman Fatima <aimanfatimadl@gmail.com>

Signed-off-by: Aiman Fatima <aimanfatimadl@gmail.com>
2022-10-17 09:30:33 -04:00
Chris Davis
74b5492601 fix: Use os.PathSeparator instead of hard-coded string to resolve local file paths (#10945) (#10946)
fix: Use os.PathSeparator instead of hard-coded string to resolve local file paths (#10945) (#10946)
2022-10-14 13:54:17 -07:00
Michael Crenshaw
187cd4337a docs: appset PR generator docs fixes (#10567)
* docs: appset PR generator docs fixes

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

* oh, that field is actually a thing

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

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-12 11:30:49 -04:00
Michael Crenshaw
b20ef3ecae docs: add link to 2.4-2.5 upgrade guide (#10808)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-12 11:29:53 -04:00
Michael Crenshaw
3ce54d0b98 docs: more docs for directory apps (#10879)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-12 11:19:34 -04:00
Michael Crenshaw
0d882f6da2 docs: clarify how default RBAC policy works (#10896)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-12 11:17:10 -04:00
Mayursinh Sarvaiya
8b78e94e37 fix(ui): sync option label doesn't check corresponding box (#10863) (#10876)
* fix(ui): sync option label doesn't check corresponding box

Signed-off-by: Mayursinh Sarvaiya <marvinduff97@gmail.com>

* fix: lint

Signed-off-by: Mayursinh Sarvaiya <marvinduff97@gmail.com>

Signed-off-by: Mayursinh Sarvaiya <marvinduff97@gmail.com>
2022-10-10 14:52:41 -04:00
Nir Shtein
8fc1f80c75 fix: clicking HEAD in bitbucket leads to a 404 page (#10862)
* Wrap error objects to include context

Signed-off-by: Nir Shtein <89006520+nirsht@users.noreply.github.com>

* fix: duplicate source namespace validation (#10853)

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: Nir Shtein <89006520+nirsht@users.noreply.github.com>

* Fix CR

Signed-off-by: Nir Shtein <89006520+nirsht@users.noreply.github.com>

* Change 'branch' to 'src' when building url path

Signed-off-by: Nir Shtein <89006520+nirsht@users.noreply.github.com>

* Revert "Fix CR"

This reverts commit 4b92408412.

Signed-off-by: Nir Shtein <89006520+nirsht@users.noreply.github.com>

* Revert "Wrap error objects to include context"

This reverts commit d1789bd271.

Signed-off-by: Nir Shtein <89006520+nirsht@users.noreply.github.com>

Signed-off-by: Nir Shtein <89006520+nirsht@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-09 12:11:11 -04:00
Sakshi Jain
983a7b0536 fix: added css to change cursor to pointer on hover (#10864) (#10867)
* added css to change cursor to pointer on hover

Signed-off-by: Sakshi <sakshi.jain7597@gmail.com>

* moved cursor change to only label and input

Signed-off-by: Sakshi <sakshi.jain7597@gmail.com>

Signed-off-by: Sakshi <sakshi.jain7597@gmail.com>
2022-10-09 12:05:32 -04:00
Michael Crenshaw
761636badf docs: fix examples for ArgoCD ApplicationSet Git Generator (#10857)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-08 14:48:56 -04:00
Michael Crenshaw
cb60ddc696 docs: remove unused plugin config fields (#10304)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-08 13:32:07 -04:00
Michael Crenshaw
814964f077 Revert "fix: add applicationset to crds generated by gen-crd-spec (#10833)"
This reverts commit 5cf1a6705b.

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-07 20:23:53 -04:00
Matt Morrison
f360009ff5 fix: consider destination cluster name when validating destinations (#10594)
Signed-off-by: Matt Morrison <matt.morrison@zapier.com>

Signed-off-by: Matt Morrison <matt.morrison@zapier.com>
2022-10-07 16:49:39 -04:00
Minchao
7381470fbe docs: fix advice about preferred version in high availability (#10619)
* docs: fix advice about preferred version in high availability

Signed-off-by: Minchao <minchao.220@gmail.com>

* Update docs/operator-manual/high_availability.md

Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Signed-off-by: Minchao <minchao.220@gmail.com>

Signed-off-by: Minchao <minchao.220@gmail.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-07 16:11:27 -04:00
Lars Kellogg-Stedman
c0ecf0271b docs: Correct grammar issues in docs on manifest path annotations (#10776)
The "Webhook and Manifest Paths Annotation" section of the documentation
contained a number of grammar and spelling issues as well as what appeared
to be some unintentionally pasted text.

This commit attempts to address these issues.

Signed-off-by: Lars Kellogg-Stedman <lars@oddbit.com>

Signed-off-by: Lars Kellogg-Stedman <lars@oddbit.com>
2022-10-07 15:34:04 -04:00
Denis Krivenko
6686e43b4f fix: Add missing statuses to MinIO Tenant health check (#10815)
Signed-off-by: dnskr <dnskrv88@gmail.com>

Signed-off-by: dnskr <dnskrv88@gmail.com>
2022-10-07 15:03:50 -04:00
Eddie Knight
d321825d9f chore: Added recommended permissions to github actions workflows (#10812)
* Added recommended permissions to 4 of 5 workflows

Signed-off-by: Eddie Knight <iv.eddieknight@gmail.com>

* Added release.yaml permissions... might need to add pagages:write

Signed-off-by: Eddie Knight <iv.eddieknight@gmail.com>

* Updated inline comments

Signed-off-by: Eddie Knight <iv.eddieknight@gmail.com>

Signed-off-by: Eddie Knight <iv.eddieknight@gmail.com>
2022-10-07 14:42:41 -04:00
Richard Jennings
5cf1a6705b fix: add applicationset to crds generated by gen-crd-spec (#10833)
* add applicationset to crds generated

Signed-off-by: Richard Jennings <richardjennings@gmail.com>

* update applicationset crd

Signed-off-by: Richard Jennings <richardjennings@gmail.com>

* remove description from applicationset crd

Signed-off-by: Richard Jennings <richardjennings@gmail.com>

Signed-off-by: Richard Jennings <richardjennings@gmail.com>
2022-10-07 10:53:06 -04:00
jannfis
db7d8be912 fix(ui): Don't jump back to tiles view on app deletion (#8764) (#10826)
Signed-off-by: jannfis <jann@mistrust.net>

Signed-off-by: jannfis <jann@mistrust.net>
2022-10-06 14:07:27 -04:00
rumstead
4d31d46d4c docs: Update link to resource customizations (#10827) (#10828)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
2022-10-06 12:04:34 -04:00
argo-bot
029be590bf Bump version to 2.4.14 2022-10-05 17:01:30 +00:00
argo-bot
65abd05b60 Bump version to 2.4.14 2022-10-05 17:01:24 +00:00
Michael Crenshaw
b9fb7623ad chore: upgrade dex to v2.35.1 (#10797) (#10799)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-05 11:45:12 -04:00
argo-bot
19ec34e134 Bump version to 2.4.13 2022-10-03 20:44:25 +00:00
argo-bot
5f74aa5c24 Bump version to 2.4.13 2022-10-03 20:44:20 +00:00
Em Karisch
b350c11935 docs: add note about multiple sync options on annotation (#10739)
Signed-off-by: Em Karisch <em@khaos.solutions>

Signed-off-by: Em Karisch <em@khaos.solutions>
2022-10-03 15:53:32 -04:00
Buk Bukowski
c271f1a6c1 docs: fix broken links in faq.md (#10744)
* fix broken links in faq.md

Signed-off-by: Bukowa <gitbukowa@gmail.com>

* doc:faq.md: fix

Signed-off-by: bukowa <gitbukowa@gmail.com>

Signed-off-by: Bukowa <gitbukowa@gmail.com>
Signed-off-by: bukowa <gitbukowa@gmail.com>
2022-10-03 15:52:53 -04:00
Michael Crenshaw
e6bd9469f8 chore: upgrade Dex to 2.35.0 (#10775)
* chore: upgrade dex to v2.35.0

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* upgrade github workflow too

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-10-03 15:45:55 -04:00
Michael Crenshaw
2bb180b3d9 docs: syncWindows in project.yaml (#10591)
* docs: syncWindows in project.yaml

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

* trailing newline

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

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-10-01 19:59:51 -04:00
Ishita Sequeira
216b10e6d8 fix: fix subscription health check (#10450)
Signed-off-by: ishitasequeira <ishiseq29@gmail.com>

Signed-off-by: ishitasequeira <ishiseq29@gmail.com>

Signed-off-by: ishitasequeira <ishiseq29@gmail.com>
2022-09-30 19:45:18 -04:00
Mohammad Abusaa
fc8f57a0b5 docs: Update Generators-Pull-Request.md (#10643) (#10642)
Signed-off-by: Mohammad Abusaa <abusaa_mz@hotmail.com>

Signed-off-by: Mohammad Abusaa <abusaa_mz@hotmail.com>
2022-09-30 19:09:44 -04:00
Ahmed Mahmoud BACHIRI
56c2e3c81d docs: fix typo in GitHub section (#10723)
Replace and with an

Signed-off-by: Ahmed Mahmoud BACHIRI <bachiriahmedmahmoud@gmail.com>

Signed-off-by: Ahmed Mahmoud BACHIRI <bachiriahmedmahmoud@gmail.com>
2022-09-30 19:04:08 -04:00
Michael Crenshaw
83931b8515 chore: upgrade dex to v2.32.1-distroless (#10746)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2022-09-30 18:54:39 -04:00
cleverhu
712df99420 fix: Fix a nil pointer crash for repo server (#10696)
Fixes: https://github.com/argoproj/argo-cd/issues/10614
Signed-off-by: cleverhu <shouping.hu@daocloud.io>

Signed-off-by: cleverhu <shouping.hu@daocloud.io>
Co-authored-by: jannfis <jann@mistrust.net>
2022-09-26 08:56:05 +00:00
argo-bot
41f54aa556 Bump version to 2.4.12 2022-09-16 00:26:31 +00:00
argo-bot
540fe1b762 Bump version to 2.4.12 2022-09-16 00:26:22 +00:00
Michael Crenshaw
66ebec630a docs: decision about logs RBAC enforcement in release notes for 2.4 (#10564)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-09-15 14:42:25 -04:00
msvechla
a6b5aa2766 fix: add skip-test-tls flag to optionally skip testing for tls (#9679) (#10484)
* feat: add skip-test-tls flag to optionally skip testing for tls, fixes #9679

Signed-off-by: msvechla <m.svechla@gmail.com>

* docs: update cli documentation

Signed-off-by: msvechla <m.svechla@gmail.com>

Signed-off-by: msvechla <m.svechla@gmail.com>
2022-09-15 11:59:08 -04:00
Minchao
1ac264e9a1 docs: update description of policy.csv example in rbac.md (#10565)
Signed-off-by: Minchao <minchao.220@gmail.com>

Signed-off-by: Minchao <minchao.220@gmail.com>
2022-09-15 08:11:47 -04:00
Greg Knoblauch
128a261513 docs: Fix Broken Link in Getting Started Docs (#10585)
* Fix Broken Link

Signed-off-by: Greg Knoblauch <knoblauch.greg@gmail.com>

* Update docs/getting_started.md

Co-authored-by: asingh <11219262+ashutosh16@users.noreply.github.com>
Signed-off-by: Greg Knoblauch <knoblauch.greg@gmail.com>

Signed-off-by: Greg Knoblauch <knoblauch.greg@gmail.com>
Co-authored-by: asingh <11219262+ashutosh16@users.noreply.github.com>
2022-09-15 08:08:44 -04:00
Gerald Roncajolo
8552cc3f07 fix: update deploymentConfig's healthcheck to wait for replicationController to be Available (#10462)
* update deploymentConfig's healthcheck to wait for replicationController to be available

Signed-off-by: Roncajolo Gerald <groncajolo@softwaymedical.fr>

* Add Softway Medical to users

Signed-off-by: Roncajolo Gerald <groncajolo@softwaymedical.fr>

Signed-off-by: Roncajolo Gerald <groncajolo@softwaymedical.fr>
2022-09-14 07:21:28 +00:00
Mickaël Canévet
cb05b8fb4a docs: remove duplicate word in user-management doc (#10546)
Signed-off-by: Mickaël Canévet <mickael.canevet@jellysmack.com>

Signed-off-by: Mickaël Canévet <mickael.canevet@jellysmack.com>
2022-09-09 11:24:12 -04:00
asingh
2ca18ab5fe fix: hide terminal on the non-pod resource kind (#9980) (#10556)
Signed-off-by: ashutosh16 <11219262+ashutosh16@users.noreply.github.com>

Signed-off-by: ashutosh16 <11219262+ashutosh16@users.noreply.github.com>
2022-09-09 11:23:32 -04:00
rishabh625
e8d2d3a7e0 fix: added github and gitlab response mock and replaced external calls (#9305)
* Added mock for gitlab and github for Unit test

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>

* Added missing mock endpoint

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>

* removed println and aserted for 1 master branch

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>

* removed auth header assertion

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>

* procfile to run binaries instead go run

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>

* procfile to run binaries instead go run

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>

* reverted unintentional testdata change

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>

* Added test for branch do not exists

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>
2022-09-06 11:37:33 -04:00
Michael Crenshaw
6d348ce4a1 test: fix flaky gitea tests (#10354)
* test: fix flaky gitea tests

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

* embed test data

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

Signed-off-by: CI <michael@crenshaw.dev>
2022-09-06 09:55:27 -04:00
rishabh625
3c2683dfe9 fix: Added mock for gitea response in appset PR,SCM generator (#9400)
* fix: Added mock for gitea response

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>

* applied reviewers comment

Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>
2022-09-06 09:55:05 -04:00
Jesse Suen
8aa4df6f17 fix: appset controller should preserve argocd refresh annotation (#10510)
Signed-off-by: Jesse Suen <jesse@akuity.io>

Signed-off-by: Jesse Suen <jesse@akuity.io>
2022-09-06 08:53:00 -04:00
Takumi Sue
7db5c5c589 fix: invalid error handling (#10384) (#10385)
os.IsNotExist only supports errors returned by the os package

Signed-off-by: mikutas <23391543+mikutas@users.noreply.github.com>

Signed-off-by: mikutas <23391543+mikutas@users.noreply.github.com>
2022-09-06 08:52:14 -04:00
argo-bot
3d9e9f2f95 Bump version to 2.4.11 2022-08-22 08:58:21 +00:00
argo-bot
ca7d83f645 Bump version to 2.4.11 2022-08-22 08:58:04 +00:00
jannfis
e59f4889a4 Pin gitops-engine to v0.7.3
Signed-off-by: jannfis <jann@mistrust.net>
2022-08-22 08:27:03 +00:00
jannfis
fea6197af4 fix: Correctly assume cluster-scoped resources to be self-referenced (#10390)
Signed-off-by: jannfis <jann@mistrust.net>

Signed-off-by: jannfis <jann@mistrust.net>
2022-08-18 20:38:10 +00:00
Xijun Dai
5b576acf5d docs: fix typo in upgrade notes (#10377)
Signed-off-by: Xijun Dai <daixijun1990@gmail.com>

Signed-off-by: Xijun Dai <daixijun1990@gmail.com>
2022-08-18 10:22:36 -04:00
argo-bot
2ccc17afcb Bump version to 2.4.10 2022-08-17 20:48:21 +00:00
argo-bot
e7521ed7b8 Bump version to 2.4.10 2022-08-17 20:48:17 +00:00
Michael Crenshaw
f83bed0d4b fix: missing actions (#10327) (#10359)
Signed-off-by: CI <michael@crenshaw.dev>

Signed-off-by: CI <michael@crenshaw.dev>
2022-08-17 16:33:07 -04:00
JesseBot
88274b6870 docs: Add "Create Namespace" to sync options doc (#3490) (#10326)
* Add create namespace to the sync options doc

Signed-off-by: JesseBot <jessebot@linux.com>

* Update docs/user-guide/sync-options.md

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

Signed-off-by: JesseBot <jessebot@linux.com>
Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
2022-08-17 15:12:09 -04:00
jsmcnair
431ee12282 docs: Document safe concurrent processing of sidecar CMP (#10336)
Signed-off-by: jsmcnair <john.mcnair@yellowdog.co>

Signed-off-by: jsmcnair <john.mcnair@yellowdog.co>
2022-08-15 16:06:56 -04:00
Tadayuki Onishi
3b17121d44 fix: Suppressed ssh scheme url warn log (#9836)
* Fixed ssh scheme warn log degrade by #8508
Signed-off-by: kenchan0130 <tt.tanishi100@gmail.com>

* Expanded repository type getCAPath testing
Signed-off-by: kenchan0130 <tt.tanishi100@gmail.com>
2022-08-15 12:19:01 -04:00
Michael Crenshaw
f071b29b5f fix: respect ARGOCD_GIT_MODULES_ENABLED in the appset controller (#10285) (#10287)
* fix: respect ARGOCD_GIT_MODULES_ENABLED in the appset controller (#10285)

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

* remove duplicate line

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

Signed-off-by: CI <michael@crenshaw.dev>
2022-08-12 14:47:02 -04:00
Michael Crenshaw
5ed749e827 docs: clusterResources in declarative cluster config (#10219)
* docs: clusterResources in declarative cluster config

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

* add article

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

Signed-off-by: CI <michael@crenshaw.dev>
2022-08-11 13:50:12 -04:00
argo-bot
1ba9008536 Bump version to 2.4.9 2022-08-11 15:08:32 +00:00
argo-bot
2b873f0b3a Bump version to 2.4.9 2022-08-11 15:08:25 +00:00
Michael Crenshaw
3fdb6ae960 docs: fix version reference for logs UI fix (#10245)
Signed-off-by: CI <michael@crenshaw.dev>
2022-08-09 17:27:27 -04:00
Brandon High
d40ebce7b3 docs: Document ignoreAggregatedRoles setting (#10206)
Signed-off-by: Brandon High <highb@users.noreply.github.com>
2022-08-09 12:05:01 -04:00
César M. Cristóbal
d945e9f256 docs: fix microsoft user management mapping role (#10251)
Signed-off-by: CI <michael@crenshaw.dev>
2022-08-09 10:17:18 -04:00
Sverre Boschman
fb75ada4c2 docs(applicationset): fix layout matrix/merge generator restrictions (#10246)
Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>

Signed-off-by: Sverre Boschman <1142569+sboschman@users.noreply.github.com>
2022-08-09 10:08:15 -04:00
Kerwood
05c9ba27e3 fix: Drop all references to exec unless the feature is enabled (#9920) (#10187)
* fix:  Drop all references to exec unless the feature is enabled #9920

Signed-off-by: Patrick Kerwood <patrick@kerwood.dk>

* fixed tslint issues

Signed-off-by: Patrick Kerwood <patrick@kerwood.dk>
2022-08-08 16:33:10 -04:00
reggie-k
77c972d27e fix: UI part for logs RBAC - do not display the logs tab when no RBAC in place (#7211) (#9828)
* show logs tab only upon explicit rbac allow policy

Signed-off-by: reggie-k <reginakagan@gmail.com>

* 2.4.7 docs edit

Signed-off-by: reggie-k <reginakagan@gmail.com>
2022-08-08 16:31:11 -04:00
jannfis
7e0ee5c449 fix: Ignore non-self-referencing resources while pruning (#10198)
* fix: Ignore non-self-referencing resources while pruning

Signed-off-by: jannfis <jann@mistrust.net>
2022-08-08 17:44:12 +00:00
Sahdev Zala
164284e329 docs: correct the api field description for the GitLab example (#10081)
The api field description for the GitLab example seems mistakenly
copied from the GitHub example.

Signed-off-by: Sahdev Zala <spzala@us.ibm.com>
2022-08-05 15:24:53 -04:00
Renaud Guérin
ac2c1618b2 docs: Use ConfigMap to disable TLS (#10106)
* docs: Use ConfigMap to disable TLS

Signed-off-by: Renaud Guerin <renaud@renaudguerin.net>

* Fix typo

Signed-off-by: Renaud Guerin <renaud@renaudguerin.net>
2022-08-04 17:00:15 -04:00
my-git9
4ee796604a docs: improve Installation.md (#10173)
Signed-off-by: xin.li <xin.li@daocloud.io>
2022-08-04 10:23:20 -04:00
Yves Richard
118d4d3c58 docs: fix kustomize namePrefix misconception in application.yaml (#10162)
* Update docs/operator-manual/application.yaml

- Removed comment about what namePrefix does. (i.e. it does not add a prefix to the image)
- Added examples of other supported transformers. (based on looking at the source code)
- Added link to the kustomize docs where the transormers are described in more detail.

* Update kustomize casing to be consistent

Signed-off-by: whyvez <yves@premise.com>
2022-08-03 14:40:10 -04:00
Mohamed Iflan
912fe33009 docs: Fixed indentation Error (#10123)
* Fixed indentation Error

Signed-off-by: iflan7744 <iflan_mohamed@yahoo.com>

* Fixed indentation Error for top-level data key

Signed-off-by: iflan7744 <iflan_mohamed@yahoo.com>

Co-authored-by: iflan7744 <iflan_mohamed@yahoo.com>
Signed-off-by: CI <michael@crenshaw.dev>
2022-08-01 10:40:08 -04:00
argo-bot
844f79eb9d Bump version to 2.4.8 2022-07-29 16:47:18 +00:00
argo-bot
ecfa0da491 Bump version to 2.4.8 2022-07-29 16:47:13 +00:00
Alexander Matyushentsev
fac8466e86 fix: extensions is not loading for ConfigMap/Pods (#10010)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-07-28 12:50:06 -07:00
Alexander Matyushentsev
ac34ff23c4 feat: support application level extensions (#9923)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-07-28 12:50:03 -07:00
Alexander Matyushentsev
a85d88d479 feat: support multiple extensions per resource group/kind (#9834)
* feat: support multiple extensions per resource group/kind

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

* apply reviewers suggestions

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

* apply reviewer notes: stream extension files one by one

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

* wrap errors

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

* skip symlinks

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-07-28 12:50:00 -07:00
dependabot[bot]
40075da70c chore(deps): bump moment from 2.29.3 to 2.29.4 in /ui (#9897)
Bumps [moment](https://github.com/moment/moment) from 2.29.3 to 2.29.4.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.3...2.29.4)

Signed-off-by: CI <michael@crenshaw.dev>
---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-28 15:37:25 -04:00
Snyk bot
779e383f64 fix: upgrade moment from 2.29.2 to 2.29.3 (#9330)
Snyk has created this PR to upgrade moment from 2.29.2 to 2.29.3.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/argoproj/project/d2931792-eef9-4d7c-b9d6-c0cbd2bd4dbe?utm_source=github&utm_medium=referral&page=upgrade-pr
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-28 15:36:47 -04:00
Michael Crenshaw
3e523dbab7 fix: skip redirect url validation when it's the base href (#10058) (#10116)
* fix: skip redirect url validation when it's the base href (#10058)

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

nicer way of doing it

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

* fix missin arg

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-27 16:38:05 -04:00
Michael Crenshaw
4df892fecf docs: add OpenSSH breaking change notes (#10104)
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-27 15:26:49 -04:00
Michael Crenshaw
670a1756d7 fix: avoid CVE-2022-28948 (#10093)
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-27 15:03:09 -04:00
Michael Crenshaw
5721f559f0 chore: update parse-url (#10101)
* chore: upgrade parse-url

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

* edit a generated file, because that's smart

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-27 14:57:06 -04:00
Sahdev Zala
e23178a8d1 docs: add api field example in the appset security doc (#10087)
It seems like most of the work for the mentioned issue below is done
under the PR #9466 but from the issue description, it's probably
worth to mention the example as added here.

Related #9352

Signed-off-by: Sahdev Zala <spzala@us.ibm.com>
2022-07-26 09:15:31 -04:00
Hyeonmin Park
918e5eadf4 fix: Set HOST_ARCH for yarn build from platform (#10018)
Signed-off-by: Hyeonmin Park <hyeonmin.park@kennysoft.kr>
2022-07-25 12:27:29 -04:00
34FathomBelow
55de2b9dab chore: update redis to 7.0.4 avoid CVE-2022-30065 (#10059)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-07-20 17:11:44 -04:00
Ashutosh
c48004f944 docs: add argocd-server grpc metric usage (#10007)
Signed-off-by: Ashutosh <mail.ashutosh8@gmail.com>

Co-authored-by: Ashutosh <mail.ashutosh8@gmail.com>
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-20 14:58:32 -04:00
Michael Crenshaw
f7b6a38041 chore: upgrade Dex to 2.32.0 (#10036) (#10042)
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-20 10:45:24 -04:00
Michael Crenshaw
91eb9925ef chore: update redis to avoid CVE-2022-2097 (#10031)
* chore: update redis to avoid CVE-2022-2097

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

* codegen

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-20 10:38:36 -04:00
34FathomBelow
6190964899 chore: update haproxy to 2.0.29 for redis-ha (#10045)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-07-19 15:05:40 -04:00
argo-bot
81630e6d50 Bump version to 2.4.7 2022-07-18 21:07:45 +00:00
argo-bot
e31fdb6105 Bump version to 2.4.7 2022-07-18 21:07:38 +00:00
Michael Crenshaw
2e194b1087 chore: upgrade parse-url to avoid SNYK-JS-PARSEURL-2936249 (#9826)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-07-18 14:13:15 -04:00
Jim Wright
cec5799d97 Support files in argocd.argoproj.io/manifest-generate-paths annotation (#9908)
Signed-off-by: Jim Wright <jmwri93@gmail.com>
2022-07-18 11:02:26 -04:00
Michael Crenshaw
7ab2ba361c docs: use quotes to emphasize that ConfigMap value is a string (#9995)
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-16 12:21:39 -04:00
Michael Crenshaw
1d5e15c600 fix: terminal websocket write lock to avoid races (#10011)
* fix: protect terminal WriteMessage with a lock

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

* give write its own lock

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-15 21:43:38 -04:00
Michael Crenshaw
f4f52212ba docs: document directory app include/exclude fields (#9997)
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-15 21:42:58 -04:00
Michael Crenshaw
507c669259 docs: simplify Docker toolchain docs (#9966) (#10006)
* docs: simplify Docker toolchain docs (#9966)

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

* to be or not to be

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

* pin dependencies to avoid absurdity

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-15 11:51:48 -04:00
Soumya Ghosh Dastidar
993459aebc fix: updated all a tags to Link tags in app summary (#9777)
* fix: updated all a tags to Link tags

Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>

* fix: revert external links to a tags

Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>

* fix: linting

Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>
2022-07-15 10:17:53 -04:00
rishabh625
3293aa0bb7 fix: e2e test to use func from clusterauth instead creating one with old logic (#9989)
Signed-off-by: rishabh625 <rishabhmishra625@gmail.com>
2022-07-15 09:22:34 -04:00
Hyeonmin Park
aafb6ce0a3 fix: add missing download CLI tool URL response for ppc64le, s390x (#9983)
Signed-off-by: Hyeonmin Park <hyeonmin.park@kennysoft.kr>
2022-07-15 08:55:35 -04:00
Kostis (Codefresh)
d3d490632d docs: supported versions (#9876)
* docs: supported versions

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

* docs: supported versions feedback

Signed-off-by: Kostis Kapelonis <kostis@codefresh.io>
2022-07-13 11:09:39 -04:00
argo-bot
a48bca03c7 Bump version to 2.4.6 2022-07-12 22:19:23 +00:00
argo-bot
6930ceb414 Bump version to 2.4.6 2022-07-12 22:19:14 +00:00
CI
01b7a73922 chore: fix build error
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-12 16:46:39 -04:00
taksenov
ff2d9b918d docs: fix typo in Generators-Git.md (#9949)
`ApplictionSet` --> `ApplicationSet`
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-12 16:29:03 -04:00
Jake
cea91ce935 docs: add terminal documentation (#9948)
Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>
2022-07-12 16:28:24 -04:00
Michael Crenshaw
51b73096f5 fix: 'unexpected reserved bits' breaking web terminal (#9605) (#9895)
* fix: 'unexpected reserved bits' breaking web terminal (#9605)

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

* make things more like they were originally, since the mutex fixes the problem

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

* fix typo, don't pass around a pointer when it isn't necessary

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

* apply suggestions

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-07-12 16:28:01 -04:00
Yuan Tang
2c166dac97 feat: Treat connection reset as a retryable error (#9739)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
2022-07-12 16:25:08 -04:00
jannfis
16c015f0cb test: Use dedicated multi-arch workloads in e2e tests (#9921)
* test: Use dedicated multi-arch workloads in e2e tests

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

* Use correct tag

Signed-off-by: jannfis <jann@mistrust.net>
2022-07-12 16:24:41 -04:00
Xiao Yang
7ca60cb957 fix: argocd login just hangs on 2.4.0 #9679 (#9935)
Signed-off-by: Xiao Yang <muma.378@163.com>

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-12 16:24:23 -04:00
Jake
d0c80ee0bb fix: CMP manifest generation fails with ENHANCE_YOUR_CALM if over 40s (#9922)
* fix: CMP manifest generation fails with ENHANCE_YOUR_CALM if over 40s

Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>

* fix timeouts across all gRPC servers

Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>

* use common consts

Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>
2022-07-12 16:24:00 -04:00
yongguangl
9f1a33865a fix: NotAfter is not set when ValidFor is set (#9911)
Signed-off-by: yongguangl <1363186473@qq.com>
2022-07-12 16:21:21 -04:00
Hyeonmin Park
f09c84f30a fix: add missing download CLI tool link for ppc64le, s390x (#9649)
Signed-off-by: Hyeonmin Park <hyeonmin.park@kennysoft.kr>
2022-07-12 16:21:03 -04:00
jannfis
f7f7493e9f fix: Check tracking annotation for being self-referencing (#9791)
* fix: Check tracking annotation for being self-referencing

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

* Tweak isManagedLiveObj() logic

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

* Rename isManagedLiveResource to isSelfReferencedObj

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

* Add e2e test

Signed-off-by: jannfis <jann@mistrust.net>
2022-07-12 16:20:21 -04:00
jannfis
c1ddb53d29 fix: Make change of tracking method work at runtime (#9820)
* fix: Make change of tracking method work at runtime

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

* GetAppName() will figure tracking label or annotation on its own

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

* Correct test comments and add another test

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

* Add a read lock before getting cache settings

Signed-off-by: jannfis <jann@mistrust.net>
2022-07-12 16:19:41 -04:00
Shunki
e04288482d fix: argo-cd git submodule is using SSH auth instead of HTTPs (#3118) (#9821)
* fix: argo-cd git submodule is using SSH auth instead of HTTPs (#3118)

Signed-off-by: shunki-fujita <shunki-fujita@cybozu.co.jp>

* Add submodule functions and unit tests
Signed-off-by: shunki-fujita <shunki-fujita@cybozu.co.jp>
2022-07-12 16:16:48 -04:00
YaytayAtWork
1f3e1ec803 #9429: Adding blank line so list is formatted correctly. (#9880)
Signed-off-by: CI <michael@crenshaw.dev>
2022-07-12 16:14:05 -04:00
Jake
c3423e8df3 docs: small fix for plugin stream filtering (#9871)
Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>
2022-07-12 16:13:45 -04:00
Didrik Finnøy
5ef48c1123 docs: Document the possibility of rendering Helm charts with Kustomize (#9841)
* Update kustomize.md

Resolves  #7835.

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

* Removed unnecessary command flag from example. Minor text edits.

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

* spelling

Signed-off-by: Didrik Finnøy <djfinnoy@protonmail.com>
2022-07-12 16:13:22 -04:00
YaytayAtWork
e3ae286e2d docs: getting started notes on self-signed cert (#9429) (#9784)
* Fix #9429: A couple of notes in the docs to explain that the default certificate is insecure.

Signed-off-by: Jim Talbut <jim.talbut@groupgti.com>

* Fixes #9429: More verbose, but complete, text for Getting Started.

Signed-off-by: Jim Talbut <jim.talbut@groupgti.com>
2022-07-12 16:12:41 -04:00
Michael Crenshaw
7abf6713b4 test: check for error messages from CI env (#9953)
test: check for error messages from CI env (#9953)

Signed-off-by: CI <michael@crenshaw.dev>
2022-07-12 15:31:44 -04:00
argo-bot
0232073ccf Bump version to 2.4.5 2022-07-12 16:08:04 +00:00
argo-bot
860d8fd7e1 Bump version to 2.4.5 2022-07-12 16:07:57 +00:00
Michael Crenshaw
147ff80543 Merge pull request from GHSA-7943-82jg-wmw5
* add tests to demonstrate issue

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

more

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

docs

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

settings tests

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

tests for OIDC handlers, consolidating test helpers

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

consolidate

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

consolidate

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

docs

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

* fix log message

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-07-12 08:46:13 -04:00
Michael Crenshaw
3800a1e49d Merge pull request from GHSA-pmjg-52h9-72qv
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

formatting

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

fixes from comments

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

fix test

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-07-12 08:45:22 -04:00
argo-bot
fe80bdcfdc Bump version to 2.4.4 2022-07-07 06:57:43 +00:00
argo-bot
94c09dff59 Bump version to 2.4.4 2022-07-07 06:57:37 +00:00
jannfis
3d9e4d439e test: Remove circular symlinks from testdata (#9886)
* test: Remove circular symlinks from testdata

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

* Another test case

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

* Use defer for changing back to original workdir

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

* Abort the test on error in defer

Signed-off-by: jannfis <jann@mistrust.net>
2022-07-06 19:18:51 +00:00
noah
4a955e25a0 docs: custom secret must be labeled (#9835)
As far as I can tell, this isn't explicitly documented anywhere (some docs mentioned this label in reference to ConfigMaps) I only figure it out by looking at the code.
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-07-01 15:55:34 -04:00
noah
4f99f251bf fix: missing path segments for git file generator (#9839)
* fix: missing path segments for git file generator

given the path:

  /one/two/file.yaml

This change adds the params:

path[1]=two
path.filename=file.yaml
path.filenameNormalized

The use case is for symmetry with other generators (e.g., merge with a directory generator using the key path[1]). As no existing parameter values are changed it should be non-breaking.

Signed-off-by: Noah Perks Sloan <noah@hackedu.io>

* fix: expose all path elements for directory generator

This makes it consistent with the files generator and removes un-intuitive behavior without any breaking change.

docs: clarify - can use either baseName or nth path element
docs: use "directory", like the name of the generator, where "folder" was mentioned
Signed-off-by: Noah Perks Sloan <noah@hackedu.io>
2022-07-01 15:54:15 -04:00
Alexander Matyushentsev
fd418cec0d fix: make sure api server informer does not stop after setting change (#9842)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-06-30 15:30:33 -07:00
Xiao Yang
dc291a629f fix: support resource logs and exec (#9833)
Signed-off-by: Xiao Yang <muma.378@163.com>
2022-06-30 09:07:00 -04:00
Paulo Coelho
e23a1c6026 docs: update archlinux install with official package (#9718)
Signed-off-by: Paulo Coelho <prscoelho@protonmail.com>
2022-06-29 16:38:21 -04:00
Chris Reilly
aee88c6452 docs: explain rightmost git generator path parameter behavior (#9799)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-29 16:31:15 -04:00
KevinSnyderCodes
3f111cc640 git: prune any deleted refs before fetching (#9504)
* git: prune any deleted refers before fetching

This commit modifies `nativeGitClient.Fetch()` to call `git remote prune origin` before fetching refs.

In some cases, an old branch may exist that conflicts with the name of a new branch. The old branch will have been deleted from `origin` but still exist locally in the `argocd-repo-server`.

Example: an old branch `feature/foo` conflicts with a new branch `feature/foo/bar`

In these cases, syncing an application results in the error:

```
rpc error: code = Internal desc = Failed to fetch default: `git fetch origin --tags --force` failed exit status 1: error: cannot lock ref 'refs/remotes/origin/feature/foo/bar': 'refs/remotes/origin/feature/foo' exists; cannot create 'refs/remotes/origin/feature/foo/bar' From https://github.com/org/repo ! [new branch] feature/foo/bar -> origin/feature/foo/bar (unable to update local ref) error: some local refs could not be updated; try running 'git remote prune origin' to remove any old, conflicting branches
```

Adding `git remote prune origin` before fetching, as recommended by the error message, should fix this issue.

The current workaround is to restart the `argocd-repo-server` which should flush the local repository folder. This works when Argo CD is installed using the Helm chart.

Signed-off-by: Kevin Snyder <kevin.snyder.codes@gmail.com>

* fix: added extra protection to syncing app with replace (#9187)

* fix: added extra protection to syncing app with replace

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

* Code clean up

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

* Updated logic for isAppOfAppsPattern

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

* Updated text strings as per comment

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

* Fixed lint issue

Signed-off-by: ciiay <yicai@redhat.com>
Signed-off-by: Kevin Snyder <kevin.snyder.codes@gmail.com>

* chore: Simplified GetRepoHTTPClient function (#9396)

* chore: Simplified GetRepoHTTPClient function

Signed-off-by: ls0f <lovedboy.tk@qq.com>

* simplified code and improve unit test coverage

Signed-off-by: ls0f <lovedboy.tk@qq.com>
Signed-off-by: Kevin Snyder <kevin.snyder.codes@gmail.com>

* Only prune if fetch error message indicates that it is worthwhile, add unit tests

Confirmed that `Test_nativeGitClient_Fetch_Prune` fails without the bug fix, succeeds with it.

Signed-off-by: Kevin Snyder <kevin.snyder.codes@gmail.com>

* fix: avoid k8s call before authorization for terminal endpoint (#9434)

* fix: avoid k8s API call before authorization in k8s endpoint

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

* check for bad project

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

* lint

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

* more logging

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

* handle 404, return 500 instead of 400 for other errors

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

* use user input

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

* refactor validation

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

* fix tests

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

* fixes, tests

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
Signed-off-by: Kevin Snyder <kevin.snyder.codes@gmail.com>

* Match against "try running 'git remote prune origin'"

Signed-off-by: Kevin Snyder <kevin.snyder.codes@gmail.com>

Co-authored-by: Yi Cai <yicai@redhat.com>
Co-authored-by: ls0f <lovedboy.tk@qq.com>
Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-29 16:28:51 -04:00
Jake
596038fc0f fix: configurable CMP tar exclusions (#9675) (#9789)
* feat: configurable CMP tar exclusions

Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>

* rename cmp to plugin

Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>

* add test for tar stream exclusions

Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>

* fix tests

Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>

* update cmp guide

Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>

* fully parameterize

Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com>
2022-06-29 16:27:41 -04:00
argo-bot
471685feae Bump version to 2.4.3 2022-06-27 20:53:14 +00:00
argo-bot
42e1f29117 Bump version to 2.4.3 2022-06-27 20:53:07 +00:00
Michael Crenshaw
c089f9a5e5 fix: respect OIDC providers' supported token signing algorithms (#9433) (#9761)
* fix: respect OIDC providers' supported token signing algorithms (#9433)

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

* go mod tidy

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-27 16:32:35 -04:00
TomHellier
1dc5e6aaf9 fix: websockets for terminal not working on subPath (#9795)
Signed-off-by: Tom Hellier <me@tomhellier.com>
2022-06-27 13:26:11 -07:00
Alexander Matyushentsev
82726fcbcf fix: avoid closing and re-opening port of api server settings change (#9778)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-06-24 10:17:20 -07:00
Nicolas Fillot
e715e085aa [ArgoCD] Fixing webhook typo in case of error in GetManifests (#9671)
Signed-off-by: Nicolas Fillot <nfillot@weborama.com>

Co-authored-by: Nicolas Fillot <nfillot@weborama.com>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-23 09:27:15 -04:00
Michael Crenshaw
7db5ab71b0 fix: overrides should not appear in the manifest cache key (#9601)
* fix: overrides should not appear in the manifest cache key

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

* fix Helm regression

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

* fix test

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

* fix test again

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-22 09:24:29 -04:00
argo-bot
c6d0c8baaa Bump version to 2.4.2 2022-06-21 20:32:13 +00:00
argo-bot
2115bf7746 Bump version to 2.4.2 2022-06-21 20:32:08 +00:00
Yaakov Selkowitz
0a2520f511 test/remote: Allow override of base image (#9734)
ubuntu:22.04 bumped the ppc64el baseline to POWER9, rendering this
unusable on existing POWER8 systems.  This allows customization similar
to the top-level Dockerfile.

Signed-off-by: Yaakov Selkowitz <yselkowi@redhat.com>
2022-06-21 15:24:13 -04:00
Soumya Ghosh Dastidar
211e9f6127 fix: updated config file permission requirements for windows (#9732)
* fix: reduced config file permission restriction on windows

Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>

* fix: updated localconfig tests to check error

Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>
2022-06-21 15:09:48 -04:00
hritikch24
792e278080 Update sync-options.md (#9687)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-21 14:49:10 -04:00
Michael Crenshaw
93bf321002 fix: project filter (#9651) (#9709)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-21 14:39:34 -04:00
Joren Zandstra
48c2e0bf21 fix broken symlink in Dockerfile (#9674)
Signed-off-by: Joren Zandstra <jorenzandstra@yahoo.com>
2022-06-21 14:39:26 -04:00
Soumya Ghosh Dastidar
b4b893ca1c fix: updated baseHRefRegex to perform lazy match (#9724)
* fix: updated baseHRefRegex to perform lazy match

Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>

* feat: added unit tests for replaceBaseHRef

Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>
2022-06-21 10:39:12 -07:00
argo-bot
52e6025f8b Bump version to 2.4.1 2022-06-21 16:27:47 +00:00
argo-bot
b121b89c81 Bump version to 2.4.1 2022-06-21 16:27:40 +00:00
Michael Crenshaw
12149c0710 chore: fix docs gen
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-21 10:34:03 -04:00
Michael Crenshaw
9d67469428 Merge pull request from GHSA-jhqp-vf4w-rpwq
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

defer instead of multiple close calls

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

oops

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

don't count jsonnet against max

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

fix codegen

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

add caveat about 300x ratio

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

fix versions

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

fix tests/lint

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-21 09:40:36 -04:00
Michael Crenshaw
04c3053964 Merge pull request from GHSA-q4w5-4gq2-98vm
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

fix tests/lint

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-21 09:39:56 -04:00
Michael Crenshaw
17f7f4f462 Merge pull request from GHSA-2m7h-86qq-fp4v
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

fix references

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

use long enough state param for oauth2

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

typo

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

more entropy

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

fix tests

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

fix tests/lint

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-21 09:39:01 -04:00
Michael Crenshaw
8bc3ef690d Merge pull request from GHSA-h4w9-6x78-8vrj
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

fix tests/lint

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-21 09:36:38 -04:00
Michael Crenshaw
8fe9a58c21 test: directory app manifest generation (#9503)
* test: directory app manifest generation

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

* git doesn't support empty dirs

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-14 16:12:12 -04:00
Leonardo Luz Almeida
269c61a9c8 chore: Implement tests to validate aws auth retry (#9627)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-06-14 10:11:38 -04:00
Leonardo Luz Almeida
9a08c123f9 chore: Implement a retry in aws auth command (#9618)
Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-06-14 10:10:43 -04:00
jannfis
971f0f1ff1 test: Remove temp directories from repo server tests (#9501)
Signed-off-by: jannfis <jann@mistrust.net>
2022-06-13 15:42:29 -04:00
jannfis
1ae2f97b05 test: Make context tests idempodent (#9502)
Signed-off-by: jannfis <jann@mistrust.net>
2022-06-13 15:41:55 -04:00
Michael Crenshaw
bb26cc207b test: fix plugin var test for OSX (#9590)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-13 15:37:00 -04:00
Christian Hernandez
77d3dcdc62 Update Generators-Git.md (#9632)
Document how to deploy from the root of the git repository

Signed-off-by: Christian Hernandez <christian@codefresh.io>
2022-06-13 10:57:28 -04:00
Hari Sekhon
f414a8e985 docs: added environment variables documentation (#8680)
* added environment variables page

Signed-off-by: Hari Sekhon <harisekhon@gmail.com>

* added Environment Variables page to User Guide

Signed-off-by: Hari Sekhon <harisekhon@gmail.com>

* reformatted table cells as multiline for clarity

Signed-off-by: Hari Sekhon <harisekhon@gmail.com>

* fixed typo

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-13 10:38:39 -04:00
argo-bot
91aefabc5b Bump version to 2.4.0 2022-06-10 17:13:43 +00:00
argo-bot
56b8e2f356 Bump version to 2.4.0 2022-06-10 17:13:30 +00:00
Michael Crenshaw
101477a638 docs: document OpenSSH upgrade (#9598) (#9615)
docs: document OpenSSH upgrade (#9598) (#9615)

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-09 15:59:59 -07:00
Alexander Matyushentsev
9bf7d1b95b fix: change repo-server command to expand 'ARGOCD_REDIS_SERVICE' env variable (#9628)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-06-09 15:59:54 -07:00
Daniel Helfand
da8e7b9697 fix: use serviceaccount name instead of struct (#9614) (#9617)
* fix: use serviceaccount name instead of struct

Signed-off-by: Daniel Helfand <helfand.4@gmail.com>

* fix: change name of param from sa to serviceAccount

Signed-off-by: Daniel Helfand <helfand.4@gmail.com>
2022-06-08 16:20:29 -04:00
Daniel Helfand
eb183dcde1 fix: create serviceaccount token for v1.24 clusters (#9546)
* fix: create serviceaccount token for v1.24 clusters

Signed-off-by: Daniel Helfand <helfand.4@gmail.com>

* change create to get in err

Signed-off-by: Daniel Helfand <helfand.4@gmail.com>
2022-06-08 14:01:25 -04:00
Michael Crenshaw
ccecc693c2 docs: document argocd cluster add behavior for 1.24 clusters (#9611)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-08 13:54:38 -04:00
Yaakov Selkowitz
dc1d4b060d chore: Fix working directory for remote e2e test image (#9600)
Commit cc6c625401 changed a RUN mkdir
command into a WORKDIR, which also affected the entrypoint.  This
triggered an error in goreman which looks for Procfile (which is
installed here in the root directory) in the working directory.

Since COPY creates any missing directories in the destination path,
there is no need for a separate step to create it.  This change leaves
WORKDIR as the default (the root directory) as before.

Signed-off-by: Yaakov Selkowitz <yselkowi@redhat.com>
2022-06-07 17:31:33 +00:00
Michael Crenshaw
512233806c chore: fix long socket path breaking test on osx (#9391)
* chore: fix long socket path breaking test on osx

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

* comment

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

* simplify

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

* simplify

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-06 17:48:42 -04:00
argo-bot
b84dd8bbfa Bump version to 2.4.0-rc5 2022-06-06 19:03:38 +00:00
argo-bot
e6f37d7245 Bump version to 2.4.0-rc5 2022-06-06 19:03:30 +00:00
Michael Crenshaw
57bac9ac75 chore: update changelog
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-06 14:59:46 -04:00
34FathomBelow
3034183791 chore: upgrade base image to ubuntu:20.04 (#9551)
Signed-off-by: douhunt <douhunt@protonmail.com>

Co-authored-by: douhunt <douhunt@protonmail.com>
Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-06 14:52:10 -04:00
34FathomBelow
26c87b3f16 chore upgrade base image for test containers Ubuntu:22.04 (#9563)
Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>
2022-06-06 14:52:02 -04:00
34FathomBelow
bd8d26d444 chore: update Kex-Algorithms (#9561)
* chore: update Kex-Algorithms

Signed-off-by: douhunt <douhunt@protonmail.com>

* sorted kex-algorithms

Signed-off-by: Justin Marquis <34fathombelow@protonmail.com>

Co-authored-by: douhunt <douhunt@protonmail.com>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-06 14:51:54 -04:00
Michael Crenshaw
a6c58748cd fix: missing Helm params (#9565) (#9566)
* fix: missing Helm params

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

* use absolute paths, fix tests

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

* fix race in test

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-04 20:17:12 -04:00
Bjorn Stange
46af59e258 docs: fix cm typo (#9577)
Signed-off-by: Bjorn Stange <bjorn.stange@expel.io>
2022-06-03 13:21:08 -04:00
Alexander Matyushentsev
867660a709 chore: remove obsolete repo-server unit test (#9559)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-06-03 09:30:57 -04:00
margueritepd
b1addf5bf1 docs: document action RBAC action and application resource path (#8413)
Signed-off-by: Marguerite des Trois Maisons <marguerite+github@pagerduty.com>

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-02 17:51:08 -04:00
Pierre Crégut
0a9d1607e2 feat: Add plugin call variables to sidecar plugin discovery (#9273) (#9319)
* fix: do not export repo-server environment to sidecar (#9393)

getPluginEnvs is both used for local plugins and sidecar plugins. For the later
do not include the environement variables of the repo-server in the supplied
variables.

Fixes: #9393
Signed-off-by: Pierre Crégut <pierre.cregut@orange.com>

* feat: Add plugin call variables to sidecar plugin discovery (#9273)

Gives access to variables declared in the call of the plugin in the application
manifest to the discover command run on the CMP server.

Variables are prefixed with ARGOCD_ENV_ to avoid security issues (plugin call
overiding important variables).

Fixes #9273

Signed-off-by: Pierre Crégut <pierre.cregut@orange.com>
2022-06-02 17:50:29 -04:00
Michael Crenshaw
09fc32e6cb docs: document plugin prefixed env vars (#9548)
* docs: document plugin prefixed env vars

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

* restructure, clarify env vars from main container behavior

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

* grammer

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

* grammer

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

* no link - the cert is bad

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

* fixes

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-06-02 15:46:50 -04:00
argo-bot
1be9296e6c Bump version to 2.4.0-rc4 2022-06-01 22:49:24 +00:00
argo-bot
76fad02f4a Bump version to 2.4.0-rc4 2022-06-01 22:49:15 +00:00
Alexander Matyushentsev
2f8eb04b84 fix: web terminal due to query parameters name mismatch (#9560)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-06-01 14:39:32 -07:00
argo-bot
66aa0e6e01 Bump version to 2.4.0-rc3 2022-05-31 19:24:04 +00:00
argo-bot
955270eb0d Bump version to 2.4.0-rc3 2022-05-31 19:23:57 +00:00
Michael Crenshaw
225a0af9f7 docs: security warning for plugins (#9547)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-31 11:49:36 -07:00
Leonardo Luz Almeida
5191cd077c chore: Improve application logs adding message context (#9435)
* chore: Improve application logs adding message context

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

* fix bug returning error incorrectly

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

* Fix unit-test and avoid api breaking change

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

* Fix test

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

* Fix e2e test

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

* Fix e2e test

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

* small fix

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

* Address review comments

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-05-31 14:19:02 -04:00
Leonardo Luz Almeida
c6b928c830 fix: Ignore diff with schema (#9170) 2022-05-31 10:27:32 -07:00
Michael Crenshaw
4e73b3c7ee docs: document new repo-server ServiceAccount (#9484)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-31 12:28:38 -04:00
Michael Crenshaw
708c9e79b9 fix: avoid k8s call before authorization for terminal endpoint (#9434)
* fix: avoid k8s API call before authorization in k8s endpoint

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

* check for bad project

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

* lint

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

* more logging

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

* handle 404, return 500 instead of 400 for other errors

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

* use user input

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

* refactor validation

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

* fix tests

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

* fixes, tests

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-31 12:18:25 -04:00
ls0f
da2c249814 receiveFile memory optimization: do not use bytes.buffer but write directly to file (#9415)
Signed-off-by: ls0f <lovedboy.tk@qq.com>
2022-05-31 12:17:39 -04:00
smcavallo
c27cf3f95e feat: support pod exec terminal logging (#9385)
* feat: support pod exec terminal logging
Signed-off-by: smcavallo <smcavallo@hotmail.com>

* enhanced validation and logging when resource not found
Signed-off-by: smcavallo <smcavallo@hotmail.com>

* fix lint
Signed-off-by: smcavallo <smcavallo@hotmail.com>

* log warning when pod or container not found
Signed-off-by: smcavallo <smcavallo@hotmail.com>

* go/log-injection fixes
Signed-off-by: smcavallo <smcavallo@hotmail.com>

* log levels and lowercase message
Signed-off-by: smcavallo <smcavallo@hotmail.com>
2022-05-31 12:17:01 -04:00
Daniel Helfand
dbd3ce3133 docs: add applicationset and notifications controllers to running locally instructions (#9517)
Signed-off-by: Daniel Helfand <helfand.4@gmail.com>

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-31 12:11:53 -04:00
Pavel Savchenko
58062c45de docs: Update 2.3 notes - mention helm chart (#9512)
the helm chart values should be copied as-is into the `notifications` section of the argo-cd chart

Signed-off-by: Pavel Savchenko <asfaltboy@gmail.com>
2022-05-31 12:11:35 -04:00
reggie-k
3c61070411 docs: logs RBAC known UI issue section (#9479)
* updated changelog and upgrade instructions to contain know UI issue with logs rbac

Signed-off-by: reggie-k <reginakagan@gmail.com>

* updated changelog and upgrade instructions to contain know UI issue with logs rbac

Signed-off-by: reggie-k <reginakagan@gmail.com>
2022-05-31 12:11:09 -04:00
Michael Crenshaw
697fc77379 docs: more appset security docs (#9466)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-31 12:10:40 -04:00
Michael Crenshaw
6655a22b0a docs: plugins need their own writeable tmp volume (#9389)
* docs: plugin needs temp dir

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

* revert temp changes

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

* fix version number

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

* update upgrade instructions

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

* simplify

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-31 12:07:56 -04:00
Michael Crenshaw
0d109279a8 docs: fix PR generators list (#9387)
* docs: fix PR generators list

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

* grammar

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-31 12:07:32 -04:00
neosu
4c1e1e0ad6 Fixes: #9364 (#9367)
In the #8929, the project parameter had changed to projects.

5f5d7aa59b/server/application/application.proto (L23)
Signed-off-by: neosu <neo@neobaran.com>
2022-05-30 19:19:27 -07:00
Michael Crenshaw
078cfe130b fix: test race (#9469)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-24 08:15:41 -07:00
Michael Crenshaw
cd098638f8 fix: lint (#9444)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-24 08:15:27 -07:00
Dan Garfield
2826a9215d refactor: Update notification engine (#9386)
refactor: Update notification engine  (#9386)

Signed-off-by: todaywasawesome <dan@codefresh.io>
2022-05-23 23:50:45 -07:00
Alexander Matyushentsev
13bef3a831 fix: api server should dynamically enabled terminal handler (#9497)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-05-23 23:49:56 -07:00
Alexander Matyushentsev
c6f80377a8 fix: Undefined cluster in UI when app is referencing cluster by name (#9493)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-05-23 22:52:34 -07:00
Alexander Matyushentsev
a8a451a84b fix: make more proto fields optional (#9490)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-05-23 13:46:15 -07:00
argo-bot
cd5b2af358 Bump version to 2.4.0-rc2 2022-05-18 12:32:45 +00:00
argo-bot
f6f9fa2cd6 Bump version to 2.4.0-rc2 2022-05-18 12:32:41 +00:00
jannfis
c7749ca67e 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:22 +02:00
Michael Crenshaw
3399a81bed 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: 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
80e5c55ca0 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
Saumeya Katyal
c4182aedc7 fix: update filter combo-box icon color (#9416)
Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2022-05-16 14:26:56 +00:00
Saumeya Katyal
e4404372af fix: favorite icon and overlapping app title (#9130)
Signed-off-by: saumeya <saumeyakatyal@gmail.com>
2022-05-16 14:26:35 +00:00
Leonardo Luz Almeida
12140f8152 chore: Improve otel grpc traces adding span correlation (#9371)
* chore: Improve otel grpc traces adding span correlation

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

* Create a tracer for argocd controller

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

* Update controller command doc

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

* Instrument cmp-client

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

* Add otlp config as part of configmaps

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

* update manifests

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
2022-05-13 15:13:43 -04:00
Chetan Banavikalmutt
6cfd394445 fix: ListResourceActions() returns duplicate actions (#9360)
Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
2022-05-13 15:09:33 -04:00
Michael Crenshaw
1998b016c0 docs: clarify Role/ClusterRole uses for exec feature (#9354)
* docs: clarify Role/ClusterRole uses for exec feature

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

* fix missed `get`s

Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-12 11:14:10 -04:00
Michael Crenshaw
74bc1731f9 feat(manifests): Add service account for repo server (#9301) (#9355)
Signed-off-by: Hao Xin <haoxinst@gmail.com>
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>

Co-authored-by: Hao Xin <haoxinst@qq.com>
2022-05-11 13:28:13 -04:00
Michael Crenshaw
bb28b3c697 docs: logs RBAC upgrate notes (#9345) (#9356)
Signed-off-by: Michael Crenshaw <michael@crenshaw.dev>
2022-05-10 20:38:25 -04:00
Regina Scott
0ee9993369 fix: grouped node titles no longer wrap (#9340)
Signed-off-by: Regina Scott <rescott@redhat.com>
2022-05-09 19:34:14 -04:00
argo-bot
d8f845a126 Bump version to 2.4.0-rc1 2022-05-06 23:10:53 +00:00
argo-bot
5901b46785 Bump version to 2.4.0-rc1 2022-05-06 23:10:45 +00:00
David J. M. Karlsen
88542a616f feat: Add cli support for additional linux based architectures, s390x + ppc64le (#8991)
feat: Add cli support for additional linux based architectures, s390x + ppc64le (#8991)

Signed-off-by: David J. M. Karlsen <david@davidkarlsen.com>

* add more architectures for linux

Signed-off-by: David J. M. Karlsen <david@davidkarlsen.com>

* drop aix arch as it won't compile

Signed-off-by: David J. M. Karlsen <david@davidkarlsen.com>

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-05-06 16:10:03 -07:00
Alexander Matyushentsev
cbe4f1b92e chore: add linux/s390x,linux/ppc64le platforms to release workflow (#9324)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2022-05-06 16:09:59 -07:00
906 changed files with 20783 additions and 113683 deletions

View File

@@ -1,19 +0,0 @@
---
name: Security log
about: Propose adding security-related logs or tagging existing logs with security fields
title: "seclog: [Event Description]"
labels: security-log
assignees: notfromstatefarm
---
# Event to be logged
Specify the event that needs to be logged or existing logs that need to be tagged.
# Proposed level
What security level should these events be logged under? Refer to https://argo-cd.readthedocs.io/en/latest/operator-manual/security/#security-field for more info.
# Common Weakness Enumeration
Is there an associated [CWE](https://cwe.mitre.org/) that could be tagged as well?

View File

@@ -9,7 +9,6 @@ on:
pull_request:
branches:
- 'master'
- 'release-*'
env:
# Golang version to use across CI steps
@@ -25,12 +24,12 @@ permissions:
jobs:
check-go:
name: Ensure Go modules synchronicity
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Setup Golang
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Download all Go modules
@@ -43,16 +42,16 @@ jobs:
build-go:
name: Build & cache Go code
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Setup Golang
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Restore go build cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
uses: actions/cache@6998d139ddd3e68c71e9e398d8e40b71a2f39812 # v3.2.5
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -67,23 +66,23 @@ jobs:
contents: read # for actions/checkout to fetch code
pull-requests: read # for golangci/golangci-lint-action to fetch pull requests
name: Lint Go code
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Setup Golang
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Run golangci-lint
uses: golangci/golangci-lint-action@0ad9a0988b3973e851ab0a07adf248ec2e100376 # v3.3.1
with:
version: v1.46.2
version: v1.45.2
args: --timeout 10m --exclude SA5011 --verbose
test-go:
name: Run unit tests for Go packages
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
needs:
- build-go
env:
@@ -93,11 +92,11 @@ jobs:
- name: Create checkout directory
run: mkdir -p ~/go/src/github.com/argoproj
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Create symlink in GOPATH
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -117,7 +116,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
uses: actions/cache@6998d139ddd3e68c71e9e398d8e40b71a2f39812 # v3.2.5
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -150,7 +149,7 @@ jobs:
test-go-race:
name: Run unit tests with -race, for Go packages
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
needs:
- build-go
env:
@@ -160,11 +159,11 @@ jobs:
- name: Create checkout directory
run: mkdir -p ~/go/src/github.com/argoproj
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Create symlink in GOPATH
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -184,7 +183,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
uses: actions/cache@6998d139ddd3e68c71e9e398d8e40b71a2f39812 # v3.2.5
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -212,12 +211,12 @@ jobs:
codegen:
name: Check changes to generated code
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Setup Golang
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Create symlink in GOPATH
@@ -260,17 +259,17 @@ jobs:
build-ui:
name: Build, test & lint UI code
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Setup NodeJS
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with:
node-version: '12.18.4'
- name: Restore node dependency cache
id: cache-dependencies
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
uses: actions/cache@6998d139ddd3e68c71e9e398d8e40b71a2f39812 # v3.2.5
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
@@ -292,7 +291,7 @@ jobs:
analyze:
name: Process & analyze test artifacts
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
needs:
- test-go
- build-ui
@@ -300,12 +299,12 @@ jobs:
sonar_secret: ${{ secrets.SONAR_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
fetch-depth: 0
- name: Restore node dependency cache
id: cache-dependencies
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
uses: actions/cache@6998d139ddd3e68c71e9e398d8e40b71a2f39812 # v3.2.5
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
@@ -358,10 +357,10 @@ jobs:
test-e2e:
name: Run end-to-end tests
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
strategy:
matrix:
k3s-version: [v1.24.3, v1.23.3, v1.22.6]
k3s-version: [v1.23.3, v1.22.6, v1.21.2]
needs:
- build-go
env:
@@ -373,20 +372,27 @@ jobs:
ARGOCD_E2E_K3S: "true"
ARGOCD_IN_CI: "true"
ARGOCD_E2E_APISERVER_PORT: "8088"
ARGOCD_APPLICATION_NAMESPACES: "argocd-e2e-external"
ARGOCD_SERVER: "127.0.0.1:8088"
GITHUB_TOKEN: ${{ secrets.E2E_TEST_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
GITLAB_TOKEN: ${{ secrets.E2E_TEST_GITLAB_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Setup Golang
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: GH actions workaround - Kill XSP4 process
run: |
sudo pkill mono || true
# ubuntu-22.04 comes with kubectl, but the version is not pinned. The version as of 2022-12-05 is 1.26.0 which
# breaks the `TestNamespacedResourceDiffing` e2e test. So we'll pin to 1.25 and then fix the underlying issue.
- name: Install kubectl
run: |
rm /usr/local/bin/kubectl
curl -LO https://dl.k8s.io/release/v1.25.4/bin/linux/amd64/kubectl
mv kubectl /usr/local/bin/kubectl
chmod +x /usr/local/bin/kubectl
- name: Install K3S
env:
INSTALL_K3S_VERSION: ${{ matrix.k3s-version }}+k3s1
@@ -399,7 +405,7 @@ jobs:
sudo chown runner $HOME/.kube/config
kubectl version
- name: Restore go build cache
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
uses: actions/cache@6998d139ddd3e68c71e9e398d8e40b71a2f39812 # v3.2.5
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -427,7 +433,7 @@ jobs:
run: |
docker pull ghcr.io/dexidp/dex:v2.35.3
docker pull argoproj/argo-cd-ci-builder:v1.0.0
docker pull redis:7.0.8-alpine
docker pull redis:7.0.7-alpine
- name: Create target directory for binaries in the build-process
run: |
mkdir -p dist

View File

@@ -25,11 +25,11 @@ jobs:
if: github.repository == 'argoproj/argo-cd'
# CodeQL runs on ubuntu-latest and windows-latest
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

View File

@@ -24,14 +24,14 @@ jobs:
permissions:
contents: write # for git to push upgrade commit if not already deployed
if: github.repository == 'argoproj/argo-cd'
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
env:
GOPATH: /home/runner/work/argo-cd/argo-cd
steps:
- uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
- uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
path: src/github.com/argoproj/argo-cd
@@ -54,6 +54,37 @@ jobs:
# build
- uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0
- uses: docker/setup-buildx-action@f03ac48505955848960e80bbb68046aa35c7b9e7 # v2.4.1
- name: Setup cache for argocd-ui docker layer
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-single-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-single-buildx
- name: Build cache for argocd-ui stage
uses: docker/build-push-action@v2
with:
context: ./src/github.com/argoproj/argo-cd
target: argocd-ui
push: false
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
if: github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'test-arm-image')
- name: Run non-container Snyk scans
if: github.event_name == 'push'
working-directory: ./src/github.com/argoproj/argo-cd
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
run: |
npm install -g snyk
# Run with high threshold to fail build.
snyk test --org=argoproj --all-projects --exclude=docs,site --severity-threshold=high --policy-path=.snyk
snyk iac test manifests/install.yaml --org=argoproj --severity-threshold=high --policy-path=.snyk
- run: |
IMAGE_PLATFORMS=linux/amd64
if [[ "${{ github.event_name }}" == "push" || "${{ contains(github.event.pull_request.labels.*.name, 'test-arm-image') }}" == "true" ]]
@@ -62,13 +93,31 @@ jobs:
fi
echo "Building image for platforms: $IMAGE_PLATFORMS"
docker buildx build --platform $IMAGE_PLATFORMS --sbom=false --provenance=false --push="${{ github.event_name == 'push' }}" \
--cache-from "type=local,src=/tmp/.buildx-cache" \
-t ghcr.io/argoproj/argocd:${{ steps.image.outputs.tag }} \
-t quay.io/argoproj/argocd:latest .
working-directory: ./src/github.com/argoproj/argo-cd
- name: Run container Snyk scan
if: github.event_name == 'push'
working-directory: ./src/github.com/argoproj/argo-cd
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
run: |
snyk container test quay.io/argoproj/argocd:latest --org=argoproj --file=Dockerfile --severity-threshold=high
# Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
- name: Clean up build cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
if: github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'test-arm-image')
# sign container images
- name: Install cosign
uses: sigstore/cosign-installer@c3667d99424e7e6047999fb6246c0da843953c65 # v3.0.1
uses: sigstore/cosign-installer@9becc617647dfa20ae7b1151972e9b3a2c338a2b # v2.8.1
with:
cosign-release: 'v1.13.1'

View File

@@ -23,7 +23,7 @@ jobs:
contents: write # To push changes to release branch
name: Perform automatic release on trigger ${{ github.ref }}
if: github.repository == 'argoproj/argo-cd'
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
env:
# The name of the tag as supplied by the GitHub event
SOURCE_TAG: ${{ github.ref }}
@@ -43,7 +43,7 @@ jobs:
GIT_EMAIL: argoproj@gmail.com
steps:
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
@@ -147,7 +147,7 @@ jobs:
echo "RELEASE_NOTES=${RELEASE_NOTES}" >> $GITHUB_ENV
- name: Setup Golang
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: ${{ env.GOLANG_VERSION }}
@@ -219,7 +219,7 @@ jobs:
if: ${{ env.DRY_RUN != 'true' }}
- name: Install cosign
uses: sigstore/cosign-installer@c3667d99424e7e6047999fb6246c0da843953c65 # v3.0.1
uses: sigstore/cosign-installer@9becc617647dfa20ae7b1151972e9b3a2c338a2b # v2.8.1
with:
cosign-release: 'v1.13.1'

View File

@@ -1,31 +0,0 @@
name: Snyk report update
on:
schedule:
- cron: '0 0 * * 0' # midnight every Sunday
permissions:
contents: read
jobs:
snyk-report:
permissions:
contents: write # To push snyk reports
if: github.repository == 'argoproj/argo-cd'
name: Update Snyk report in the docs directory
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Build reports
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
run: |
make snyk-report
git config --global user.email 'ci@argoproj.com'
git config --global user.name 'CI'
git add docs/snyk/index.md
git add docs/snyk/*/*.html
git commit -m "[Bot] Update Snyk reports"
git push

6
.gitpod.Dockerfile vendored
View File

@@ -5,15 +5,13 @@ USER root
RUN curl -o /usr/local/bin/kubectl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \
chmod +x /usr/local/bin/kubectl
RUN curl -L https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.1/kubebuilder_2.3.1_$(go env GOOS)_$(go env GOARCH).tar.gz | \
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
ENV GOCACHE=/go-build-cache
RUN apt-get install redis-server -y
RUN go install github.com/mattn/goreman@latest
USER gitpod
ENV ARGOCD_REDIS_LOCAL=true
ENV KUBECONFIG=/tmp/kubeconfig
ENV KUBECONFIG=/tmp/kubeconfig

18
.snyk
View File

@@ -18,23 +18,5 @@ ignore:
- '*':
reason: >-
Code is only run client-side. No risk of directory traversal.
SNYK-GOLANG-GITHUBCOMEMICKLEIGORESTFUL-2435653:
- '*':
reason: >-
Argo CD uses go-restful as a transitive dependency of kube-openapi. kube-openapi is used to generate openapi
specs. We do not use go-restul at runtime and are therefore not vulnerable to this CORS misconfiguration
issue in go-restful.
SNYK-JS-FORMIDABLE-2838956:
- '*':
reason: >-
Code is only run client-side. No risk of arbitrary file upload.
SNYK-JS-PARSEPATH-2936439:
- '*':
reason: >-
The issue is that, for specific URLs, parse-path may incorrectly identify the "resource" (domain name)
portion. For example, in "http://127.0.0.1#@example.com", it identifies "example.com" as the "resource".
We use parse-path on the client side, but permissions for git URLs are checked server-side. This is a
potential usability issue, but it is not a security issue.
patch: {}

View File

@@ -1,185 +1,14 @@
# Changelog
## v2.4.8 (2022-07-29)
## v2.4.0 (Unreleased)
### Bug fixes
- feat: support application level extensions (#9923)
- feat: support multiple extensions per resource group/kind (#9834)
- fix: extensions is not loading for ConfigMap/Pods (#10010)
- fix: upgrade moment from 2.29.2 to 2.29.3 (#9330)
- fix: skip redirect url validation when it's the base href (#10058) (#10116)
- fix: avoid CVE-2022-28948 (#10093)
- fix: Set HOST_ARCH for yarn build from platform (#10018)
### Other changes
- chore(deps): bump moment from 2.29.3 to 2.29.4 in /ui (#9897)
- docs: add OpenSSH breaking change notes (#10104)
- chore: update parse-url (#10101)
- docs: add api field example in the appset security doc (#10087)
- chore: update redis to 7.0.4 avoid CVE-2022-30065 (#10059)
- docs: add argocd-server grpc metric usage (#10007)
- chore: upgrade Dex to 2.32.0 (#10036) (#10042)
- chore: update redis to avoid CVE-2022-2097 (#10031)
- chore: update haproxy to 2.0.29 for redis-ha (#10045)
## v2.4.7 (2022-07-18)
### Bug fixes
fix: Support files in argocd.argoproj.io/manifest-generate-paths annotation (#9908)
fix: terminal websocket write lock to avoid races (#10011)
fix: updated all a tags to Link tags in app summary (#9777)
fix: e2e test to use func from clusterauth instead creating one with old logic (#9989)
fix: add missing download CLI tool URL response for ppc64le, s390x (#9983)
### Other
chore: upgrade parse-url to avoid SNYK-JS-PARSEURL-2936249 (#9826)
docs: use quotes to emphasize that ConfigMap value is a string (#9995)
docs: document directory app include/exclude fields (#9997)
docs: simplify Docker toolchain docs (#9966) (#10006)
docs: supported versions (#9876)
## v2.4.6 (2022-07-12)
### Features
* feat: Treat connection reset as a retryable error (#9739)
### Bug fixes
* fix: 'unexpected reserved bits' breaking web terminal (#9605) (#9895)
* fix: argocd login just hangs on 2.4.0 #9679 (#9935)
* fix: CMP manifest generation fails with ENHANCE_YOUR_CALM if over 40s (#9922)
* fix: NotAfter is not set when ValidFor is set (#9911)
* fix: add missing download CLI tool link for ppc64le, s390x (#9649)
* fix: Check tracking annotation for being self-referencing (#9791)
* fix: Make change of tracking method work at runtime (#9820)
* fix: argo-cd git submodule is using SSH auth instead of HTTPs (#3118) (#9821)
### Other
* docs: fix typo in Generators-Git.md (#9949)
* docs: add terminal documentation (#9948)
* test: Use dedicated multi-arch workloads in e2e tests (#9921)
* docs: Adding blank line so list is formatted correctly (#9880)
* docs: small fix for plugin stream filtering (#9871)
* docs: Document the possibility of rendering Helm charts with Kustomize (#9841)
* docs: getting started notes on self-signed cert (#9429) (#9784)
* test: check for error messages from CI env (#9953)
## v2.4.5 (2022-07-12)
### Security fixes
* HIGH: Certificate verification is skipped for connections to OIDC providers ([GHSA-7943-82jg-wmw5](https://github.com/argoproj/argo-cd/security/advisories/GHSA-7943-82jg-wmw5))
* LOW: A leaked API server encryption key can allow XSS for SSO users ([GHSA-pmjg-52h9-72qv](https://github.com/argoproj/argo-cd/security/advisories/GHSA-pmjg-52h9-72qv))
### Potentially-breaking changes
The fix for GHSA-7943-82jg-wmw5 enables TLS certificate validation by default for connections to OIDC providers. If
connections to your OIDC provider fails validation, SSO will be broken for your Argo CD instance. You should test 2.4.5
before upgrading it to production. From the new documentation:
> By default, all connections made by the API server to OIDC providers (either external providers or the bundled Dex
> instance) must pass certificate validation. These connections occur when getting the OIDC provider's well-known
> configuration, when getting the OIDC provider's keys, and when exchanging an authorization code or verifying an ID
> token as part of an OIDC login flow.
>
> Disabling certificate verification might make sense if:
> * You are using the bundled Dex instance **and** your Argo CD instance has TLS configured with a self-signed certificate
> **and** you understand and accept the risks of skipping OIDC provider cert verification.
> * You are using an external OIDC provider **and** that provider uses an invalid certificate **and** you cannot solve
> the problem by setting `oidcConfig.rootCA` **and** you understand and accept the risks of skipping OIDC provider cert
> verification.
>
> If either of those two applies, then you can disable OIDC provider certificate verification by setting
> `oidc.tls.insecure.skip.verify` to `"true"` in the `argocd-cm` ConfigMap.
### Bug fixes
* fix: webhook typo in case of error in GetManifests (#9671)
## v2.4.4 (2022-07-07)
### Bug fixes
- fix: missing path segments for git file generator (#9839)
- fix: make sure api server informer does not stop after setting change (#9842)
- fix: support resource logs and exec (#9833)
- fix: configurable CMP tar exclusions (#9675) (#9789)
- fix: prune any deleted refs before fetching (#9504)
### Other
- test: Remove circular symlinks from testdata (#9886)
- docs: custom secret must be labeled (#9835)
- docs: update archlinux install with official package (#9718)
- docs: explain rightmost git generator path parameter behavior (#9799)
## v2.4.3 (2022-06-27)
### Bug fixes
- fix: respect OIDC providers' supported token signing algorithms (#9433) (#9761)
- fix websockets for terminal not working on subPath (#9795)
- fix: avoid closing and re-opening port of api server settings change (#9778)
- fix: [ArgoCD] Fixing webhook typo in case of error in GetManifests (#9671)
- fix: overrides should not appear in the manifest cache key (#9601)
## v2.4.2 (2022-06-21)
### Bug fixes
* fix: project filter (#9651) (#9709)
* fix: broken symlink in Dockerfile (#9674)
* fix: updated baseHRefRegex to perform lazy match (#9724)
* fix: updated config file permission requirements for windows (#9666)
### Other
* docs: Update sync-options.md (#9687)
* test/remote: Allow override of base image (#9734)
## v2.4.1 (2022-06-21)
### Security fixes
* CRITICAL: External URLs for Deployments can include javascript ([GHSA-h4w9-6x78-8vrj](https://github.com/argoproj/argo-cd/security/advisories/GHSA-h4w9-6x78-8vrj))
* HIGH: Insecure entropy in PKCE/Oauth2/OIDC params ([GHSA-2m7h-86qq-fp4v](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2m7h-86qq-fp4v))
* MODERATE: DoS through large directory app manifest files ([GHSA-jhqp-vf4w-rpwq](https://github.com/argoproj/argo-cd/security/advisories/GHSA-jhqp-vf4w-rpwq))
* MODERATE: Symlink following allows leaking out-of-bounds YAML files from Argo CD repo-server ([GHSA-q4w5-4gq2-98vm](https://github.com/argoproj/argo-cd/security/advisories/GHSA-q4w5-4gq2-98vm))
### Potentially-breaking changes
From the [GHSA-2m7h-86qq-fp4v](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2m7h-86qq-fp4v) description:
> The patch introduces a new `reposerver.max.combined.directory.manifests.size` config parameter, which you should tune before upgrading in production. It caps the maximum total file size of .yaml/.yml/.json files in directory-type (raw manifest) Applications. The default max is 10M per Application. This max is designed to keep any single app from consuming more than 3G of memory in the repo-server (manifests consume more space in memory than on disk). The 300x ratio assumes a maliciously-crafted manifest file. If you only want to protect against accidental excessive memory use, it is probably safe to use a smaller ratio.
>
> If your organization uses directory-type Applications with very many manifests or very large manifests then check the size of those manifests and tune the config parameter before deploying this change to production. When testing, make sure to do a "hard refresh" in either the CLI or UI to test your directory-type App. That will make sure you're using the new max logic instead of relying on cached manifest responses from Redis.
### Other
* test: directory app manifest generation (#9503)
* chore: Implement tests to validate aws auth retry (#9627)
* chore: Implement a retry in aws auth command (#9618)
* test: Remove temp directories from repo server tests (#9501)
* test: Make context tests idempodent (#9502)
* test: fix plugin var test for OSX (#9590)
* docs: Document how to deploy from the root of the git repository (#9632)
* docs: added environment variables documentation (#8680)
## v2.4.0 (2022-06-10)
### Web Terminal In Argo CD UI
### Web Terminal In Argo CD UI
Feature enables engineers to start a shell in the running application container without leaving the web interface. Just find the required Kubernetes
Pod using the Application Details page, click on it and select the Terminal tab. The shell starts automatically and enables you to execute the required
commands, and helps to troubleshoot the application state.
### Access Control For Pod Logs & Web Terminal
### Access Control For Pod Logs & Web Terminal
Argo CD is used to manage the critical infrastructure of multiple organizations, which makes security the top priority of the project. We've listened to
your feedback and introduced additional access control settings that control access to Kubernetes Pod logs and the new Web Terminal feature.
@@ -197,12 +26,12 @@ Upon pressing the "LOGS" tab in pod view by users who don't have an explicit all
The new feature allows emitting richer telemetry data that might make identifying performance bottlenecks easier. The new feature is available for argocd-server
and argocd-repo-server components and can be enabled using the --otlp-address flag.
### Power PC and IBM Z Support
### Power PC and IBM Z Support
The list of supported architectures has been expanded, and now includes IBM Z (s390x) and PowerPC (ppc64le). Starting with the v2.4 release the official quay.io
repository is going to have images for amd64, arm64, ppc64le, and s390x architectures.
### Other Notable Changes
### Other Notable Changes
Overall v2.4 release includes more than 300 hundred commits from nearly 90 contributors. Here is a short sample of the contributions:
@@ -211,116 +40,6 @@ Overall v2.4 release includes more than 300 hundred commits from nearly 90 contr
* Secured Redis connection
* ApplicationSet Gitea support
## v2.3.7 (2022-07-29)
### Notes
This is mainly a security related release and updates compatibility with Kubernetes 1.24.
**Attention:** The base image for 2.3.x reached end-of-life on July 14, 2022. This release upgraded the base image to Ubuntu 22.04 LTS. The change should have no effect on the majority of users. But if any of your git providers only supports now-deprecated key hash algorithms, then Application syncing might break. See the [2.2-to-2.3 upgrade notes](https://argo-cd.readthedocs.io/en/latest/operator-manual/upgrading/2.2-2.3/#support-for-private-repo-ssh-keys-using-the-sha-1-signature-hash-algorithm-is-removed-in-237) for details and workaround instructions.
### Bug fixes
- fix: skip redirect url validation when it's the base href (#10058) (#10116)
- fix: upgrade moment from 2.29.2 to 2.29.3 (#9330)
- fix: avoid CVE-2022-28948 (#10093)
- fix: use serviceaccount name instead of struct (#9614)
- fix: create serviceaccount token for v1.24 clusters (#9546)
### Other changes
- test: Remove cluster e2e tests not intended for release-2.3
- test: Remove circular symlinks from testdata (#9886)
- chore(deps): bump moment from 2.29.3 to 2.29.4 in /ui (#9897)
- chore: upgrade moment to latest version to fix CVE (#9005)
- chore: move dependencies to dev dependencies (#8541)
- docs: add OpenSSH breaking change notes (#10104)
- chore: update parse-url (#10101)
- chore: upgrade base image to 22.04 (#10103)
- docs: simplify Docker toolchain docs (#9966) (#10006)
- chore: update redis to 6.2.7 avoid CVE-2022-30065/CVE-2022-2097 (#10062)
- chore: upgrade Dex to 2.32.0 (#10036) (#10042)
- chore: update haproxy to 2.0.29 for redis-ha (#10045)
- test: check for error messages from CI env (#9953)
## v2.3.6 (2022-07-12)
### Security fixes
* HIGH: Certificate verification is skipped for connections to OIDC providers ([GHSA-7943-82jg-wmw5](https://github.com/argoproj/argo-cd/security/advisories/GHSA-7943-82jg-wmw5))
* LOW: A leaked API server encryption key can allow XSS for SSO users ([GHSA-pmjg-52h9-72qv](https://github.com/argoproj/argo-cd/security/advisories/GHSA-pmjg-52h9-72qv))
### Potentially-breaking changes
The fix for GHSA-7943-82jg-wmw5 enables TLS certificate validation by default for connections to OIDC providers. If
connections to your OIDC provider fails validation, SSO will be broken for your Argo CD instance. You should test 2.3.6
before upgrading it to production. From the new documentation:
> By default, all connections made by the API server to OIDC providers (either external providers or the bundled Dex
> instance) must pass certificate validation. These connections occur when getting the OIDC provider's well-known
> configuration, when getting the OIDC provider's keys, and when exchanging an authorization code or verifying an ID
> token as part of an OIDC login flow.
>
> Disabling certificate verification might make sense if:
> * You are using the bundled Dex instance **and** your Argo CD instance has TLS configured with a self-signed certificate
> **and** you understand and accept the risks of skipping OIDC provider cert verification.
> * You are using an external OIDC provider **and** that provider uses an invalid certificate **and** you cannot solve
> the problem by setting `oidcConfig.rootCA` **and** you understand and accept the risks of skipping OIDC provider cert
> verification.
>
> If either of those two applies, then you can disable OIDC provider certificate verification by setting
> `oidc.tls.insecure.skip.verify` to `"true"` in the `argocd-cm` ConfigMap.
### Bug fixes
* fix: webhook typo in case of error in GetManifests (#9671)
## v2.3.5 (2022-06-21)
### Security fixes
* CRITICAL: External URLs for Deployments can include javascript ([GHSA-h4w9-6x78-8vrj](https://github.com/argoproj/argo-cd/security/advisories/GHSA-h4w9-6x78-8vrj))
* HIGH: Insecure entropy in PKCE/Oauth2/OIDC params ([GHSA-2m7h-86qq-fp4v](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2m7h-86qq-fp4v))
* MODERATE: DoS through large directory app manifest files ([GHSA-jhqp-vf4w-rpwq](https://github.com/argoproj/argo-cd/security/advisories/GHSA-jhqp-vf4w-rpwq))
* MODERATE: Symlink following allows leaking out-of-bounds YAML files from Argo CD repo-server ([GHSA-q4w5-4gq2-98vm](https://github.com/argoproj/argo-cd/security/advisories/GHSA-q4w5-4gq2-98vm))
### Potentially-breaking changes
From the [GHSA-2m7h-86qq-fp4v](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2m7h-86qq-fp4v) description:
> The patch introduces a new `reposerver.max.combined.directory.manifests.size` config parameter, which you should tune before upgrading in production. It caps the maximum total file size of .yaml/.yml/.json files in directory-type (raw manifest) Applications. The default max is 10M per Application. This max is designed to keep any single app from consuming more than 3G of memory in the repo-server (manifests consume more space in memory than on disk). The 300x ratio assumes a maliciously-crafted manifest file. If you only want to protect against accidental excessive memory use, it is probably safe to use a smaller ratio.
>
> If your organization uses directory-type Applications with very many manifests or very large manifests then check the size of those manifests and tune the config parameter before deploying this change to production. When testing, make sure to do a "hard refresh" in either the CLI or UI to test your directory-type App. That will make sure you're using the new max logic instead of relying on cached manifest responses from Redis.
### Bug fixes
* fix: missing Helm params (#9565) (#9566)
### Other
* test: directory app manifest generation (#9503)
* chore: eliminate go-mpatch dependency (#9045)
* chore: Make unit tests run on platforms other than amd64 (#8995)
* chore: remove obsolete repo-server unit test (#9559)
* chore: update golangci-lint (#8988)
* fix: test race (#9469)
* chore: upgrade golangci-lint to v1.46.2 (#9448)
* test: fix ErrorContains (#9445)
## v2.3.4 (2022-05-18)
### Security fixes
- CRITICAL: Argo CD will trust invalid JWT claims if anonymous access is enabled (https://github.com/argoproj/argo-cd/security/advisories/GHSA-r642-gv9p-2wjj)
- LOW: Login screen allows message spoofing if SSO is enabled (https://github.com/argoproj/argo-cd/security/advisories/GHSA-xmg8-99r8-jc2j)
- MODERATE: Symlink following allows leaking out-of-bound manifests and JSON files from Argo CD repo-server (https://github.com/argoproj/argo-cd/security/advisories/GHSA-6gcg-hp2x-q54h)
### Bug Fixes
- fix: Fix docs build error (#8895)
- fix: fix broken monaco editor collapse icons (#8709)
- chore: upgrade to go 1.17.8 (#8866) (#9004)
- fix: allow cli/ui to follow logs (#8987) (#9065)
## v2.3.3 (2022-03-29)
@@ -462,174 +181,6 @@ Both bundled Helm and Kustomize binaries have been upgraded to the latest versio
- refactor: Introduce 'byClusterName' secret index to speedup cluster server URL lookup (#8133)
- refactor: Move project filtering to server side (#8102)
## v2.2.12 (2022-07-29)
### Notes
This is mainly a security related release and updates compatibility with Kubernetes 1.24.
**Attention:** The base image for 2.2.x reached end-of-life on January 20, 2022. This release upgraded the base image to Ubuntu 22.04 LTS. The change should have no effect on the majority of users. But if any of your git providers only supports now-deprecated key hash algorithms, then Application syncing might break. See the [2.1-to-2.2 upgrade notes](https://argo-cd.readthedocs.io/en/latest/operator-manual/upgrading/2.1-2.2/#support-for-private-repo-ssh-keys-using-the-sha-1-signature-hash-algorithm-is-removed-in-2212) for details and workaround instructions.
### Bug fixes
- fix: create serviceaccount token for v1.24 clusters (#9546)
- fix: upgrade moment from 2.29.2 to 2.29.3 (#9330)
- fix: avoid CVE-2022-28948 (#10093)
### Other changes
- chore: Remove deprecated K8s versions from test matrix
- chore: Go mod tidy
- test: Remove circular symlinks from testdata (#9886)
- test: Fix e2e tests for release-2.2 branch
- chore: bump redoc vesion to avoid CVE-2021-23820 (#8604)
- chore(deps): bump moment from 2.29.3 to 2.29.4 in /ui (#9897)
- chore: upgrade moment to latest version to fix CVE (#9005)
- chore: move dependencies to dev dependencies (#8541)
- docs: add OpenSSH breaking change notes (#10104)
- chore: update parse-url (#10101)
- chore: fix codegen
- chore: fix codegen
- chore: upgrade base image to 22.04 (#10105)
- docs: simplify Docker toolchain docs (#9966) (#10006)
- chore: update redis to 6.2.7 avoid CVE-2022-30065/CVE-2022-2097 (#10068)
- chore: upgrade Dex to 2.32.0 (#10036) (#10042)
- chore: update haproxy to 2.0.29 for redis-ha (#10045)
- test: check for error messages from CI env (#9953)
## v2.2.11 (2022-07-12)
### Security fixes
* HIGH: Certificate verification is skipped for connections to OIDC providers ([GHSA-7943-82jg-wmw5](https://github.com/argoproj/argo-cd/security/advisories/GHSA-7943-82jg-wmw5))
* LOW: A leaked API server encryption key can allow XSS for SSO users ([GHSA-pmjg-52h9-72qv](https://github.com/argoproj/argo-cd/security/advisories/GHSA-pmjg-52h9-72qv))
### Potentially-breaking changes
The fix for GHSA-7943-82jg-wmw5 enables TLS certificate validation by default for connections to OIDC providers. If
connections to your OIDC provider fails validation, SSO will be broken for your Argo CD instance. You should test 2.2.11
before upgrading it to production. From the new documentation:
> By default, all connections made by the API server to OIDC providers (either external providers or the bundled Dex
> instance) must pass certificate validation. These connections occur when getting the OIDC provider's well-known
> configuration, when getting the OIDC provider's keys, and when exchanging an authorization code or verifying an ID
> token as part of an OIDC login flow.
>
> Disabling certificate verification might make sense if:
> * You are using the bundled Dex instance **and** your Argo CD instance has TLS configured with a self-signed certificate
> **and** you understand and accept the risks of skipping OIDC provider cert verification.
> * You are using an external OIDC provider **and** that provider uses an invalid certificate **and** you cannot solve
> the problem by setting `oidcConfig.rootCA` **and** you understand and accept the risks of skipping OIDC provider cert
> verification.
>
> If either of those two applies, then you can disable OIDC provider certificate verification by setting
> `oidc.tls.insecure.skip.verify` to `"true"` in the `argocd-cm` ConfigMap.
### Features
* feat: enable specifying root ca for oidc (#6712)
### Bug fixes
* fix: webhook typo in case of error in GetManifests (#9671)
## v2.2.10 (2022-06-21)
### Security fixes
* CRITICAL: External URLs for Deployments can include javascript ([GHSA-h4w9-6x78-8vrj](https://github.com/argoproj/argo-cd/security/advisories/GHSA-h4w9-6x78-8vrj))
* HIGH: Insecure entropy in PKCE/Oauth2/OIDC params ([GHSA-2m7h-86qq-fp4v](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2m7h-86qq-fp4v))
* MODERATE: DoS through large directory app manifest files ([GHSA-jhqp-vf4w-rpwq](https://github.com/argoproj/argo-cd/security/advisories/GHSA-jhqp-vf4w-rpwq))
* MODERATE: Symlink following allows leaking out-of-bounds YAML files from Argo CD repo-server ([GHSA-q4w5-4gq2-98vm](https://github.com/argoproj/argo-cd/security/advisories/GHSA-q4w5-4gq2-98vm))
### Potentially-breaking changes
From the [GHSA-2m7h-86qq-fp4v](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2m7h-86qq-fp4v) description:
> The patch introduces a new `reposerver.max.combined.directory.manifests.size` config parameter, which you should tune before upgrading in production. It caps the maximum total file size of .yaml/.yml/.json files in directory-type (raw manifest) Applications. The default max is 10M per Application. This max is designed to keep any single app from consuming more than 3G of memory in the repo-server (manifests consume more space in memory than on disk). The 300x ratio assumes a maliciously-crafted manifest file. If you only want to protect against accidental excessive memory use, it is probably safe to use a smaller ratio.
>
> If your organization uses directory-type Applications with very many manifests or very large manifests then check the size of those manifests and tune the config parameter before deploying this change to production. When testing, make sure to do a "hard refresh" in either the CLI or UI to test your directory-type App. That will make sure you're using the new max logic instead of relying on cached manifest responses from Redis.
### Bug fixes
* fix: missing Helm params (#9565) (#9566)
### Other
* test: directory app manifest generation (#9503)
* test: fix erroneous test change
* chore: eliminate go-mpatch dependency (#9045)
* chore: Make unit tests run on platforms other than amd64 (#8995)
* chore: remove obsolete repo-server unit test (#9559)
* chore: upgrade golangci-lint to v1.46.2 (#9448)
* chore: update golangci-lint (#8988)
## v2.2.9 (2022-05-18)
### Notes
This is a security release. We urge all users of the 2.2.z branch to update as soon as possible. Please refer to the _Security fixes_ section below for more details.
### Security fixes
- CRITICAL: Argo CD will trust invalid JWT claims if anonymous access is enabled (https://github.com/argoproj/argo-cd/security/advisories/GHSA-r642-gv9p-2wjj)
- LOW: Login screen allows message spoofing if SSO is enabled (https://github.com/argoproj/argo-cd/security/advisories/GHSA-xmg8-99r8-jc2j)
- MODERATE: Symlink following allows leaking out-of-bound manifests and JSON files from Argo CD repo-server (https://github.com/argoproj/argo-cd/security/advisories/GHSA-6gcg-hp2x-q54h)
## v2.2.8 (2022-03-22)
### Special notes
This release contains the fix for a security issue with critical severity. We recommend users on the 2.2 release branch to update to this release as soon as possible.
More information can be found in the related
[security advisory](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2f5v-8r3f-8pww).
### Changes
As part of the security fix, the Argo CD UI no longer automatically presents child resources of allow-listed resources unless the child resources are also allow-listed. For example, Pods are not going to show up if only Deployment is added to the allow-list.
If you have [projects](https://argo-cd.readthedocs.io/en/stable/user-guide/projects/) configured with allow-lists, make sure the allow-lists include all the resources you want users to be able to view/manage through the UI. For example, if your project allows `Deployments`, you would add `ReplicaSets` and `Pods`.
#### Bug Fixes
- fix: application resource APIs must enforce project restrictions
## v2.2.7 (2022-03-08)
### Bug Fixes
- fix: correct jsonnet paths resolution (#8721)
## v2.2.6 (2022-03-06)
### Bug Fixes
- fix: prevent file traversal using helm file values param and application details api (#8606)
- fix!: enforce app create/update privileges when getting repo details (#8558)
- feat: support custom helm values file schemes (#8535)
## v2.2.5 (2022-02-04)
- fix: Resolve symlinked value files correctly (#8387)
## v2.2.4 (2022-02-03)
### Special notes
This release contains the fix for a security issue with high severity. We recommend users on the 2.2 release branch to update to this release as soon as possible.
More information can be found in the related
[security advisory](https://github.com/argoproj/argo-cd/security/advisories/GHSA-63qx-x74g-jcr7)
### Bug Fixes
- fix: Prevent value files outside repository root
### Other changes
- chore: upgrade dex to v2.30.2 (backport of #8237) (#8257)
## v2.2.3 (2022-01-18)
- fix: Application exist panic when execute api call (#8188)
@@ -687,117 +238,6 @@ as there are no conflicts with other Kubernetes tools, and you can easily instal
* Cluster name support in project destinations (#7198)
* around 30 more features and a total of 84 bug fixes
## v2.1.16 (2022-06-21)
### Security fixes
* CRITICAL: External URLs for Deployments can include javascript ([GHSA-h4w9-6x78-8vrj](https://github.com/argoproj/argo-cd/security/advisories/GHSA-h4w9-6x78-8vrj))
* HIGH: Insecure entropy in PKCE/Oauth2/OIDC params ([GHSA-2m7h-86qq-fp4v](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2m7h-86qq-fp4v))
* MODERATE: DoS through large directory app manifest files ([GHSA-jhqp-vf4w-rpwq](https://github.com/argoproj/argo-cd/security/advisories/GHSA-jhqp-vf4w-rpwq))
* MODERATE: Symlink following allows leaking out-of-bounds YAML files from Argo CD repo-server ([GHSA-q4w5-4gq2-98vm](https://github.com/argoproj/argo-cd/security/advisories/GHSA-q4w5-4gq2-98vm))
**Note:** This will be the last security fix release in the 2.1.x series. Please [upgrade to a newer minor version](https://argo-cd.readthedocs.io/en/latest/operator-manual/upgrading/overview/) to continue to get security fixes.
### Potentially-breaking changes
From the [GHSA-2m7h-86qq-fp4v](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2m7h-86qq-fp4v) description:
> The patch introduces a new `reposerver.max.combined.directory.manifests.size` config parameter, which you should tune before upgrading in production. It caps the maximum total file size of .yaml/.yml/.json files in directory-type (raw manifest) Applications. The default max is 10M per Application. This max is designed to keep any single app from consuming more than 3G of memory in the repo-server (manifests consume more space in memory than on disk). The 300x ratio assumes a maliciously-crafted manifest file. If you only want to protect against accidental excessive memory use, it is probably safe to use a smaller ratio.
>
> If your organization uses directory-type Applications with very many manifests or very large manifests then check the size of those manifests and tune the config parameter before deploying this change to production. When testing, make sure to do a "hard refresh" in either the CLI or UI to test your directory-type App. That will make sure you're using the new max logic instead of relying on cached manifest responses from Redis.
### Bug fixes
* fix: missing Helm params (#9565) (#9566)
### Other
* test: directory app manifest generation (#9503)
* test: fix erroneous test change
* chore: eliminate go-mpatch dependency (#9045)
* chore: Make unit tests run on platforms other than amd64 (#8995)
* chore: remove obsolete repo-server unit test (#9559)
* chore: upgrade golangci-lint to v1.46.2 (#9448)
* chore: update golangci-lint (#8988)
* test: fix ErrorContains (#9445)
## v2.1.15 (2022-05-18)
### Notes
This is a security release. We urge all users of the 2.1.z branch to update as soon as possible. Please refer to the _Security fixes_ section below for more details.
### Security fixes
- CRITICAL: Argo CD will trust invalid JWT claims if anonymous access is enabled (https://github.com/argoproj/argo-cd/security/advisories/GHSA-r642-gv9p-2wjj)
- LOW: Login screen allows message spoofing if SSO is enabled (https://github.com/argoproj/argo-cd/security/advisories/GHSA-xmg8-99r8-jc2j)
- MODERATE: Symlink following allows leaking out-of-bound manifests and JSON files from Argo CD repo-server (https://github.com/argoproj/argo-cd/security/advisories/GHSA-6gcg-hp2x-q54h)
## v2.1.14 (2022-03-22)
### Special notes
This release contains the fix for a security issue with critical severity. We recommend users on the 2.1 release branch to update to this release as soon as possible.
More information can be found in the related
[security advisory](https://github.com/argoproj/argo-cd/security/advisories/GHSA-2f5v-8r3f-8pww).
### Changes
As part of the security fix, the Argo CD UI no longer automatically presents child resources of allow-listed resources unless the child resources are also allow-listed. For example, Pods are not going to show up if only Deployment is added to the allow-list.
If you have [projects](https://argo-cd.readthedocs.io/en/stable/user-guide/projects/) configured with allow-lists, make sure the allow-lists include all the resources you want users to be able to view/manage through the UI. For example, if your project allows `Deployments`, you would add `ReplicaSets` and `Pods`.
#### Bug Fixes
- fix: application resource APIs must enforce project restrictions
## v2.1.13 (2022-03-22)
Unused release number.
## v2.1.12 (2022-03-08)
### Bug Fixes
- fix: correct jsonnet paths resolution (#8721)
## v2.1.11 (2022-03-06)
### Bug Fixes
- fix: prevent file traversal using helm file values param and application details api (#8606)
- fix!: enforce app create/update privileges when getting repo details (#8558)
- feat: support custom helm values file schemes (#8535)
## v2.1.10 (2022-02-04)
### Bug Fixes
- fix: Resolve symlinked value files correctly (#8387)
## v2.1.9 (2022-02-03)
### Special notes
This release contains the fix for a security issue with high severity. We recommend users on the 2.1 release branch to update to this release as soon as possible.
More information can be found in the related
[security advisory](https://github.com/argoproj/argo-cd/security/advisories/GHSA-63qx-x74g-jcr7)
### Bug Fixes
- fix: Prevent value files outside repository root
## v2.1.8 (2021-12-13)
### Bug Fixes
- 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.7 (2021-12-14)
- fix: issue with keepalive (#7861)
@@ -1008,7 +448,7 @@ resources, you will have to adapt your cluster resources allow lists to explicit
## v1.8.4 (2021-02-05)
- feat: set X-XSS-Protection while serving static content (#5412)
- fix: version info should be available if anonymous access is enabled (#5422)
- fix: version info should be avaialble if anonymous access is enabled (#5422)
- fix: disable jwt claim audience validation #5381 (#5413)
- fix: /api/version should not return tools version for unauthenticated requests (#5415)
- fix: account tokens should be rejected if required capability is disabled (#5414)

View File

@@ -38,11 +38,10 @@ FROM $BASE_IMAGE AS argocd-base
USER root
ENV ARGOCD_USER_ID=999
ENV DEBIAN_FRONTEND=noninteractive
RUN groupadd -g $ARGOCD_USER_ID argocd && \
useradd -r -u $ARGOCD_USER_ID -g argocd argocd && \
RUN groupadd -g 999 argocd && \
useradd -r -u 999 -g argocd argocd && \
mkdir -p /home/argocd && \
chown argocd:0 /home/argocd && \
chmod g=u /home/argocd && \
@@ -75,7 +74,7 @@ RUN mkdir -p tls && \
ENV USER=argocd
USER $ARGOCD_USER_ID
USER 999
WORKDIR /home/argocd
####################################################################################################
@@ -129,4 +128,4 @@ RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-k8s-auth
USER $ARGOCD_USER_ID
USER 999

View File

@@ -47,7 +47,7 @@ ARGOCD_E2E_DEX_PORT?=5556
ARGOCD_E2E_YARN_HOST?=localhost
ARGOCD_E2E_DISABLE_AUTH?=
ARGOCD_E2E_TEST_TIMEOUT?=45m
ARGOCD_E2E_TEST_TIMEOUT?=30m
ARGOCD_IN_CI?=false
ARGOCD_TEST_E2E?=true
@@ -81,8 +81,6 @@ define run-in-test-server
-e ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} \
-e ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} \
-e ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} \
-e ARGOCD_APPLICATION_NAMESPACES \
-e GITHUB_TOKEN \
-v ${DOCKER_SRC_MOUNT} \
-v ${GOPATH}/pkg/mod:/go/pkg/mod${VOLUME_MOUNT} \
-v ${GOCACHE}:/tmp/go-build-cache${VOLUME_MOUNT} \
@@ -104,7 +102,6 @@ define run-in-test-client
-e HOME=/home/user \
-e GOPATH=/go \
-e ARGOCD_E2E_K3S=$(ARGOCD_E2E_K3S) \
-e GITHUB_TOKEN \
-e GOCACHE=/tmp/go-build-cache \
-e ARGOCD_LINT_GOGC=$(ARGOCD_LINT_GOGC) \
-v ${DOCKER_SRC_MOUNT} \
@@ -119,7 +116,7 @@ endef
#
define exec-in-test-server
docker exec -it -u $(shell id -u):$(shell id -g) -e ARGOCD_E2E_RECORD=$(ARGOCD_E2E_RECORD) -e ARGOCD_E2E_K3S=$(ARGOCD_E2E_K3S) argocd-test-server $(1)
docker exec -it -u $(shell id -u):$(shell id -g) -e ARGOCD_E2E_K3S=$(ARGOCD_E2E_K3S) argocd-test-server $(1)
endef
PATH:=$(PATH):$(PWD)/hack
@@ -243,10 +240,8 @@ release-cli: clean-debug build-ui
.PHONY: test-tools-image
test-tools-image:
ifndef SKIP_TEST_TOOLS_IMAGE
docker build --build-arg UID=$(shell id -u) -t $(TEST_TOOLS_PREFIX)$(TEST_TOOLS_IMAGE) -f test/container/Dockerfile .
docker tag $(TEST_TOOLS_PREFIX)$(TEST_TOOLS_IMAGE) $(TEST_TOOLS_PREFIX)$(TEST_TOOLS_IMAGE):$(TEST_TOOLS_TAG)
endif
.PHONY: manifests-local
manifests-local:
@@ -286,7 +281,7 @@ ifeq ($(DEV_IMAGE), true)
# the dist directory is under .dockerignore.
IMAGE_TAG="dev-$(shell git describe --always --dirty)"
image: build-ui
DOCKER_BUILDKIT=1 docker build --platform=linux/amd64 -t argocd-base --target argocd-base .
DOCKER_BUILDKIT=1 docker build -t argocd-base --target argocd-base .
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd ./cmd
ln -sfn ${DIST_DIR}/argocd ${DIST_DIR}/argocd-server
ln -sfn ${DIST_DIR}/argocd ${DIST_DIR}/argocd-application-controller
@@ -294,7 +289,7 @@ image: build-ui
ln -sfn ${DIST_DIR}/argocd ${DIST_DIR}/argocd-cmp-server
ln -sfn ${DIST_DIR}/argocd ${DIST_DIR}/argocd-dex
cp Dockerfile.dev dist
DOCKER_BUILDKIT=1 docker build --platform=linux/amd64 -t $(IMAGE_PREFIX)argocd:$(IMAGE_TAG) -f dist/Dockerfile.dev dist
docker build -t $(IMAGE_PREFIX)argocd:$(IMAGE_TAG) -f dist/Dockerfile.dev dist
else
image:
DOCKER_BUILDKIT=1 docker build -t $(IMAGE_PREFIX)argocd:$(IMAGE_TAG) .
@@ -342,7 +337,7 @@ lint-local:
golangci-lint --version
# NOTE: If you get a "Killed" OOM message, try reducing the value of GOGC
# See https://github.com/golangci/golangci-lint#memory-usage-of-golangci-lint
GOGC=$(ARGOCD_LINT_GOGC) GOMAXPROCS=2 golangci-lint run --fix --verbose --timeout 3000s
GOGC=$(ARGOCD_LINT_GOGC) GOMAXPROCS=2 golangci-lint run --fix --verbose --timeout 300s
.PHONY: lint-ui
lint-ui: test-tools-image
@@ -406,7 +401,7 @@ test-e2e:
test-e2e-local: cli-local
# NO_PROXY ensures all tests don't go out through a proxy if one is configured on the test system
export GO111MODULE=off
ARGOCD_E2E_RECORD=${ARGOCD_E2E_RECORD} ARGOCD_GPG_ENABLED=true NO_PROXY=* ./hack/test.sh -timeout $(ARGOCD_E2E_TEST_TIMEOUT) -v ./test/e2e
ARGOCD_GPG_ENABLED=true NO_PROXY=* ./hack/test.sh -timeout $(ARGOCD_E2E_TEST_TIMEOUT) -v ./test/e2e
# Spawns a shell in the test server container for debugging purposes
debug-test-server: test-tools-image
@@ -427,7 +422,6 @@ start-e2e: test-tools-image
.PHONY: start-e2e-local
start-e2e-local: mod-vendor-local dep-ui-local cli-local
kubectl create ns argocd-e2e || true
kubectl create ns argocd-e2e-external || true
kubectl config set-context --current --namespace=argocd-e2e
kustomize build test/manifests/base | kubectl apply -f -
kubectl apply -f https://raw.githubusercontent.com/open-cluster-management/api/a6845f2ebcb186ec26b832f60c988537a58f3859/cluster/v1alpha1/0000_04_clusters.open-cluster-management.io_placementdecisions.crd.yaml
@@ -448,14 +442,13 @@ start-e2e-local: mod-vendor-local dep-ui-local cli-local
ARGOCD_ZJWT_FEATURE_FLAG=always \
ARGOCD_IN_CI=$(ARGOCD_IN_CI) \
BIN_MODE=$(ARGOCD_BIN_MODE) \
ARGOCD_APPLICATION_NAMESPACES=argocd-e2e-external \
ARGOCD_E2E_TEST=true \
goreman -f $(ARGOCD_PROCFILE) start ${ARGOCD_START}
# Cleans VSCode debug.test files from sub-dirs to prevent them from being included in by golang embed
.PHONY: clean-debug
clean-debug:
-find ${CURRENT_DIR} -name debug.test -exec rm -f {} +
-find ${CURRENT_DIR} -name debug.test | xargs rm -f
.PHONY: clean
clean: clean-debug
@@ -468,7 +461,7 @@ start: test-tools-image
# Starts a local instance of ArgoCD
.PHONY: start-local
start-local: mod-vendor-local dep-ui-local cli-local
start-local: mod-vendor-local dep-ui-local
# check we can connect to Docker to start Redis
killall goreman || true
kubectl create ns argocd || true
@@ -480,7 +473,6 @@ start-local: mod-vendor-local dep-ui-local cli-local
ARGOCD_IN_CI=false \
ARGOCD_GPG_ENABLED=$(ARGOCD_GPG_ENABLED) \
ARGOCD_E2E_TEST=false \
ARGOCD_APPLICATION_NAMESPACES=$(ARGOCD_APPLICATION_NAMESPACES) \
goreman -f $(ARGOCD_PROCFILE) start ${ARGOCD_START}
# Run goreman start with exclude option , provide exclude env variable with list of services
@@ -512,7 +504,7 @@ build-docs-local:
.PHONY: build-docs
build-docs:
docker run ${MKDOCS_RUN_ARGS} --rm -it -v ${CURRENT_DIR}:/docs --entrypoint "" ${MKDOCS_DOCKER_IMAGE} sh -c 'pip install -r docs/requirements.txt; mkdocs build'
docker run ${MKDOCS_RUN_ARGS} --rm -it -p 8000:8000 -v ${CURRENT_DIR}:/docs ${MKDOCS_DOCKER_IMAGE} build
.PHONY: serve-docs-local
serve-docs-local:
@@ -520,7 +512,7 @@ serve-docs-local:
.PHONY: serve-docs
serve-docs:
docker run ${MKDOCS_RUN_ARGS} --rm -it -p 8000:8000 -v ${CURRENT_DIR}/site:/site -w /site --entrypoint "" ${MKDOCS_DOCKER_IMAGE} python3 -m http.server --bind 0.0.0.0 8000
docker run ${MKDOCS_RUN_ARGS} --rm -it -p 8000:8000 -v ${CURRENT_DIR}:/docs ${MKDOCS_DOCKER_IMAGE} serve -a 0.0.0.0:8000
# Verify that kubectl can connect to your K8s cluster from Docker
@@ -577,15 +569,3 @@ applicationset-controller:
.PHONY: checksums
checksums:
sha256sum ./dist/$(BIN_NAME)-* | awk -F './dist/' '{print $$1 $$2}' > ./dist/$(BIN_NAME)-$(TARGET_VERSION)-checksums.txt
.PHONY: snyk-container-tests
snyk-container-tests:
./hack/snyk-container-tests.sh
.PHONY: snyk-non-container-tests
snyk-non-container-tests:
./hack/snyk-non-container-tests.sh
.PHONY: snyk-report
snyk-report:
./hack/snyk-report.sh $(target_branch)

View File

@@ -1,7 +1,7 @@
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} --otlp-address=${ARGOCD_OTLP_ADDRESS} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''}"
api-server: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-server $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} --otlp-address=${ARGOCD_OTLP_ADDRESS} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''}"
dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v2/cmd gendexcfg -o `pwd`/dist/dex.yaml && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml ghcr.io/dexidp/dex:$(grep "image: ghcr.io/dexidp/dex" manifests/base/dex/argocd-dex-server-deployment.yaml | cut -d':' -f3) dex serve /dex.yaml"
redis: 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:$(grep "image: redis" manifests/base/redis/argocd-redis-deployment.yaml | cut -d':' -f3) --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; fi"
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} --otlp-address=${ARGOCD_OTLP_ADDRESS}"
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} --otlp-address=${ARGOCD_OTLP_ADDRESS}"
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:7.0.0-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:-./test/cmp} ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-repo-server ARGOCD_GPG_ENABLED=${ARGOCD_GPG_ENABLED:-false} $COMMAND --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --otlp-address=${ARGOCD_OTLP_ADDRESS}"
cmp-server: [ "$ARGOCD_E2E_TEST" == 'true' ] && exit 0 || [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_BINARY_NAME=argocd-cmp-server ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} $COMMAND --config-dir-path ./test/cmp --loglevel debug --otlp-address=${ARGOCD_OTLP_ADDRESS}"
ui: sh -c 'cd ui && ${ARGOCD_E2E_YARN_CMD:-yarn} start'

View File

@@ -1,7 +1,6 @@
## Who uses Argo CD?
As the Argo Community grows, we'd like to keep track of our users. Please send a
PR with your organization name if you are using Argo CD.
As the Argo Community grows, we'd like to keep track of our users. Please send a PR with your organization name if you are using Argo CD.
Currently, the following organizations are **officially** using Argo CD:
@@ -9,7 +8,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [3Rein](https://www.3rein.com/)
1. [7shifts](https://www.7shifts.com/)
1. [Adevinta](https://www.adevinta.com/)
1. [Adfinis](https://adfinis.com)
1. [Adventure](https://jp.adventurekk.com/)
1. [Akuity](https://akuity.io/)
1. [Alibaba Group](https://www.alibabagroup.com/)
@@ -19,7 +17,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Ant Group](https://www.antgroup.com/)
1. [AppDirect](https://www.appdirect.com)
1. [Arctiq Inc.](https://www.arctiq.ca)
1. [ARZ Allgemeines Rechenzentrum GmbH](https://www.arz.at/)
1. [ARZ Allgemeines Rechenzentrum GmbH ](https://www.arz.at/)
1. [Axual B.V.](https://axual.com)
1. [Baloise](https://www.baloise.com)
1. [BCDevExchange DevOps Platform](https://bcdevexchange.org/DevOpsPlatform)
@@ -31,13 +29,11 @@ Currently, the following organizations are **officially** using Argo CD:
1. [BMW Group](https://www.bmwgroup.com/)
1. [Boozt](https://www.booztgroup.com/)
1. [Boticario](https://www.boticario.com.br/)
1. [Bulder Bank](https://bulderbank.no)
1. [Camptocamp](https://camptocamp.com)
1. [Capital One](https://www.capitalone.com)
1. [CARFAX](https://www.carfax.com)
1. [Casavo](https://casavo.com)
1. [Celonis](https://www.celonis.com/)
1. [CERN](https://home.cern/)
1. [Chargetrip](https://chargetrip.com)
1. [Chime](https://www.chime.com)
1. [Cisco ET&I](https://eti.cisco.com/)
@@ -45,7 +41,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Codefresh](https://www.codefresh.io/)
1. [Codility](https://www.codility.com/)
1. [Commonbond](https://commonbond.co/)
1. [Coralogix](https://coralogix.com/)
1. [CROZ d.o.o.](https://croz.net/)
1. [Crédit Agricole CIB](https://www.ca-cib.com)
1. [CyberAgent](https://www.cyberagent.co.jp/en/)
@@ -57,37 +52,28 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Devtron Labs](https://github.com/devtron-labs/devtron)
1. [EDF Renewables](https://www.edf-re.com/)
1. [edX](https://edx.org)
1. [Elastic](https://elastic.co/)
1. [Electronic Arts Inc.](https://www.ea.com)
1. [Elementor](https://elementor.com/)
1. [Electronic Arts Inc. ](https://www.ea.com)
1. [Elium](https://www.elium.com)
1. [END.](https://www.endclothing.com/)
1. [Energisme](https://energisme.com/)
1. [enigmo](https://enigmo.co.jp/)
1. [Faro](https://www.faro.com/)
1. [Fave](https://myfave.com)
1. [Flip](https://flip.id)
1. [Fonoa](https://www.fonoa.com/)
1. [freee](https://corp.freee.co.jp/en/company/)
1. [Freshop, Inc](https://www.freshop.com/)
1. [Future PLC](https://www.futureplc.com/)
1. [G DATA CyberDefense AG](https://www.gdata-software.com/)
1. [Garner](https://www.garnercorp.com)
1. [Generali Deutschland AG](https://www.generali.de/)
1. [Gitpod](https://www.gitpod.io)
1. [Gllue](https://gllue.com)
1. [gloat](https://gloat.com/)
1. [GLOBIS](https://globis.com)
1. [Glovo](https://www.glovoapp.com)
1. [GMETRI](https://gmetri.com/)
1. [Gojek](https://www.gojek.io/)
1. [Greenpass](https://www.greenpass.com.br/)
1. [Gridfuse](https://gridfuse.com/)
1. [Grupo MasMovil](https://grupomasmovil.com/en/)
1. [Handelsbanken](https://www.handelsbanken.se)
1. [Healy](https://www.healyworld.net)
1. [Helio](https://helio.exchange)
1. [Hetki](https://hetki.ai)
1. [hipages](https://hipages.com.au/)
1. [Hiya](https://hiya.com)
1. [Honestbank](https://honestbank.com)
@@ -96,13 +82,11 @@ Currently, the following organizations are **officially** using Argo CD:
1. [IITS-Consulting](https://iits-consulting.de)
1. [imaware](https://imaware.health)
1. [Index Exchange](https://www.indexexchange.com/)
1. [Info Support](https://www.infosupport.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. [Kaltura](https://corp.kaltura.com/)
1. [Kandji](https://www.kandji.io/)
1. [KarrotPay](https://www.daangnpay.com/)
1. [Karrot](https://www.daangn.com/)
1. [Kasa](https://kasa.co.kr/)
@@ -112,13 +96,10 @@ Currently, the following organizations are **officially** using Argo CD:
1. [KintoHub](https://www.kintohub.com/)
1. [KompiTech GmbH](https://www.kompitech.com/)
1. [KubeSphere](https://github.com/kubesphere)
1. [Kurly](https://www.kurly.com/)
1. [LexisNexis](https://www.lexisnexis.com/)
1. [Lian Chu Securities](https://lczq.com)
1. [Lightricks](https://www.lightricks.com/)
1. [LINE](https://linecorp.com/en/)
1. [Lytt](https://www.lytt.co/)
1. [Magic Leap](https://www.magicleap.com/)
1. [Majid Al Futtaim](https://www.majidalfuttaim.com/)
1. [Major League Baseball](https://mlb.com)
1. [Mambu](https://www.mambu.com/)
@@ -126,7 +107,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Mattermost](https://www.mattermost.com)
1. [Max Kelsen](https://www.maxkelsen.com/)
1. [MeDirect](https://medirect.com.mt/)
1. [Meican](https://meican.com/)
1. [Metanet](http://www.metanet.co.kr/en/)
1. [MindSpore](https://mindspore.cn)
1. [Mirantis](https://mirantis.com/)
@@ -136,12 +116,10 @@ Currently, the following organizations are **officially** using Argo CD:
1. [MOO Print](https://www.moo.com/)
1. [MTN Group](https://www.mtn.com/)
1. [Natura &Co](https://naturaeco.com/)
1. [Nethopper](https://nethopper.io)
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. [OCCMundial](https://occ.com.mx)
1. [Octadesk](https://octadesk.com)
1. [omegaUp](https://omegaUp.com)
1. [openEuler](https://openeuler.org)
@@ -149,32 +127,22 @@ Currently, the following organizations are **officially** using Argo CD:
1. [openLooKeng](https://openlookeng.io)
1. [OpenSaaS Studio](https://opensaas.studio)
1. [Opensurvey](https://www.opensurvey.co.kr/)
1. [OpsVerse](https://opsverse.io)
1. [Optoro](https://www.optoro.com/)
1. [Orbital Insight](https://orbitalinsight.com/)
1. [p3r](https://www.p3r.one/)
1. [Packlink](https://www.packlink.com/)
1. [Pandosearch](https://www.pandosearch.com/en/home)
1. [PagerDuty](https://www.pagerduty.com/)
1. [Patreon](https://www.patreon.com/)
1. [PayPay](https://paypay.ne.jp/)
1. [Peloton Interactive](https://www.onepeloton.com/)
1. [Pipefy](https://www.pipefy.com/)
1. [Pismo](https://pismo.io/)
1. [Polarpoint.io](https://polarpoint.io)
1. [PostFinance](https://github.com/postfinance)
1. [Preferred Networks](https://preferred.jp/en/)
1. [Productboard](https://www.productboard.com/)
1. [Prudential](https://prudential.com.sg)
1. [PUBG](https://www.pubg.com)
1. [Qonto](https://qonto.com)
1. [QuintoAndar](https://quintoandar.com.br)
1. [Quipper](https://www.quipper.com/)
1. [RapidAPI](https://www.rapidapi.com/)
1. [Recreation.gov](https://www.recreation.gov/)
1. [Red Hat](https://www.redhat.com/)
1. [Redpill Linpro](https://www.redpill-linpro.com/)
1. [reev.com](https://www.reev.com/)
1. [RightRev](https://rightrev.com/)
1. [Rise](https://www.risecard.eu/)
1. [Riskified](https://www.riskified.com/)
@@ -189,11 +157,8 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Smilee.io](https://smilee.io)
1. [Snapp](https://snapp.ir/)
1. [Snyk](https://snyk.io/)
1. [Softway Medical](https://www.softwaymedical.fr/)
1. [South China Morning Post (SCMP)](https://www.scmp.com/)
1. [Speee](https://speee.jp/)
1. [Spendesk](https://spendesk.com/)
1. [Splunk](https://splunk.com/)
1. [Spores Labs](https://spores.app)
1. [Stuart](https://stuart.com/)
1. [Sumo Logic](https://sumologic.com/)
@@ -205,7 +170,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [TableCheck](https://tablecheck.com/)
1. [Tailor Brands](https://www.tailorbrands.com)
1. [Tamkeen Technologies](https://tamkeentech.sa/)
1. [Techcombank](https://www.techcombank.com.vn/trang-chu)
1. [Technacy](https://www.technacy.it/)
1. [Tesla](https://tesla.com/)
1. [ThousandEyes](https://www.thousandeyes.com/)
@@ -213,7 +177,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Tiger Analytics](https://www.tigeranalytics.com/)
1. [Tigera](https://www.tigera.io/)
1. [Toss](https://toss.im/en)
1. [Trendyol](https://www.trendyol.com/)
1. [tru.ID](https://tru.id)
1. [Twilio SendGrid](https://sendgrid.com)
1. [tZERO](https://www.tzero.com/)
@@ -230,7 +193,6 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Walkbase](https://www.walkbase.com/)
1. [Webstores](https://www.webstores.nl)
1. [Wehkamp](https://www.wehkamp.nl/)
1. [WeMaintain](https://www.wemaintain.com/)
1. [WeMo Scooter](https://www.wemoscooter.com/)
1. [Whitehat Berlin](https://whitehat.berlin) by Guido Maria Serra +Fenaroli
1. [Witick](https://witick.io/)
@@ -242,3 +204,5 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Yubo](https://www.yubo.live/)
1. [Zimpler](https://www.zimpler.com/)
1. [ZOZO](https://corp.zozo.com/)
1. [Trendyol](https://www.trendyol.com/)
1. [RapidAPI](https://www.rapidapi.com/)

View File

@@ -1 +1 @@
2.5.15
2.4.23

View File

@@ -19,6 +19,7 @@ import (
"fmt"
"time"
"github.com/go-logr/logr"
log "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
@@ -36,11 +37,11 @@ import (
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/util/db"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned"
argoutil "github.com/argoproj/argo-cd/v2/util/argo"
"github.com/argoproj/argo-cd/v2/util/db"
)
const (
@@ -61,6 +62,7 @@ var (
// ApplicationSetReconciler reconciles a ApplicationSet object
type ApplicationSetReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
Recorder record.EventRecorder
Generators map[string]generators.Generator
@@ -75,14 +77,15 @@ type ApplicationSetReconciler struct {
// +kubebuilder:rbac:groups=argoproj.io,resources=applicationsets/status,verbs=get;update;patch
func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logCtx := log.WithField("applicationset", req.NamespacedName)
_ = r.Log.WithValues("applicationset", req.NamespacedName)
_ = log.WithField("applicationset", req.NamespacedName)
var applicationSetInfo argov1alpha1.ApplicationSet
var applicationSetInfo argoprojiov1alpha1.ApplicationSet
parametersGenerated := false
if err := r.Get(ctx, req.NamespacedName, &applicationSetInfo); err != nil {
if client.IgnoreNotFound(err) != nil {
logCtx.WithError(err).Infof("unable to get ApplicationSet: '%v' ", err)
log.WithError(err).Infof("unable to get ApplicationSet: '%v' ", err)
}
return ctrl.Result{}, client.IgnoreNotFound(err)
}
@@ -93,17 +96,17 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
// Log a warning if there are unrecognized generators
_ = utils.CheckInvalidGenerators(&applicationSetInfo)
utils.CheckInvalidGenerators(&applicationSetInfo)
// desiredApplications is the main list of all expected Applications from all generators in this appset.
desiredApplications, applicationSetReason, err := r.generateApplications(applicationSetInfo)
if err != nil {
_ = r.setApplicationSetStatusCondition(ctx,
&applicationSetInfo,
argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionErrorOccurred,
argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionErrorOccurred,
Message: err.Error(),
Reason: string(applicationSetReason),
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}, parametersGenerated,
)
return ctrl.Result{}, err
@@ -120,15 +123,15 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
//
// Changes to watched resources will cause this to be reconciled sooner than
// the RequeueAfter time.
logCtx.Errorf("error occurred during application validation: %s", err.Error())
log.Errorf("error occurred during application validation: %s", err.Error())
_ = r.setApplicationSetStatusCondition(ctx,
&applicationSetInfo,
argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionErrorOccurred,
argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionErrorOccurred,
Message: err.Error(),
Reason: argov1alpha1.ApplicationSetReasonApplicationValidationError,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonApplicationValidationError,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}, parametersGenerated,
)
return ctrl.Result{RequeueAfter: ReconcileRequeueOnValidationError}, nil
@@ -145,7 +148,7 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
var message string
for _, v := range validateErrors {
message = v.Error()
logCtx.Errorf("validation error found during application validation: %s", message)
log.Errorf("validation error found during application validation: %s", message)
}
if len(validateErrors) > 1 {
// Only the last message gets added to the appset status, to keep the size reasonable.
@@ -153,11 +156,11 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
_ = r.setApplicationSetStatusCondition(ctx,
&applicationSetInfo,
argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionErrorOccurred,
argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionErrorOccurred,
Message: message,
Reason: argov1alpha1.ApplicationSetReasonApplicationValidationError,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonApplicationValidationError,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}, parametersGenerated,
)
}
@@ -167,11 +170,11 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
if err != nil {
_ = r.setApplicationSetStatusCondition(ctx,
&applicationSetInfo,
argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionErrorOccurred,
argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionErrorOccurred,
Message: err.Error(),
Reason: argov1alpha1.ApplicationSetReasonUpdateApplicationError,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonUpdateApplicationError,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}, parametersGenerated,
)
return ctrl.Result{}, err
@@ -181,11 +184,11 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
if err != nil {
_ = r.setApplicationSetStatusCondition(ctx,
&applicationSetInfo,
argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionErrorOccurred,
argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionErrorOccurred,
Message: err.Error(),
Reason: argov1alpha1.ApplicationSetReasonCreateApplicationError,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonCreateApplicationError,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}, parametersGenerated,
)
return ctrl.Result{}, err
@@ -197,11 +200,11 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
if err != nil {
_ = r.setApplicationSetStatusCondition(ctx,
&applicationSetInfo,
argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionResourcesUpToDate,
argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionResourcesUpToDate,
Message: err.Error(),
Reason: argov1alpha1.ApplicationSetReasonDeleteApplicationError,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonDeleteApplicationError,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}, parametersGenerated,
)
return ctrl.Result{}, err
@@ -212,14 +215,14 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
delete(applicationSetInfo.Annotations, common.AnnotationApplicationSetRefresh)
err := r.Client.Update(ctx, &applicationSetInfo)
if err != nil {
logCtx.Warnf("error occurred while updating ApplicationSet: %v", err)
log.Warnf("error occurred while updating ApplicationSet: %v", err)
_ = r.setApplicationSetStatusCondition(ctx,
&applicationSetInfo,
argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionErrorOccurred,
argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionErrorOccurred,
Message: err.Error(),
Reason: argov1alpha1.ApplicationSetReasonRefreshApplicationError,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonRefreshApplicationError,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}, parametersGenerated,
)
return ctrl.Result{}, err
@@ -227,16 +230,16 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
requeueAfter := r.getMinRequeueAfter(&applicationSetInfo)
logCtx.WithField("requeueAfter", requeueAfter).Info("end reconcile")
log.WithField("requeueAfter", requeueAfter).Info("end reconcile")
if len(validateErrors) == 0 {
if err := r.setApplicationSetStatusCondition(ctx,
&applicationSetInfo,
argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionResourcesUpToDate,
argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionResourcesUpToDate,
Message: "All applications have been generated successfully",
Reason: argov1alpha1.ApplicationSetReasonApplicationSetUpToDate,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonApplicationSetUpToDate,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}, parametersGenerated,
); err != nil {
return ctrl.Result{}, err
@@ -248,67 +251,67 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}, nil
}
func getParametersGeneratedCondition(parametersGenerated bool, message string) argov1alpha1.ApplicationSetCondition {
var paramtersGeneratedCondition argov1alpha1.ApplicationSetCondition
func getParametersGeneratedCondition(parametersGenerated bool, message string) argoprojiov1alpha1.ApplicationSetCondition {
var paramtersGeneratedCondition argoprojiov1alpha1.ApplicationSetCondition
if parametersGenerated {
paramtersGeneratedCondition = argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionParametersGenerated,
paramtersGeneratedCondition = argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionParametersGenerated,
Message: "Successfully generated parameters for all Applications",
Reason: argov1alpha1.ApplicationSetReasonParametersGenerated,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonParametersGenerated,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}
} else {
paramtersGeneratedCondition = argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionParametersGenerated,
paramtersGeneratedCondition = argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionParametersGenerated,
Message: message,
Reason: argov1alpha1.ApplicationSetReasonErrorOccurred,
Status: argov1alpha1.ApplicationSetConditionStatusFalse,
Reason: argoprojiov1alpha1.ApplicationSetReasonErrorOccurred,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusFalse,
}
}
return paramtersGeneratedCondition
}
func getResourceUpToDateCondition(errorOccurred bool, message string, reason string) argov1alpha1.ApplicationSetCondition {
var resourceUpToDateCondition argov1alpha1.ApplicationSetCondition
func getResourceUpToDateCondition(errorOccurred bool, message string, reason string) argoprojiov1alpha1.ApplicationSetCondition {
var resourceUpToDateCondition argoprojiov1alpha1.ApplicationSetCondition
if errorOccurred {
resourceUpToDateCondition = argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionResourcesUpToDate,
resourceUpToDateCondition = argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionResourcesUpToDate,
Message: message,
Reason: reason,
Status: argov1alpha1.ApplicationSetConditionStatusFalse,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusFalse,
}
} else {
resourceUpToDateCondition = argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionResourcesUpToDate,
resourceUpToDateCondition = argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionResourcesUpToDate,
Message: "ApplicationSet up to date",
Reason: argov1alpha1.ApplicationSetReasonApplicationSetUpToDate,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonApplicationSetUpToDate,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}
}
return resourceUpToDateCondition
}
func (r *ApplicationSetReconciler) setApplicationSetStatusCondition(ctx context.Context, applicationSet *argov1alpha1.ApplicationSet, condition argov1alpha1.ApplicationSetCondition, paramtersGenerated bool) error {
func (r *ApplicationSetReconciler) setApplicationSetStatusCondition(ctx context.Context, applicationSet *argoprojiov1alpha1.ApplicationSet, condition argoprojiov1alpha1.ApplicationSetCondition, paramtersGenerated bool) error {
// check if error occurred during reconcile process
errOccurred := condition.Type == argov1alpha1.ApplicationSetConditionErrorOccurred
errOccurred := condition.Type == argoprojiov1alpha1.ApplicationSetConditionErrorOccurred
var errOccurredCondition argov1alpha1.ApplicationSetCondition
var errOccurredCondition argoprojiov1alpha1.ApplicationSetCondition
if errOccurred {
errOccurredCondition = condition
} else {
errOccurredCondition = argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionErrorOccurred,
errOccurredCondition = argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionErrorOccurred,
Message: "Successfully generated parameters for all Applications",
Reason: argov1alpha1.ApplicationSetReasonApplicationSetUpToDate,
Status: argov1alpha1.ApplicationSetConditionStatusFalse,
Reason: argoprojiov1alpha1.ApplicationSetReasonApplicationSetUpToDate,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusFalse,
}
}
paramtersGeneratedCondition := getParametersGeneratedCondition(paramtersGenerated, condition.Message)
resourceUpToDateCondition := getResourceUpToDateCondition(errOccurred, condition.Message, condition.Reason)
newConditions := []argov1alpha1.ApplicationSetCondition{errOccurredCondition, paramtersGeneratedCondition, resourceUpToDateCondition}
newConditions := []argoprojiov1alpha1.ApplicationSetCondition{errOccurredCondition, paramtersGeneratedCondition, resourceUpToDateCondition}
needToUpdateConditions := false
for _, condition := range newConditions {
@@ -320,10 +323,10 @@ func (r *ApplicationSetReconciler) setApplicationSetStatusCondition(ctx context.
}
}
}
evaluatedTypes := map[argov1alpha1.ApplicationSetConditionType]bool{
argov1alpha1.ApplicationSetConditionErrorOccurred: true,
argov1alpha1.ApplicationSetConditionParametersGenerated: true,
argov1alpha1.ApplicationSetConditionResourcesUpToDate: true,
evaluatedTypes := map[argoprojiov1alpha1.ApplicationSetConditionType]bool{
argoprojiov1alpha1.ApplicationSetConditionErrorOccurred: true,
argoprojiov1alpha1.ApplicationSetConditionParametersGenerated: true,
argoprojiov1alpha1.ApplicationSetConditionResourcesUpToDate: true,
}
if needToUpdateConditions || len(applicationSet.Status.Conditions) < 3 {
@@ -352,7 +355,7 @@ func (r *ApplicationSetReconciler) setApplicationSetStatusCondition(ctx context.
// validateGeneratedApplications uses the Argo CD validation functions to verify the correctness of the
// generated applications.
func (r *ApplicationSetReconciler) validateGeneratedApplications(ctx context.Context, desiredApplications []argov1alpha1.Application, applicationSetInfo argov1alpha1.ApplicationSet, namespace string) (map[int]error, error) {
func (r *ApplicationSetReconciler) validateGeneratedApplications(ctx context.Context, desiredApplications []argov1alpha1.Application, applicationSetInfo argoprojiov1alpha1.ApplicationSet, namespace string) (map[int]error, error) {
errorsByIndex := map[int]error{}
namesSet := map[string]bool{}
for i, app := range desiredApplications {
@@ -392,7 +395,7 @@ func (r *ApplicationSetReconciler) validateGeneratedApplications(ctx context.Con
return errorsByIndex, nil
}
func (r *ApplicationSetReconciler) getMinRequeueAfter(applicationSetInfo *argov1alpha1.ApplicationSet) time.Duration {
func (r *ApplicationSetReconciler) getMinRequeueAfter(applicationSetInfo *argoprojiov1alpha1.ApplicationSet) time.Duration {
var res time.Duration
for _, requestedGenerator := range applicationSetInfo.Spec.Generators {
@@ -412,7 +415,7 @@ func (r *ApplicationSetReconciler) getMinRequeueAfter(applicationSetInfo *argov1
return res
}
func getTempApplication(applicationSetTemplate argov1alpha1.ApplicationSetTemplate) *argov1alpha1.Application {
func getTempApplication(applicationSetTemplate argoprojiov1alpha1.ApplicationSetTemplate) *argov1alpha1.Application {
var tmplApplication argov1alpha1.Application
tmplApplication.Annotations = applicationSetTemplate.Annotations
tmplApplication.Labels = applicationSetTemplate.Labels
@@ -424,20 +427,20 @@ func getTempApplication(applicationSetTemplate argov1alpha1.ApplicationSetTempla
return &tmplApplication
}
func (r *ApplicationSetReconciler) generateApplications(applicationSetInfo argov1alpha1.ApplicationSet) ([]argov1alpha1.Application, argov1alpha1.ApplicationSetReasonType, error) {
func (r *ApplicationSetReconciler) generateApplications(applicationSetInfo argoprojiov1alpha1.ApplicationSet) ([]argov1alpha1.Application, argoprojiov1alpha1.ApplicationSetReasonType, error) {
var res []argov1alpha1.Application
var firstError error
var applicationSetReason argov1alpha1.ApplicationSetReasonType
var applicationSetReason argoprojiov1alpha1.ApplicationSetReasonType
for _, requestedGenerator := range applicationSetInfo.Spec.Generators {
t, err := generators.Transform(requestedGenerator, r.Generators, applicationSetInfo.Spec.Template, &applicationSetInfo, map[string]interface{}{})
t, err := generators.Transform(requestedGenerator, r.Generators, applicationSetInfo.Spec.Template, &applicationSetInfo)
if err != nil {
log.WithError(err).WithField("generator", requestedGenerator).
Error("error generating application from params")
if firstError == nil {
firstError = err
applicationSetReason = argov1alpha1.ApplicationSetReasonApplicationParamsGenerationError
applicationSetReason = argoprojiov1alpha1.ApplicationSetReasonApplicationParamsGenerationError
}
continue
}
@@ -446,14 +449,14 @@ func (r *ApplicationSetReconciler) generateApplications(applicationSetInfo argov
tmplApplication := getTempApplication(a.Template)
for _, p := range a.Params {
app, err := r.Renderer.RenderTemplateParams(tmplApplication, applicationSetInfo.Spec.SyncPolicy, p, applicationSetInfo.Spec.GoTemplate)
app, err := r.Renderer.RenderTemplateParams(tmplApplication, applicationSetInfo.Spec.SyncPolicy, p)
if err != nil {
log.WithError(err).WithField("params", a.Params).WithField("generator", requestedGenerator).
Error("error generating application from params")
if firstError == nil {
firstError = err
applicationSetReason = argov1alpha1.ApplicationSetReasonRenderTemplateParamsError
applicationSetReason = argoprojiov1alpha1.ApplicationSetReasonRenderTemplateParamsError
}
continue
}
@@ -477,7 +480,7 @@ func (r *ApplicationSetReconciler) SetupWithManager(mgr ctrl.Manager) error {
return nil
}
// ...make sure it's a application set...
if owner.APIVersion != argov1alpha1.SchemeGroupVersion.String() || owner.Kind != "ApplicationSet" {
if owner.APIVersion != argoprojiov1alpha1.GroupVersion.String() || owner.Kind != "ApplicationSet" {
return nil
}
@@ -488,7 +491,7 @@ func (r *ApplicationSetReconciler) SetupWithManager(mgr ctrl.Manager) error {
}
return ctrl.NewControllerManagedBy(mgr).
For(&argov1alpha1.ApplicationSet{}).
For(&argoprojiov1alpha1.ApplicationSet{}).
Owns(&argov1alpha1.Application{}).
Watches(
&source.Kind{Type: &corev1.Secret{}},
@@ -504,7 +507,7 @@ func (r *ApplicationSetReconciler) SetupWithManager(mgr ctrl.Manager) error {
// - For new applications, it will call create
// - For existing application, it will call update
// The function also adds owner reference to all applications, and uses it to delete them.
func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context, applicationSet argov1alpha1.ApplicationSet, desiredApplications []argov1alpha1.Application) error {
func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context, applicationSet argoprojiov1alpha1.ApplicationSet, desiredApplications []argov1alpha1.Application) error {
var firstError error
// Creates or updates the application in appList
@@ -562,7 +565,7 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
// createInCluster will filter from the desiredApplications only the application that needs to be created
// Then it will call createOrUpdateInCluster to do the actual create
func (r *ApplicationSetReconciler) createInCluster(ctx context.Context, applicationSet argov1alpha1.ApplicationSet, desiredApplications []argov1alpha1.Application) error {
func (r *ApplicationSetReconciler) createInCluster(ctx context.Context, applicationSet argoprojiov1alpha1.ApplicationSet, desiredApplications []argov1alpha1.Application) error {
var createApps []argov1alpha1.Application
current, err := r.getCurrentApplications(ctx, applicationSet)
@@ -588,7 +591,7 @@ func (r *ApplicationSetReconciler) createInCluster(ctx context.Context, applicat
return r.createOrUpdateInCluster(ctx, applicationSet, createApps)
}
func (r *ApplicationSetReconciler) getCurrentApplications(_ context.Context, applicationSet argov1alpha1.ApplicationSet) ([]argov1alpha1.Application, error) {
func (r *ApplicationSetReconciler) getCurrentApplications(_ context.Context, applicationSet argoprojiov1alpha1.ApplicationSet) ([]argov1alpha1.Application, error) {
// TODO: Should this use the context param?
var current argov1alpha1.ApplicationList
err := r.Client.List(context.Background(), &current, client.MatchingFields{".metadata.controller": applicationSet.Name})
@@ -602,7 +605,7 @@ func (r *ApplicationSetReconciler) getCurrentApplications(_ context.Context, app
// deleteInCluster will delete Applications that are currently on the cluster, but not in appList.
// The function must be called after all generators had been called and generated applications
func (r *ApplicationSetReconciler) deleteInCluster(ctx context.Context, applicationSet argov1alpha1.ApplicationSet, desiredApplications []argov1alpha1.Application) error {
func (r *ApplicationSetReconciler) deleteInCluster(ctx context.Context, applicationSet argoprojiov1alpha1.ApplicationSet, desiredApplications []argov1alpha1.Application) error {
// settingsMgr := settings.NewSettingsManager(context.TODO(), r.KubeClientset, applicationSet.Namespace)
// argoDB := db.NewDB(applicationSet.Namespace, settingsMgr, r.KubeClientset)
// clusterList, err := argoDB.ListClusters(ctx)
@@ -657,7 +660,7 @@ func (r *ApplicationSetReconciler) deleteInCluster(ctx context.Context, applicat
}
// removeFinalizerOnInvalidDestination removes the Argo CD resources finalizer if the application contains an invalid target (eg missing cluster)
func (r *ApplicationSetReconciler) removeFinalizerOnInvalidDestination(ctx context.Context, applicationSet argov1alpha1.ApplicationSet, app *argov1alpha1.Application, clusterList *argov1alpha1.ClusterList, appLog *log.Entry) error {
func (r *ApplicationSetReconciler) removeFinalizerOnInvalidDestination(ctx context.Context, applicationSet argoprojiov1alpha1.ApplicationSet, app *argov1alpha1.Application, clusterList *argov1alpha1.ClusterList, appLog *log.Entry) error {
// Only check if the finalizers need to be removed IF there are finalizers to remove
if len(app.Finalizers) == 0 {

View File

@@ -26,9 +26,9 @@ import (
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake"
dbmocks "github.com/argoproj/argo-cd/v2/util/db/mocks"
)
@@ -37,30 +37,30 @@ type generatorMock struct {
mock.Mock
}
func (g *generatorMock) GetTemplate(appSetGenerator *argov1alpha1.ApplicationSetGenerator) *argov1alpha1.ApplicationSetTemplate {
func (g *generatorMock) GetTemplate(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) *argoprojiov1alpha1.ApplicationSetTemplate {
args := g.Called(appSetGenerator)
return args.Get(0).(*argov1alpha1.ApplicationSetTemplate)
return args.Get(0).(*argoprojiov1alpha1.ApplicationSetTemplate)
}
func (g *generatorMock) GenerateParams(appSetGenerator *argov1alpha1.ApplicationSetGenerator, _ *argov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (g *generatorMock) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, _ *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
args := g.Called(appSetGenerator)
return args.Get(0).([]map[string]interface{}), args.Error(1)
return args.Get(0).([]map[string]string), args.Error(1)
}
type rendererMock struct {
mock.Mock
}
func (g *generatorMock) GetRequeueAfter(appSetGenerator *argov1alpha1.ApplicationSetGenerator) time.Duration {
func (g *generatorMock) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration {
args := g.Called(appSetGenerator)
return args.Get(0).(time.Duration)
}
func (r *rendererMock) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argov1alpha1.ApplicationSetSyncPolicy, params map[string]interface{}, useGoTemplate bool) (*argov1alpha1.Application, error) {
args := r.Called(tmpl, params, useGoTemplate)
func (r *rendererMock) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, params map[string]string) (*argov1alpha1.Application, error) {
args := r.Called(tmpl, params)
if args.Error(1) != nil {
return nil, args.Error(1)
@@ -72,7 +72,7 @@ func (r *rendererMock) RenderTemplateParams(tmpl *argov1alpha1.Application, sync
func TestExtractApplications(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
@@ -80,8 +80,8 @@ func TestExtractApplications(t *testing.T) {
for _, c := range []struct {
name string
params []map[string]interface{}
template argov1alpha1.ApplicationSetTemplate
params []map[string]string
template argoprojiov1alpha1.ApplicationSetTemplate
generateParamsError error
rendererError error
expectErr bool
@@ -89,9 +89,9 @@ func TestExtractApplications(t *testing.T) {
}{
{
name: "Generate two applications",
params: []map[string]interface{}{{"name": "app1"}, {"name": "app2"}},
template: argov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argov1alpha1.ApplicationSetTemplateMeta{
params: []map[string]string{{"name": "app1"}, {"name": "app2"}},
template: argoprojiov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argoprojiov1alpha1.ApplicationSetTemplateMeta{
Name: "name",
Namespace: "namespace",
Labels: map[string]string{"label_name": "label_value"},
@@ -108,9 +108,9 @@ func TestExtractApplications(t *testing.T) {
},
{
name: "Handles error from the render",
params: []map[string]interface{}{{"name": "app1"}, {"name": "app2"}},
template: argov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argov1alpha1.ApplicationSetTemplateMeta{
params: []map[string]string{{"name": "app1"}, {"name": "app2"}},
template: argoprojiov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argoprojiov1alpha1.ApplicationSetTemplateMeta{
Name: "name",
Namespace: "namespace",
Labels: map[string]string{"label_name": "label_value"},
@@ -131,7 +131,7 @@ func TestExtractApplications(t *testing.T) {
t.Run(cc.name, func(t *testing.T) {
appSet := &argov1alpha1.ApplicationSet{
appSet := &argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
@@ -141,15 +141,15 @@ func TestExtractApplications(t *testing.T) {
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(appSet).Build()
generatorMock := generatorMock{}
generator := argov1alpha1.ApplicationSetGenerator{
List: &argov1alpha1.ListGenerator{},
generator := argoprojiov1alpha1.ApplicationSetGenerator{
List: &argoprojiov1alpha1.ListGenerator{},
}
generatorMock.On("GenerateParams", &generator).
Return(cc.params, cc.generateParamsError)
generatorMock.On("GetTemplate", &generator).
Return(&argov1alpha1.ApplicationSetTemplate{})
Return(&argoprojiov1alpha1.ApplicationSetTemplate{})
rendererMock := rendererMock{}
@@ -159,10 +159,10 @@ func TestExtractApplications(t *testing.T) {
for _, p := range cc.params {
if cc.rendererError != nil {
rendererMock.On("RenderTemplateParams", getTempApplication(cc.template), p, false).
rendererMock.On("RenderTemplateParams", getTempApplication(cc.template), p).
Return(nil, cc.rendererError)
} else {
rendererMock.On("RenderTemplateParams", getTempApplication(cc.template), p, false).
rendererMock.On("RenderTemplateParams", getTempApplication(cc.template), p).
Return(&app, nil)
expectedApps = append(expectedApps, app)
}
@@ -180,13 +180,13 @@ func TestExtractApplications(t *testing.T) {
KubeClientset: kubefake.NewSimpleClientset(),
}
got, reason, err := r.generateApplications(argov1alpha1.ApplicationSet{
got, reason, err := r.generateApplications(argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{generator},
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{generator},
Template: cc.template,
},
})
@@ -211,39 +211,39 @@ func TestExtractApplications(t *testing.T) {
func TestMergeTemplateApplications(t *testing.T) {
scheme := runtime.NewScheme()
_ = argov1alpha1.AddToScheme(scheme)
_ = argoprojiov1alpha1.AddToScheme(scheme)
_ = argov1alpha1.AddToScheme(scheme)
client := fake.NewClientBuilder().WithScheme(scheme).Build()
for _, c := range []struct {
name string
params []map[string]interface{}
template argov1alpha1.ApplicationSetTemplate
overrideTemplate argov1alpha1.ApplicationSetTemplate
expectedMerged argov1alpha1.ApplicationSetTemplate
params []map[string]string
template argoprojiov1alpha1.ApplicationSetTemplate
overrideTemplate argoprojiov1alpha1.ApplicationSetTemplate
expectedMerged argoprojiov1alpha1.ApplicationSetTemplate
expectedApps []argov1alpha1.Application
}{
{
name: "Generate app",
params: []map[string]interface{}{{"name": "app1"}},
template: argov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argov1alpha1.ApplicationSetTemplateMeta{
params: []map[string]string{{"name": "app1"}},
template: argoprojiov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argoprojiov1alpha1.ApplicationSetTemplateMeta{
Name: "name",
Namespace: "namespace",
Labels: map[string]string{"label_name": "label_value"},
},
Spec: argov1alpha1.ApplicationSpec{},
},
overrideTemplate: argov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argov1alpha1.ApplicationSetTemplateMeta{
overrideTemplate: argoprojiov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argoprojiov1alpha1.ApplicationSetTemplateMeta{
Name: "test",
Labels: map[string]string{"foo": "bar"},
},
Spec: argov1alpha1.ApplicationSpec{},
},
expectedMerged: argov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argov1alpha1.ApplicationSetTemplateMeta{
expectedMerged: argoprojiov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argoprojiov1alpha1.ApplicationSetTemplateMeta{
Name: "test",
Namespace: "namespace",
Labels: map[string]string{"label_name": "label_value", "foo": "bar"},
@@ -267,8 +267,8 @@ func TestMergeTemplateApplications(t *testing.T) {
t.Run(cc.name, func(t *testing.T) {
generatorMock := generatorMock{}
generator := argov1alpha1.ApplicationSetGenerator{
List: &argov1alpha1.ListGenerator{},
generator := argoprojiov1alpha1.ApplicationSetGenerator{
List: &argoprojiov1alpha1.ListGenerator{},
}
generatorMock.On("GenerateParams", &generator).
@@ -279,7 +279,7 @@ func TestMergeTemplateApplications(t *testing.T) {
rendererMock := rendererMock{}
rendererMock.On("RenderTemplateParams", getTempApplication(cc.expectedMerged), cc.params[0], false).
rendererMock.On("RenderTemplateParams", getTempApplication(cc.expectedMerged), cc.params[0]).
Return(&cc.expectedApps[0], nil)
r := ApplicationSetReconciler{
@@ -293,13 +293,13 @@ func TestMergeTemplateApplications(t *testing.T) {
KubeClientset: kubefake.NewSimpleClientset(),
}
got, _, _ := r.generateApplications(argov1alpha1.ApplicationSet{
got, _, _ := r.generateApplications(argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{generator},
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{generator},
Template: cc.template,
},
},
@@ -314,7 +314,7 @@ func TestMergeTemplateApplications(t *testing.T) {
func TestCreateOrUpdateInCluster(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
@@ -324,7 +324,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
// name is human-readable test name
name string
// appSet is the ApplicationSet we are generating resources for
appSet argov1alpha1.ApplicationSet
appSet argoprojiov1alpha1.ApplicationSet
// existingApps are the apps that already exist on the cluster
existingApps []argov1alpha1.Application
// desiredApps are the generated apps to create/update
@@ -334,7 +334,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
}{
{
name: "Create an app that doesn't exist",
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
@@ -364,13 +364,13 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
},
{
name: "Update an existing app with a different project name",
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -422,13 +422,13 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
},
{
name: "Create a new app and check it doesn't replace the existing app",
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -480,13 +480,13 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
},
{
name: "Ensure that labels and annotations are added (via update) into an exiting application",
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -542,13 +542,13 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
},
{
name: "Ensure that labels and annotations are removed from an existing app",
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -601,14 +601,14 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
},
},
{
name: "Ensure that status and operation fields are not overridden by an update, when removing labels/annotations",
appSet: argov1alpha1.ApplicationSet{
name: "Ensure that status and operation fields are not overriden by an update, when removing labels/annotations",
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -673,14 +673,14 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
},
},
{
name: "Ensure that status and operation fields are not overridden by an update, when removing labels/annotations and adding other fields",
appSet: argov1alpha1.ApplicationSet{
name: "Ensure that status and operation fields are not overriden by an update, when removing labels/annotations and adding other fields",
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
Source: argov1alpha1.ApplicationSource{Path: "path", TargetRevision: "revision", RepoURL: "repoURL"},
@@ -754,13 +754,13 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
},
{
name: "Ensure that argocd notifications state and refresh annotation is preserved from an existing app",
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -861,7 +861,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
@@ -896,13 +896,13 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
} {
t.Run(c.name, func(t *testing.T) {
appSet := argov1alpha1.ApplicationSet{
appSet := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -985,7 +985,7 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
@@ -1058,13 +1058,13 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
t.Run(c.name, func(t *testing.T) {
appSet := argov1alpha1.ApplicationSet{
appSet := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -1144,20 +1144,20 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
func TestCreateApplications(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
for _, c := range []struct {
appSet argov1alpha1.ApplicationSet
appSet argoprojiov1alpha1.ApplicationSet
existsApps []argov1alpha1.Application
apps []argov1alpha1.Application
expected []argov1alpha1.Application
}{
{
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
@@ -1186,13 +1186,13 @@ func TestCreateApplications(t *testing.T) {
},
},
{
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -1243,13 +1243,13 @@ func TestCreateApplications(t *testing.T) {
},
},
{
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -1337,14 +1337,14 @@ func TestCreateApplications(t *testing.T) {
func TestDeleteInCluster(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
for _, c := range []struct {
// appSet is the application set on which the delete function is called
appSet argov1alpha1.ApplicationSet
appSet argoprojiov1alpha1.ApplicationSet
// existingApps is the current state of Applications on the cluster
existingApps []argov1alpha1.Application
// desireApps is the apps generated by the generator that we wish to keep alive
@@ -1355,13 +1355,13 @@ func TestDeleteInCluster(t *testing.T) {
notExpected []argov1alpha1.Application
}{
{
appSet: argov1alpha1.ApplicationSet{
appSet: argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Template: argov1alpha1.ApplicationSetTemplate{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Template: argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
@@ -1491,17 +1491,17 @@ func TestDeleteInCluster(t *testing.T) {
func TestGetMinRequeueAfter(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
client := fake.NewClientBuilder().WithScheme(scheme).Build()
generator := argov1alpha1.ApplicationSetGenerator{
List: &argov1alpha1.ListGenerator{},
Git: &argov1alpha1.GitGenerator{},
Clusters: &argov1alpha1.ClusterGenerator{},
generator := argoprojiov1alpha1.ApplicationSetGenerator{
List: &argoprojiov1alpha1.ListGenerator{},
Git: &argoprojiov1alpha1.GitGenerator{},
Clusters: &argoprojiov1alpha1.ClusterGenerator{},
}
generatorMock0 := generatorMock{}
@@ -1527,9 +1527,9 @@ func TestGetMinRequeueAfter(t *testing.T) {
},
}
got := r.getMinRequeueAfter(&argov1alpha1.ApplicationSet{
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{generator},
got := r.getMinRequeueAfter(&argoprojiov1alpha1.ApplicationSet{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{generator},
},
})
@@ -1539,7 +1539,7 @@ func TestGetMinRequeueAfter(t *testing.T) {
func TestValidateGeneratedApplications(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
@@ -1739,7 +1739,7 @@ func TestValidateGeneratedApplications(t *testing.T) {
KubeClientset: kubeclientset,
}
appSetInfo := argov1alpha1.ApplicationSet{}
appSetInfo := argoprojiov1alpha1.ApplicationSet{}
validationErrors, _ := r.validateGeneratedApplications(context.TODO(), cc.apps, appSetInfo, "namespace")
var errorMessages []string
@@ -1777,7 +1777,7 @@ func TestValidateGeneratedApplications(t *testing.T) {
func TestReconcilerValidationErrorBehaviour(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
@@ -1786,16 +1786,15 @@ func TestReconcilerValidationErrorBehaviour(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "default", Namespace: "argocd"},
Spec: argov1alpha1.AppProjectSpec{SourceRepos: []string{"*"}, Destinations: []argov1alpha1.ApplicationDestination{{Namespace: "*", Server: "https://good-cluster"}}},
}
appSet := argov1alpha1.ApplicationSet{
appSet := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "argocd",
},
Spec: argov1alpha1.ApplicationSetSpec{
GoTemplate: true,
Generators: []argov1alpha1.ApplicationSetGenerator{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{
{
List: &argov1alpha1.ListGenerator{
List: &argoprojiov1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{{
Raw: []byte(`{"cluster": "good-cluster","url": "https://good-cluster"}`),
}, {
@@ -1804,15 +1803,15 @@ func TestReconcilerValidationErrorBehaviour(t *testing.T) {
},
},
},
Template: argov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argov1alpha1.ApplicationSetTemplateMeta{
Name: "{{.cluster}}",
Template: argoprojiov1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: argoprojiov1alpha1.ApplicationSetTemplateMeta{
Name: "{{cluster}}",
Namespace: "argocd",
},
Spec: argov1alpha1.ApplicationSpec{
Source: argov1alpha1.ApplicationSource{RepoURL: "https://github.com/argoproj/argocd-example-apps", Path: "guestbook"},
Project: "default",
Destination: argov1alpha1.ApplicationDestination{Server: "{{.url}}"},
Destination: argov1alpha1.ApplicationDestination{Server: "{{url}}"},
},
},
},
@@ -1832,6 +1831,7 @@ func TestReconcilerValidationErrorBehaviour(t *testing.T) {
}}, nil)
r := ApplicationSetReconciler{
Log: ctrl.Log.WithName("controllers").WithName("ApplicationSet"),
Client: client,
Scheme: scheme,
Renderer: &utils.Render{},
@@ -1871,33 +1871,33 @@ func TestReconcilerValidationErrorBehaviour(t *testing.T) {
func TestSetApplicationSetStatusCondition(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
appSet := argov1alpha1.ApplicationSet{
appSet := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "name",
Namespace: "argocd",
},
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
{List: &argov1alpha1.ListGenerator{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{
{List: &argoprojiov1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{{
Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
}},
}},
},
Template: argov1alpha1.ApplicationSetTemplate{},
Template: argoprojiov1alpha1.ApplicationSetTemplate{},
},
}
appCondition := argov1alpha1.ApplicationSetCondition{
Type: argov1alpha1.ApplicationSetConditionResourcesUpToDate,
appCondition := argoprojiov1alpha1.ApplicationSetCondition{
Type: argoprojiov1alpha1.ApplicationSetConditionResourcesUpToDate,
Message: "All applications have been generated successfully",
Reason: argov1alpha1.ApplicationSetReasonApplicationSetUpToDate,
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
Reason: argoprojiov1alpha1.ApplicationSetReasonApplicationSetUpToDate,
Status: argoprojiov1alpha1.ApplicationSetConditionStatusTrue,
}
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
@@ -1907,6 +1907,7 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).Build()
r := ApplicationSetReconciler{
Log: ctrl.Log.WithName("controllers").WithName("ApplicationSet"),
Client: client,
Scheme: scheme,
Renderer: &utils.Render{},

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/event"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
// clusterSecretEventHandler is used when watching Secrets to check if they are ArgoCD Cluster Secrets, and if so

View File

@@ -15,12 +15,13 @@ import (
"github.com/argoproj/argo-cd/v2/applicationset/generators"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func TestClusterEventHandler(t *testing.T) {
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoprojiov1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
err = argov1alpha1.AddToScheme(scheme)
@@ -28,13 +29,13 @@ func TestClusterEventHandler(t *testing.T) {
tests := []struct {
name string
items []argov1alpha1.ApplicationSet
items []argoprojiov1alpha1.ApplicationSet
secret corev1.Secret
expectedRequests []ctrl.Request
}{
{
name: "no application sets should mean no requests",
items: []argov1alpha1.ApplicationSet{},
items: []argoprojiov1alpha1.ApplicationSet{},
secret: corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Namespace: "argocd",
@@ -48,16 +49,16 @@ func TestClusterEventHandler(t *testing.T) {
},
{
name: "a cluster generator should produce a request",
items: []argov1alpha1.ApplicationSet{
items: []argoprojiov1alpha1.ApplicationSet{
{
ObjectMeta: v1.ObjectMeta{
Name: "my-app-set",
Namespace: "argocd",
},
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{
{
Clusters: &argov1alpha1.ClusterGenerator{},
Clusters: &argoprojiov1alpha1.ClusterGenerator{},
},
},
},
@@ -78,16 +79,16 @@ func TestClusterEventHandler(t *testing.T) {
},
{
name: "multiple cluster generators should produce multiple requests",
items: []argov1alpha1.ApplicationSet{
items: []argoprojiov1alpha1.ApplicationSet{
{
ObjectMeta: v1.ObjectMeta{
Name: "my-app-set",
Namespace: "argocd",
},
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{
{
Clusters: &argov1alpha1.ClusterGenerator{},
Clusters: &argoprojiov1alpha1.ClusterGenerator{},
},
},
},
@@ -97,10 +98,10 @@ func TestClusterEventHandler(t *testing.T) {
Name: "my-app-set2",
Namespace: "argocd",
},
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{
{
Clusters: &argov1alpha1.ClusterGenerator{},
Clusters: &argoprojiov1alpha1.ClusterGenerator{},
},
},
},
@@ -122,16 +123,16 @@ func TestClusterEventHandler(t *testing.T) {
},
{
name: "non-cluster generator should not match",
items: []argov1alpha1.ApplicationSet{
items: []argoprojiov1alpha1.ApplicationSet{
{
ObjectMeta: v1.ObjectMeta{
Name: "my-app-set",
Namespace: "another-namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{
{
Clusters: &argov1alpha1.ClusterGenerator{},
Clusters: &argoprojiov1alpha1.ClusterGenerator{},
},
},
},
@@ -141,10 +142,10 @@ func TestClusterEventHandler(t *testing.T) {
Name: "app-set-non-cluster",
Namespace: "argocd",
},
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{
{
List: &argov1alpha1.ListGenerator{},
List: &argoprojiov1alpha1.ListGenerator{},
},
},
},
@@ -166,16 +167,16 @@ func TestClusterEventHandler(t *testing.T) {
{
name: "non-argo cd secret should not match",
items: []argov1alpha1.ApplicationSet{
items: []argoprojiov1alpha1.ApplicationSet{
{
ObjectMeta: v1.ObjectMeta{
Name: "my-app-set",
Namespace: "another-namespace",
},
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{
{
Clusters: &argov1alpha1.ClusterGenerator{},
Clusters: &argoprojiov1alpha1.ClusterGenerator{},
},
},
},
@@ -195,7 +196,7 @@ func TestClusterEventHandler(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
appSetList := argov1alpha1.ApplicationSetList{
appSetList := argoprojiov1alpha1.ApplicationSetList{
Items: test.items,
}

View File

@@ -5,8 +5,6 @@ import (
"testing"
"time"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
corev1 "k8s.io/api/core/v1"
@@ -17,13 +15,16 @@ import (
kubefake "k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
argoappsetv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func TestRequeueAfter(t *testing.T) {
mockServer := argoCDServiceMock{}
ctx := context.Background()
scheme := runtime.NewScheme()
err := argov1alpha1.AddToScheme(scheme)
err := argoappsetv1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
gvrToListKind := map[schema.GroupVersionResource]string{{
Group: "mallard.io",
@@ -59,9 +60,9 @@ func TestRequeueAfter(t *testing.T) {
"List": generators.NewListGenerator(),
"Clusters": generators.NewClusterGenerator(k8sClient, ctx, appClientset, "argocd"),
"Git": generators.NewGitGenerator(mockServer),
"SCMProvider": generators.NewSCMProviderGenerator(fake.NewClientBuilder().WithObjects(&corev1.Secret{}).Build(), generators.SCMAuthProviders{}),
"SCMProvider": generators.NewSCMProviderGenerator(fake.NewClientBuilder().WithObjects(&corev1.Secret{}).Build()),
"ClusterDecisionResource": generators.NewDuckTypeGenerator(ctx, fakeDynClient, appClientset, "argocd"),
"PullRequest": generators.NewPullRequestGenerator(k8sClient, generators.SCMAuthProviders{}),
"PullRequest": generators.NewPullRequestGenerator(k8sClient),
}
nestedGenerators := map[string]generators.Generator{
@@ -95,7 +96,7 @@ func TestRequeueAfter(t *testing.T) {
}
type args struct {
appset *argov1alpha1.ApplicationSet
appset *argoappsetv1alpha1.ApplicationSet
}
tests := []struct {
name string
@@ -103,44 +104,44 @@ func TestRequeueAfter(t *testing.T) {
want time.Duration
wantErr assert.ErrorAssertionFunc
}{
{name: "Cluster", args: args{appset: &argov1alpha1.ApplicationSet{
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{{Clusters: &argov1alpha1.ClusterGenerator{}}},
{name: "Cluster", args: args{appset: &argoappsetv1alpha1.ApplicationSet{
Spec: argoappsetv1alpha1.ApplicationSetSpec{
Generators: []argoappsetv1alpha1.ApplicationSetGenerator{{Clusters: &argoappsetv1alpha1.ClusterGenerator{}}},
},
}}, want: generators.NoRequeueAfter, wantErr: assert.NoError},
{name: "ClusterMergeNested", args: args{&argov1alpha1.ApplicationSet{
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
{Clusters: &argov1alpha1.ClusterGenerator{}},
{Merge: &argov1alpha1.MergeGenerator{
Generators: []argov1alpha1.ApplicationSetNestedGenerator{
{name: "ClusterMergeNested", args: args{&argoappsetv1alpha1.ApplicationSet{
Spec: argoappsetv1alpha1.ApplicationSetSpec{
Generators: []argoappsetv1alpha1.ApplicationSetGenerator{
{Clusters: &argoappsetv1alpha1.ClusterGenerator{}},
{Merge: &argoappsetv1alpha1.MergeGenerator{
Generators: []argoappsetv1alpha1.ApplicationSetNestedGenerator{
{
Clusters: &argov1alpha1.ClusterGenerator{},
Git: &argov1alpha1.GitGenerator{},
Clusters: &argoappsetv1alpha1.ClusterGenerator{},
Git: &argoappsetv1alpha1.GitGenerator{},
},
},
}},
},
},
}}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
{name: "ClusterMatrixNested", args: args{&argov1alpha1.ApplicationSet{
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{
{Clusters: &argov1alpha1.ClusterGenerator{}},
{Matrix: &argov1alpha1.MatrixGenerator{
Generators: []argov1alpha1.ApplicationSetNestedGenerator{
{name: "ClusterMatrixNested", args: args{&argoappsetv1alpha1.ApplicationSet{
Spec: argoappsetv1alpha1.ApplicationSetSpec{
Generators: []argoappsetv1alpha1.ApplicationSetGenerator{
{Clusters: &argoappsetv1alpha1.ClusterGenerator{}},
{Matrix: &argoappsetv1alpha1.MatrixGenerator{
Generators: []argoappsetv1alpha1.ApplicationSetNestedGenerator{
{
Clusters: &argov1alpha1.ClusterGenerator{},
Git: &argov1alpha1.GitGenerator{},
Clusters: &argoappsetv1alpha1.ClusterGenerator{},
Git: &argoappsetv1alpha1.GitGenerator{},
},
},
}},
},
},
}}, want: generators.DefaultRequeueAfterSeconds, wantErr: assert.NoError},
{name: "ListGenerator", args: args{appset: &argov1alpha1.ApplicationSet{
Spec: argov1alpha1.ApplicationSetSpec{
Generators: []argov1alpha1.ApplicationSetGenerator{{List: &argov1alpha1.ListGenerator{}}},
{name: "ListGenerator", args: args{appset: &argoappsetv1alpha1.ApplicationSet{
Spec: argoappsetv1alpha1.ApplicationSetSpec{
Generators: []argoappsetv1alpha1.ApplicationSetGenerator{{List: &argoappsetv1alpha1.ListGenerator{}}},
},
}}, want: generators.NoRequeueAfter, wantErr: assert.NoError},
}

View File

@@ -1,19 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- clusters: {}
template:
metadata:
name: '{{name}}-guestbook'
spec:
project: "default"
source:
repoURL: https://github.com/argoproj/argocd-example-apps/
targetRevision: HEAD
path: guestbook
destination:
server: '{{server}}'
namespace: guestbook

View File

@@ -3,12 +3,11 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- clusters: {}
template:
metadata:
name: '{{.name}}-guestbook'
name: '{{name}}-guestbook'
spec:
project: "default"
source:
@@ -16,5 +15,5 @@ spec:
targetRevision: HEAD
path: guestbook
destination:
server: '{{.server}}'
server: '{{server}}'
namespace: guestbook

View File

@@ -1,27 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: book-import
spec:
generators:
- clusterDecisionResource:
configMapRef: ocm-placement
name: test-placement
requeueAfterSeconds: 30
template:
metadata:
name: '{{clusterName}}-book-import'
spec:
project: "default"
source:
repoURL: https://github.com/open-cluster-management/application-samples.git
targetRevision: HEAD
path: book-import
destination:
name: '{{clusterName}}'
namespace: bookimport
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true

View File

@@ -3,7 +3,6 @@ kind: ApplicationSet
metadata:
name: book-import
spec:
goTemplate: true
generators:
- clusterDecisionResource:
configMapRef: ocm-placement
@@ -11,7 +10,7 @@ spec:
requeueAfterSeconds: 30
template:
metadata:
name: '{{.clusterName}}-book-import'
name: '{{clusterName}}-book-import'
spec:
project: "default"
source:
@@ -19,7 +18,7 @@ spec:
targetRevision: HEAD
path: book-import
destination:
name: '{{.clusterName}}'
name: '{{clusterName}}'
namespace: bookimport
syncPolicy:
automated:

View File

@@ -1,22 +0,0 @@
# This is an example of a typical ApplicationSet which uses the cluster generator.
# An ApplicationSet is comprised with two stanzas:
# - spec.generator - producer of a list of values supplied as arguments to an app template
# - spec.template - an application template, which has been parameterized
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- clusters: {}
template:
metadata:
name: '{{name}}-guestbook'
spec:
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
chart: guestbook
destination:
server: '{{server}}'
namespace: guestbook

View File

@@ -7,17 +7,16 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- clusters: {}
template:
metadata:
name: '{{.name}}-guestbook'
name: '{{name}}-guestbook'
spec:
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
chart: guestbook
destination:
server: '{{.server}}'
server: '{{server}}'
namespace: guestbook

View File

@@ -19,15 +19,15 @@ spec:
project: default
template:
metadata:
name: '{{.name}}-guestbook'
name: '{{name}}-guestbook'
labels:
environment: '{{.metadata.labels.environment}}'
environment: '{{metadata.labels.environment}}'
spec:
project: '{{.values.project}}'
project: '{{values.project}}'
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
chart: guestbook
destination:
server: '{{.server}}'
server: '{{server}}'
namespace: guestbook

View File

@@ -1,44 +0,0 @@
# This example demonstrates the git directory generator, which produces an items list
# based on discovery of directories in a git repo matching a specified pattern.
# Git generators automatically provide {{path}} and {{path.basename}} as available
# variables to the app template.
#
# Suppose the following git directory structure (note the use of different config tools):
#
# cluster-deployments
# └── add-ons
# ├── argo-rollouts
# │   ├── all.yaml
# │   └── kustomization.yaml
# ├── argo-workflows
# │   └── install.yaml
# ├── grafana
# │   ├── Chart.yaml
# │   └── values.yaml
# └── prometheus-operator
# ├── Chart.yaml
# └── values.yaml
#
# The following ApplicationSet would produce four applications (in different namespaces),
# using the directory basename as both the namespace and application name.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-addons
spec:
generators:
- git:
repoURL: https://github.com/infra-team/cluster-deployments.git
directories:
- path: add-ons/*
template:
metadata:
name: '{{path.basename}}'
spec:
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: http://kubernetes.default.svc
namespace: '{{path.basename}}'

View File

@@ -26,7 +26,6 @@ kind: ApplicationSet
metadata:
name: cluster-addons
spec:
goTemplate: true
generators:
- git:
repoURL: https://github.com/infra-team/cluster-deployments.git
@@ -34,12 +33,12 @@ spec:
- path: add-ons/*
template:
metadata:
name: '{{.path.basename}}'
name: '{{path.basename}}'
spec:
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: '{{.path.path}}'
path: '{{path}}'
destination:
server: http://kubernetes.default.svc
namespace: '{{.path.basename}}'
namespace: '{{path.basename}}'

View File

@@ -1,55 +0,0 @@
# This example demonstrates a git file generator which traverses the directory structure of a git
# repository to discover items based on a filename convention. For each file discovered, the
# contents of the discovered files themselves, act as the set of inputs to the app template.
#
# Suppose the following git directory structure:
#
# cluster-deployments
# ├── apps
# │ └── guestbook
# │ └── install.yaml
# └── cluster-config
# ├── engineering
# │ ├── dev
# │ │ └── config.json
# │ └── prod
# │ └── config.json
# └── finance
# ├── dev
# │ └── config.json
# └── prod
# └── config.json
#
# The discovered files (e.g. config.json) files can be any structured data supplied to the
# generated application. e.g.:
# {
# "aws_account": "123456",
# "asset_id": "11223344"
# "cluster": {
# "owner": "Jesse_Suen@intuit.com",
# "name": "engineering-dev",
# "address": "http://1.2.3.4"
# }
# }
#
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- git:
repoURL: https://github.com/infra-team/cluster-deployments.git
files:
- path: "**/config.json"
template:
metadata:
name: '{{cluster.name}}-guestbook'
spec:
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: apps/guestbook
destination:
server: '{{cluster.address}}'
namespace: guestbook

View File

@@ -37,7 +37,6 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- git:
repoURL: https://github.com/infra-team/cluster-deployments.git
@@ -45,12 +44,12 @@ spec:
- path: "**/config.json"
template:
metadata:
name: '{{.cluster.name}}-guestbook'
name: '{{cluster.name}}-guestbook'
spec:
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: apps/guestbook
destination:
server: '{{.cluster.address}}'
server: '{{cluster.address}}'
namespace: guestbook

View File

@@ -1,68 +0,0 @@
# This example demonstrates a git file generator which produces its items based on one or
# more files referenced in a git repo. The referenced files would contain a json/yaml list of
# arbitrary structured objects. Each item of the list would become a set of parameters to a
# generated application.
#
# Suppose the following git directory structure:
#
# cluster-deployments
# ├── apps
# │ └── guestbook
# │ ├── v1.0
# │ │ └── install.yaml
# │ └── v2.0
# │ └── install.yaml
# └── config
# └── clusters.json
#
# In this example, the `clusters.json` file is json list of structured data:
# [
# {
# "account": "123456",
# "asset_id": "11223344",
# "cluster": {
# "owner": "Jesse_Suen@intuit.com",
# "name": "engineering-dev",
# "address": "http://1.2.3.4"
# },
# "appVersions": {
# "prometheus-operator": "v0.38",
# "guestbook": "v2.0"
# }
# },
# {
# "account": "456789",
# "asset_id": "55667788",
# "cluster": {
# "owner": "Alexander_Matyushentsev@intuit.com",
# "name": "engineering-prod",
# "address": "http://2.4.6.8"
# },
# "appVersions": {
# "prometheus-operator": "v0.38",
# "guestbook": "v1.0"
# }
# }
# ]
#
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- git:
repoURL: https://github.com/infra-team/cluster-deployments.git
files:
- path: config/clusters.json
template:
metadata:
name: '{{cluster.name}}-guestbook'
spec:
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: apps/guestbook/{{appVersions.guestbook}}
destination:
server: http://kubernetes.default.svc
namespace: guestbook

View File

@@ -50,7 +50,6 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- git:
repoURL: https://github.com/infra-team/cluster-deployments.git
@@ -58,12 +57,12 @@ spec:
- path: config/clusters.json
template:
metadata:
name: '{{.cluster.name}}-guestbook'
name: '{{cluster.name}}-guestbook'
spec:
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: apps/guestbook/{{.appVersions.guestbook}}
path: apps/guestbook/{{appVersions.guestbook}}
destination:
server: http://kubernetes.default.svc
namespace: guestbook

View File

@@ -1,33 +0,0 @@
# The list generator specifies a literal list of argument values to the app spec template.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- list:
elements:
- cluster: engineering-dev
url: https://1.2.3.4
values:
project: dev
- cluster: engineering-prod
url: https://2.4.6.8
values:
project: prod
- cluster: finance-preprod
url: https://9.8.7.6
values:
project: preprod
template:
metadata:
name: '{{cluster}}-guestbook'
spec:
project: '{{values.project}}'
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: guestbook/{{cluster}}
destination:
server: '{{url}}'
namespace: guestbook

View File

@@ -4,7 +4,6 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- list:
elements:
@@ -22,13 +21,13 @@ spec:
project: preprod
template:
metadata:
name: '{{.cluster}}-guestbook'
name: '{{cluster}}-guestbook'
spec:
project: '{{.values.project}}'
project: '{{values.project}}'
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: guestbook/{{.cluster}}
path: guestbook/{{cluster}}
destination:
server: '{{.url}}'
server: '{{url}}'
namespace: guestbook

View File

@@ -1,48 +0,0 @@
# App templates can also be defined as part of the generator's template stanza. Sometimes it is
# useful to do this in order to override the spec.template stanza, and when simple string
# parameterization are insufficient. In the below examples, the generators[].XXX.template is
# a partial definition, which overrides/patch the default template.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- list:
elements:
- cluster: engineering-dev
url: https://1.2.3.4
template:
metadata: {}
spec:
project: "project"
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
path: '{{cluster}}-override'
destination: {}
- list:
elements:
- cluster: engineering-prod
url: https://1.2.3.4
template:
metadata: {}
spec:
project: "project2"
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
path: '{{cluster}}-override2'
destination: {}
template:
metadata:
name: '{{cluster}}-guestbook'
spec:
project: "project"
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: guestbook/{{cluster}}
destination:
server: '{{url}}'
namespace: guestbook

View File

@@ -7,7 +7,6 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- list:
elements:
@@ -19,7 +18,7 @@ spec:
project: "project"
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
path: '{{.cluster}}-override'
path: '{{cluster}}-override'
destination: {}
- list:
@@ -32,18 +31,18 @@ spec:
project: "project2"
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
path: '{{.cluster}}-override2'
path: '{{cluster}}-override2'
destination: {}
template:
metadata:
name: '{{.cluster}}-guestbook'
name: '{{cluster}}-guestbook'
spec:
project: "project"
source:
repoURL: https://github.com/infra-team/cluster-deployments.git
targetRevision: HEAD
path: guestbook/{{.cluster}}
path: guestbook/{{cluster}}
destination:
server: '{{.url}}'
server: '{{url}}'
namespace: guestbook

View File

@@ -1,29 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-addons
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
revision: HEAD
directories:
- path: applicationset/examples/git-generator-directory/excludes/cluster-addons/*
- exclude: true
path: applicationset/examples/git-generator-directory/excludes/cluster-addons/exclude-helm-guestbook
template:
metadata:
name: '{{path.basename}}'
spec:
project: "my-project"
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
syncPolicy:
syncOptions:
- CreateNamespace=true

View File

@@ -4,7 +4,6 @@ metadata:
name: cluster-addons
namespace: argocd
spec:
goTemplate: true
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
@@ -15,16 +14,16 @@ spec:
path: applicationset/examples/git-generator-directory/excludes/cluster-addons/exclude-helm-guestbook
template:
metadata:
name: '{{.path.basename}}'
name: '{{path.basename}}'
spec:
project: "my-project"
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{.path}}'
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{.path.basename}}'
namespace: '{{path.basename}}'
syncPolicy:
syncOptions:
- CreateNamespace=true

View File

@@ -1,27 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-addons
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
revision: HEAD
directories:
- path: applicationset/examples/git-generator-directory/cluster-addons/*
template:
metadata:
name: '{{path.basename}}'
spec:
project: "my-project"
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
syncPolicy:
syncOptions:
- CreateNamespace=true

View File

@@ -4,7 +4,6 @@ metadata:
name: cluster-addons
namespace: argocd
spec:
goTemplate: true
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
@@ -13,16 +12,16 @@ spec:
- path: applicationset/examples/git-generator-directory/cluster-addons/*
template:
metadata:
name: '{{.path.basename}}'
name: '{{path.basename}}'
spec:
project: "my-project"
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{.path.path}}'
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{.path.basename}}'
namespace: '{{path.basename}}'
syncPolicy:
syncOptions:
- CreateNamespace=true

View File

@@ -1,24 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
revision: HEAD
files:
- path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
template:
metadata:
name: '{{cluster.name}}-guestbook'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: "applicationset/examples/git-generator-files-discovery/apps/guestbook"
destination:
server: https://kubernetes.default.svc
#server: '{{cluster.address}}'
namespace: guestbook

View File

@@ -3,7 +3,6 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
@@ -12,7 +11,7 @@ spec:
- path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
template:
metadata:
name: '{{.cluster.name}}-guestbook'
name: '{{cluster.name}}-guestbook'
spec:
project: default
source:
@@ -21,5 +20,5 @@ spec:
path: "applicationset/examples/git-generator-files-discovery/apps/guestbook"
destination:
server: https://kubernetes.default.svc
#server: '{{.cluster.address}}'
#server: '{{cluster.address}}'
namespace: guestbook

View File

@@ -1,24 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- list:
elements:
- cluster: engineering-dev
url: https://kubernetes.default.svc
- cluster: engineering-prod
url: https://kubernetes.default.svc
template:
metadata:
name: '{{cluster}}-guestbook'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: applicationset/examples/list-generator/guestbook/{{cluster}}
destination:
server: '{{url}}'
namespace: guestbook

View File

@@ -3,7 +3,6 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- list:
elements:
@@ -13,13 +12,13 @@ spec:
url: https://kubernetes.default.svc
template:
metadata:
name: '{{.cluster}}-guestbook'
name: '{{cluster}}-guestbook'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: applicationset/examples/list-generator/guestbook/{{.cluster}}
path: applicationset/examples/list-generator/guestbook/{{cluster}}
destination:
server: '{{.url}}'
server: '{{url}}'
namespace: guestbook

View File

@@ -1,33 +0,0 @@
# This example demonstrates the combining of the git generator with a cluster generator
# The expected output would be an application per git directory and a cluster (application_count = git directory * clusters)
#
#
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-git
spec:
generators:
- matrix:
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
revision: HEAD
directories:
- path: applicationset/examples/matrix/cluster-addons/*
- clusters:
selector:
matchLabels:
argocd.argoproj.io/secret-type: cluster
template:
metadata:
name: '{{path.basename}}-{{name}}'
spec:
project: '{{metadata.labels.environment}}'
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: '{{server}}'
namespace: '{{path.basename}}'

View File

@@ -7,7 +7,6 @@ kind: ApplicationSet
metadata:
name: cluster-git
spec:
goTemplate: true
generators:
- matrix:
generators:
@@ -22,13 +21,13 @@ spec:
argocd.argoproj.io/secret-type: cluster
template:
metadata:
name: '{{.path.basename}}-{{.name}}'
name: '{{path.basename}}-{{name}}'
spec:
project: '{{.metadata.labels.environment}}'
project: '{{metadata.labels.environment}}'
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{.path.path}}'
path: '{{path}}'
destination:
server: '{{.server}}'
namespace: '{{.path.basename}}'
server: '{{server}}'
namespace: '{{path.basename}}'

View File

@@ -1,39 +0,0 @@
# This example demonstrates the combining of the git generator with a list generator
# The expected output would be an application per git directory and a list entry (application_count = git directory * list entries)
#
#
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: list-git
spec:
generators:
- matrix:
generators:
- git:
repoURL: https://github.com/argoproj/argo-cd.git
revision: HEAD
directories:
- path: applicationset/examples/matrix/cluster-addons/*
- list:
elements:
- cluster: engineering-dev
url: https://1.2.3.4
values:
project: dev
- cluster: engineering-prod
url: https://2.4.6.8
values:
project: prod
template:
metadata:
name: '{{path.basename}}-{{cluster}}'
spec:
project: '{{values.project}}'
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: '{{url}}'
namespace: '{{path.basename}}'

View File

@@ -7,7 +7,6 @@ kind: ApplicationSet
metadata:
name: list-git
spec:
goTemplate: true
generators:
- matrix:
generators:
@@ -28,13 +27,13 @@ spec:
project: prod
template:
metadata:
name: '{{.path.basename}}-{{.cluster}}'
name: '{{path.basename}}-{{cluster}}'
spec:
project: '{{.values.project}}'
project: '{{values.project}}'
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{.path.path}}'
path: '{{path}}'
destination:
server: '{{.url}}'
namespace: '{{.path.basename}}'
server: '{{url}}'
namespace: '{{path.basename}}'

View File

@@ -1,37 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: list-and-list
namespace: argocd
spec:
generators:
- matrix:
generators:
- list:
elements:
- cluster: engineering-dev
url: https://kubernetes.default.svc
values:
project: default
- cluster: engineering-prod
url: https://kubernetes.default.svc
values:
project: default
- list:
elements:
- values:
suffix: '1'
- values:
suffix: '2'
template:
metadata:
name: '{{cluster}}-{{values.suffix}}'
spec:
project: '{{values.project}}'
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: '{{url}}'
namespace: '{{path.basename}}'

View File

@@ -4,7 +4,6 @@ metadata:
name: list-and-list
namespace: argocd
spec:
goTemplate: true
generators:
- matrix:
generators:
@@ -26,13 +25,13 @@ spec:
suffix: '2'
template:
metadata:
name: '{{.cluster}}-{{.values.suffix}}'
name: '{{cluster}}-{{values.suffix}}'
spec:
project: '{{.values.project}}'
project: '{{values.project}}'
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{.path.path}}'
path: '{{path}}'
destination:
server: '{{.url}}'
namespace: '{{.path.basename}}'
server: '{{url}}'
namespace: '{{path.basename}}'

View File

@@ -1,67 +0,0 @@
# The matrix generator can contain other combination-type generators (matrix and union). But nested matrix and union
# generators cannot contain further-nested matrix or union generators.
#
# The generators are evaluated from most-nested to least-nested. In this case:
# 1. The union generator joins two lists to make 3 parameter sets.
# 2. The inner matrix generator takes the cartesian product of the two lists to make 4 parameters sets.
# 3. The outer matrix generator takes the cartesian product of the 3 union and the 4 inner matrix parameter sets to
# make 3*4=12 final parameter sets.
# 4. The 12 final parameter sets are evaluated against the top-level template to generate 12 Applications.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: matrix-and-union-in-matrix
spec:
generators:
- matrix:
generators:
- union:
mergeKeys:
- cluster
generators:
- list:
elements:
- cluster: engineering-dev
url: https://kubernetes.default.svc
values:
project: default
- cluster: engineering-prod
url: https://kubernetes.default.svc
values:
project: default
- list:
elements:
- cluster: engineering-dev
url: https://kubernetes.default.svc
values:
project: default
- cluster: engineering-test
url: https://kubernetes.default.svc
values:
project: default
- matrix:
generators:
- list:
elements:
- values:
suffix: '1'
- values:
suffix: '2'
- list:
elements:
- values:
prefix: 'first'
- values:
prefix: 'second'
template:
metadata:
name: '{{values.prefix}}-{{cluster}}-{{values.suffix}}'
spec:
project: '{{values.project}}'
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: '{{url}}'
namespace: '{{path.basename}}'

View File

@@ -12,7 +12,6 @@ kind: ApplicationSet
metadata:
name: matrix-and-union-in-matrix
spec:
goTemplate: true
generators:
- matrix:
generators:
@@ -56,13 +55,13 @@ spec:
prefix: 'second'
template:
metadata:
name: '{{.values.prefix}}-{{.cluster}}-{{.values.suffix}}'
name: '{{values.prefix}}-{{cluster}}-{{values.suffix}}'
spec:
project: '{{.values.project}}'
project: '{{values.project}}'
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: '{{.path.path}}'
path: '{{path}}'
destination:
server: '{{.url}}'
namespace: '{{.path.basename}}'
server: '{{url}}'
namespace: '{{path.basename}}'

View File

@@ -1,44 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: merge-clusters-and-list
spec:
generators:
- merge:
mergeKeys:
- server
generators:
- clusters:
values:
kafka: 'true'
redis: 'false'
# For clusters with a specific label, enable Kafka.
- clusters:
selector:
matchLabels:
use-kafka: 'false'
values:
kafka: 'false'
# For a specific cluster, enable Redis.
- list:
elements:
- server: https://some-specific-cluster
values.redis: 'true'
template:
metadata:
name: '{{name}}'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps/
targetRevision: HEAD
path: helm-guestbook
helm:
parameters:
- name: kafka
value: '{{values.kafka}}'
- name: redis
value: '{{values.redis}}'
destination:
server: '{{server}}'
namespace: default

View File

@@ -3,7 +3,6 @@ kind: ApplicationSet
metadata:
name: merge-clusters-and-list
spec:
goTemplate: true
generators:
- merge:
mergeKeys:
@@ -27,7 +26,7 @@ spec:
values.redis: 'true'
template:
metadata:
name: '{{.name}}'
name: '{{name}}'
spec:
project: default
source:
@@ -37,9 +36,9 @@ spec:
helm:
parameters:
- name: kafka
value: '{{.values.kafka}}'
value: '{{values.kafka}}'
- name: redis
value: '{{.values.redis}}'
value: '{{values.redis}}'
destination:
server: '{{.server}}'
server: '{{server}}'
namespace: default

View File

@@ -1,43 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: merge-two-matrixes
spec:
generators:
- merge:
mergeKeys:
- server
- environment
generators:
- matrix:
generators:
- clusters:
values:
replicaCount: '2'
- list:
elements:
- environment: staging
namespace: guestbook-non-prod
- environment: prod
namespace: guestbook
- list:
elements:
- server: https://kubernetes.default.svc
environment: staging
values.replicaCount: '1'
template:
metadata:
name: '{{name}}-guestbook-{{environment}}'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps/
targetRevision: HEAD
path: helm-guestbook
helm:
parameters:
- name: replicaCount
value: '{{values.replicaCount}}'
destination:
server: '{{server}}'
namespace: '{{namespace}}'

View File

@@ -3,7 +3,6 @@ kind: ApplicationSet
metadata:
name: merge-two-matrixes
spec:
goTemplate: true
generators:
- merge:
mergeKeys:
@@ -28,7 +27,7 @@ spec:
values.replicaCount: '1'
template:
metadata:
name: '{{.name}}-guestbook-{{.environment}}'
name: '{{name}}-guestbook-{{environment}}'
spec:
project: default
source:
@@ -38,7 +37,7 @@ spec:
helm:
parameters:
- name: replicaCount
value: '{{.values.replicaCount}}'
value: '{{values.replicaCount}}'
destination:
server: '{{.server}}'
namespace: '{{.namespace}}'
server: '{{server}}'
namespace: '{{namespace}}'

View File

@@ -1,40 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp
spec:
generators:
- pullRequest:
github:
# The GitHub organization or user.
owner: myorg
# The Github repository
repo: myrepo
# For GitHub Enterprise. (optional)
api: https://git.example.com/
# Reference to a Secret containing an access token. (optional)
tokenRef:
secretName: github-token
key: token
# Labels is used to filter the PRs that you want to target. (optional)
labels:
- preview
template:
metadata:
name: 'myapp-{{ branch }}-{{ number }}'
spec:
source:
repoURL: 'https://github.com/myorg/myrepo.git'
targetRevision: '{{ head_sha }}'
path: helm-guestbook
helm:
parameters:
- name: "image.tag"
value: "pull-{{ head_sha }}"
project: default
destination:
server: https://kubernetes.default.svc
namespace: "{{ branch }}-{{ number }}"
syncPolicy:
syncOptions:
- CreateNamespace=true

View File

@@ -3,7 +3,6 @@ kind: ApplicationSet
metadata:
name: myapp
spec:
goTemplate: true
generators:
- pullRequest:
github:
@@ -22,20 +21,20 @@ spec:
- preview
template:
metadata:
name: 'myapp-{{ .branch }}-{{ .number }}'
name: 'myapp-{{ branch }}-{{ number }}'
spec:
source:
repoURL: 'https://github.com/myorg/myrepo.git'
targetRevision: '{{ .head_sha }}'
targetRevision: '{{ head_sha }}'
path: helm-guestbook
helm:
parameters:
- name: "image.tag"
value: "pull-{{ .head_sha }}"
value: "pull-{{ head_sha }}"
project: default
destination:
server: https://kubernetes.default.svc
namespace: "{{ .branch }}-{{ .number }}"
namespace: "{{ branch }}-{{ number }}"
syncPolicy:
syncOptions:
- CreateNamespace=true

View File

@@ -1,24 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- scmProvider:
github:
organization: argoproj
cloneProtocol: https
filters:
- repositoryMatch: example-apps
template:
metadata:
name: '{{ repository }}-guestbook'
spec:
project: "default"
source:
repoURL: '{{ url }}'
targetRevision: '{{ branch }}'
path: guestbook
destination:
server: https://kubernetes.default.svc
namespace: guestbook

View File

@@ -3,7 +3,6 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- scmProvider:
github:
@@ -13,12 +12,12 @@ spec:
- repositoryMatch: example-apps
template:
metadata:
name: '{{ .repository }}-guestbook'
name: '{{ repository }}-guestbook'
spec:
project: "default"
source:
repoURL: '{{ .url }}'
targetRevision: '{{ .branch }}'
repoURL: '{{ url }}'
targetRevision: '{{ branch }}'
path: guestbook
destination:
server: https://kubernetes.default.svc

View File

@@ -1,36 +0,0 @@
# App templates can also be defined as part of the generator's template stanza. Sometimes it is
# useful to do this in order to override the spec.template stanza, and when simple string
# parameterization are insufficient. In the below examples, the generators[].XXX.template is
# a partial definition, which overrides/patch the default template.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- list:
elements:
- cluster: engineering-dev
url: https://kubernetes.default.svc
template:
metadata: {}
spec:
project: "default"
source:
targetRevision: HEAD
repoURL: https://github.com/argoproj/argo-cd.git
path: 'applicationset/examples/template-override/{{cluster}}-override'
destination: {}
template:
metadata:
name: '{{cluster}}-guestbook'
spec:
project: "default"
source:
repoURL: https://github.com/argoproj/argo-cd.git
targetRevision: HEAD
path: applicationset/examples/template-override/default
destination:
server: '{{url}}'
namespace: guestbook

View File

@@ -7,7 +7,6 @@ kind: ApplicationSet
metadata:
name: guestbook
spec:
goTemplate: true
generators:
- list:
elements:
@@ -20,12 +19,12 @@ spec:
source:
targetRevision: HEAD
repoURL: https://github.com/argoproj/argo-cd.git
path: 'applicationset/examples/template-override/{{.cluster}}-override'
path: 'applicationset/examples/template-override/{{cluster}}-override'
destination: {}
template:
metadata:
name: '{{.cluster}}-guestbook'
name: '{{cluster}}-guestbook'
spec:
project: "default"
source:
@@ -33,5 +32,5 @@ spec:
targetRevision: HEAD
path: applicationset/examples/template-override/default
destination:
server: '{{.url}}'
server: '{{url}}'
namespace: guestbook

View File

@@ -3,6 +3,8 @@ package generators
import (
"context"
"fmt"
"regexp"
"strings"
"time"
log "github.com/sirupsen/logrus"
@@ -15,7 +17,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
argoappsetv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoappsetv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
const (
@@ -35,8 +37,6 @@ type ClusterGenerator struct {
settingsManager *settings.SettingsManager
}
var render = &utils.Render{}
func NewClusterGenerator(c client.Client, ctx context.Context, clientset kubernetes.Interface, namespace string) Generator {
settingsManager := settings.NewSettingsManager(ctx, clientset, namespace)
@@ -62,7 +62,7 @@ func (g *ClusterGenerator) GetTemplate(appSetGenerator *argoappsetv1alpha1.Appli
}
func (g *ClusterGenerator) GenerateParams(
appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator, appSet *argoappsetv1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator, _ *argoappsetv1alpha1.ApplicationSet) ([]map[string]string, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
@@ -91,7 +91,7 @@ func (g *ClusterGenerator) GenerateParams(
return nil, err
}
res := []map[string]interface{}{}
res := []map[string]string{}
secretsFound := []corev1.Secret{}
@@ -104,102 +104,43 @@ func (g *ClusterGenerator) GenerateParams(
} else if !ignoreLocalClusters {
// If there is no secret for the cluster, it's the local cluster, so handle it here.
params := map[string]interface{}{}
params := map[string]string{}
params["name"] = cluster.Name
params["nameNormalized"] = cluster.Name
params["server"] = cluster.Server
err = appendTemplatedValues(appSetGenerator.Clusters.Values, params, appSet)
if err != nil {
return nil, err
for key, value := range appSetGenerator.Clusters.Values {
params[fmt.Sprintf("values.%s", key)] = value
}
res = append(res, params)
log.WithField("cluster", "local cluster").Info("matched local cluster")
res = append(res, params)
}
}
// For each matching cluster secret (non-local clusters only)
for _, cluster := range secretsFound {
params := map[string]interface{}{}
params := map[string]string{}
params["name"] = string(cluster.Data["name"])
params["nameNormalized"] = utils.SanitizeName(string(cluster.Data["name"]))
params["nameNormalized"] = sanitizeName(string(cluster.Data["name"]))
params["server"] = string(cluster.Data["server"])
if appSet.Spec.GoTemplate {
meta := map[string]interface{}{}
if len(cluster.ObjectMeta.Annotations) > 0 {
meta["annotations"] = cluster.ObjectMeta.Annotations
}
if len(cluster.ObjectMeta.Labels) > 0 {
meta["labels"] = cluster.ObjectMeta.Labels
}
params["metadata"] = meta
} else {
for key, value := range cluster.ObjectMeta.Annotations {
params[fmt.Sprintf("metadata.annotations.%s", key)] = value
}
for key, value := range cluster.ObjectMeta.Labels {
params[fmt.Sprintf("metadata.labels.%s", key)] = value
}
for key, value := range cluster.ObjectMeta.Annotations {
params[fmt.Sprintf("metadata.annotations.%s", key)] = value
}
err = appendTemplatedValues(appSetGenerator.Clusters.Values, params, appSet)
if err != nil {
return nil, err
for key, value := range cluster.ObjectMeta.Labels {
params[fmt.Sprintf("metadata.labels.%s", key)] = value
}
for key, value := range appSetGenerator.Clusters.Values {
params[fmt.Sprintf("values.%s", key)] = value
}
log.WithField("cluster", cluster.Name).Info("matched cluster secret")
res = append(res, params)
log.WithField("cluster", cluster.Name).Info("matched cluster secret")
}
return res, nil
}
func appendTemplatedValues(clusterValues map[string]string, params map[string]interface{}, appSet *argoappsetv1alpha1.ApplicationSet) error {
// We create a local map to ensure that we do not fall victim to a billion-laughs attack. We iterate through the
// cluster values map and only replace values in said map if it has already been whitelisted in the params map.
// Once we iterate through all the cluster values we can then safely merge the `tmp` map into the main params map.
tmp := map[string]interface{}{}
for key, value := range clusterValues {
result, err := replaceTemplatedString(value, params, appSet)
if err != nil {
return err
}
if appSet.Spec.GoTemplate {
if tmp["values"] == nil {
tmp["values"] = map[string]string{}
}
tmp["values"].(map[string]string)[key] = result
} else {
tmp[fmt.Sprintf("values.%s", key)] = result
}
}
for key, value := range tmp {
params[key] = value
}
return nil
}
func replaceTemplatedString(value string, params map[string]interface{}, appSet *argoappsetv1alpha1.ApplicationSet) (string, error) {
replacedTmplStr, err := render.Replace(value, params, appSet.Spec.GoTemplate)
if err != nil {
return "", err
}
return replacedTmplStr, nil
}
func (g *ClusterGenerator) getSecretsByClusterName(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator) (map[string]corev1.Secret, error) {
// List all Clusters:
clusterSecretList := &corev1.SecretList{}
@@ -226,3 +167,20 @@ func (g *ClusterGenerator) getSecretsByClusterName(appSetGenerator *argoappsetv1
return res, nil
}
// sanitize the name in accordance with the below rules
// 1. contain no more than 253 characters
// 2. contain only lowercase alphanumeric characters, '-' or '.'
// 3. start and end with an alphanumeric character
func sanitizeName(name string) string {
invalidDNSNameChars := regexp.MustCompile("[^-a-z0-9.]")
maxDNSNameLength := 253
name = strings.ToLower(name)
name = invalidDNSNameChars.ReplaceAllString(name, "-")
if len(name) > maxDNSNameLength {
name = name[:maxDNSNameLength]
}
return strings.Trim(name, "-.")
}

View File

@@ -3,7 +3,6 @@ package generators
import (
"context"
"fmt"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -11,10 +10,11 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"testing"
kubefake "k8s.io/client-go/kubernetes/fake"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoappsetv1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
"github.com/stretchr/testify/assert"
)
@@ -86,7 +86,7 @@ func TestGenerateParams(t *testing.T) {
name string
selector metav1.LabelSelector
values map[string]string
expected []map[string]interface{}
expected []map[string]string
// clientError is true if a k8s client error should be simulated
clientError bool
expectedError error
@@ -94,23 +94,15 @@ func TestGenerateParams(t *testing.T) {
{
name: "no label selector",
selector: metav1.LabelSelector{},
values: map[string]string{
"lol1": "lol",
"lol2": "{{values.lol1}}{{values.lol1}}",
"lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}",
"foo": "bar",
"bar": "{{ metadata.annotations.foo.argoproj.io }}",
"bat": "{{ metadata.labels.environment }}",
"aaa": "{{ server }}",
"no-op": "{{ this-does-not-exist }}",
}, expected: []map[string]interface{}{
{"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "production", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "production", "values.aaa": "https://production-01.example.com", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
values: nil,
expected: []map[string]string{
{"name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production"},
{"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "staging", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "staging", "values.aaa": "https://staging-01.example.com", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
{"name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging"},
{"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "nameNormalized": "in-cluster", "name": "in-cluster", "server": "https://kubernetes.default.svc"},
{"name": "in-cluster", "server": "https://kubernetes.default.svc"},
},
clientError: false,
expectedError: nil,
@@ -123,7 +115,7 @@ func TestGenerateParams(t *testing.T) {
},
},
values: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{"name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production"},
@@ -143,7 +135,7 @@ func TestGenerateParams(t *testing.T) {
values: map[string]string{
"foo": "bar",
},
expected: []map[string]interface{}{
expected: []map[string]string{
{"values.foo": "bar", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production"},
},
@@ -167,7 +159,7 @@ func TestGenerateParams(t *testing.T) {
values: map[string]string{
"foo": "bar",
},
expected: []map[string]interface{}{
expected: []map[string]string{
{"values.foo": "bar", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging"},
{"values.foo": "bar", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar",
@@ -196,7 +188,7 @@ func TestGenerateParams(t *testing.T) {
values: map[string]string{
"name": "baz",
},
expected: []map[string]interface{}{
expected: []map[string]string{
{"values.name": "baz", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo",
"metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging"},
},
@@ -233,395 +225,12 @@ func TestGenerateParams(t *testing.T) {
var clusterGenerator = NewClusterGenerator(cl, context.Background(), appClientset, "namespace")
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{},
}
got, err := clusterGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
Clusters: &argoprojiov1alpha1.ClusterGenerator{
got, err := clusterGenerator.GenerateParams(&argoappsetv1alpha1.ApplicationSetGenerator{
Clusters: &argoappsetv1alpha1.ClusterGenerator{
Selector: testCase.selector,
Values: testCase.values,
},
}, &applicationSetInfo)
if testCase.expectedError != nil {
assert.EqualError(t, err, testCase.expectedError.Error())
} else {
assert.NoError(t, err)
assert.ElementsMatch(t, testCase.expected, got)
}
})
}
}
func TestGenerateParamsGoTemplate(t *testing.T) {
clusters := []client.Object{
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "staging-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
Annotations: map[string]string{
"foo.argoproj.io": "staging",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("staging-01"),
"server": []byte("https://staging-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "production-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
Annotations: map[string]string{
"foo.argoproj.io": "production",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("production_01/west"),
"server": []byte("https://production-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
}
testCases := []struct {
name string
selector metav1.LabelSelector
values map[string]string
expected []map[string]interface{}
// clientError is true if a k8s client error should be simulated
clientError bool
expectedError error
}{
{
name: "no label selector",
selector: metav1.LabelSelector{},
values: map[string]string{
"lol1": "lol",
"lol2": "{{ .values.lol1 }}{{ .values.lol1 }}",
"lol3": "{{ .values.lol2 }}{{ .values.lol2 }}{{ .values.lol2 }}",
"foo": "bar",
"bar": "{{ if not (empty .metadata) }}{{index .metadata.annotations \"foo.argoproj.io\" }}{{ end }}",
"bat": "{{ if not (empty .metadata) }}{{.metadata.labels.environment}}{{ end }}",
"aaa": "{{ .server }}",
"no-op": "{{ .thisDoesNotExist }}",
}, expected: []map[string]interface{}{
{
"name": "production_01/west",
"nameNormalized": "production-01-west",
"server": "https://production-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
"annotations": map[string]string{
"foo.argoproj.io": "production",
},
},
"values": map[string]string{
"lol1": "lol",
"lol2": "<no value><no value>",
"lol3": "<no value><no value><no value>",
"foo": "bar",
"bar": "production",
"bat": "production",
"aaa": "https://production-01.example.com",
"no-op": "<no value>",
},
},
{
"name": "staging-01",
"nameNormalized": "staging-01",
"server": "https://staging-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
"annotations": map[string]string{
"foo.argoproj.io": "staging",
},
},
"values": map[string]string{
"lol1": "lol",
"lol2": "<no value><no value>",
"lol3": "<no value><no value><no value>",
"foo": "bar",
"bar": "staging",
"bat": "staging",
"aaa": "https://staging-01.example.com",
"no-op": "<no value>",
},
},
{
"nameNormalized": "in-cluster",
"name": "in-cluster",
"server": "https://kubernetes.default.svc",
"values": map[string]string{
"lol1": "lol",
"lol2": "<no value><no value>",
"lol3": "<no value><no value><no value>",
"foo": "bar",
"bar": "",
"bat": "",
"aaa": "https://kubernetes.default.svc",
"no-op": "<no value>",
},
},
},
clientError: false,
expectedError: nil,
},
{
name: "secret type label selector",
selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
},
},
values: nil,
expected: []map[string]interface{}{
{
"name": "production_01/west",
"nameNormalized": "production-01-west",
"server": "https://production-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
"annotations": map[string]string{
"foo.argoproj.io": "production",
},
},
},
{
"name": "staging-01",
"nameNormalized": "staging-01",
"server": "https://staging-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
"annotations": map[string]string{
"foo.argoproj.io": "staging",
},
},
},
},
clientError: false,
expectedError: nil,
},
{
name: "production-only",
selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"environment": "production",
},
},
values: map[string]string{
"foo": "bar",
},
expected: []map[string]interface{}{
{
"name": "production_01/west",
"nameNormalized": "production-01-west",
"server": "https://production-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
"annotations": map[string]string{
"foo.argoproj.io": "production",
},
},
"values": map[string]string{
"foo": "bar",
},
},
},
clientError: false,
expectedError: nil,
},
{
name: "production or staging",
selector: metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "environment",
Operator: "In",
Values: []string{
"production",
"staging",
},
},
},
},
values: map[string]string{
"foo": "bar",
},
expected: []map[string]interface{}{
{
"name": "production_01/west",
"nameNormalized": "production-01-west",
"server": "https://production-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
"annotations": map[string]string{
"foo.argoproj.io": "production",
},
},
"values": map[string]string{
"foo": "bar",
},
},
{
"name": "staging-01",
"nameNormalized": "staging-01",
"server": "https://staging-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
"annotations": map[string]string{
"foo.argoproj.io": "staging",
},
},
"values": map[string]string{
"foo": "bar",
},
},
},
clientError: false,
expectedError: nil,
},
{
name: "production or staging with match labels",
selector: metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "environment",
Operator: "In",
Values: []string{
"production",
"staging",
},
},
},
MatchLabels: map[string]string{
"org": "foo",
},
},
values: map[string]string{
"name": "baz",
},
expected: []map[string]interface{}{
{
"name": "staging-01",
"nameNormalized": "staging-01",
"server": "https://staging-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
"annotations": map[string]string{
"foo.argoproj.io": "staging",
},
},
"values": map[string]string{
"name": "baz",
},
},
},
clientError: false,
expectedError: nil,
},
{
name: "simulate client error",
selector: metav1.LabelSelector{},
values: nil,
expected: nil,
clientError: true,
expectedError: fmt.Errorf("could not list Secrets"),
},
}
// convert []client.Object to []runtime.Object, for use by kubefake package
runtimeClusters := []runtime.Object{}
for _, clientCluster := range clusters {
runtimeClusters = append(runtimeClusters, clientCluster)
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
appClientset := kubefake.NewSimpleClientset(runtimeClusters...)
fakeClient := fake.NewClientBuilder().WithObjects(clusters...).Build()
cl := &possiblyErroringFakeCtrlRuntimeClient{
fakeClient,
testCase.clientError,
}
var clusterGenerator = NewClusterGenerator(cl, context.Background(), appClientset, "namespace")
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{
GoTemplate: true,
},
}
got, err := clusterGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
Clusters: &argoprojiov1alpha1.ClusterGenerator{
Selector: testCase.selector,
Values: testCase.values,
},
}, &applicationSetInfo)
}, nil)
if testCase.expectedError != nil {
assert.EqualError(t, err, testCase.expectedError.Error())
@@ -636,10 +245,10 @@ func TestGenerateParamsGoTemplate(t *testing.T) {
func TestSanitizeClusterName(t *testing.T) {
t.Run("valid DNS-1123 subdomain name", func(t *testing.T) {
assert.Equal(t, "cluster-name", utils.SanitizeName("cluster-name"))
assert.Equal(t, "cluster-name", sanitizeName("cluster-name"))
})
t.Run("invalid DNS-1123 subdomain name", func(t *testing.T) {
invalidName := "-.--CLUSTER/name -./.-"
assert.Equal(t, "cluster-name", utils.SanitizeName(invalidName))
assert.Equal(t, "cluster-name", sanitizeName(invalidName))
})
}

View File

@@ -17,7 +17,7 @@ import (
"k8s.io/client-go/kubernetes"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
var _ Generator = (*DuckTypeGenerator)(nil)
@@ -60,7 +60,7 @@ func (g *DuckTypeGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.Appl
return &appSetGenerator.ClusterDecisionResource.Template
}
func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, _ *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
@@ -152,7 +152,7 @@ func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.A
}
res := []map[string]interface{}{}
res := []map[string]string{}
clusterDecisions := []interface{}{}
// Build the decision slice
@@ -178,7 +178,7 @@ func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.A
for _, cluster := range clusterDecisions {
// generated instance of cluster params
params := map[string]interface{}{}
params := map[string]string{}
log.Infof("cluster: %v", cluster)
matchValue := cluster.(map[string]interface{})[matchKey]
@@ -215,14 +215,7 @@ func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.A
}
for key, value := range appSetGenerator.ClusterDecisionResource.Values {
if appSet.Spec.GoTemplate {
if params["values"] == nil {
params["values"] = map[string]string{}
}
params["values"].(map[string]string)[key] = value
} else {
params[fmt.Sprintf("values.%s", key)] = value
}
params[fmt.Sprintf("values.%s", key)] = value
}
res = append(res, params)

View File

@@ -14,7 +14,7 @@ import (
kubefake "k8s.io/client-go/kubernetes/fake"
"sigs.k8s.io/controller-runtime/pkg/client"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
"testing"
)
@@ -149,7 +149,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
labelSelector metav1.LabelSelector
resource *unstructured.Unstructured
values map[string]string
expected []map[string]interface{}
expected []map[string]string
expectedError error
}{
{
@@ -157,7 +157,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
resourceName: "",
resource: duckType,
values: nil,
expected: []map[string]interface{}{},
expected: []map[string]string{},
expectedError: fmt.Errorf("There is a problem with the definition of the ClusterDecisionResource generator"),
},
/*** This does not work with the FAKE runtime client, fieldSelectors are broken.
@@ -175,7 +175,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
resourceName: resourceName,
resource: duckType,
values: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{"clusterName": "production-01", "name": "production-01", "server": "https://production-01.example.com"},
{"clusterName": "staging-01", "name": "staging-01", "server": "https://staging-01.example.com"},
@@ -189,7 +189,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
values: map[string]string{
"foo": "bar",
},
expected: []map[string]interface{}{
expected: []map[string]string{
{"clusterName": "production-01", "values.foo": "bar", "name": "production-01", "server": "https://production-01.example.com"},
},
expectedError: nil,
@@ -217,7 +217,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
labelSelector: metav1.LabelSelector{MatchLabels: map[string]string{"duck": "all-species"}},
resource: duckType,
values: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{"clusterName": "production-01", "name": "production-01", "server": "https://production-01.example.com"},
{"clusterName": "staging-01", "name": "staging-01", "server": "https://staging-01.example.com"},
@@ -232,7 +232,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
values: map[string]string{
"foo": "bar",
},
expected: []map[string]interface{}{
expected: []map[string]string{
{"clusterName": "production-01", "values.foo": "bar", "name": "production-01", "server": "https://production-01.example.com"},
},
expectedError: nil,
@@ -249,7 +249,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
}},
resource: duckType,
values: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{"clusterName": "production-01", "name": "production-01", "server": "https://production-01.example.com"},
{"clusterName": "staging-01", "name": "staging-01", "server": "https://staging-01.example.com"},
@@ -295,13 +295,6 @@ func TestGenerateParamsForDuckType(t *testing.T) {
var duckTypeGenerator = NewDuckTypeGenerator(context.Background(), fakeDynClient, appClientset, "namespace")
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{},
}
got, err := duckTypeGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
ClusterDecisionResource: &argoprojiov1alpha1.DuckTypeGenerator{
ConfigMapRef: "my-configmap",
@@ -309,307 +302,7 @@ func TestGenerateParamsForDuckType(t *testing.T) {
LabelSelector: testCase.labelSelector,
Values: testCase.values,
},
}, &applicationSetInfo)
if testCase.expectedError != nil {
assert.EqualError(t, err, testCase.expectedError.Error())
} else {
assert.NoError(t, err)
assert.ElementsMatch(t, testCase.expected, got)
}
})
}
}
func TestGenerateParamsForDuckTypeGoTemplate(t *testing.T) {
clusters := []client.Object{
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "staging-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
Annotations: map[string]string{
"foo.argoproj.io": "staging",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("staging-01"),
"server": []byte("https://staging-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "production-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
Annotations: map[string]string{
"foo.argoproj.io": "production",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("production-01"),
"server": []byte("https://production-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
}
duckType := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": resourceApiVersion,
"kind": "Duck",
"metadata": map[string]interface{}{
"name": resourceName,
"namespace": "namespace",
"labels": map[string]interface{}{"duck": "all-species"},
},
"status": map[string]interface{}{
"decisions": []interface{}{
map[string]interface{}{
"clusterName": "staging-01",
},
map[string]interface{}{
"clusterName": "production-01",
},
},
},
},
}
duckTypeProdOnly := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": resourceApiVersion,
"kind": "Duck",
"metadata": map[string]interface{}{
"name": resourceName,
"namespace": "namespace",
"labels": map[string]interface{}{"duck": "spotted"},
},
"status": map[string]interface{}{
"decisions": []interface{}{
map[string]interface{}{
"clusterName": "production-01",
},
},
},
},
}
duckTypeEmpty := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": resourceApiVersion,
"kind": "Duck",
"metadata": map[string]interface{}{
"name": resourceName,
"namespace": "namespace",
"labels": map[string]interface{}{"duck": "canvasback"},
},
"status": map[string]interface{}{},
},
}
configMap := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "my-configmap",
Namespace: "namespace",
},
Data: map[string]string{
"apiVersion": resourceApiVersion,
"kind": resourceKind,
"statusListKey": "decisions",
"matchKey": "clusterName",
},
}
testCases := []struct {
name string
configMapRef string
resourceName string
labelSelector metav1.LabelSelector
resource *unstructured.Unstructured
values map[string]string
expected []map[string]interface{}
expectedError error
}{
{
name: "no duck resource",
resourceName: "",
resource: duckType,
values: nil,
expected: []map[string]interface{}{},
expectedError: fmt.Errorf("There is a problem with the definition of the ClusterDecisionResource generator"),
},
/*** This does not work with the FAKE runtime client, fieldSelectors are broken.
{
name: "invalid name for duck resource",
resourceName: resourceName + "-different",
resource: duckType,
values: nil,
expected: []map[string]string{},
expectedError: fmt.Errorf("duck.mallard.io \"quak\" not found"),
},
***/
{
name: "duck type generator resourceName",
resourceName: resourceName,
resource: duckType,
values: nil,
expected: []map[string]interface{}{
{"clusterName": "production-01", "name": "production-01", "server": "https://production-01.example.com"},
{"clusterName": "staging-01", "name": "staging-01", "server": "https://staging-01.example.com"},
},
expectedError: nil,
},
{
name: "production-only",
resourceName: resourceName,
resource: duckTypeProdOnly,
values: map[string]string{
"foo": "bar",
},
expected: []map[string]interface{}{
{"clusterName": "production-01", "values": map[string]string{"foo": "bar"}, "name": "production-01", "server": "https://production-01.example.com"},
},
expectedError: nil,
},
{
name: "duck type empty status",
resourceName: resourceName,
resource: duckTypeEmpty,
values: nil,
expected: nil,
expectedError: nil,
},
{
name: "duck type empty status labelSelector.matchLabels",
resourceName: "",
labelSelector: metav1.LabelSelector{MatchLabels: map[string]string{"duck": "canvasback"}},
resource: duckTypeEmpty,
values: nil,
expected: nil,
expectedError: nil,
},
{
name: "duck type generator labelSelector.matchLabels",
resourceName: "",
labelSelector: metav1.LabelSelector{MatchLabels: map[string]string{"duck": "all-species"}},
resource: duckType,
values: nil,
expected: []map[string]interface{}{
{"clusterName": "production-01", "name": "production-01", "server": "https://production-01.example.com"},
{"clusterName": "staging-01", "name": "staging-01", "server": "https://staging-01.example.com"},
},
expectedError: nil,
},
{
name: "production-only labelSelector.matchLabels",
resourceName: "",
resource: duckTypeProdOnly,
labelSelector: metav1.LabelSelector{MatchLabels: map[string]string{"duck": "spotted"}},
values: map[string]string{
"foo": "bar",
},
expected: []map[string]interface{}{
{"clusterName": "production-01", "values": map[string]string{"foo": "bar"}, "name": "production-01", "server": "https://production-01.example.com"},
},
expectedError: nil,
},
{
name: "duck type generator labelSelector.matchExpressions",
resourceName: "",
labelSelector: metav1.LabelSelector{MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "duck",
Operator: "In",
Values: []string{"all-species", "marbled"},
},
}},
resource: duckType,
values: nil,
expected: []map[string]interface{}{
{"clusterName": "production-01", "name": "production-01", "server": "https://production-01.example.com"},
{"clusterName": "staging-01", "name": "staging-01", "server": "https://staging-01.example.com"},
},
expectedError: nil,
},
{
name: "duck type generator resourceName and labelSelector.matchExpressions",
resourceName: resourceName,
labelSelector: metav1.LabelSelector{MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "duck",
Operator: "In",
Values: []string{"all-species", "marbled"},
},
}},
resource: duckType,
values: nil,
expected: nil,
expectedError: fmt.Errorf("There is a problem with the definition of the ClusterDecisionResource generator"),
},
}
// convert []client.Object to []runtime.Object, for use by kubefake package
runtimeClusters := []runtime.Object{}
for _, clientCluster := range clusters {
runtimeClusters = append(runtimeClusters, clientCluster)
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
appClientset := kubefake.NewSimpleClientset(append(runtimeClusters, configMap)...)
gvrToListKind := map[schema.GroupVersionResource]string{{
Group: "mallard.io",
Version: "v1",
Resource: "ducks",
}: "DuckList"}
fakeDynClient := dynfake.NewSimpleDynamicClientWithCustomListKinds(runtime.NewScheme(), gvrToListKind, testCase.resource)
var duckTypeGenerator = NewDuckTypeGenerator(context.Background(), fakeDynClient, appClientset, "namespace")
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{
GoTemplate: true,
},
}
got, err := duckTypeGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
ClusterDecisionResource: &argoprojiov1alpha1.DuckTypeGenerator{
ConfigMapRef: "my-configmap",
Name: testCase.resourceName,
LabelSelector: testCase.labelSelector,
Values: testCase.values,
},
}, &applicationSetInfo)
}, nil)
if testCase.expectedError != nil {
assert.EqualError(t, err, testCase.expectedError.Error())

View File

@@ -3,36 +3,21 @@ package generators
import (
"reflect"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/imdario/mergo"
log "github.com/sirupsen/logrus"
)
const (
selectorKey = "Selector"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
type TransformResult struct {
Params []map[string]interface{}
Params []map[string]string
Template argoprojiov1alpha1.ApplicationSetTemplate
}
// Transform a spec generator to list of paramSets and a template
func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, allGenerators map[string]Generator, baseTemplate argoprojiov1alpha1.ApplicationSetTemplate, appSet *argoprojiov1alpha1.ApplicationSet, genParams map[string]interface{}) ([]TransformResult, error) {
selector, err := metav1.LabelSelectorAsSelector(requestedGenerator.Selector)
if err != nil {
return nil, err
}
//Transform a spec generator to list of paramSets and a template
func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, allGenerators map[string]Generator, baseTemplate argoprojiov1alpha1.ApplicationSetTemplate, appSet *argoprojiov1alpha1.ApplicationSet) ([]TransformResult, error) {
res := []TransformResult{}
var firstError error
interpolatedGenerator := requestedGenerator.DeepCopy()
generators := GetRelevantGenerators(&requestedGenerator, allGenerators)
for _, g := range generators {
@@ -46,20 +31,8 @@ func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, al
}
continue
}
var params []map[string]interface{}
if len(genParams) != 0 {
tempInterpolatedGenerator, err := InterpolateGenerator(&requestedGenerator, genParams, appSet.Spec.GoTemplate)
interpolatedGenerator = &tempInterpolatedGenerator
if err != nil {
log.WithError(err).WithField("genParams", genParams).
Error("error interpolating params for generator")
if firstError == nil {
firstError = err
}
continue
}
}
params, err = g.GenerateParams(interpolatedGenerator, appSet)
params, err := g.GenerateParams(&requestedGenerator, appSet)
if err != nil {
log.WithError(err).WithField("generator", g).
Error("error generating params")
@@ -68,34 +41,16 @@ func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, al
}
continue
}
var filterParams []map[string]interface{}
for _, param := range params {
if requestedGenerator.Selector != nil && !selector.Matches(labels.Set(keepOnlyStringValues(param))) {
continue
}
filterParams = append(filterParams, param)
}
res = append(res, TransformResult{
Params: filterParams,
Params: params,
Template: mergedTemplate,
})
}
return res, firstError
}
func keepOnlyStringValues(in map[string]interface{}) map[string]string {
var out map[string]string = map[string]string{}
for key, value := range in {
if _, ok := value.(string); ok {
out[key] = value.(string)
}
}
return out
}
func GetRelevantGenerators(requestedGenerator *argoprojiov1alpha1.ApplicationSetGenerator, generators map[string]Generator) []Generator {
@@ -107,13 +62,9 @@ func GetRelevantGenerators(requestedGenerator *argoprojiov1alpha1.ApplicationSet
if !field.CanInterface() {
continue
}
name := v.Type().Field(i).Name
if name == selectorKey {
continue
}
if !reflect.ValueOf(field.Interface()).IsNil() {
res = append(res, generators[name])
res = append(res, generators[v.Type().Field(i).Name])
}
}
@@ -121,6 +72,7 @@ func GetRelevantGenerators(requestedGenerator *argoprojiov1alpha1.ApplicationSet
}
func mergeGeneratorTemplate(g Generator, requestedGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetTemplate argoprojiov1alpha1.ApplicationSetTemplate) (argoprojiov1alpha1.ApplicationSetTemplate, error) {
// Make a copy of the value from `GetTemplate()` before merge, rather than copying directly into
// the provided parameter (which will touch the original resource object returned by client-go)
dest := g.GetTemplate(requestedGenerator).DeepCopy()
@@ -129,16 +81,3 @@ func mergeGeneratorTemplate(g Generator, requestedGenerator *argoprojiov1alpha1.
return *dest, err
}
// InterpolateGenerator allows interpolating the matrix's 2nd child generator with values from the 1st child generator
// "params" parameter is an array, where each index corresponds to a generator. Each index contains a map w/ that generator's parameters.
func InterpolateGenerator(requestedGenerator *argoprojiov1alpha1.ApplicationSetGenerator, params map[string]interface{}, useGoTemplate bool) (argoprojiov1alpha1.ApplicationSetGenerator, error) {
render := utils.Render{}
interpolatedGenerator, err := render.RenderGeneratorParams(requestedGenerator, params, useGoTemplate)
if err != nil {
log.WithError(err).WithField("interpolatedGenerator", interpolatedGenerator).Error("error interpolating generator with other generator's parameter")
return *interpolatedGenerator, err
}
return *interpolatedGenerator, nil
}

View File

@@ -1,323 +0,0 @@
package generators
import (
"context"
"testing"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
testutils "github.com/argoproj/argo-cd/v2/applicationset/utils/test"
argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/stretchr/testify/mock"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
kubefake "k8s.io/client-go/kubernetes/fake"
crtclient "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
func TestMatchValues(t *testing.T) {
testCases := []struct {
name string
elements []apiextensionsv1.JSON
selector *metav1.LabelSelector
expected []map[string]interface{}
}{
{
name: "no filter",
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
selector: &metav1.LabelSelector{},
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
},
{
name: "nil",
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
selector: nil,
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
},
{
name: "values.foo should be foo but is ignore element",
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"values.foo": "foo",
},
},
expected: []map[string]interface{}{},
},
{
name: "values.foo should be bar",
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"values.foo": "bar",
},
},
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url", "values.foo": "bar"}},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
var listGenerator = NewListGenerator()
var data = map[string]Generator{
"List": listGenerator,
}
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{},
}
results, err := Transform(argoprojiov1alpha1.ApplicationSetGenerator{
Selector: testCase.selector,
List: &argoprojiov1alpha1.ListGenerator{
Elements: testCase.elements,
Template: emptyTemplate(),
}},
data,
emptyTemplate(),
&applicationSetInfo, nil)
assert.NoError(t, err)
assert.ElementsMatch(t, testCase.expected, results[0].Params)
})
}
}
func emptyTemplate() argoprojiov1alpha1.ApplicationSetTemplate {
return argoprojiov1alpha1.ApplicationSetTemplate{
Spec: argov1alpha1.ApplicationSpec{
Project: "project",
},
}
}
func getMockClusterGenerator() Generator {
clusters := []crtclient.Object{
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "staging-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "staging",
"org": "foo",
},
Annotations: map[string]string{
"foo.argoproj.io": "staging",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("staging-01"),
"server": []byte("https://staging-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "production-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "production",
"org": "bar",
},
Annotations: map[string]string{
"foo.argoproj.io": "production",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("production_01/west"),
"server": []byte("https://production-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
}
runtimeClusters := []runtime.Object{}
appClientset := kubefake.NewSimpleClientset(runtimeClusters...)
fakeClient := fake.NewClientBuilder().WithObjects(clusters...).Build()
return NewClusterGenerator(fakeClient, context.Background(), appClientset, "namespace")
}
func getMockGitGenerator() Generator {
argoCDServiceMock := testutils.ArgoCDServiceMock{Mock: &mock.Mock{}}
argoCDServiceMock.Mock.On("GetDirectories", mock.Anything, mock.Anything, mock.Anything).Return([]string{"app1", "app2", "app_3", "p1/app4"}, nil)
var gitGenerator = NewGitGenerator(argoCDServiceMock)
return gitGenerator
}
func TestGetRelevantGenerators(t *testing.T) {
testGenerators := map[string]Generator{
"Clusters": getMockClusterGenerator(),
"Git": getMockGitGenerator(),
}
testGenerators["Matrix"] = NewMatrixGenerator(testGenerators)
testGenerators["Merge"] = NewMergeGenerator(testGenerators)
testGenerators["List"] = NewListGenerator()
requestedGenerator := &argoprojiov1alpha1.ApplicationSetGenerator{
List: &argoprojiov1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
}}
relevantGenerators := GetRelevantGenerators(requestedGenerator, testGenerators)
assert.Len(t, relevantGenerators, 1)
assert.IsType(t, &ListGenerator{}, relevantGenerators[0])
requestedGenerator = &argoprojiov1alpha1.ApplicationSetGenerator{
Clusters: &argoprojiov1alpha1.ClusterGenerator{
Selector: metav1.LabelSelector{},
Template: argoprojiov1alpha1.ApplicationSetTemplate{},
Values: nil,
},
}
relevantGenerators = GetRelevantGenerators(requestedGenerator, testGenerators)
assert.Len(t, relevantGenerators, 1)
assert.IsType(t, &ClusterGenerator{}, relevantGenerators[0])
requestedGenerator = &argoprojiov1alpha1.ApplicationSetGenerator{
Git: &argoprojiov1alpha1.GitGenerator{
RepoURL: "",
Directories: nil,
Files: nil,
Revision: "",
RequeueAfterSeconds: nil,
Template: argoprojiov1alpha1.ApplicationSetTemplate{},
},
}
relevantGenerators = GetRelevantGenerators(requestedGenerator, testGenerators)
assert.Len(t, relevantGenerators, 1)
assert.IsType(t, &GitGenerator{}, relevantGenerators[0])
}
func TestInterpolateGenerator(t *testing.T) {
requestedGenerator := &argoprojiov1alpha1.ApplicationSetGenerator{
Clusters: &argoprojiov1alpha1.ClusterGenerator{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"path-basename": "{{path.basename}}",
"path-zero": "{{path[0]}}",
"path-full": "{{path}}",
}},
},
}
gitGeneratorParams := map[string]interface{}{
"path": "p1/p2/app3",
"path.basename": "app3",
"path[0]": "p1",
"path[1]": "p2",
"path.basenameNormalized": "app3",
}
interpolatedGenerator, err := InterpolateGenerator(requestedGenerator, gitGeneratorParams, false)
if err != nil {
log.WithError(err).WithField("requestedGenerator", requestedGenerator).Error("error interpolating Generator")
return
}
assert.Equal(t, "app3", interpolatedGenerator.Clusters.Selector.MatchLabels["path-basename"])
assert.Equal(t, "p1", interpolatedGenerator.Clusters.Selector.MatchLabels["path-zero"])
assert.Equal(t, "p1/p2/app3", interpolatedGenerator.Clusters.Selector.MatchLabels["path-full"])
fileNamePath := argoprojiov1alpha1.GitFileGeneratorItem{
Path: "{{name}}",
}
fileServerPath := argoprojiov1alpha1.GitFileGeneratorItem{
Path: "{{server}}",
}
requestedGenerator = &argoprojiov1alpha1.ApplicationSetGenerator{
Git: &argoprojiov1alpha1.GitGenerator{
Files: append([]argoprojiov1alpha1.GitFileGeneratorItem{}, fileNamePath, fileServerPath),
Template: argoprojiov1alpha1.ApplicationSetTemplate{},
},
}
clusterGeneratorParams := map[string]interface{}{
"name": "production_01/west", "server": "https://production-01.example.com",
}
interpolatedGenerator, err = InterpolateGenerator(requestedGenerator, clusterGeneratorParams, false)
if err != nil {
log.WithError(err).WithField("requestedGenerator", requestedGenerator).Error("error interpolating Generator")
return
}
assert.Equal(t, "production_01/west", interpolatedGenerator.Git.Files[0].Path)
assert.Equal(t, "https://production-01.example.com", interpolatedGenerator.Git.Files[1].Path)
}
func TestInterpolateGenerator_go(t *testing.T) {
requestedGenerator := &argoprojiov1alpha1.ApplicationSetGenerator{
Clusters: &argoprojiov1alpha1.ClusterGenerator{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"path-basename": "{{base .path.path}}",
"path-zero": "{{index .path.segments 0}}",
"path-full": "{{.path.path}}",
"kubernetes.io/environment": `{{default "foo" .my_label}}`,
}},
},
}
gitGeneratorParams := map[string]interface{}{
"path": map[string]interface{}{
"path": "p1/p2/app3",
"segments": []string{"p1", "p2", "app3"},
},
}
interpolatedGenerator, err := InterpolateGenerator(requestedGenerator, gitGeneratorParams, true)
require.NoError(t, err)
if err != nil {
log.WithError(err).WithField("requestedGenerator", requestedGenerator).Error("error interpolating Generator")
return
}
assert.Equal(t, "app3", interpolatedGenerator.Clusters.Selector.MatchLabels["path-basename"])
assert.Equal(t, "p1", interpolatedGenerator.Clusters.Selector.MatchLabels["path-zero"])
assert.Equal(t, "p1/p2/app3", interpolatedGenerator.Clusters.Selector.MatchLabels["path-full"])
fileNamePath := argoprojiov1alpha1.GitFileGeneratorItem{
Path: "{{.name}}",
}
fileServerPath := argoprojiov1alpha1.GitFileGeneratorItem{
Path: "{{.server}}",
}
requestedGenerator = &argoprojiov1alpha1.ApplicationSetGenerator{
Git: &argoprojiov1alpha1.GitGenerator{
Files: append([]argoprojiov1alpha1.GitFileGeneratorItem{}, fileNamePath, fileServerPath),
Template: argoprojiov1alpha1.ApplicationSetTemplate{},
},
}
clusterGeneratorParams := map[string]interface{}{
"name": "production_01/west", "server": "https://production-01.example.com",
}
interpolatedGenerator, err = InterpolateGenerator(requestedGenerator, clusterGeneratorParams, true)
if err != nil {
log.WithError(err).WithField("requestedGenerator", requestedGenerator).Error("error interpolating Generator")
return
}
assert.Equal(t, "production_01/west", interpolatedGenerator.Git.Files[0].Path)
assert.Equal(t, "https://production-01.example.com", interpolatedGenerator.Git.Files[1].Path)
}

View File

@@ -14,8 +14,7 @@ import (
"sigs.k8s.io/yaml"
"github.com/argoproj/argo-cd/v2/applicationset/services"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
var _ Generator = (*GitGenerator)(nil)
@@ -46,7 +45,7 @@ func (g *GitGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.Appli
return DefaultRequeueAfterSeconds
}
func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, _ *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
@@ -57,11 +56,11 @@ func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Applic
}
var err error
var res []map[string]interface{}
if len(appSetGenerator.Git.Directories) != 0 {
res, err = g.generateParamsForGitDirectories(appSetGenerator, appSet.Spec.GoTemplate)
} else if len(appSetGenerator.Git.Files) != 0 {
res, err = g.generateParamsForGitFiles(appSetGenerator, appSet.Spec.GoTemplate)
var res []map[string]string
if appSetGenerator.Git.Directories != nil {
res, err = g.generateParamsForGitDirectories(appSetGenerator)
} else if appSetGenerator.Git.Files != nil {
res, err = g.generateParamsForGitFiles(appSetGenerator)
} else {
return nil, EmptyAppSetGeneratorError
}
@@ -72,7 +71,7 @@ func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Applic
return res, nil
}
func (g *GitGenerator) generateParamsForGitDirectories(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, useGoTemplate bool) ([]map[string]interface{}, error) {
func (g *GitGenerator) generateParamsForGitDirectories(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) ([]map[string]string, error) {
// Directories, not files
allPaths, err := g.repos.GetDirectories(context.TODO(), appSetGenerator.Git.RepoURL, appSetGenerator.Git.Revision)
@@ -89,12 +88,12 @@ func (g *GitGenerator) generateParamsForGitDirectories(appSetGenerator *argoproj
requestedApps := g.filterApps(appSetGenerator.Git.Directories, allPaths)
res := g.generateParamsFromApps(requestedApps, appSetGenerator, useGoTemplate)
res := g.generateParamsFromApps(requestedApps, appSetGenerator)
return res, nil
}
func (g *GitGenerator) generateParamsForGitFiles(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, useGoTemplate bool) ([]map[string]interface{}, error) {
func (g *GitGenerator) generateParamsForGitFiles(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) ([]map[string]string, error) {
// Get all files that match the requested path string, removing duplicates
allFiles := make(map[string][]byte)
@@ -117,11 +116,11 @@ func (g *GitGenerator) generateParamsForGitFiles(appSetGenerator *argoprojiov1al
sort.Strings(allPaths)
// Generate params from each path, and return
res := []map[string]interface{}{}
res := []map[string]string{}
for _, path := range allPaths {
// A JSON / YAML file path can contain multiple sets of parameters (ie it is an array)
paramsArray, err := g.generateParamsFromGitFile(path, allFiles[path], useGoTemplate)
paramsArray, err := g.generateParamsFromGitFile(path, allFiles[path])
if err != nil {
return nil, fmt.Errorf("unable to process file '%s': %v", path, err)
}
@@ -133,7 +132,7 @@ func (g *GitGenerator) generateParamsForGitFiles(appSetGenerator *argoprojiov1al
return res, nil
}
func (g *GitGenerator) generateParamsFromGitFile(filePath string, fileContent []byte, useGoTemplate bool) ([]map[string]interface{}, error) {
func (g *GitGenerator) generateParamsFromGitFile(filePath string, fileContent []byte) ([]map[string]string, error) {
objectsFound := []map[string]interface{}{}
// First, we attempt to parse as an array
@@ -148,46 +147,29 @@ func (g *GitGenerator) generateParamsFromGitFile(filePath string, fileContent []
objectsFound = append(objectsFound, singleObj)
}
res := []map[string]interface{}{}
res := []map[string]string{}
// Flatten all objects found, and return them
for _, objectFound := range objectsFound {
params := map[string]interface{}{}
if useGoTemplate {
for k, v := range objectFound {
params[k] = v
}
paramPath := map[string]interface{}{}
paramPath["path"] = path.Dir(filePath)
paramPath["basename"] = path.Base(paramPath["path"].(string))
paramPath["filename"] = path.Base(filePath)
paramPath["basenameNormalized"] = utils.SanitizeName(path.Base(paramPath["path"].(string)))
paramPath["filenameNormalized"] = utils.SanitizeName(path.Base(paramPath["filename"].(string)))
paramPath["segments"] = strings.Split(paramPath["path"].(string), "/")
params["path"] = paramPath
} else {
flat, err := flatten.Flatten(objectFound, "", flatten.DotStyle)
if err != nil {
return nil, err
}
for k, v := range flat {
params[k] = fmt.Sprintf("%v", v)
}
params["path"] = path.Dir(filePath)
params["path.basename"] = path.Base(params["path"].(string))
params["path.filename"] = path.Base(filePath)
params["path.basenameNormalized"] = utils.SanitizeName(path.Base(params["path"].(string)))
params["path.filenameNormalized"] = utils.SanitizeName(path.Base(params["path.filename"].(string)))
for k, v := range strings.Split(params["path"].(string), "/") {
if len(v) > 0 {
params["path["+strconv.Itoa(k)+"]"] = v
}
flat, err := flatten.Flatten(objectFound, "", flatten.DotStyle)
if err != nil {
return nil, err
}
params := map[string]string{}
for k, v := range flat {
params[k] = fmt.Sprintf("%v", v)
}
params["path"] = path.Dir(filePath)
params["path.basename"] = path.Base(params["path"])
params["path.filename"] = path.Base(filePath)
params["path.basenameNormalized"] = sanitizeName(path.Base(params["path"]))
params["path.filenameNormalized"] = sanitizeName(path.Base(params["path.filename"]))
for k, v := range strings.Split(params["path"], "/") {
if len(v) > 0 {
params["path["+strconv.Itoa(k)+"]"] = v
}
}
res = append(res, params)
}
@@ -223,32 +205,21 @@ func (g *GitGenerator) filterApps(Directories []argoprojiov1alpha1.GitDirectoryG
return res
}
func (g *GitGenerator) generateParamsFromApps(requestedApps []string, _ *argoprojiov1alpha1.ApplicationSetGenerator, useGoTemplate bool) []map[string]interface{} {
// TODO: At some point, the applicationSetGenerator param should be used
func (g *GitGenerator) generateParamsFromApps(requestedApps []string, _ *argoprojiov1alpha1.ApplicationSetGenerator) []map[string]string {
// TODO: At some point, the appicationSetGenerator param should be used
res := make([]map[string]interface{}, len(requestedApps))
res := make([]map[string]string, len(requestedApps))
for i, a := range requestedApps {
params := make(map[string]interface{}, 5)
if useGoTemplate {
paramPath := map[string]interface{}{}
paramPath["path"] = a
paramPath["basename"] = path.Base(a)
paramPath["basenameNormalized"] = utils.SanitizeName(path.Base(a))
paramPath["segments"] = strings.Split(paramPath["path"].(string), "/")
params["path"] = paramPath
} else {
params["path"] = a
params["path.basename"] = path.Base(a)
params["path.basenameNormalized"] = utils.SanitizeName(path.Base(a))
for k, v := range strings.Split(params["path"].(string), "/") {
if len(v) > 0 {
params["path["+strconv.Itoa(k)+"]"] = v
}
params := make(map[string]string, 2)
params["path"] = a
params["path.basename"] = path.Base(a)
params["path.basenameNormalized"] = sanitizeName(path.Base(a))
for k, v := range strings.Split(params["path"], "/") {
if len(v) > 0 {
params["path["+strconv.Itoa(k)+"]"] = v
}
}
res[i] = params
}

View File

@@ -1,6 +1,7 @@
package generators
import (
"context"
"fmt"
"testing"
@@ -8,8 +9,7 @@ import (
"github.com/stretchr/testify/mock"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
testutils "github.com/argoproj/argo-cd/v2/applicationset/utils/test"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
// type clientSet struct {
@@ -20,15 +20,42 @@ import (
// return io.NewCloser(func() error { return nil }), c.RepoServerServiceClient, nil
// }
type argoCDServiceMock struct {
mock *mock.Mock
}
func (a argoCDServiceMock) GetApps(ctx context.Context, repoURL string, revision string) ([]string, error) {
args := a.mock.Called(ctx, repoURL, revision)
return args.Get(0).([]string), args.Error(1)
}
func (a argoCDServiceMock) GetFiles(ctx context.Context, repoURL string, revision string, pattern string) (map[string][]byte, error) {
args := a.mock.Called(ctx, repoURL, revision, pattern)
return args.Get(0).(map[string][]byte), args.Error(1)
}
func (a argoCDServiceMock) GetFileContent(ctx context.Context, repoURL string, revision string, path string) ([]byte, error) {
args := a.mock.Called(ctx, repoURL, revision, path)
return args.Get(0).([]byte), args.Error(1)
}
func (a argoCDServiceMock) GetDirectories(ctx context.Context, repoURL string, revision string) ([]string, error) {
args := a.mock.Called(ctx, repoURL, revision)
return args.Get(0).([]string), args.Error(1)
}
func Test_generateParamsFromGitFile(t *testing.T) {
params, err := (*GitGenerator)(nil).generateParamsFromGitFile("path/dir/file_name.yaml", []byte(`
foo:
bar: baz
`), false)
`))
if err != nil {
t.Fatal(err)
}
assert.Equal(t, []map[string]interface{}{
assert.Equal(t, []map[string]string{
{
"foo.bar": "baz",
"path": "path/dir",
@@ -42,34 +69,6 @@ foo:
}, params)
}
func Test_generateParamsFromGitFileGoTemplate(t *testing.T) {
params, err := (*GitGenerator)(nil).generateParamsFromGitFile("path/dir/file_name.yaml", []byte(`
foo:
bar: baz
`), true)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, []map[string]interface{}{
{
"foo": map[string]interface{}{
"bar": "baz",
},
"path": map[string]interface{}{
"path": "path/dir",
"basename": "dir",
"filename": "file_name.yaml",
"basenameNormalized": "dir",
"filenameNormalized": "file-name.yaml",
"segments": []string{
"path",
"dir",
},
},
},
}, params)
}
func TestGitGenerateParamsFromDirectories(t *testing.T) {
cases := []struct {
@@ -77,7 +76,7 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
directories []argoprojiov1alpha1.GitDirectoryGeneratorItem
repoApps []string
repoError error
expected []map[string]interface{}
expected []map[string]string
expectedError error
}{
{
@@ -90,7 +89,7 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
"p1/app4",
},
repoError: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1", "path[0]": "app1"},
{"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2", "path[0]": "app2"},
{"path": "app_3", "path.basename": "app_3", "path.basenameNormalized": "app-3", "path[0]": "app_3"},
@@ -107,7 +106,7 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
"p1/p2/p3/app4",
},
repoError: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{"path": "p1/app2", "path.basename": "app2", "path[0]": "p1", "path[1]": "app2", "path.basenameNormalized": "app2"},
{"path": "p1/p2/app3", "path.basename": "app3", "path[0]": "p1", "path[1]": "p2", "path[2]": "app3", "path.basenameNormalized": "app3"},
},
@@ -124,7 +123,7 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
"p2/app3",
},
repoError: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{"path": "app1", "path.basename": "app1", "path[0]": "app1", "path.basenameNormalized": "app1"},
{"path": "app2", "path.basename": "app2", "path[0]": "app2", "path.basenameNormalized": "app2"},
{"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path[1]": "app3", "path.basenameNormalized": "app3"},
@@ -142,7 +141,7 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
"p2/app3",
},
repoError: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{"path": "app1", "path.basename": "app1", "path[0]": "app1", "path.basenameNormalized": "app1"},
{"path": "app2", "path.basename": "app2", "path[0]": "app2", "path.basenameNormalized": "app2"},
{"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path[1]": "app3", "path.basenameNormalized": "app3"},
@@ -154,7 +153,7 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
directories: []argoprojiov1alpha1.GitDirectoryGeneratorItem{{Path: "*"}},
repoApps: []string{},
repoError: nil,
expected: []map[string]interface{}{},
expected: []map[string]string{},
expectedError: nil,
},
{
@@ -162,7 +161,7 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
directories: []argoprojiov1alpha1.GitDirectoryGeneratorItem{{Path: "*"}},
repoApps: []string{},
repoError: fmt.Errorf("error"),
expected: []map[string]interface{}{},
expected: []map[string]string{},
expectedError: fmt.Errorf("error"),
},
}
@@ -173,9 +172,9 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
t.Run(testCaseCopy.name, func(t *testing.T) {
t.Parallel()
argoCDServiceMock := testutils.ArgoCDServiceMock{Mock: &mock.Mock{}}
argoCDServiceMock := argoCDServiceMock{mock: &mock.Mock{}}
argoCDServiceMock.Mock.On("GetDirectories", mock.Anything, mock.Anything, mock.Anything).Return(testCaseCopy.repoApps, testCaseCopy.repoError)
argoCDServiceMock.mock.On("GetDirectories", mock.Anything, mock.Anything, mock.Anything).Return(testCaseCopy.repoApps, testCaseCopy.repoError)
var gitGenerator = NewGitGenerator(argoCDServiceMock)
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
@@ -193,7 +192,7 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
},
}
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo)
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], nil)
if testCaseCopy.expectedError != nil {
assert.EqualError(t, err, testCaseCopy.expectedError.Error())
@@ -202,250 +201,7 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
assert.Equal(t, testCaseCopy.expected, got)
}
argoCDServiceMock.Mock.AssertExpectations(t)
})
}
}
func TestGitGenerateParamsFromDirectoriesGoTemplate(t *testing.T) {
cases := []struct {
name string
directories []argoprojiov1alpha1.GitDirectoryGeneratorItem
repoApps []string
repoError error
expected []map[string]interface{}
expectedError error
}{
{
name: "happy flow - created apps",
directories: []argoprojiov1alpha1.GitDirectoryGeneratorItem{{Path: "*"}},
repoApps: []string{
"app1",
"app2",
"app_3",
"p1/app4",
},
repoError: nil,
expected: []map[string]interface{}{
{
"path": map[string]interface{}{
"path": "app1",
"basename": "app1",
"basenameNormalized": "app1",
"segments": []string{
"app1",
},
},
},
{
"path": map[string]interface{}{
"path": "app2",
"basename": "app2",
"basenameNormalized": "app2",
"segments": []string{
"app2",
},
},
},
{
"path": map[string]interface{}{
"path": "app_3",
"basename": "app_3",
"basenameNormalized": "app-3",
"segments": []string{
"app_3",
},
},
},
},
expectedError: nil,
},
{
name: "It filters application according to the paths",
directories: []argoprojiov1alpha1.GitDirectoryGeneratorItem{{Path: "p1/*"}, {Path: "p1/*/*"}},
repoApps: []string{
"app1",
"p1/app2",
"p1/p2/app3",
"p1/p2/p3/app4",
},
repoError: nil,
expected: []map[string]interface{}{
{
"path": map[string]interface{}{
"path": "p1/app2",
"basename": "app2",
"basenameNormalized": "app2",
"segments": []string{
"p1",
"app2",
},
},
},
{
"path": map[string]interface{}{
"path": "p1/p2/app3",
"basename": "app3",
"basenameNormalized": "app3",
"segments": []string{
"p1",
"p2",
"app3",
},
},
},
},
expectedError: nil,
},
{
name: "It filters application according to the paths with Exclude",
directories: []argoprojiov1alpha1.GitDirectoryGeneratorItem{{Path: "p1/*", Exclude: true}, {Path: "*"}, {Path: "*/*"}},
repoApps: []string{
"app1",
"app2",
"p1/app2",
"p1/app3",
"p2/app3",
},
repoError: nil,
expected: []map[string]interface{}{
{
"path": map[string]interface{}{
"path": "app1",
"basename": "app1",
"basenameNormalized": "app1",
"segments": []string{
"app1",
},
},
},
{
"path": map[string]interface{}{
"path": "app2",
"basename": "app2",
"basenameNormalized": "app2",
"segments": []string{
"app2",
},
},
},
{
"path": map[string]interface{}{
"path": "p2/app3",
"basename": "app3",
"basenameNormalized": "app3",
"segments": []string{
"p2",
"app3",
},
},
},
},
expectedError: nil,
},
{
name: "Expecting same exclude behavior with different order",
directories: []argoprojiov1alpha1.GitDirectoryGeneratorItem{{Path: "*"}, {Path: "*/*"}, {Path: "p1/*", Exclude: true}},
repoApps: []string{
"app1",
"app2",
"p1/app2",
"p1/app3",
"p2/app3",
},
repoError: nil,
expected: []map[string]interface{}{
{
"path": map[string]interface{}{
"path": "app1",
"basename": "app1",
"basenameNormalized": "app1",
"segments": []string{
"app1",
},
},
},
{
"path": map[string]interface{}{
"path": "app2",
"basename": "app2",
"basenameNormalized": "app2",
"segments": []string{
"app2",
},
},
},
{
"path": map[string]interface{}{
"path": "p2/app3",
"basename": "app3",
"basenameNormalized": "app3",
"segments": []string{
"p2",
"app3",
},
},
},
},
expectedError: nil,
},
{
name: "handles empty response from repo server",
directories: []argoprojiov1alpha1.GitDirectoryGeneratorItem{{Path: "*"}},
repoApps: []string{},
repoError: nil,
expected: []map[string]interface{}{},
expectedError: nil,
},
{
name: "handles error from repo server",
directories: []argoprojiov1alpha1.GitDirectoryGeneratorItem{{Path: "*"}},
repoApps: []string{},
repoError: fmt.Errorf("error"),
expected: []map[string]interface{}{},
expectedError: fmt.Errorf("error"),
},
}
for _, testCase := range cases {
testCaseCopy := testCase
t.Run(testCaseCopy.name, func(t *testing.T) {
t.Parallel()
argoCDServiceMock := testutils.ArgoCDServiceMock{Mock: &mock.Mock{}}
argoCDServiceMock.Mock.On("GetDirectories", mock.Anything, mock.Anything, mock.Anything).Return(testCaseCopy.repoApps, testCaseCopy.repoError)
var gitGenerator = NewGitGenerator(argoCDServiceMock)
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{
GoTemplate: true,
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{{
Git: &argoprojiov1alpha1.GitGenerator{
RepoURL: "RepoURL",
Revision: "Revision",
Directories: testCaseCopy.directories,
},
}},
},
}
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo)
if testCaseCopy.expectedError != nil {
assert.EqualError(t, err, testCaseCopy.expectedError.Error())
} else {
assert.NoError(t, err)
assert.Equal(t, testCaseCopy.expected, got)
}
argoCDServiceMock.Mock.AssertExpectations(t)
argoCDServiceMock.mock.AssertExpectations(t)
})
}
@@ -461,7 +217,7 @@ func TestGitGenerateParamsFromFiles(t *testing.T) {
repoFileContents map[string][]byte
// if repoPathsError is non-nil, the call to GetPaths(...) will return this error value
repoPathsError error
expected []map[string]interface{}
expected []map[string]string
expectedError error
}{
{
@@ -492,7 +248,7 @@ func TestGitGenerateParamsFromFiles(t *testing.T) {
}`),
},
repoPathsError: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
@@ -529,7 +285,7 @@ func TestGitGenerateParamsFromFiles(t *testing.T) {
files: []argoprojiov1alpha1.GitFileGeneratorItem{{Path: "**/config.json"}},
repoFileContents: map[string][]byte{},
repoPathsError: fmt.Errorf("paths error"),
expected: []map[string]interface{}{},
expected: []map[string]string{},
expectedError: fmt.Errorf("paths error"),
},
{
@@ -539,7 +295,7 @@ func TestGitGenerateParamsFromFiles(t *testing.T) {
"cluster-config/production/config.json": []byte(`invalid json file`),
},
repoPathsError: nil,
expected: []map[string]interface{}{},
expected: []map[string]string{},
expectedError: fmt.Errorf("unable to process file 'cluster-config/production/config.json': unable to parse file: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type map[string]interface {}"),
},
{
@@ -568,7 +324,7 @@ func TestGitGenerateParamsFromFiles(t *testing.T) {
]`),
},
repoPathsError: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
@@ -620,7 +376,7 @@ cluster:
`),
},
repoPathsError: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
@@ -668,7 +424,7 @@ cluster:
address: https://kubernetes.default.svc`),
},
repoPathsError: nil,
expected: []map[string]interface{}{
expected: []map[string]string{
{
"cluster.owner": "john.doe@example.com",
"cluster.name": "production",
@@ -705,8 +461,8 @@ cluster:
t.Run(testCaseCopy.name, func(t *testing.T) {
t.Parallel()
argoCDServiceMock := testutils.ArgoCDServiceMock{Mock: &mock.Mock{}}
argoCDServiceMock.Mock.On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything).
argoCDServiceMock := argoCDServiceMock{mock: &mock.Mock{}}
argoCDServiceMock.mock.On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(testCaseCopy.repoFileContents, testCaseCopy.repoPathsError)
var gitGenerator = NewGitGenerator(argoCDServiceMock)
@@ -725,7 +481,7 @@ cluster:
},
}
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo)
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], nil)
fmt.Println(got, err)
if testCaseCopy.expectedError != nil {
@@ -735,357 +491,8 @@ cluster:
assert.ElementsMatch(t, testCaseCopy.expected, got)
}
argoCDServiceMock.Mock.AssertExpectations(t)
})
}
}
func TestGitGenerateParamsFromFilesGoTemplate(t *testing.T) {
cases := []struct {
name string
// files is the list of paths/globs to match
files []argoprojiov1alpha1.GitFileGeneratorItem
// repoFileContents maps repo path to the literal contents of that path
repoFileContents map[string][]byte
// if repoPathsError is non-nil, the call to GetPaths(...) will return this error value
repoPathsError error
expected []map[string]interface{}
expectedError error
}{
{
name: "happy flow: create params from git files",
files: []argoprojiov1alpha1.GitFileGeneratorItem{{Path: "**/config.json"}},
repoFileContents: map[string][]byte{
"cluster-config/production/config.json": []byte(`{
"cluster": {
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc"
},
"key1": "val1",
"key2": {
"key2_1": "val2_1",
"key2_2": {
"key2_2_1": "val2_2_1"
}
},
"key3": 123
}`),
"cluster-config/staging/config.json": []byte(`{
"cluster": {
"owner": "foo.bar@example.com",
"name": "staging",
"address": "https://kubernetes.default.svc"
}
}`),
},
repoPathsError: nil,
expected: []map[string]interface{}{
{
"cluster": map[string]interface{}{
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
},
"key1": "val1",
"key2": map[string]interface{}{
"key2_1": "val2_1",
"key2_2": map[string]interface{}{
"key2_2_1": "val2_2_1",
},
},
"key3": float64(123),
"path": map[string]interface{}{
"path": "cluster-config/production",
"basename": "production",
"filename": "config.json",
"basenameNormalized": "production",
"filenameNormalized": "config.json",
"segments": []string{
"cluster-config",
"production",
},
},
},
{
"cluster": map[string]interface{}{
"owner": "foo.bar@example.com",
"name": "staging",
"address": "https://kubernetes.default.svc",
},
"path": map[string]interface{}{
"path": "cluster-config/staging",
"basename": "staging",
"filename": "config.json",
"basenameNormalized": "staging",
"filenameNormalized": "config.json",
"segments": []string{
"cluster-config",
"staging",
},
},
},
},
expectedError: nil,
},
{
name: "handles error during getting repo paths",
files: []argoprojiov1alpha1.GitFileGeneratorItem{{Path: "**/config.json"}},
repoFileContents: map[string][]byte{},
repoPathsError: fmt.Errorf("paths error"),
expected: []map[string]interface{}{},
expectedError: fmt.Errorf("paths error"),
},
{
name: "test invalid JSON file returns error",
files: []argoprojiov1alpha1.GitFileGeneratorItem{{Path: "**/config.json"}},
repoFileContents: map[string][]byte{
"cluster-config/production/config.json": []byte(`invalid json file`),
},
repoPathsError: nil,
expected: []map[string]interface{}{},
expectedError: fmt.Errorf("unable to process file 'cluster-config/production/config.json': unable to parse file: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type map[string]interface {}"),
},
{
name: "test JSON array",
files: []argoprojiov1alpha1.GitFileGeneratorItem{{Path: "**/config.json"}},
repoFileContents: map[string][]byte{
"cluster-config/production/config.json": []byte(`
[
{
"cluster": {
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
"inner": {
"one" : "two"
}
}
},
{
"cluster": {
"owner": "john.doe@example.com",
"name": "staging",
"address": "https://kubernetes.default.svc"
}
}
]`),
},
repoPathsError: nil,
expected: []map[string]interface{}{
{
"cluster": map[string]interface{}{
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
"inner": map[string]interface{}{
"one": "two",
},
},
"path": map[string]interface{}{
"path": "cluster-config/production",
"basename": "production",
"filename": "config.json",
"basenameNormalized": "production",
"filenameNormalized": "config.json",
"segments": []string{
"cluster-config",
"production",
},
},
},
{
"cluster": map[string]interface{}{
"owner": "john.doe@example.com",
"name": "staging",
"address": "https://kubernetes.default.svc",
},
"path": map[string]interface{}{
"path": "cluster-config/production",
"basename": "production",
"filename": "config.json",
"basenameNormalized": "production",
"filenameNormalized": "config.json",
"segments": []string{
"cluster-config",
"production",
},
},
},
},
expectedError: nil,
},
{
name: "Test YAML flow",
files: []argoprojiov1alpha1.GitFileGeneratorItem{{Path: "**/config.yaml"}},
repoFileContents: map[string][]byte{
"cluster-config/production/config.yaml": []byte(`
cluster:
owner: john.doe@example.com
name: production
address: https://kubernetes.default.svc
key1: val1
key2:
key2_1: val2_1
key2_2:
key2_2_1: val2_2_1
`),
"cluster-config/staging/config.yaml": []byte(`
cluster:
owner: foo.bar@example.com
name: staging
address: https://kubernetes.default.svc
`),
},
repoPathsError: nil,
expected: []map[string]interface{}{
{
"cluster": map[string]interface{}{
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
},
"key1": "val1",
"key2": map[string]interface{}{
"key2_1": "val2_1",
"key2_2": map[string]interface{}{
"key2_2_1": "val2_2_1",
},
},
"path": map[string]interface{}{
"path": "cluster-config/production",
"basename": "production",
"filename": "config.yaml",
"basenameNormalized": "production",
"filenameNormalized": "config.yaml",
"segments": []string{
"cluster-config",
"production",
},
},
},
{
"cluster": map[string]interface{}{
"owner": "foo.bar@example.com",
"name": "staging",
"address": "https://kubernetes.default.svc",
},
"path": map[string]interface{}{
"path": "cluster-config/staging",
"basename": "staging",
"filename": "config.yaml",
"basenameNormalized": "staging",
"filenameNormalized": "config.yaml",
"segments": []string{
"cluster-config",
"staging",
},
},
},
},
expectedError: nil,
},
{
name: "test YAML array",
files: []argoprojiov1alpha1.GitFileGeneratorItem{{Path: "**/config.yaml"}},
repoFileContents: map[string][]byte{
"cluster-config/production/config.yaml": []byte(`
- cluster:
owner: john.doe@example.com
name: production
address: https://kubernetes.default.svc
inner:
one: two
- cluster:
owner: john.doe@example.com
name: staging
address: https://kubernetes.default.svc`),
},
repoPathsError: nil,
expected: []map[string]interface{}{
{
"cluster": map[string]interface{}{
"owner": "john.doe@example.com",
"name": "production",
"address": "https://kubernetes.default.svc",
"inner": map[string]interface{}{
"one": "two",
},
},
"path": map[string]interface{}{
"path": "cluster-config/production",
"basename": "production",
"filename": "config.yaml",
"basenameNormalized": "production",
"filenameNormalized": "config.yaml",
"segments": []string{
"cluster-config",
"production",
},
},
},
{
"cluster": map[string]interface{}{
"owner": "john.doe@example.com",
"name": "staging",
"address": "https://kubernetes.default.svc",
},
"path": map[string]interface{}{
"path": "cluster-config/production",
"basename": "production",
"filename": "config.yaml",
"basenameNormalized": "production",
"filenameNormalized": "config.yaml",
"segments": []string{
"cluster-config",
"production",
},
},
},
},
expectedError: nil,
},
}
for _, testCase := range cases {
testCaseCopy := testCase
t.Run(testCaseCopy.name, func(t *testing.T) {
t.Parallel()
argoCDServiceMock := testutils.ArgoCDServiceMock{Mock: &mock.Mock{}}
argoCDServiceMock.Mock.On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(testCaseCopy.repoFileContents, testCaseCopy.repoPathsError)
var gitGenerator = NewGitGenerator(argoCDServiceMock)
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{
GoTemplate: true,
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{{
Git: &argoprojiov1alpha1.GitGenerator{
RepoURL: "RepoURL",
Revision: "Revision",
Files: testCaseCopy.files,
},
}},
},
}
got, err := gitGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo)
fmt.Println(got, err)
if testCaseCopy.expectedError != nil {
assert.EqualError(t, err, testCaseCopy.expectedError.Error())
} else {
assert.NoError(t, err)
assert.ElementsMatch(t, testCaseCopy.expected, got)
}
argoCDServiceMock.Mock.AssertExpectations(t)
argoCDServiceMock.mock.AssertExpectations(t)
})
}
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"time"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
// Generator defines the interface implemented by all ApplicationSet generators.
@@ -12,9 +12,9 @@ type Generator interface {
// GenerateParams interprets the ApplicationSet and generates all relevant parameters for the application template.
// The expected / desired list of parameters is returned, it then will be render and reconciled
// against the current state of the Applications in the cluster.
GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error)
GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error)
// GetRequeueAfter is the generator can controller the next reconciled loop
// GetRequeueAfter is the the generator can controller the next reconciled loop
// In case there is more then one generator the time will be the minimum of the times.
// In case NoRequeueAfter is empty, it will be ignored
GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"time"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
var _ Generator = (*ListGenerator)(nil)
@@ -26,7 +26,7 @@ func (g *ListGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.Applicat
return &appSetGenerator.List.Template
}
func (g *ListGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (g *ListGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, _ *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
}
@@ -35,42 +35,39 @@ func (g *ListGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Appli
return nil, EmptyAppSetGeneratorError
}
res := make([]map[string]interface{}, len(appSetGenerator.List.Elements))
res := make([]map[string]string, len(appSetGenerator.List.Elements))
for i, tmpItem := range appSetGenerator.List.Elements {
params := map[string]interface{}{}
params := map[string]string{}
var element map[string]interface{}
err := json.Unmarshal(tmpItem.Raw, &element)
if err != nil {
return nil, fmt.Errorf("error unmarshling list element %v", err)
}
if appSet.Spec.GoTemplate {
res[i] = element
} else {
for key, value := range element {
if key == "values" {
values, ok := (value).(map[string]interface{})
if !ok {
return nil, fmt.Errorf("error parsing values map")
}
for k, v := range values {
value, ok := v.(string)
if !ok {
return nil, fmt.Errorf("error parsing value as string %v", err)
}
params[fmt.Sprintf("values.%s", k)] = value
}
} else {
v, ok := value.(string)
for key, value := range element {
if key == "values" {
values, ok := (value).(map[string]interface{})
if !ok {
return nil, fmt.Errorf("error parsing values map")
}
for k, v := range values {
value, ok := v.(string)
if !ok {
return nil, fmt.Errorf("error parsing value as string %v", err)
}
params[key] = v
params[fmt.Sprintf("values.%s", k)] = value
}
res[i] = params
} else {
v, ok := value.(string)
if !ok {
return nil, fmt.Errorf("error parsing value as string %v", err)
}
params[key] = v
}
}
res[i] = params
}
return res, nil

View File

@@ -5,22 +5,21 @@ import (
"github.com/stretchr/testify/assert"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func TestGenerateListParams(t *testing.T) {
testCases := []struct {
elements []apiextensionsv1.JSON
expected []map[string]interface{}
expected []map[string]string
}{
{
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
expected: []map[string]string{{"cluster": "cluster", "url": "url"}},
}, {
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url", "values.foo": "bar"}},
expected: []map[string]string{{"cluster": "cluster", "url": "url", "values.foo": "bar"}},
},
}
@@ -28,57 +27,13 @@ func TestGenerateListParams(t *testing.T) {
var listGenerator = NewListGenerator()
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{},
}
got, err := listGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
List: &argoprojiov1alpha1.ListGenerator{
Elements: testCase.elements,
}}, &applicationSetInfo)
}}, nil)
assert.NoError(t, err)
assert.ElementsMatch(t, testCase.expected, got)
}
}
func TestGenerateListParamsGoTemplate(t *testing.T) {
testCases := []struct {
elements []apiextensionsv1.JSON
expected []map[string]interface{}
}{
{
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
}, {
elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
expected: []map[string]interface{}{{"cluster": "cluster", "url": "url", "values": map[string]interface{}{"foo": "bar"}}},
},
}
for _, testCase := range testCases {
var listGenerator = NewListGenerator()
applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{
GoTemplate: true,
},
}
got, err := listGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
List: &argoprojiov1alpha1.ListGenerator{
Elements: testCase.elements,
}}, &applicationSetInfo)
assert.NoError(t, err)
assert.ElementsMatch(t, testCase.expected, got)
}
}

View File

@@ -4,10 +4,8 @@ import (
"fmt"
"time"
"github.com/imdario/mergo"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
var _ Generator = (*MatrixGenerator)(nil)
@@ -30,7 +28,7 @@ func NewMatrixGenerator(supportedGenerators map[string]Generator) Generator {
return m
}
func (m *MatrixGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (m *MatrixGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
if appSetGenerator.Matrix == nil {
return nil, EmptyAppSetGeneratorError
@@ -44,42 +42,31 @@ func (m *MatrixGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.App
return nil, ErrMoreThanTwoGenerators
}
res := []map[string]interface{}{}
res := []map[string]string{}
g0, err := m.getParams(appSetGenerator.Matrix.Generators[0], appSet, nil)
g0, err := m.getParams(appSetGenerator.Matrix.Generators[0], appSet)
if err != nil {
return nil, err
}
g1, err := m.getParams(appSetGenerator.Matrix.Generators[1], appSet)
if err != nil {
return nil, err
}
for _, a := range g0 {
g1, err := m.getParams(appSetGenerator.Matrix.Generators[1], appSet, a)
if err != nil {
return nil, fmt.Errorf("failed to get params for second generator in the matrix generator: %w", err)
}
for _, b := range g1 {
if appSet.Spec.GoTemplate {
tmp := map[string]interface{}{}
if err := mergo.Merge(&tmp, a); err != nil {
return nil, fmt.Errorf("failed to merge params from the first generator in the matrix generator with temp map: %w", err)
}
if err := mergo.Merge(&tmp, b); err != nil {
return nil, fmt.Errorf("failed to merge params from the first generator in the matrix generator with the second: %w", err)
}
res = append(res, tmp)
} else {
val, err := utils.CombineStringMaps(a, b)
if err != nil {
return nil, fmt.Errorf("failed to combine string maps with merging params for the matrix generator: %w", err)
}
res = append(res, utils.ConvertToMapStringInterface(val))
for _, a := range g0 {
for _, b := range g1 {
val, err := utils.CombineStringMaps(a, b)
if err != nil {
return nil, err
}
res = append(res, val)
}
}
return res, nil
}
func (m *MatrixGenerator) getParams(appSetBaseGenerator argoprojiov1alpha1.ApplicationSetNestedGenerator, appSet *argoprojiov1alpha1.ApplicationSet, params map[string]interface{}) ([]map[string]interface{}, error) {
func (m *MatrixGenerator) getParams(appSetBaseGenerator argoprojiov1alpha1.ApplicationSetNestedGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
matrixGen, err := getMatrixGenerator(appSetBaseGenerator)
if err != nil {
return nil, err
@@ -99,12 +86,10 @@ func (m *MatrixGenerator) getParams(appSetBaseGenerator argoprojiov1alpha1.Appli
PullRequest: appSetBaseGenerator.PullRequest,
Matrix: matrixGen,
Merge: mergeGen,
Selector: appSetBaseGenerator.Selector,
},
m.supportedGenerators,
argoprojiov1alpha1.ApplicationSetTemplate{},
appSet,
params)
appSet)
if err != nil {
return nil, fmt.Errorf("child generator returned an error on parameter generation: %v", err)

View File

@@ -1,24 +1,14 @@
package generators
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
kubefake "k8s.io/client-go/kubernetes/fake"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
testutils "github.com/argoproj/argo-cd/v2/applicationset/utils/test"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func TestMatrixGenerate(t *testing.T) {
@@ -37,7 +27,7 @@ func TestMatrixGenerate(t *testing.T) {
name string
baseGenerators []argoprojiov1alpha1.ApplicationSetNestedGenerator
expectedErr error
expected []map[string]interface{}
expected []map[string]string
}{
{
name: "happy flow - generate params",
@@ -49,7 +39,7 @@ func TestMatrixGenerate(t *testing.T) {
List: listGenerator,
},
},
expected: []map[string]interface{}{
expected: []map[string]string{
{"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1", "cluster": "Cluster", "url": "Url"},
{"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2", "cluster": "Cluster", "url": "Url"},
},
@@ -74,7 +64,7 @@ func TestMatrixGenerate(t *testing.T) {
},
},
},
expected: []map[string]interface{}{
expected: []map[string]string{
{"a": "1", "b": "1"},
{"a": "1", "b": "2"},
{"a": "2", "b": "1"},
@@ -137,13 +127,8 @@ func TestMatrixGenerate(t *testing.T) {
testCaseCopy := testCase // Since tests may run in parallel
t.Run(testCaseCopy.name, func(t *testing.T) {
genMock := &generatorMock{}
appSet := &argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{},
}
mock := &generatorMock{}
appSet := &argoprojiov1alpha1.ApplicationSet{}
for _, g := range testCaseCopy.baseGenerators {
@@ -151,7 +136,7 @@ func TestMatrixGenerate(t *testing.T) {
Git: g.Git,
List: g.List,
}
genMock.On("GenerateParams", mock.AnythingOfType("*v1alpha1.ApplicationSetGenerator"), appSet).Return([]map[string]interface{}{
mock.On("GenerateParams", &gitGeneratorSpec, appSet).Return([]map[string]string{
{
"path": "app1",
"path.basename": "app1",
@@ -164,13 +149,13 @@ func TestMatrixGenerate(t *testing.T) {
},
}, nil)
genMock.On("GetTemplate", &gitGeneratorSpec).
mock.On("GetTemplate", &gitGeneratorSpec).
Return(&argoprojiov1alpha1.ApplicationSetTemplate{})
}
var matrixGenerator = NewMatrixGenerator(
map[string]Generator{
"Git": genMock,
"Git": mock,
"List": &ListGenerator{},
},
)
@@ -183,202 +168,7 @@ func TestMatrixGenerate(t *testing.T) {
}, appSet)
if testCaseCopy.expectedErr != nil {
assert.ErrorIs(t, err, testCaseCopy.expectedErr)
} else {
assert.NoError(t, err)
assert.Equal(t, testCaseCopy.expected, got)
}
})
}
}
func TestMatrixGenerateGoTemplate(t *testing.T) {
gitGenerator := &argoprojiov1alpha1.GitGenerator{
RepoURL: "RepoURL",
Revision: "Revision",
Directories: []argoprojiov1alpha1.GitDirectoryGeneratorItem{{Path: "*"}},
}
listGenerator := &argoprojiov1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "Cluster","url": "Url"}`)}},
}
testCases := []struct {
name string
baseGenerators []argoprojiov1alpha1.ApplicationSetNestedGenerator
expectedErr error
expected []map[string]interface{}
}{
{
name: "happy flow - generate params",
baseGenerators: []argoprojiov1alpha1.ApplicationSetNestedGenerator{
{
Git: gitGenerator,
},
{
List: listGenerator,
},
},
expected: []map[string]interface{}{
{
"path": map[string]string{
"path": "app1",
"basename": "app1",
"basenameNormalized": "app1",
},
"cluster": "Cluster",
"url": "Url",
},
{
"path": map[string]string{
"path": "app2",
"basename": "app2",
"basenameNormalized": "app2",
},
"cluster": "Cluster",
"url": "Url",
},
},
},
{
name: "happy flow - generate params from two lists",
baseGenerators: []argoprojiov1alpha1.ApplicationSetNestedGenerator{
{
List: &argoprojiov1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{
{Raw: []byte(`{"a": "1"}`)},
{Raw: []byte(`{"a": "2"}`)},
},
},
},
{
List: &argoprojiov1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{
{Raw: []byte(`{"b": "1"}`)},
{Raw: []byte(`{"b": "2"}`)},
},
},
},
},
expected: []map[string]interface{}{
{"a": "1", "b": "1"},
{"a": "1", "b": "2"},
{"a": "2", "b": "1"},
{"a": "2", "b": "2"},
},
},
{
name: "returns error if there is less than two base generators",
baseGenerators: []argoprojiov1alpha1.ApplicationSetNestedGenerator{
{
Git: gitGenerator,
},
},
expectedErr: ErrLessThanTwoGenerators,
},
{
name: "returns error if there is more than two base generators",
baseGenerators: []argoprojiov1alpha1.ApplicationSetNestedGenerator{
{
List: listGenerator,
},
{
List: listGenerator,
},
{
List: listGenerator,
},
},
expectedErr: ErrMoreThanTwoGenerators,
},
{
name: "returns error if there is more than one inner generator in the first base generator",
baseGenerators: []argoprojiov1alpha1.ApplicationSetNestedGenerator{
{
Git: gitGenerator,
List: listGenerator,
},
{
Git: gitGenerator,
},
},
expectedErr: ErrMoreThenOneInnerGenerators,
},
{
name: "returns error if there is more than one inner generator in the second base generator",
baseGenerators: []argoprojiov1alpha1.ApplicationSetNestedGenerator{
{
List: listGenerator,
},
{
Git: gitGenerator,
List: listGenerator,
},
},
expectedErr: ErrMoreThenOneInnerGenerators,
},
}
for _, testCase := range testCases {
testCaseCopy := testCase // Since tests may run in parallel
t.Run(testCaseCopy.name, func(t *testing.T) {
genMock := &generatorMock{}
appSet := &argoprojiov1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
Name: "set",
},
Spec: argoprojiov1alpha1.ApplicationSetSpec{
GoTemplate: true,
},
}
for _, g := range testCaseCopy.baseGenerators {
gitGeneratorSpec := argoprojiov1alpha1.ApplicationSetGenerator{
Git: g.Git,
List: g.List,
}
genMock.On("GenerateParams", mock.AnythingOfType("*v1alpha1.ApplicationSetGenerator"), appSet).Return([]map[string]interface{}{
{
"path": map[string]string{
"path": "app1",
"basename": "app1",
"basenameNormalized": "app1",
},
},
{
"path": map[string]string{
"path": "app2",
"basename": "app2",
"basenameNormalized": "app2",
},
},
}, nil)
genMock.On("GetTemplate", &gitGeneratorSpec).
Return(&argoprojiov1alpha1.ApplicationSetTemplate{})
}
var matrixGenerator = NewMatrixGenerator(
map[string]Generator{
"Git": genMock,
"List": &ListGenerator{},
},
)
got, err := matrixGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
Matrix: &argoprojiov1alpha1.MatrixGenerator{
Generators: testCaseCopy.baseGenerators,
Template: argoprojiov1alpha1.ApplicationSetTemplate{},
},
}, appSet)
if testCaseCopy.expectedErr != nil {
assert.ErrorIs(t, err, testCaseCopy.expectedErr)
assert.EqualError(t, err, testCaseCopy.expectedErr.Error())
} else {
assert.NoError(t, err)
assert.Equal(t, testCaseCopy.expected, got)
@@ -499,344 +289,6 @@ func TestMatrixGetRequeueAfter(t *testing.T) {
}
}
func TestInterpolatedMatrixGenerate(t *testing.T) {
interpolatedGitGenerator := &argoprojiov1alpha1.GitGenerator{
RepoURL: "RepoURL",
Revision: "Revision",
Files: []argoprojiov1alpha1.GitFileGeneratorItem{
{Path: "examples/git-generator-files-discovery/cluster-config/dev/config.json"},
{Path: "examples/git-generator-files-discovery/cluster-config/prod/config.json"},
},
}
interpolatedClusterGenerator := &argoprojiov1alpha1.ClusterGenerator{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{"environment": "{{path.basename}}"},
MatchExpressions: nil,
},
}
testCases := []struct {
name string
baseGenerators []argoprojiov1alpha1.ApplicationSetNestedGenerator
expectedErr error
expected []map[string]interface{}
clientError bool
}{
{
name: "happy flow - generate interpolated params",
baseGenerators: []argoprojiov1alpha1.ApplicationSetNestedGenerator{
{
Git: interpolatedGitGenerator,
},
{
Clusters: interpolatedClusterGenerator,
},
},
expected: []map[string]interface{}{
{"path": "examples/git-generator-files-discovery/cluster-config/dev/config.json", "path.basename": "dev", "path.basenameNormalized": "dev", "name": "dev-01", "nameNormalized": "dev-01", "server": "https://dev-01.example.com", "metadata.labels.environment": "dev", "metadata.labels.argocd.argoproj.io/secret-type": "cluster"},
{"path": "examples/git-generator-files-discovery/cluster-config/prod/config.json", "path.basename": "prod", "path.basenameNormalized": "prod", "name": "prod-01", "nameNormalized": "prod-01", "server": "https://prod-01.example.com", "metadata.labels.environment": "prod", "metadata.labels.argocd.argoproj.io/secret-type": "cluster"},
},
clientError: false,
},
}
clusters := []client.Object{
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "dev-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "dev",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("dev-01"),
"server": []byte("https://dev-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "prod-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "prod",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("prod-01"),
"server": []byte("https://prod-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
}
// convert []client.Object to []runtime.Object, for use by kubefake package
runtimeClusters := []runtime.Object{}
for _, clientCluster := range clusters {
runtimeClusters = append(runtimeClusters, clientCluster)
}
for _, testCase := range testCases {
testCaseCopy := testCase // Since tests may run in parallel
t.Run(testCaseCopy.name, func(t *testing.T) {
genMock := &generatorMock{}
appSet := &argoprojiov1alpha1.ApplicationSet{}
appClientset := kubefake.NewSimpleClientset(runtimeClusters...)
fakeClient := fake.NewClientBuilder().WithObjects(clusters...).Build()
cl := &possiblyErroringFakeCtrlRuntimeClient{
fakeClient,
testCase.clientError,
}
var clusterGenerator = NewClusterGenerator(cl, context.Background(), appClientset, "namespace")
for _, g := range testCaseCopy.baseGenerators {
gitGeneratorSpec := argoprojiov1alpha1.ApplicationSetGenerator{
Git: g.Git,
Clusters: g.Clusters,
}
genMock.On("GenerateParams", mock.AnythingOfType("*v1alpha1.ApplicationSetGenerator"), appSet).Return([]map[string]interface{}{
{
"path": "examples/git-generator-files-discovery/cluster-config/dev/config.json",
"path.basename": "dev",
"path.basenameNormalized": "dev",
},
{
"path": "examples/git-generator-files-discovery/cluster-config/prod/config.json",
"path.basename": "prod",
"path.basenameNormalized": "prod",
},
}, nil)
genMock.On("GetTemplate", &gitGeneratorSpec).
Return(&argoprojiov1alpha1.ApplicationSetTemplate{})
}
var matrixGenerator = NewMatrixGenerator(
map[string]Generator{
"Git": genMock,
"Clusters": clusterGenerator,
},
)
got, err := matrixGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
Matrix: &argoprojiov1alpha1.MatrixGenerator{
Generators: testCaseCopy.baseGenerators,
Template: argoprojiov1alpha1.ApplicationSetTemplate{},
},
}, appSet)
if testCaseCopy.expectedErr != nil {
assert.ErrorIs(t, err, testCaseCopy.expectedErr)
} else {
assert.NoError(t, err)
assert.Equal(t, testCaseCopy.expected, got)
}
})
}
}
func TestInterpolatedMatrixGenerateGoTemplate(t *testing.T) {
interpolatedGitGenerator := &argoprojiov1alpha1.GitGenerator{
RepoURL: "RepoURL",
Revision: "Revision",
Files: []argoprojiov1alpha1.GitFileGeneratorItem{
{Path: "examples/git-generator-files-discovery/cluster-config/dev/config.json"},
{Path: "examples/git-generator-files-discovery/cluster-config/prod/config.json"},
},
}
interpolatedClusterGenerator := &argoprojiov1alpha1.ClusterGenerator{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{"environment": "{{.path.basename}}"},
MatchExpressions: nil,
},
}
testCases := []struct {
name string
baseGenerators []argoprojiov1alpha1.ApplicationSetNestedGenerator
expectedErr error
expected []map[string]interface{}
clientError bool
}{
{
name: "happy flow - generate interpolated params",
baseGenerators: []argoprojiov1alpha1.ApplicationSetNestedGenerator{
{
Git: interpolatedGitGenerator,
},
{
Clusters: interpolatedClusterGenerator,
},
},
expected: []map[string]interface{}{
{
"path": map[string]string{
"path": "examples/git-generator-files-discovery/cluster-config/dev/config.json",
"basename": "dev",
"basenameNormalized": "dev",
},
"name": "dev-01",
"nameNormalized": "dev-01",
"server": "https://dev-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"environment": "dev",
"argocd.argoproj.io/secret-type": "cluster",
},
},
},
{
"path": map[string]string{
"path": "examples/git-generator-files-discovery/cluster-config/prod/config.json",
"basename": "prod",
"basenameNormalized": "prod",
},
"name": "prod-01",
"nameNormalized": "prod-01",
"server": "https://prod-01.example.com",
"metadata": map[string]interface{}{
"labels": map[string]string{
"environment": "prod",
"argocd.argoproj.io/secret-type": "cluster",
},
},
},
},
clientError: false,
},
}
clusters := []client.Object{
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "dev-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "dev",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("dev-01"),
"server": []byte("https://dev-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
&corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "prod-01",
Namespace: "namespace",
Labels: map[string]string{
"argocd.argoproj.io/secret-type": "cluster",
"environment": "prod",
},
},
Data: map[string][]byte{
"config": []byte("{}"),
"name": []byte("prod-01"),
"server": []byte("https://prod-01.example.com"),
},
Type: corev1.SecretType("Opaque"),
},
}
// convert []client.Object to []runtime.Object, for use by kubefake package
runtimeClusters := []runtime.Object{}
for _, clientCluster := range clusters {
runtimeClusters = append(runtimeClusters, clientCluster)
}
for _, testCase := range testCases {
testCaseCopy := testCase // Since tests may run in parallel
t.Run(testCaseCopy.name, func(t *testing.T) {
genMock := &generatorMock{}
appSet := &argoprojiov1alpha1.ApplicationSet{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
GoTemplate: true,
},
}
appClientset := kubefake.NewSimpleClientset(runtimeClusters...)
fakeClient := fake.NewClientBuilder().WithObjects(clusters...).Build()
cl := &possiblyErroringFakeCtrlRuntimeClient{
fakeClient,
testCase.clientError,
}
var clusterGenerator = NewClusterGenerator(cl, context.Background(), appClientset, "namespace")
for _, g := range testCaseCopy.baseGenerators {
gitGeneratorSpec := argoprojiov1alpha1.ApplicationSetGenerator{
Git: g.Git,
Clusters: g.Clusters,
}
genMock.On("GenerateParams", mock.AnythingOfType("*v1alpha1.ApplicationSetGenerator"), appSet).Return([]map[string]interface{}{
{
"path": map[string]string{
"path": "examples/git-generator-files-discovery/cluster-config/dev/config.json",
"basename": "dev",
"basenameNormalized": "dev",
},
},
{
"path": map[string]string{
"path": "examples/git-generator-files-discovery/cluster-config/prod/config.json",
"basename": "prod",
"basenameNormalized": "prod",
},
},
}, nil)
genMock.On("GetTemplate", &gitGeneratorSpec).
Return(&argoprojiov1alpha1.ApplicationSetTemplate{})
}
var matrixGenerator = NewMatrixGenerator(
map[string]Generator{
"Git": genMock,
"Clusters": clusterGenerator,
},
)
got, err := matrixGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
Matrix: &argoprojiov1alpha1.MatrixGenerator{
Generators: testCaseCopy.baseGenerators,
Template: argoprojiov1alpha1.ApplicationSetTemplate{},
},
}, appSet)
if testCaseCopy.expectedErr != nil {
assert.ErrorIs(t, err, testCaseCopy.expectedErr)
} else {
assert.NoError(t, err)
assert.Equal(t, testCaseCopy.expected, got)
}
})
}
}
type generatorMock struct {
mock.Mock
}
@@ -847,10 +299,10 @@ func (g *generatorMock) GetTemplate(appSetGenerator *argoprojiov1alpha1.Applicat
return args.Get(0).(*argoprojiov1alpha1.ApplicationSetTemplate)
}
func (g *generatorMock) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (g *generatorMock) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
args := g.Called(appSetGenerator, appSet)
return args.Get(0).([]map[string]interface{}), args.Error(1)
return args.Get(0).([]map[string]string), args.Error(1)
}
func (g *generatorMock) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration {
@@ -859,72 +311,3 @@ func (g *generatorMock) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.Appl
return args.Get(0).(time.Duration)
}
func TestGitGenerator_GenerateParams_list_x_git_matrix_generator(t *testing.T) {
// Given a matrix generator over a list generator and a git files generator, the nested git files generator should
// be treated as a files generator, and it should produce parameters.
// This tests for a specific bug where a nested git files generator was being treated as a directory generator. This
// happened because, when the matrix generator was being processed, the nested git files generator was being
// interpolated by the deeplyReplace function. That function cannot differentiate between a nil slice and an empty
// slice. So it was replacing the `Directories` field with an empty slice, which the ApplicationSet controller
// interpreted as meaning this was a directory generator, not a files generator.
// Now instead of checking for nil, we check whether the field is a non-empty slice. This test prevents a regression
// of that bug.
listGeneratorMock := &generatorMock{}
listGeneratorMock.On("GenerateParams", mock.AnythingOfType("*v1alpha1.ApplicationSetGenerator"), mock.AnythingOfType("*v1alpha1.ApplicationSet")).Return([]map[string]interface{}{
{"some": "value"},
}, nil)
listGeneratorMock.On("GetTemplate", mock.AnythingOfType("*v1alpha1.ApplicationSetGenerator")).Return(&argoprojiov1alpha1.ApplicationSetTemplate{})
gitGeneratorSpec := &argoprojiov1alpha1.GitGenerator{
RepoURL: "https://git.example.com",
Files: []argoprojiov1alpha1.GitFileGeneratorItem{
{Path: "some/path.json"},
},
}
repoServiceMock := testutils.ArgoCDServiceMock{Mock: &mock.Mock{}}
repoServiceMock.Mock.On("GetFiles", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(map[string][]byte{
"some/path.json": []byte("test: content"),
}, nil)
gitGenerator := NewGitGenerator(repoServiceMock)
matrixGenerator := NewMatrixGenerator(map[string]Generator{
"List": listGeneratorMock,
"Git": gitGenerator,
})
matrixGeneratorSpec := &argoprojiov1alpha1.MatrixGenerator{
Generators: []argoprojiov1alpha1.ApplicationSetNestedGenerator{
{
List: &argoprojiov1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{
{
Raw: []byte(`{"some": "value"}`),
},
},
},
},
{
Git: gitGeneratorSpec,
},
},
}
params, err := matrixGenerator.GenerateParams(&argoprojiov1alpha1.ApplicationSetGenerator{
Matrix: matrixGeneratorSpec,
}, &argoprojiov1alpha1.ApplicationSet{})
require.NoError(t, err)
assert.Equal(t, []map[string]interface{}{{
"path": "some",
"path.basename": "some",
"path.basenameNormalized": "some",
"path.filename": "path.json",
"path.filenameNormalized": "path.json",
"path[0]": "some",
"some": "value",
"test": "content",
}}, params)
}

View File

@@ -5,10 +5,8 @@ import (
"fmt"
"time"
"github.com/imdario/mergo"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
var _ Generator = (*MergeGenerator)(nil)
@@ -34,8 +32,8 @@ func NewMergeGenerator(supportedGenerators map[string]Generator) Generator {
// getParamSetsForAllGenerators generates params for each child generator in a MergeGenerator. Param sets are returned
// in slices ordered according to the order of the given generators.
func (m *MergeGenerator) getParamSetsForAllGenerators(generators []argoprojiov1alpha1.ApplicationSetNestedGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([][]map[string]interface{}, error) {
var paramSets [][]map[string]interface{}
func (m *MergeGenerator) getParamSetsForAllGenerators(generators []argoprojiov1alpha1.ApplicationSetNestedGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([][]map[string]string, error) {
var paramSets [][]map[string]string
for _, generator := range generators {
generatorParamSets, err := m.getParams(generator, appSet)
if err != nil {
@@ -48,7 +46,7 @@ func (m *MergeGenerator) getParamSetsForAllGenerators(generators []argoprojiov1a
}
// GenerateParams gets the params produced by the MergeGenerator.
func (m *MergeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (m *MergeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
if appSetGenerator.Merge == nil {
return nil, EmptyAppSetGeneratorError
}
@@ -75,24 +73,16 @@ func (m *MergeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Appl
for mergeKeyValue, baseParamSet := range baseParamSetsByMergeKey {
if overrideParamSet, exists := paramSetsByMergeKey[mergeKeyValue]; exists {
if appSet.Spec.GoTemplate {
if err := mergo.Merge(&baseParamSet, overrideParamSet, mergo.WithOverride); err != nil {
return nil, fmt.Errorf("failed to merge base param set with override param set: %w", err)
}
baseParamSetsByMergeKey[mergeKeyValue] = baseParamSet
} else {
overriddenParamSet, err := utils.CombineStringMapsAllowDuplicates(baseParamSet, overrideParamSet)
if err != nil {
return nil, err
}
baseParamSetsByMergeKey[mergeKeyValue] = utils.ConvertToMapStringInterface(overriddenParamSet)
overriddenParamSet, err := utils.CombineStringMapsAllowDuplicates(baseParamSet, overrideParamSet)
if err != nil {
return nil, err
}
baseParamSetsByMergeKey[mergeKeyValue] = overriddenParamSet
}
}
}
mergedParamSets := make([]map[string]interface{}, len(baseParamSetsByMergeKey))
mergedParamSets := make([]map[string]string, len(baseParamSetsByMergeKey))
var i = 0
for _, mergedParamSet := range baseParamSetsByMergeKey {
mergedParamSets[i] = mergedParamSet
@@ -105,7 +95,7 @@ func (m *MergeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Appl
// getParamSetsByMergeKey converts the given list of parameter sets to a map of parameter sets where the key is the
// unique key of the parameter set as determined by the given mergeKeys. If any two parameter sets share the same merge
// key, getParamSetsByMergeKey will throw NonUniqueParamSets.
func getParamSetsByMergeKey(mergeKeys []string, paramSets []map[string]interface{}) (map[string]map[string]interface{}, error) {
func getParamSetsByMergeKey(mergeKeys []string, paramSets []map[string]string) (map[string]map[string]string, error) {
if len(mergeKeys) < 1 {
return nil, ErrNoMergeKeys
}
@@ -115,9 +105,9 @@ func getParamSetsByMergeKey(mergeKeys []string, paramSets []map[string]interface
deDuplicatedMergeKeys[mergeKey] = false
}
paramSetsByMergeKey := make(map[string]map[string]interface{}, len(paramSets))
paramSetsByMergeKey := make(map[string]map[string]string, len(paramSets))
for _, paramSet := range paramSets {
paramSetKey := make(map[string]interface{})
paramSetKey := make(map[string]string)
for mergeKey := range deDuplicatedMergeKeys {
paramSetKey[mergeKey] = paramSet[mergeKey]
}
@@ -136,7 +126,7 @@ func getParamSetsByMergeKey(mergeKeys []string, paramSets []map[string]interface
}
// getParams get the parameters generated by this generator.
func (m *MergeGenerator) getParams(appSetBaseGenerator argoprojiov1alpha1.ApplicationSetNestedGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (m *MergeGenerator) getParams(appSetBaseGenerator argoprojiov1alpha1.ApplicationSetNestedGenerator, appSet *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
matrixGen, err := getMatrixGenerator(appSetBaseGenerator)
if err != nil {
return nil, err
@@ -156,12 +146,10 @@ func (m *MergeGenerator) getParams(appSetBaseGenerator argoprojiov1alpha1.Applic
PullRequest: appSetBaseGenerator.PullRequest,
Matrix: matrixGen,
Merge: mergeGen,
Selector: appSetBaseGenerator.Selector,
},
m.supportedGenerators,
argoprojiov1alpha1.ApplicationSetTemplate{},
appSet,
map[string]interface{}{})
appSet)
if err != nil {
return nil, fmt.Errorf("child generator returned an error on parameter generation: %v", err)

View File

@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func getNestedListGenerator(json string) *argoprojiov1alpha1.ApplicationSetNestedGenerator {
@@ -35,7 +35,7 @@ func getTerminalListGeneratorMultiple(jsons []string) argoprojiov1alpha1.Applica
return generator
}
func listOfMapsToSet(maps []map[string]interface{}) (map[string]bool, error) {
func listOfMapsToSet(maps []map[string]string) (map[string]bool, error) {
set := make(map[string]bool, len(maps))
for _, paramMap := range maps {
paramMapAsJson, err := json.Marshal(paramMap)
@@ -55,7 +55,7 @@ func TestMergeGenerate(t *testing.T) {
baseGenerators []argoprojiov1alpha1.ApplicationSetNestedGenerator
mergeKeys []string
expectedErr error
expected []map[string]interface{}
expected []map[string]string
}{
{
name: "no generators",
@@ -79,7 +79,7 @@ func TestMergeGenerate(t *testing.T) {
*getNestedListGenerator(`{"a": "3_1","b": "different","c": "3_3"}`), // gets ignored because its merge key value isn't in the base params set
},
mergeKeys: []string{"b"},
expected: []map[string]interface{}{
expected: []map[string]string{
{"a": "2_1", "b": "same", "c": "1_3"},
},
},
@@ -90,7 +90,7 @@ func TestMergeGenerate(t *testing.T) {
*getNestedListGenerator(`{"a": "a"}`),
},
mergeKeys: []string{"b"},
expected: []map[string]interface{}{
expected: []map[string]string{
{"a": "a"},
},
},
@@ -101,7 +101,7 @@ func TestMergeGenerate(t *testing.T) {
*getNestedListGenerator(`{"b": "b"}`),
},
mergeKeys: []string{"b"},
expected: []map[string]interface{}{
expected: []map[string]string{
{"a": "a"},
},
},
@@ -119,7 +119,7 @@ func TestMergeGenerate(t *testing.T) {
*getNestedListGenerator(`{"a": "1", "b": "1", "c": "added"}`),
},
mergeKeys: []string{"a", "b"},
expected: []map[string]interface{}{
expected: []map[string]string{
{"a": "1", "b": "1", "c": "added"},
{"a": "1", "b": "2"},
{"a": "2", "b": "1"},
@@ -141,7 +141,7 @@ func TestMergeGenerate(t *testing.T) {
*getNestedListGenerator(`{"a": "1", "b": "3", "d": "added"}`),
},
mergeKeys: []string{"a", "b"},
expected: []map[string]interface{}{
expected: []map[string]string{
{"a": "1", "b": "3", "c": "added", "d": "added"},
{"a": "2", "b": "2"},
},
@@ -213,9 +213,9 @@ func TestParamSetsAreUniqueByMergeKeys(t *testing.T) {
testCases := []struct {
name string
mergeKeys []string
paramSets []map[string]interface{}
paramSets []map[string]string
expectedErr error
expected map[string]map[string]interface{}
expected map[string]map[string]string
}{
{
name: "no merge keys",
@@ -225,37 +225,28 @@ func TestParamSetsAreUniqueByMergeKeys(t *testing.T) {
{
name: "no paramSets",
mergeKeys: []string{"key"},
expected: make(map[string]map[string]interface{}),
expected: make(map[string]map[string]string),
},
{
name: "simple key, unique paramSets",
mergeKeys: []string{"key"},
paramSets: []map[string]interface{}{{"key": "a"}, {"key": "b"}},
expected: map[string]map[string]interface{}{
paramSets: []map[string]string{{"key": "a"}, {"key": "b"}},
expected: map[string]map[string]string{
`{"key":"a"}`: {"key": "a"},
`{"key":"b"}`: {"key": "b"},
},
},
{
name: "simple key object, unique paramSets",
mergeKeys: []string{"key"},
paramSets: []map[string]interface{}{{"key": map[string]interface{}{"hello": "world"}}, {"key": "b"}},
expected: map[string]map[string]interface{}{
`{"key":{"hello":"world"}}`: {"key": map[string]interface{}{"hello": "world"}},
`{"key":"b"}`: {"key": "b"},
},
},
{
name: "simple key, non-unique paramSets",
mergeKeys: []string{"key"},
paramSets: []map[string]interface{}{{"key": "a"}, {"key": "b"}, {"key": "b"}},
paramSets: []map[string]string{{"key": "a"}, {"key": "b"}, {"key": "b"}},
expectedErr: fmt.Errorf("%w. Duplicate key was %s", ErrNonUniqueParamSets, `{"key":"b"}`),
},
{
name: "simple key, duplicated key name, unique paramSets",
mergeKeys: []string{"key", "key"},
paramSets: []map[string]interface{}{{"key": "a"}, {"key": "b"}},
expected: map[string]map[string]interface{}{
paramSets: []map[string]string{{"key": "a"}, {"key": "b"}},
expected: map[string]map[string]string{
`{"key":"a"}`: {"key": "a"},
`{"key":"b"}`: {"key": "b"},
},
@@ -263,46 +254,32 @@ func TestParamSetsAreUniqueByMergeKeys(t *testing.T) {
{
name: "simple key, duplicated key name, non-unique paramSets",
mergeKeys: []string{"key", "key"},
paramSets: []map[string]interface{}{{"key": "a"}, {"key": "b"}, {"key": "b"}},
paramSets: []map[string]string{{"key": "a"}, {"key": "b"}, {"key": "b"}},
expectedErr: fmt.Errorf("%w. Duplicate key was %s", ErrNonUniqueParamSets, `{"key":"b"}`),
},
{
name: "compound key, unique paramSets",
mergeKeys: []string{"key1", "key2"},
paramSets: []map[string]interface{}{
paramSets: []map[string]string{
{"key1": "a", "key2": "a"},
{"key1": "a", "key2": "b"},
{"key1": "b", "key2": "a"},
},
expected: map[string]map[string]interface{}{
expected: map[string]map[string]string{
`{"key1":"a","key2":"a"}`: {"key1": "a", "key2": "a"},
`{"key1":"a","key2":"b"}`: {"key1": "a", "key2": "b"},
`{"key1":"b","key2":"a"}`: {"key1": "b", "key2": "a"},
},
},
{
name: "compound key object, unique paramSets",
mergeKeys: []string{"key1", "key2"},
paramSets: []map[string]interface{}{
{"key1": "a", "key2": map[string]interface{}{"hello": "world"}},
{"key1": "a", "key2": "b"},
{"key1": "b", "key2": "a"},
},
expected: map[string]map[string]interface{}{
`{"key1":"a","key2":{"hello":"world"}}`: {"key1": "a", "key2": map[string]interface{}{"hello": "world"}},
`{"key1":"a","key2":"b"}`: {"key1": "a", "key2": "b"},
`{"key1":"b","key2":"a"}`: {"key1": "b", "key2": "a"},
},
},
{
name: "compound key, duplicate key names, unique paramSets",
mergeKeys: []string{"key1", "key1", "key2"},
paramSets: []map[string]interface{}{
paramSets: []map[string]string{
{"key1": "a", "key2": "a"},
{"key1": "a", "key2": "b"},
{"key1": "b", "key2": "a"},
},
expected: map[string]map[string]interface{}{
expected: map[string]map[string]string{
`{"key1":"a","key2":"a"}`: {"key1": "a", "key2": "a"},
`{"key1":"a","key2":"b"}`: {"key1": "a", "key2": "b"},
`{"key1":"b","key2":"a"}`: {"key1": "b", "key2": "a"},
@@ -311,7 +288,7 @@ func TestParamSetsAreUniqueByMergeKeys(t *testing.T) {
{
name: "compound key, non-unique paramSets",
mergeKeys: []string{"key1", "key2"},
paramSets: []map[string]interface{}{
paramSets: []map[string]string{
{"key1": "a", "key2": "a"},
{"key1": "a", "key2": "a"},
{"key1": "b", "key2": "a"},
@@ -321,7 +298,7 @@ func TestParamSetsAreUniqueByMergeKeys(t *testing.T) {
{
name: "compound key, duplicate key names, non-unique paramSets",
mergeKeys: []string{"key1", "key1", "key2"},
paramSets: []map[string]interface{}{
paramSets: []map[string]string{
{"key1": "a", "key2": "a"},
{"key1": "a", "key2": "a"},
{"key1": "b", "key2": "a"},

View File

@@ -9,11 +9,9 @@ import (
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/gosimple/slug"
"github.com/argoproj/argo-cd/v2/applicationset/services/pull_request"
pullrequest "github.com/argoproj/argo-cd/v2/applicationset/services/pull_request"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
var _ Generator = (*PullRequestGenerator)(nil)
@@ -25,13 +23,11 @@ const (
type PullRequestGenerator struct {
client client.Client
selectServiceProviderFunc func(context.Context, *argoprojiov1alpha1.PullRequestGenerator, *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error)
auth SCMAuthProviders
}
func NewPullRequestGenerator(client client.Client, auth SCMAuthProviders) Generator {
func NewPullRequestGenerator(client client.Client) Generator {
g := &PullRequestGenerator{
client: client,
auth: auth,
}
g.selectServiceProviderFunc = g.selectServiceProvider
return g
@@ -51,7 +47,7 @@ func (g *PullRequestGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.A
return &appSetGenerator.PullRequest.Template
}
func (g *PullRequestGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (g *PullRequestGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
}
@@ -70,32 +66,12 @@ func (g *PullRequestGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
if err != nil {
return nil, fmt.Errorf("error listing repos: %v", err)
}
params := make([]map[string]interface{}, 0, len(pulls))
// In order to follow the DNS label standard as defined in RFC 1123,
// we need to limit the 'branch' to 50 to give room to append/suffix-ing it
// with 13 more characters. Also, there is the need to clean it as recommended
// here https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names
slug.MaxLength = 50
// Converting underscores to dashes
slug.CustomSub = map[string]string{
"_": "-",
}
var shortSHALength int
params := make([]map[string]string, 0, len(pulls))
for _, pull := range pulls {
shortSHALength = 8
if len(pull.HeadSHA) < 8 {
shortSHALength = len(pull.HeadSHA)
}
params = append(params, map[string]interface{}{
"number": strconv.Itoa(pull.Number),
"branch": pull.Branch,
"branch_slug": slug.Make(pull.Branch),
"head_sha": pull.HeadSHA,
"head_short_sha": pull.HeadSHA[:shortSHALength],
params = append(params, map[string]string{
"number": strconv.Itoa(pull.Number),
"branch": pull.Branch,
"head_sha": pull.HeadSHA,
})
}
return params, nil
@@ -104,15 +80,12 @@ func (g *PullRequestGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
// selectServiceProvider selects the provider to get pull requests from the configuration
func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, generatorConfig *argoprojiov1alpha1.PullRequestGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error) {
if generatorConfig.Github != nil {
return g.github(ctx, generatorConfig.Github, applicationSetInfo)
}
if generatorConfig.GitLab != nil {
providerConfig := generatorConfig.GitLab
providerConfig := generatorConfig.Github
token, err := g.getSecretRef(ctx, providerConfig.TokenRef, applicationSetInfo.Namespace)
if err != nil {
return nil, fmt.Errorf("error fetching Secret token: %v", err)
}
return pullrequest.NewGitLabService(ctx, token, providerConfig.API, providerConfig.Project, providerConfig.Labels, providerConfig.PullRequestState)
return pullrequest.NewGithubService(ctx, token, providerConfig.API, providerConfig.Owner, providerConfig.Repo, providerConfig.Labels)
}
if generatorConfig.Gitea != nil {
providerConfig := generatorConfig.Gitea
@@ -137,24 +110,6 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
return nil, fmt.Errorf("no Pull Request provider implementation configured")
}
func (g *PullRequestGenerator) github(ctx context.Context, cfg *argoprojiov1alpha1.PullRequestGeneratorGithub, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error) {
// use an app if it was configured
if cfg.AppSecretName != "" {
auth, err := g.auth.GitHubApps.GetAuthSecret(ctx, cfg.AppSecretName)
if err != nil {
return nil, fmt.Errorf("error getting GitHub App secret: %v", err)
}
return pullrequest.NewGithubAppService(*auth, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels)
}
// always default to token, even if not set (public access)
token, err := g.getSecretRef(ctx, cfg.TokenRef, applicationSetInfo.Namespace)
if err != nil {
return nil, fmt.Errorf("error fetching Secret token: %v", err)
}
return pullrequest.NewGithubService(ctx, token, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels)
}
// getSecretRef gets the value of the key for the specified Secret resource.
func (g *PullRequestGenerator) getSecretRef(ctx context.Context, ref *argoprojiov1alpha1.SecretRef, namespace string) (string, error) {
if ref == nil {

View File

@@ -11,14 +11,14 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake"
pullrequest "github.com/argoproj/argo-cd/v2/applicationset/services/pull_request"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func TestPullRequestGithubGenerateParams(t *testing.T) {
ctx := context.Background()
cases := []struct {
selectFunc func(context.Context, *argoprojiov1alpha1.PullRequestGenerator, *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error)
expected []map[string]interface{}
expected []map[string]string
expectedErr error
}{
{
@@ -35,63 +35,11 @@ func TestPullRequestGithubGenerateParams(t *testing.T) {
nil,
)
},
expected: []map[string]interface{}{
expected: []map[string]string{
{
"number": "1",
"branch": "branch1",
"branch_slug": "branch1",
"head_sha": "089d92cbf9ff857a39e6feccd32798ca700fb958",
"head_short_sha": "089d92cb",
},
},
expectedErr: nil,
},
{
selectFunc: func(context.Context, *argoprojiov1alpha1.PullRequestGenerator, *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error) {
return pullrequest.NewFakeService(
ctx,
[]*pullrequest.PullRequest{
&pullrequest.PullRequest{
Number: 2,
Branch: "feat/areally+long_pull_request_name_to_test_argo_slugification_and_branch_name_shortening_feature",
HeadSHA: "9b34ff5bd418e57d58891eb0aa0728043ca1e8be",
},
},
nil,
)
},
expected: []map[string]interface{}{
{
"number": "2",
"branch": "feat/areally+long_pull_request_name_to_test_argo_slugification_and_branch_name_shortening_feature",
"branch_slug": "feat-areally-long-pull-request-name-to-test-argo",
"head_sha": "9b34ff5bd418e57d58891eb0aa0728043ca1e8be",
"head_short_sha": "9b34ff5b",
},
},
expectedErr: nil,
},
{
selectFunc: func(context.Context, *argoprojiov1alpha1.PullRequestGenerator, *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error) {
return pullrequest.NewFakeService(
ctx,
[]*pullrequest.PullRequest{
&pullrequest.PullRequest{
Number: 1,
Branch: "a-very-short-sha",
HeadSHA: "abcd",
},
},
nil,
)
},
expected: []map[string]interface{}{
{
"number": "1",
"branch": "a-very-short-sha",
"branch_slug": "a-very-short-sha",
"head_sha": "abcd",
"head_short_sha": "abcd",
"number": "1",
"branch": "branch1",
"head_sha": "089d92cbf9ff857a39e6feccd32798ca700fb958",
},
},
expectedErr: nil,
@@ -116,7 +64,6 @@ func TestPullRequestGithubGenerateParams(t *testing.T) {
generatorConfig := argoprojiov1alpha1.ApplicationSetGenerator{
PullRequest: &argoprojiov1alpha1.PullRequestGenerator{},
}
got, gotErr := gen.GenerateParams(&generatorConfig, nil)
assert.Equal(t, c.expectedErr, gotErr)
assert.ElementsMatch(t, c.expected, got)

View File

@@ -9,10 +9,8 @@ import (
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/argoproj/argo-cd/v2/applicationset/services/github_app_auth"
"github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
var _ Generator = (*SCMProviderGenerator)(nil)
@@ -25,23 +23,10 @@ type SCMProviderGenerator struct {
client client.Client
// Testing hooks.
overrideProvider scm_provider.SCMProviderService
SCMAuthProviders
}
type SCMAuthProviders struct {
GitHubApps github_app_auth.Credentials
}
func NewSCMProviderGenerator(client client.Client, providers SCMAuthProviders) Generator {
return &SCMProviderGenerator{
client: client,
SCMAuthProviders: providers,
}
}
// Testing generator
func NewTestSCMProviderGenerator(overrideProvider scm_provider.SCMProviderService) Generator {
return &SCMProviderGenerator{overrideProvider: overrideProvider}
func NewSCMProviderGenerator(client client.Client) Generator {
return &SCMProviderGenerator{client: client}
}
func (g *SCMProviderGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration {
@@ -58,7 +43,7 @@ func (g *SCMProviderGenerator) GetTemplate(appSetGenerator *argoprojiov1alpha1.A
return &appSetGenerator.SCMProvider.Template
}
func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) ([]map[string]string, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
}
@@ -75,10 +60,13 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
if g.overrideProvider != nil {
provider = g.overrideProvider
} else if providerConfig.Github != nil {
var err error
provider, err = g.githubProvider(ctx, providerConfig.Github, applicationSetInfo)
token, err := g.getSecretRef(ctx, providerConfig.Github.TokenRef, applicationSetInfo.Namespace)
if err != nil {
return nil, fmt.Errorf("scm provider: %w", err)
return nil, fmt.Errorf("error fetching Github token: %v", err)
}
provider, err = scm_provider.NewGithubProvider(ctx, providerConfig.Github.Organization, token, providerConfig.Github.API, providerConfig.Github.AllBranches)
if err != nil {
return nil, fmt.Errorf("error initializing Github service: %v", err)
}
} else if providerConfig.Gitlab != nil {
token, err := g.getSecretRef(ctx, providerConfig.Gitlab.TokenRef, applicationSetInfo.Namespace)
@@ -113,15 +101,6 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
if scmError != nil {
return nil, fmt.Errorf("error initializing Bitbucket Server service: %v", scmError)
}
} else if providerConfig.AzureDevOps != nil {
token, err := g.getSecretRef(ctx, providerConfig.AzureDevOps.AccessTokenRef, applicationSetInfo.Namespace)
if err != nil {
return nil, fmt.Errorf("error fetching Azure Devops access token: %v", err)
}
provider, err = scm_provider.NewAzureDevOpsProvider(ctx, token, providerConfig.AzureDevOps.Organization, providerConfig.AzureDevOps.API, providerConfig.AzureDevOps.TeamProject, providerConfig.AzureDevOps.AllBranches)
if err != nil {
return nil, fmt.Errorf("error initializing Azure Devops service: %v", err)
}
} else if providerConfig.Bitbucket != nil {
appPassword, err := g.getSecretRef(ctx, providerConfig.Bitbucket.AppPasswordRef, applicationSetInfo.Namespace)
if err != nil {
@@ -140,23 +119,15 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
if err != nil {
return nil, fmt.Errorf("error listing repos: %v", err)
}
params := make([]map[string]interface{}, 0, len(repos))
var shortSHALength int
params := make([]map[string]string, 0, len(repos))
for _, repo := range repos {
shortSHALength = 8
if len(repo.SHA) < 8 {
shortSHALength = len(repo.SHA)
}
params = append(params, map[string]interface{}{
"organization": repo.Organization,
"repository": repo.Repository,
"url": repo.URL,
"branch": repo.Branch,
"sha": repo.SHA,
"short_sha": repo.SHA[:shortSHALength],
"labels": strings.Join(repo.Labels, ","),
"branchNormalized": utils.SanitizeName(repo.Branch),
params = append(params, map[string]string{
"organization": repo.Organization,
"repository": repo.Repository,
"url": repo.URL,
"branch": repo.Branch,
"sha": repo.SHA,
"labels": strings.Join(repo.Labels, ","),
})
}
return params, nil
@@ -184,25 +155,3 @@ func (g *SCMProviderGenerator) getSecretRef(ctx context.Context, ref *argoprojio
}
return string(tokenBytes), nil
}
func (g *SCMProviderGenerator) githubProvider(ctx context.Context, github *argoprojiov1alpha1.SCMProviderGeneratorGithub, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) (scm_provider.SCMProviderService, error) {
if github.AppSecretName != "" {
auth, err := g.GitHubApps.GetAuthSecret(ctx, github.AppSecretName)
if err != nil {
return nil, fmt.Errorf("error fetching Github app secret: %v", err)
}
return scm_provider.NewGithubAppProviderFor(
*auth,
github.Organization,
github.API,
github.AllBranches,
)
}
token, err := g.getSecretRef(ctx, github.TokenRef, applicationSetInfo.Namespace)
if err != nil {
return nil, fmt.Errorf("error fetching Github token: %v", err)
}
return scm_provider.NewGithubProvider(ctx, github.Organization, token, github.API, github.AllBranches)
}

View File

@@ -10,7 +10,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func TestSCMProviderGetSecretRef(t *testing.T) {
@@ -87,7 +87,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
Repository: "repo1",
URL: "git@github.com:myorg/repo1.git",
Branch: "main",
SHA: "0bc57212c3cbbec69d20b34c507284bd300def5b",
SHA: "abcd1234",
Labels: []string{"prod", "staging"},
},
{
@@ -95,7 +95,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
Repository: "repo2",
URL: "git@github.com:myorg/repo2.git",
Branch: "main",
SHA: "59d0",
SHA: "00000000",
},
},
}
@@ -109,9 +109,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
assert.Equal(t, "repo1", params[0]["repository"])
assert.Equal(t, "git@github.com:myorg/repo1.git", params[0]["url"])
assert.Equal(t, "main", params[0]["branch"])
assert.Equal(t, "0bc57212c3cbbec69d20b34c507284bd300def5b", params[0]["sha"])
assert.Equal(t, "0bc57212", params[0]["short_sha"])
assert.Equal(t, "59d0", params[1]["short_sha"])
assert.Equal(t, "abcd1234", params[0]["sha"])
assert.Equal(t, "prod,staging", params[0]["labels"])
assert.Equal(t, "repo2", params[1]["repository"])
}

View File

@@ -1,19 +0,0 @@
package github_app_auth
import "context"
// Authentication has the authentication information required to access the GitHub API and repositories.
type Authentication struct {
// Id specifies the ID of the GitHub app used to access the repo
Id int64
// InstallationId specifies the installation ID of the GitHub App used to access the repo
InstallationId int64
// EnterpriseBaseURL specifies the base URL of GitHub Enterprise installation. If empty will default to https://api.github.com
EnterpriseBaseURL string
// PrivateKey in PEM format.
PrivateKey string
}
type Credentials interface {
GetAuthSecret(ctx context.Context, secretName string) (*Authentication, error)
}

View File

@@ -1,33 +0,0 @@
package github_app
import (
"fmt"
"net/http"
"github.com/bradleyfalzon/ghinstallation/v2"
"github.com/google/go-github/v35/github"
"github.com/argoproj/argo-cd/v2/applicationset/services/github_app_auth"
)
// Client builds a github client for the given app authentication.
func Client(g github_app_auth.Authentication, url string) (*github.Client, error) {
rt, err := ghinstallation.New(http.DefaultTransport, g.Id, g.InstallationId, []byte(g.PrivateKey))
if err != nil {
return nil, fmt.Errorf("failed to create github app install: %w", err)
}
if url == "" {
url = g.EnterpriseBaseURL
}
var client *github.Client
httpClient := http.Client{Transport: rt}
if url == "" {
client = github.NewClient(&httpClient)
} else {
client, err = github.NewEnterpriseClient(url, url, &httpClient)
if err != nil {
return nil, fmt.Errorf("failed to create github enterprise client: %w", err)
}
}
return client, nil
}

View File

@@ -7,7 +7,7 @@ import (
"net/http/httptest"
"testing"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
"github.com/stretchr/testify/assert"
)

View File

@@ -1,89 +0,0 @@
[
{
"id": 35385049,
"iid": 15442,
"project_id": 278964,
"title": "Draft: Use structured logging for DB load balancer",
"description": "",
"state": "opened",
"created_at": "2019-08-20T10:58:54.413Z",
"updated_at": "2019-08-20T12:01:49.849Z",
"merged_by": null,
"merged_at": null,
"closed_by": null,
"closed_at": null,
"target_branch": "master",
"source_branch": "use-structured-logging-for-db-load-balancer",
"user_notes_count": 1,
"upvotes": 0,
"downvotes": 0,
"assignee": {
"id": 4088036,
"name": "Hordur Freyr Yngvason",
"username": "hfyngvason",
"state": "active",
"avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/4088036/avatar.png",
"web_url": "https://gitlab.com/hfyngvason"
},
"author": {
"id": 4088036,
"name": "Hordur Freyr Yngvason",
"username": "hfyngvason",
"state": "active",
"avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/4088036/avatar.png",
"web_url": "https://gitlab.com/hfyngvason"
},
"assignees": [
{
"id": 4088036,
"name": "Hordur Freyr Yngvason",
"username": "hfyngvason",
"state": "active",
"avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/4088036/avatar.png",
"web_url": "https://gitlab.com/hfyngvason"
}
],
"reviewers": [
{
"id": 2535118,
"name": "Thong Kuah",
"username": "tkuah",
"state": "active",
"avatar_url": "https://secure.gravatar.com/avatar/f7b51bdd49a4914d29504d7ff4c3f7b9?s=80&d=identicon",
"web_url": "https://gitlab.com/tkuah"
}
],
"source_project_id": 278964,
"target_project_id": 278964,
"labels": [
"backend",
"backstage",
"database",
"database::review pending",
"group::autodevops and kubernetes"
],
"work_in_progress": true,
"milestone": null,
"merge_when_pipeline_succeeds": false,
"merge_status": "can_be_merged",
"sha": "2fc4e8b972ff3208ec63b6143e34ad67ff343ad7",
"merge_commit_sha": null,
"discussion_locked": null,
"should_remove_source_branch": null,
"force_remove_source_branch": true,
"reference": "!15442",
"web_url": "https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/15442",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
},
"squash": true,
"task_completion_status": {
"count": 12,
"completed_count": 0
},
"approvals_before_merge": 1
}
]

View File

@@ -58,7 +58,7 @@ func (g *GithubService) List(ctx context.Context) ([]*PullRequest, error) {
for {
pulls, resp, err := g.client.PullRequests.List(ctx, g.owner, g.repo, opts)
if err != nil {
return nil, fmt.Errorf("error listing pull requests for %s/%s: %w", g.owner, g.repo, err)
return nil, fmt.Errorf("error listing pull requests for %s/%s: %v", g.owner, g.repo, err)
}
for _, pull := range pulls {
if !containLabels(g.labels, pull.Labels) {

View File

@@ -1,19 +0,0 @@
package pull_request
import (
"github.com/argoproj/argo-cd/v2/applicationset/services/github_app_auth"
"github.com/argoproj/argo-cd/v2/applicationset/services/internal/github_app"
)
func NewGithubAppService(g github_app_auth.Authentication, url, owner, repo string, labels []string) (PullRequestService, error) {
client, err := github_app.Client(g, url)
if err != nil {
return nil, err
}
return &GithubService{
client: client,
owner: owner,
repo: repo,
labels: labels,
}, nil
}

View File

@@ -1,83 +0,0 @@
package pull_request
import (
"context"
"fmt"
"os"
gitlab "github.com/xanzy/go-gitlab"
)
type GitLabService struct {
client *gitlab.Client
project string
labels []string
pullRequestState string
}
var _ PullRequestService = (*GitLabService)(nil)
func NewGitLabService(ctx context.Context, token, url, project string, labels []string, pullRequestState string) (PullRequestService, error) {
var clientOptionFns []gitlab.ClientOptionFunc
// Set a custom Gitlab base URL if one is provided
if url != "" {
clientOptionFns = append(clientOptionFns, gitlab.WithBaseURL(url))
}
if token == "" {
token = os.Getenv("GITLAB_TOKEN")
}
client, err := gitlab.NewClient(token, clientOptionFns...)
if err != nil {
return nil, fmt.Errorf("error creating Gitlab client: %v", err)
}
return &GitLabService{
client: client,
project: project,
labels: labels,
pullRequestState: pullRequestState,
}, nil
}
func (g *GitLabService) List(ctx context.Context) ([]*PullRequest, error) {
// Filter the merge requests on labels, if they are specified.
var labels *gitlab.Labels
if len(g.labels) > 0 {
labels = (*gitlab.Labels)(&g.labels)
}
opts := &gitlab.ListProjectMergeRequestsOptions{
ListOptions: gitlab.ListOptions{
PerPage: 100,
},
Labels: labels,
}
if g.pullRequestState != "" {
opts.State = &g.pullRequestState
}
pullRequests := []*PullRequest{}
for {
mrs, resp, err := g.client.MergeRequests.ListProjectMergeRequests(g.project, opts)
if err != nil {
return nil, fmt.Errorf("error listing merge requests for project '%s': %v", g.project, err)
}
for _, mr := range mrs {
pullRequests = append(pullRequests, &PullRequest{
Number: mr.IID,
Branch: mr.SourceBranch,
HeadSHA: mr.SHA,
})
}
if resp.NextPage == 0 {
break
}
opts.Page = resp.NextPage
}
return pullRequests, nil
}

View File

@@ -1,122 +0,0 @@
package pull_request
import (
"context"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func writeMRListResponse(t *testing.T, w io.Writer) {
f, err := os.Open("fixtures/gitlab_mr_list_response.json")
if err != nil {
t.Fatalf("error opening fixture file: %v", err)
}
if _, err = io.Copy(w, f); err != nil {
t.Fatalf("error writing response: %v", err)
}
}
func TestGitLabServiceCustomBaseURL(t *testing.T) {
mux := http.NewServeMux()
server := httptest.NewServer(mux)
defer server.Close()
path := "/api/v4/projects/278964/merge_requests"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, path+"?per_page=100", r.URL.RequestURI())
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", nil, "")
assert.NoError(t, err)
_, err = svc.List(context.Background())
assert.NoError(t, err)
}
func TestGitLabServiceToken(t *testing.T) {
mux := http.NewServeMux()
server := httptest.NewServer(mux)
defer server.Close()
path := "/api/v4/projects/278964/merge_requests"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "token-123", r.Header.Get("Private-Token"))
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "token-123", server.URL, "278964", nil, "")
assert.NoError(t, err)
_, err = svc.List(context.Background())
assert.NoError(t, err)
}
func TestList(t *testing.T) {
mux := http.NewServeMux()
server := httptest.NewServer(mux)
defer server.Close()
path := "/api/v4/projects/278964/merge_requests"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, path+"?per_page=100", r.URL.RequestURI())
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "")
assert.NoError(t, err)
prs, err := svc.List(context.Background())
assert.NoError(t, err)
assert.Len(t, prs, 1)
assert.Equal(t, prs[0].Number, 15442)
assert.Equal(t, prs[0].Branch, "use-structured-logging-for-db-load-balancer")
assert.Equal(t, prs[0].HeadSHA, "2fc4e8b972ff3208ec63b6143e34ad67ff343ad7")
}
func TestListWithLabels(t *testing.T) {
mux := http.NewServeMux()
server := httptest.NewServer(mux)
defer server.Close()
path := "/api/v4/projects/278964/merge_requests"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, path+"?labels=feature%2Cready&per_page=100", r.URL.RequestURI())
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{"feature", "ready"}, "")
assert.NoError(t, err)
_, err = svc.List(context.Background())
assert.NoError(t, err)
}
func TestListWithState(t *testing.T) {
mux := http.NewServeMux()
server := httptest.NewServer(mux)
defer server.Close()
path := "/api/v4/projects/278964/merge_requests"
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, path+"?per_page=100&state=opened", r.URL.RequestURI())
writeMRListResponse(t, w)
})
svc, err := NewGitLabService(context.Background(), "", server.URL, "278964", []string{}, "opened")
assert.NoError(t, err)
_, err = svc.List(context.Background())
assert.NoError(t, err)
}

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"regexp"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func compileFilters(filters []argoprojiov1alpha1.PullRequestGeneratorFilter) ([]*Filter, error) {

View File

@@ -4,7 +4,7 @@ import (
"context"
"testing"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
"github.com/stretchr/testify/assert"
)

View File

@@ -163,7 +163,7 @@ func TestGetFiles(t *testing.T) {
revision: "this-tag-does-not-exist",
pattern: "*",
expectSubsetOfPaths: []string{},
expectedError: fmt.Errorf("Error during fetching repo: `git fetch origin this-tag-does-not-exist --tags --force --prune` failed exit status 128: fatal: couldn't find remote ref this-tag-does-not-exist"),
expectedError: fmt.Errorf("Error during fetching repo: `git fetch origin this-tag-does-not-exist --tags --force` failed exit status 128: fatal: couldn't find remote ref this-tag-does-not-exist"),
},
{
name: "pull a specific revision of example apps, and use a ** pattern",

View File

@@ -1,219 +0,0 @@
package scm_provider
import (
"context"
"fmt"
netUrl "net/url"
"strings"
"github.com/google/uuid"
"github.com/microsoft/azure-devops-go-api/azuredevops"
azureGit "github.com/microsoft/azure-devops-go-api/azuredevops/git"
)
const AZURE_DEVOPS_DEFAULT_URL = "https://dev.azure.com"
type azureDevOpsErrorTypeKeyValuesType struct {
GitRepositoryNotFound string
GitItemNotFound string
}
var AzureDevOpsErrorsTypeKeyValues = azureDevOpsErrorTypeKeyValuesType{
GitRepositoryNotFound: "GitRepositoryNotFoundException",
GitItemNotFound: "GitItemNotFoundException",
}
type AzureDevOpsClientFactory interface {
// Returns an Azure Devops Client interface.
GetClient(ctx context.Context) (azureGit.Client, error)
}
type devopsFactoryImpl struct {
connection *azuredevops.Connection
}
func (factory *devopsFactoryImpl) GetClient(ctx context.Context) (azureGit.Client, error) {
gitClient, err := azureGit.NewClient(ctx, factory.connection)
if err != nil {
return nil, fmt.Errorf("failed to get new Azure DevOps git client for SCM generator: %w", err)
}
return gitClient, nil
}
// Contains Azure Devops REST API implementation of SCMProviderService.
// See https://docs.microsoft.com/en-us/rest/api/azure/devops
type AzureDevOpsProvider struct {
organization string
teamProject string
accessToken string
clientFactory AzureDevOpsClientFactory
allBranches bool
}
var _ SCMProviderService = &AzureDevOpsProvider{}
var _ AzureDevOpsClientFactory = &devopsFactoryImpl{}
func NewAzureDevOpsProvider(ctx context.Context, accessToken string, org string, url string, project string, allBranches bool) (*AzureDevOpsProvider, error) {
if accessToken == "" {
return nil, fmt.Errorf("no access token provided")
}
devOpsURL, err := getValidDevOpsURL(url, org)
if err != nil {
return nil, err
}
connection := azuredevops.NewPatConnection(devOpsURL, accessToken)
return &AzureDevOpsProvider{organization: org, teamProject: project, accessToken: accessToken, clientFactory: &devopsFactoryImpl{connection: connection}, allBranches: allBranches}, nil
}
func (g *AzureDevOpsProvider) ListRepos(ctx context.Context, cloneProtocol string) ([]*Repository, error) {
gitClient, err := g.clientFactory.GetClient(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get Azure DevOps client: %w", err)
}
getRepoArgs := azureGit.GetRepositoriesArgs{Project: &g.teamProject}
azureRepos, err := gitClient.GetRepositories(ctx, getRepoArgs)
if err != nil {
return nil, err
}
repos := []*Repository{}
for _, azureRepo := range *azureRepos {
if azureRepo.Name == nil || azureRepo.DefaultBranch == nil || azureRepo.RemoteUrl == nil || azureRepo.Id == nil {
continue
}
repos = append(repos, &Repository{
Organization: g.organization,
Repository: *azureRepo.Name,
URL: *azureRepo.RemoteUrl,
Branch: *azureRepo.DefaultBranch,
Labels: []string{},
RepositoryId: *azureRepo.Id,
})
}
return repos, nil
}
func (g *AzureDevOpsProvider) RepoHasPath(ctx context.Context, repo *Repository, path string) (bool, error) {
gitClient, err := g.clientFactory.GetClient(ctx)
if err != nil {
return false, fmt.Errorf("failed to get Azure DevOps client: %w", err)
}
var repoId string
if uuid, isUuid := repo.RepositoryId.(uuid.UUID); isUuid { //most likely an UUID, but do type-safe check anyway. Do %v fallback if not expected type.
repoId = uuid.String()
} else {
repoId = fmt.Sprintf("%v", repo.RepositoryId)
}
branchName := repo.Branch
getItemArgs := azureGit.GetItemArgs{RepositoryId: &repoId, Project: &g.teamProject, Path: &path, VersionDescriptor: &azureGit.GitVersionDescriptor{Version: &branchName}}
_, err = gitClient.GetItem(ctx, getItemArgs)
if err != nil {
if wrappedError, isWrappedError := err.(azuredevops.WrappedError); isWrappedError && wrappedError.TypeKey != nil {
if *wrappedError.TypeKey == AzureDevOpsErrorsTypeKeyValues.GitItemNotFound {
return false, nil
}
}
return false, fmt.Errorf("failed to check for path existence in Azure DevOps: %w", err)
}
return true, nil
}
func (g *AzureDevOpsProvider) GetBranches(ctx context.Context, repo *Repository) ([]*Repository, error) {
gitClient, err := g.clientFactory.GetClient(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get Azure DevOps client: %w", err)
}
repos := []*Repository{}
if !g.allBranches {
defaultBranchName := strings.Replace(repo.Branch, "refs/heads/", "", 1) //Azure DevOps returns default branch info like 'refs/heads/main', but does not support branch lookup of this format.
getBranchArgs := azureGit.GetBranchArgs{RepositoryId: &repo.Repository, Project: &g.teamProject, Name: &defaultBranchName}
branchResult, err := gitClient.GetBranch(ctx, getBranchArgs)
if err != nil {
if wrappedError, isWrappedError := err.(azuredevops.WrappedError); isWrappedError && wrappedError.TypeKey != nil {
if *wrappedError.TypeKey == AzureDevOpsErrorsTypeKeyValues.GitRepositoryNotFound {
return repos, nil
}
}
return nil, fmt.Errorf("could not get default branch %v (%v) from repository %v: %w", defaultBranchName, repo.Branch, repo.Repository, err)
}
if branchResult.Name == nil || branchResult.Commit == nil {
return nil, fmt.Errorf("invalid branch result after requesting branch %v from repository %v", repo.Branch, repo.Repository)
}
repos = append(repos, &Repository{
Branch: *branchResult.Name,
SHA: *branchResult.Commit.CommitId,
Organization: repo.Organization,
Repository: repo.Repository,
URL: repo.URL,
Labels: []string{},
RepositoryId: repo.RepositoryId,
})
return repos, nil
}
getBranchesRequest := azureGit.GetBranchesArgs{RepositoryId: &repo.Repository, Project: &g.teamProject}
branches, err := gitClient.GetBranches(ctx, getBranchesRequest)
if err != nil {
if wrappedError, isWrappedError := err.(azuredevops.WrappedError); isWrappedError && wrappedError.TypeKey != nil {
if *wrappedError.TypeKey == AzureDevOpsErrorsTypeKeyValues.GitRepositoryNotFound {
return repos, nil
}
}
return nil, fmt.Errorf("failed getting branches from repository %v, project %v: %w", repo.Repository, g.teamProject, err)
}
if branches == nil {
return nil, fmt.Errorf("got empty branch result from repository %v, project %v: %w", repo.Repository, g.teamProject, err)
}
for _, azureBranch := range *branches {
repos = append(repos, &Repository{
Branch: *azureBranch.Name,
SHA: *azureBranch.Commit.CommitId,
Organization: repo.Organization,
Repository: repo.Repository,
URL: repo.URL,
Labels: []string{},
RepositoryId: repo.RepositoryId,
})
}
return repos, nil
}
func getValidDevOpsURL(url string, org string) (string, error) {
if url == "" {
url = AZURE_DEVOPS_DEFAULT_URL
}
separator := ""
if !strings.HasSuffix(url, "/") {
separator = "/"
}
devOpsURL := fmt.Sprintf("%s%s%s", url, separator, org)
urlCheck, err := netUrl.ParseRequestURI(devOpsURL)
if err != nil {
return "", fmt.Errorf("got an invalid URL for the Azure SCM generator: %w", err)
}
ret := urlCheck.String()
return ret, nil
}

View File

@@ -1,530 +0,0 @@
package scm_provider
import (
"context"
"fmt"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"k8s.io/utils/pointer"
azureMock "github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider/azure_devops/git/mocks"
"github.com/microsoft/azure-devops-go-api/azuredevops"
azureGit "github.com/microsoft/azure-devops-go-api/azuredevops/git"
)
func s(input string) *string {
return pointer.String(input)
}
func TestAzureDevopsRepoHasPath(t *testing.T) {
organization := "myorg"
teamProject := "myorg_project"
repoName := "myorg_project_repo"
path := "dir/subdir/item.yaml"
branchName := "my/featurebranch"
ctx := context.Background()
uuid := uuid.New().String()
testCases := []struct {
name string
pathFound bool
azureDevopsError error
returnError bool
errorMessage string
clientError error
}{
{
name: "RepoHasPath when Azure DevOps client factory fails returns error",
clientError: fmt.Errorf("Client factory error"),
},
{
name: "RepoHasPath when found returns true",
pathFound: true,
},
{
name: "RepoHasPath when no path found returns false",
pathFound: false,
azureDevopsError: azuredevops.WrappedError{TypeKey: s(AzureDevOpsErrorsTypeKeyValues.GitItemNotFound)},
},
{
name: "RepoHasPath when unknown Azure DevOps WrappedError occurs returns error",
pathFound: false,
azureDevopsError: azuredevops.WrappedError{TypeKey: s("OtherAzureDevopsException")},
returnError: true,
errorMessage: "failed to check for path existence",
},
{
name: "RepoHasPath when unknown Azure DevOps error occurs returns error",
pathFound: false,
azureDevopsError: fmt.Errorf("Undefined error from Azure Devops"),
returnError: true,
errorMessage: "failed to check for path existence",
},
{
name: "RepoHasPath when wrapped Azure DevOps error occurs without TypeKey returns error",
pathFound: false,
azureDevopsError: azuredevops.WrappedError{},
returnError: true,
errorMessage: "failed to check for path existence",
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
gitClientMock := azureMock.Client{}
clientFactoryMock := &AzureClientFactoryMock{mock: &mock.Mock{}}
clientFactoryMock.mock.On("GetClient", mock.Anything).Return(&gitClientMock, testCase.clientError)
repoId := &uuid
gitClientMock.On("GetItem", ctx, azureGit.GetItemArgs{Project: &teamProject, Path: &path, VersionDescriptor: &azureGit.GitVersionDescriptor{Version: &branchName}, RepositoryId: repoId}).Return(nil, testCase.azureDevopsError)
provider := AzureDevOpsProvider{organization: organization, teamProject: teamProject, clientFactory: clientFactoryMock}
repo := &Repository{Organization: organization, Repository: repoName, RepositoryId: uuid, Branch: branchName}
hasPath, err := provider.RepoHasPath(ctx, repo, path)
if testCase.clientError != nil {
assert.ErrorContains(t, err, testCase.clientError.Error())
gitClientMock.AssertNotCalled(t, "GetItem", ctx, azureGit.GetItemArgs{Project: &teamProject, Path: &path, VersionDescriptor: &azureGit.GitVersionDescriptor{Version: &branchName}, RepositoryId: repoId})
return
}
if testCase.returnError {
assert.ErrorContains(t, err, testCase.errorMessage)
}
assert.Equal(t, testCase.pathFound, hasPath)
gitClientMock.AssertCalled(t, "GetItem", ctx, azureGit.GetItemArgs{Project: &teamProject, Path: &path, VersionDescriptor: &azureGit.GitVersionDescriptor{Version: &branchName}, RepositoryId: repoId})
})
}
}
func TestGetDefaultBranchOnDisabledRepo(t *testing.T) {
organization := "myorg"
teamProject := "myorg_project"
repoName := "myorg_project_repo"
defaultBranch := "main"
ctx := context.Background()
testCases := []struct {
name string
azureDevOpsError error
shouldReturnError bool
}{
{
name: "azure devops error when disabled repo causes empty return value",
azureDevOpsError: azuredevops.WrappedError{TypeKey: s(AzureDevOpsErrorsTypeKeyValues.GitRepositoryNotFound)},
shouldReturnError: false,
},
{
name: "azure devops error with unknown error type returns error",
azureDevOpsError: azuredevops.WrappedError{TypeKey: s("OtherError")},
shouldReturnError: true,
},
{
name: "other error when calling azure devops returns error",
azureDevOpsError: fmt.Errorf("some unknown error"),
shouldReturnError: true,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
uuid := uuid.New().String()
gitClientMock := azureMock.Client{}
clientFactoryMock := &AzureClientFactoryMock{mock: &mock.Mock{}}
clientFactoryMock.mock.On("GetClient", mock.Anything).Return(&gitClientMock, nil)
gitClientMock.On("GetBranch", ctx, azureGit.GetBranchArgs{RepositoryId: &repoName, Project: &teamProject, Name: &defaultBranch}).Return(nil, testCase.azureDevOpsError)
repo := &Repository{Organization: organization, Repository: repoName, RepositoryId: uuid, Branch: defaultBranch}
provider := AzureDevOpsProvider{organization: organization, teamProject: teamProject, clientFactory: clientFactoryMock, allBranches: false}
branches, err := provider.GetBranches(ctx, repo)
if testCase.shouldReturnError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
assert.Empty(t, branches)
gitClientMock.AssertExpectations(t)
})
}
}
func TestGetAllBranchesOnDisabledRepo(t *testing.T) {
organization := "myorg"
teamProject := "myorg_project"
repoName := "myorg_project_repo"
defaultBranch := "main"
ctx := context.Background()
testCases := []struct {
name string
azureDevOpsError error
shouldReturnError bool
}{
{
name: "azure devops error when disabled repo causes empty return value",
azureDevOpsError: azuredevops.WrappedError{TypeKey: s(AzureDevOpsErrorsTypeKeyValues.GitRepositoryNotFound)},
shouldReturnError: false,
},
{
name: "azure devops error with unknown error type returns error",
azureDevOpsError: azuredevops.WrappedError{TypeKey: s("OtherError")},
shouldReturnError: true,
},
{
name: "other error when calling azure devops returns error",
azureDevOpsError: fmt.Errorf("some unknown error"),
shouldReturnError: true,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
uuid := uuid.New().String()
gitClientMock := azureMock.Client{}
clientFactoryMock := &AzureClientFactoryMock{mock: &mock.Mock{}}
clientFactoryMock.mock.On("GetClient", mock.Anything).Return(&gitClientMock, nil)
gitClientMock.On("GetBranches", ctx, azureGit.GetBranchesArgs{RepositoryId: &repoName, Project: &teamProject}).Return(nil, testCase.azureDevOpsError)
repo := &Repository{Organization: organization, Repository: repoName, RepositoryId: uuid, Branch: defaultBranch}
provider := AzureDevOpsProvider{organization: organization, teamProject: teamProject, clientFactory: clientFactoryMock, allBranches: true}
branches, err := provider.GetBranches(ctx, repo)
if testCase.shouldReturnError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
assert.Empty(t, branches)
gitClientMock.AssertExpectations(t)
})
}
}
func TestAzureDevOpsGetDefaultBranchStripsRefsName(t *testing.T) {
t.Run("Get branches only default branch removes characters before querying azure devops", func(t *testing.T) {
organization := "myorg"
teamProject := "myorg_project"
repoName := "myorg_project_repo"
ctx := context.Background()
uuid := uuid.New().String()
strippedBranchName := "somebranch"
defaultBranch := fmt.Sprintf("refs/heads/%v", strippedBranchName)
branchReturn := &azureGit.GitBranchStats{Name: &strippedBranchName, Commit: &azureGit.GitCommitRef{CommitId: s("abc123233223")}}
repo := &Repository{Organization: organization, Repository: repoName, RepositoryId: uuid, Branch: defaultBranch}
gitClientMock := azureMock.Client{}
clientFactoryMock := &AzureClientFactoryMock{mock: &mock.Mock{}}
clientFactoryMock.mock.On("GetClient", mock.Anything).Return(&gitClientMock, nil)
gitClientMock.On("GetBranch", ctx, azureGit.GetBranchArgs{RepositoryId: &repoName, Project: &teamProject, Name: &strippedBranchName}).Return(branchReturn, nil)
provider := AzureDevOpsProvider{organization: organization, teamProject: teamProject, clientFactory: clientFactoryMock, allBranches: false}
branches, err := provider.GetBranches(ctx, repo)
assert.NoError(t, err)
assert.Len(t, branches, 1)
assert.Equal(t, strippedBranchName, branches[0].Branch)
gitClientMock.AssertCalled(t, "GetBranch", ctx, azureGit.GetBranchArgs{RepositoryId: &repoName, Project: &teamProject, Name: &strippedBranchName})
})
}
func TestAzureDevOpsGetBranchesDefultBranchOnly(t *testing.T) {
organization := "myorg"
teamProject := "myorg_project"
repoName := "myorg_project_repo"
ctx := context.Background()
uuid := uuid.New().String()
defaultBranch := "main"
testCases := []struct {
name string
expectedBranch *azureGit.GitBranchStats
getBranchesApiError error
clientError error
}{
{
name: "GetBranches AllBranches false when single branch returned returns branch",
expectedBranch: &azureGit.GitBranchStats{Name: &defaultBranch, Commit: &azureGit.GitCommitRef{CommitId: s("abc123233223")}},
},
{
name: "GetBranches AllBranches false when request fails returns error and empty result",
getBranchesApiError: fmt.Errorf("Remote Azure Devops GetBranches error"),
},
{
name: "GetBranches AllBranches false when Azure DevOps client fails returns error",
clientError: fmt.Errorf("Could not get Azure Devops API client"),
},
{
name: "GetBranches AllBranches false when branch returned with long commit SHA",
expectedBranch: &azureGit.GitBranchStats{Name: &defaultBranch, Commit: &azureGit.GitCommitRef{CommitId: s("53863052ADF24229AB72154B4D83DAB7")}},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
gitClientMock := azureMock.Client{}
clientFactoryMock := &AzureClientFactoryMock{mock: &mock.Mock{}}
clientFactoryMock.mock.On("GetClient", mock.Anything).Return(&gitClientMock, testCase.clientError)
gitClientMock.On("GetBranch", ctx, azureGit.GetBranchArgs{RepositoryId: &repoName, Project: &teamProject, Name: &defaultBranch}).Return(testCase.expectedBranch, testCase.getBranchesApiError)
repo := &Repository{Organization: organization, Repository: repoName, RepositoryId: uuid, Branch: defaultBranch}
provider := AzureDevOpsProvider{organization: organization, teamProject: teamProject, clientFactory: clientFactoryMock, allBranches: false}
branches, err := provider.GetBranches(ctx, repo)
if testCase.clientError != nil {
assert.ErrorContains(t, err, testCase.clientError.Error())
gitClientMock.AssertNotCalled(t, "GetBranch", ctx, azureGit.GetBranchArgs{RepositoryId: &repoName, Project: &teamProject, Name: &defaultBranch})
return
}
if testCase.getBranchesApiError != nil {
assert.Empty(t, branches)
assert.ErrorContains(t, err, testCase.getBranchesApiError.Error())
} else {
if testCase.expectedBranch != nil {
assert.NotEmpty(t, branches)
}
assert.Len(t, branches, 1)
assert.Equal(t, repo.RepositoryId, branches[0].RepositoryId)
}
gitClientMock.AssertCalled(t, "GetBranch", ctx, azureGit.GetBranchArgs{RepositoryId: &repoName, Project: &teamProject, Name: &defaultBranch})
})
}
}
func TestAzureDevopsGetBranches(t *testing.T) {
organization := "myorg"
teamProject := "myorg_project"
repoName := "myorg_project_repo"
ctx := context.Background()
uuid := uuid.New().String()
testCases := []struct {
name string
expectedBranches *[]azureGit.GitBranchStats
getBranchesApiError error
clientError error
allBranches bool
expectedProcessingErrorMsg string
}{
{
name: "GetBranches when single branch returned returns this branch info",
expectedBranches: &[]azureGit.GitBranchStats{{Name: s("feature-feat1"), Commit: &azureGit.GitCommitRef{CommitId: s("abc123233223")}}},
allBranches: true,
},
{
name: "GetBranches when Azure DevOps request fails returns error and empty result",
getBranchesApiError: fmt.Errorf("Remote Azure Devops GetBranches error"),
allBranches: true,
},
{
name: "GetBranches when no branches returned returns error",
allBranches: true,
expectedProcessingErrorMsg: "empty branch result",
},
{
name: "GetBranches when git client retrievel fails returns error",
clientError: fmt.Errorf("Could not get Azure Devops API client"),
allBranches: true,
},
{
name: "GetBranches when multiple branches returned returns branch info for all branches",
expectedBranches: &[]azureGit.GitBranchStats{
{Name: s("feature-feat1"), Commit: &azureGit.GitCommitRef{CommitId: s("abc123233223")}},
{Name: s("feature/feat2"), Commit: &azureGit.GitCommitRef{CommitId: s("4334")}},
{Name: s("feature/feat2"), Commit: &azureGit.GitCommitRef{CommitId: s("53863052ADF24229AB72154B4D83DAB7")}},
},
allBranches: true,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
gitClientMock := azureMock.Client{}
clientFactoryMock := &AzureClientFactoryMock{mock: &mock.Mock{}}
clientFactoryMock.mock.On("GetClient", mock.Anything).Return(&gitClientMock, testCase.clientError)
gitClientMock.On("GetBranches", ctx, azureGit.GetBranchesArgs{RepositoryId: &repoName, Project: &teamProject}).Return(testCase.expectedBranches, testCase.getBranchesApiError)
repo := &Repository{Organization: organization, Repository: repoName, RepositoryId: uuid}
provider := AzureDevOpsProvider{organization: organization, teamProject: teamProject, clientFactory: clientFactoryMock, allBranches: testCase.allBranches}
branches, err := provider.GetBranches(ctx, repo)
if testCase.expectedProcessingErrorMsg != "" {
assert.ErrorContains(t, err, testCase.expectedProcessingErrorMsg)
assert.Nil(t, branches)
return
}
if testCase.clientError != nil {
assert.ErrorContains(t, err, testCase.clientError.Error())
gitClientMock.AssertNotCalled(t, "GetBranches", ctx, azureGit.GetBranchesArgs{RepositoryId: &repoName, Project: &teamProject})
return
}
if testCase.getBranchesApiError != nil {
assert.Empty(t, branches)
assert.ErrorContains(t, err, testCase.getBranchesApiError.Error())
} else {
if len(*testCase.expectedBranches) > 0 {
assert.NotEmpty(t, branches)
}
assert.Len(t, branches, len(*testCase.expectedBranches))
for _, branch := range branches {
assert.NotEmpty(t, branch.RepositoryId)
assert.Equal(t, repo.RepositoryId, branch.RepositoryId)
}
}
gitClientMock.AssertCalled(t, "GetBranches", ctx, azureGit.GetBranchesArgs{RepositoryId: &repoName, Project: &teamProject})
})
}
}
func TestGetAzureDevopsRepositories(t *testing.T) {
organization := "myorg"
teamProject := "myorg_project"
uuid := uuid.New()
ctx := context.Background()
repoId := &uuid
testCases := []struct {
name string
getRepositoriesError error
repositories []azureGit.GitRepository
expectedNumberOfRepos int
}{
{
name: "ListRepos when single repo found returns repo info",
repositories: []azureGit.GitRepository{{Name: s("repo1"), DefaultBranch: s("main"), RemoteUrl: s("https://remoteurl.u"), Id: repoId}},
expectedNumberOfRepos: 1,
},
{
name: "ListRepos when repo has no default branch returns empty list",
repositories: []azureGit.GitRepository{{Name: s("repo2"), RemoteUrl: s("https://remoteurl.u"), Id: repoId}},
},
{
name: "ListRepos when Azure DevOps request fails returns error",
getRepositoriesError: fmt.Errorf("Could not get repos"),
},
{
name: "ListRepos when repo has no name returns empty list",
repositories: []azureGit.GitRepository{{DefaultBranch: s("main"), RemoteUrl: s("https://remoteurl.u"), Id: repoId}},
},
{
name: "ListRepos when repo has no remote URL returns empty list",
repositories: []azureGit.GitRepository{{DefaultBranch: s("main"), Name: s("repo_name"), Id: repoId}},
},
{
name: "ListRepos when repo has no ID returns empty list",
repositories: []azureGit.GitRepository{{DefaultBranch: s("main"), Name: s("repo_name"), RemoteUrl: s("https://remoteurl.u")}},
},
{
name: "ListRepos when multiple repos returned returns list of eligible repos only",
repositories: []azureGit.GitRepository{
{Name: s("returned1"), DefaultBranch: s("main"), RemoteUrl: s("https://remoteurl.u"), Id: repoId},
{Name: s("missing_default_branch"), RemoteUrl: s("https://remoteurl.u"), Id: repoId},
{DefaultBranch: s("missing_name"), RemoteUrl: s("https://remoteurl.u"), Id: repoId},
{Name: s("missing_remote_url"), DefaultBranch: s("main"), Id: repoId},
{Name: s("missing_id"), DefaultBranch: s("main"), RemoteUrl: s("https://remoteurl.u")}},
expectedNumberOfRepos: 1,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
gitClientMock := azureMock.Client{}
gitClientMock.On("GetRepositories", ctx, azureGit.GetRepositoriesArgs{Project: s(teamProject)}).Return(&testCase.repositories, testCase.getRepositoriesError)
clientFactoryMock := &AzureClientFactoryMock{mock: &mock.Mock{}}
clientFactoryMock.mock.On("GetClient", mock.Anything).Return(&gitClientMock)
provider := AzureDevOpsProvider{organization: organization, teamProject: teamProject, clientFactory: clientFactoryMock}
repositories, err := provider.ListRepos(ctx, "https")
if testCase.getRepositoriesError != nil {
assert.Error(t, err, "Expected an error from test case %v", testCase.name)
}
if testCase.expectedNumberOfRepos == 0 {
assert.Empty(t, repositories)
} else {
assert.NotEmpty(t, repositories)
assert.Len(t, repositories, testCase.expectedNumberOfRepos)
}
gitClientMock.AssertExpectations(t)
})
}
}
type AzureClientFactoryMock struct {
mock *mock.Mock
}
func (m *AzureClientFactoryMock) GetClient(ctx context.Context) (azureGit.Client, error) {
args := m.mock.Called(ctx)
var client azureGit.Client
c := args.Get(0)
if c != nil {
client = c.(azureGit.Client)
}
var err error
if len(args) > 1 {
if e, ok := args.Get(1).(error); ok {
err = e
}
}
return client, err
}

View File

@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func TestBitbucketHasRepo(t *testing.T) {

View File

@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider/testdata"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func giteaMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {

View File

@@ -47,7 +47,7 @@ func (g *GithubProvider) GetBranches(ctx context.Context, repo *Repository) ([]*
repos := []*Repository{}
branches, err := g.listBranches(ctx, repo)
if err != nil {
return nil, fmt.Errorf("error listing branches for %s/%s: %w", repo.Organization, repo.Repository, err)
return nil, fmt.Errorf("error listing branches for %s/%s: %v", repo.Organization, repo.Repository, err)
}
for _, branch := range branches {
@@ -72,7 +72,7 @@ func (g *GithubProvider) ListRepos(ctx context.Context, cloneProtocol string) ([
for {
githubRepos, resp, err := g.client.Repositories.ListByOrg(ctx, g.organization, opt)
if err != nil {
return nil, fmt.Errorf("error listing repositories for %s: %w", g.organization, err)
return nil, fmt.Errorf("error listing repositories for %s: %v", g.organization, err)
}
for _, githubRepo := range githubRepos {
var url string

View File

@@ -1,14 +0,0 @@
package scm_provider
import (
"github.com/argoproj/argo-cd/v2/applicationset/services/github_app_auth"
"github.com/argoproj/argo-cd/v2/applicationset/services/internal/github_app"
)
func NewGithubAppProviderFor(g github_app_auth.Authentication, organization string, url string, allBranches bool) (*GithubProvider, error) {
client, err := github_app.Client(g, url)
if err != nil {
return nil, err
}
return &GithubProvider{client: client, organization: organization, allBranches: allBranches}, nil
}

View File

@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
)
func githubMockHandler(t *testing.T) func(http.ResponseWriter, *http.Request) {

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