Compare commits

...

47 Commits

Author SHA1 Message Date
Michael Crenshaw
1e71863944 feat(hydrator): add commit-server component
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Omer Azmon <omer_azmon@intuit.com>
Co-authored-by: daengdaengLee <gunho1020@gmail.com>
Co-authored-by: Juwon Hwang (Kevin) <juwon8891@gmail.com>
Co-authored-by: thisishwan2 <feel000617@gmail.com>
Co-authored-by: mirageoasis <kimhw0820@naver.com>
Co-authored-by: Robin Lieb <robin.j.lieb@gmail.com>
Co-authored-by: miiiinju1 <gms07073@ynu.ac.kr>
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>

one test file for both implementations

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

simplify

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

fix test for linux

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

fix git client mock

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

fix git client mock

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

address comments

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

unit tests

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

lint

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

fix image, fix health checks, fix merge issue

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

fix lint issues

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

remove code that doesn't work for GHE

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

changes from comments

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-12-14 12:47:26 -05:00
Michael Crenshaw
cc1f9f53f1 feat(hydrator): add sourceHydrator types
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Omer Azmon <omer_azmon@intuit.com>
Co-authored-by: daengdaengLee <gunho1020@gmail.com>
Co-authored-by: Juwon Hwang (Kevin) <juwon8891@gmail.com>
Co-authored-by: thisishwan2 <feel000617@gmail.com>
Co-authored-by: mirageoasis <kimhw0820@naver.com>
Co-authored-by: Robin Lieb <robin.j.lieb@gmail.com>
Co-authored-by: miiiinju1 <gms07073@ynu.ac.kr>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

fix(codegen): use kube_codegen.sh deepcopy and client gen correctly

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

deepcopy gen

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-12-14 12:46:40 -05:00
adriananeci
030a7be7e2 fix: Populate destination name when destination server is specified (#21063)
* Populate destination name when destination server is specified

Signed-off-by: Adrian Aneci <aneci@adobe.com>

* Lint nit

Signed-off-by: Adrian Aneci <aneci@adobe.com>

* Trigger CI

Signed-off-by: Adrian Aneci <aneci@adobe.com>

---------

Signed-off-by: Adrian Aneci <aneci@adobe.com>
2024-12-14 10:40:48 +05:30
Dan Garfield
8dbddb101a Update golang test image to use 1.23.4 multiarch (#21174)
Seems to be an issue with the current sha but this one is working.

Signed-off-by: Dan Garfield <dan@codefresh.io>
2024-12-13 15:10:52 -05:00
Michael Crenshaw
72c711e7f0 chore: simplify sync status comparison (#21140)
* chore: simplify sync status comparison

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

* add tests

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

* more tests, some docs

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

---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-12-13 17:52:21 +00:00
dependabot[bot]
be080a5319 chore(deps): bump actions/setup-go from 5.1.0 to 5.2.0 (#21123)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](41dfa10bad...3041bf56c9)

---
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-13 15:28:16 +05:30
dependabot[bot]
4b229c0484 chore(deps): bump go.opentelemetry.io/otel from 1.32.0 to 1.33.0 (#21166)
Bumps [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) from 1.32.0 to 1.33.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.32.0...v1.33.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel
  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>
2024-12-13 15:26:04 +05:30
dependabot[bot]
87c853e872 chore(deps): bump chromedriver from 131.0.2 to 131.0.3 in /ui-test (#21144)
Bumps [chromedriver](https://github.com/giggio/node-chromedriver) from 131.0.2 to 131.0.3.
- [Commits](https://github.com/giggio/node-chromedriver/compare/131.0.2...131.0.3)

---
updated-dependencies:
- dependency-name: chromedriver
  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>
2024-12-12 11:35:38 +05:30
dependabot[bot]
cc68f018fe chore(deps): bump golang.org/x/crypto from 0.30.0 to 0.31.0 (#21147)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.30.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.30.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  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>
2024-12-12 11:34:58 +05:30
Andrii Korotkov
d9be098d9c fix: Fix server side diff with fields removal (#20792) (#20842)
* fix: Fix server side diff with fields removal (#20792)

Fixes #20792

Use a new version of gitops engine with a fix.

This needs to be cherry-picked in v2.11-2.13.

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

* Use newer versions of gitops-engine and structured-merge-diff

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

---------

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
2024-12-11 21:08:30 +00:00
Minchao
6897c2e33f fix: incorrect expr for server stats in Grafana dashboard.json (#21098)
Signed-off-by: Minchao <minchao.220@gmail.com>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2024-12-11 15:50:17 +00:00
dependabot[bot]
6a3cdb6ea5 chore(deps): bump softprops/action-gh-release from 2.1.0 to 2.2.0 (#21124)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](01570a1f39...7b4da11513)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  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>
2024-12-11 16:07:55 +05:30
Michael Crenshaw
deb4d2b01e chore: avoid unnecessary alloc (#21121)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-12-11 15:59:37 +05:30
Henry Liu
a78b6287b1 fix(ui): fix select destination cluster type in create app (#20970)
Signed-off-by: henry.liu <henry.liu@daocloud.io>
2024-12-11 15:58:10 +05:30
thecooldrop
bd322fe451 chore: Improve the documentation regarding the selection of Application by Sync Windows (#21093)
Signed-off-by: TheCoolDrop <vanio.begic123@gmail.com>
2024-12-11 15:26:51 +05:30
Grégoire Bellon-Gervais
f2e4739178 docs: Add keycloak PKCE and argo-cd cli method documentation (#20698)
* Add keycloak PKCE and argo-cd cli method

Signed-off-by: Grégoire Bellon-Gervais <gregoire.bellon-gervais@docaposte.fr>

* add company

Signed-off-by: Grégoire Bellon-Gervais <gregoire.bellon-gervais@docaposte.fr>

* Oups

Signed-off-by: Grégoire Bellon-Gervais <gregoire.bellon-gervais@docaposte.fr>

* Docaposte in a separated pr

Signed-off-by: Grégoire Bellon-Gervais <gregoire.bellon-gervais@docaposte.fr>

* Fix typo and improve doc

Signed-off-by: Grégoire Bellon-Gervais <gregoire.bellon-gervais@docaposte.fr>

* A good idea :)

Signed-off-by: Grégoire Bellon-Gervais <gregoire.bellon-gervais@docaposte.fr>

---------

Signed-off-by: Grégoire Bellon-Gervais <gregoire.bellon-gervais@docaposte.fr>
2024-12-11 15:18:44 +05:30
Blake Pettersson
2fe9a220dd fix: add missing fields in listrepositories (#20991)
This fixes a regression in 2.12. Before 2.12 githubAppInstallationID,
`githubAppID` and `gitHubAppEnterpriseBaseURL` were returned, but with
2.12 the repo is retrieved with getRepositories`, which does not
include those fields.

To fix this, add those missing fields to `ListRepositories`.

Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
2024-12-11 15:17:44 +05:30
niv8
2f51067e75 psmdb.percona.com/PerconaServerMongoDB resource customization (#20628)
Signed-off-by: Niv Amitai <niv@connecteam.com>
2024-12-10 16:14:43 +05:30
Andrii Korotkov
9741c065d8 feat: Sync timeouts for applications (#6055) (#20816)
* feat: Sync timeouts for applications (#6055)

Helps with #6055

Introduces a controller-level configuration for terminating sync after timeout.

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

* Fix env variable name

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

---------

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
2024-12-10 13:59:04 +05:30
Pasha Kostohrys
90a148987d chore: reduce default max payload size in webhooks to 50MB (#21101)
* chore: reduce default max payload size in webhooks to 50MB

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

* chore: reduce default max payload size in webhooks to 50MB

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

* chore: reduce default max payload size in webhooks to 50MB

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

* chore: reduce default max payload size in webhooks to 50MB

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

---------

Signed-off-by: pashakostohrys <pavel@codefresh.io>
2024-12-10 13:08:18 +05:30
rumstead
dfbfdbab11 feat(appset): reduce cluster secret logging (#21109)
* feat(appset): reduce cluster secret logging

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

* feat(appset): reduce cluster secret logging

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

* feat(appset): reduce cluster secret logging

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

* e2e

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

---------

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
2024-12-09 16:19:35 -05:00
github-actions[bot]
eadc2a47dc [Bot] docs: Update Snyk reports (#21090)
Signed-off-by: CI <ci@argoproj.com>
Co-authored-by: CI <ci@argoproj.com>
2024-12-09 19:00:23 +00:00
Amine Benseddik
eb1bb831d4 docs: Fix argocd admin proj docs and examples (#21057)
Signed-off-by: Amine Benseddik <amine.benseddik@gmail.com>
2024-12-09 13:55:23 -05:00
dependabot[bot]
1bf56d8905 chore(deps): bump tj-actions/changed-files from 45.0.4 to 45.0.5 (#21095)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 45.0.4 to 45.0.5.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](4edd678ac3...bab30c2299)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  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>
2024-12-09 13:53:48 -05:00
dependabot[bot]
ed2fde1a8f chore(deps): bump github.com/cyphar/filepath-securejoin (#21096)
Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.3.4 to 0.3.5.
- [Release notes](https://github.com/cyphar/filepath-securejoin/releases)
- [Changelog](https://github.com/cyphar/filepath-securejoin/blob/main/CHANGELOG.md)
- [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.3.4...v0.3.5)

---
updated-dependencies:
- dependency-name: github.com/cyphar/filepath-securejoin
  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>
2024-12-09 13:53:20 -05:00
Joowon Lim
35c12d9486 chore: use %q to simplify fmt.Sprintf (#21108)
Signed-off-by: Joowon Lim <m4rinesnow34@gmail.com>
2024-12-09 13:52:32 -05:00
dependabot[bot]
96d0226a49 chore(deps): bump actions/cache from 4.1.2 to 4.2.0 (#21084)
Bumps [actions/cache](https://github.com/actions/cache) from 4.1.2 to 4.2.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](6849a64899...1bd1e32a3b)

---
updated-dependencies:
- dependency-name: actions/cache
  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>
2024-12-06 10:48:36 -05:00
Manuel Kieweg
8f0d3d0f6a feat: Timestamp for Health Status (#16972) (#18660)
* add lastTransitionTime to health status

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>

* address first feedback

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>

* set transition time if health status is unknown

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>

* extend health improvement tests

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>

* add apoplication controller test

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>

* use require for NoError

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>

* more extensive tests for health state changes

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>

* Apply suggestions from code review

Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
Signed-off-by: Manuel Kieweg <2939765+mkieweg@users.noreply.github.com>

* Code review suggestions

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>

* remove obsolete assert

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>

* Change LastTransitionTime field to pointer type

Due to implementation limitations, setting LastTransitionTime at the resource level is challenging.
Converting it to a pointer type allows it to be skipped at the resource level and prevents it from appearing
in .status.resources of the Application CR. Additionally, it doesn’t provide much value or have a known
use case right now.

Signed-off-by: Siddhesh Ghadi <sghadi1203@gmail.com>

* Resolve rebase conflicts

Signed-off-by: Siddhesh Ghadi <sghadi1203@gmail.com>

* Address review comment

Signed-off-by: Siddhesh Ghadi <sghadi1203@gmail.com>

* Trigger CI

Signed-off-by: Siddhesh Ghadi <sghadi1203@gmail.com>

---------

Signed-off-by: Manuel Kieweg <mail@manuelkieweg.de>
Signed-off-by: Manuel Kieweg <2939765+mkieweg@users.noreply.github.com>
Signed-off-by: Siddhesh Ghadi <sghadi1203@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
Co-authored-by: Siddhesh Ghadi <sghadi1203@gmail.com>
2024-12-06 17:43:36 +05:30
JM (Jason Meridth)
4f6e4088ef chore(deps): bump gitops-engine to latest (#21056)
Related to https://github.com/argoproj/gitops-engine/pull/638

Signed-off-by: jmeridth <jmeridth@gmail.com>
2024-12-05 15:03:29 -05:00
Matt Finkel
71658c8897 chore: add ziprecruiter to users (#21076)
Signed-off-by: Matt Finkel <finkel.matt@gmail.com>
2024-12-05 10:05:55 -07:00
Ishita Sequeira
fa9023a006 fix: 20791 - sync multi-source application out of order source syncs (#21071)
Signed-off-by: Ishita Sequeira <ishiseq29@gmail.com>
2024-12-05 09:35:05 -07:00
dependabot[bot]
cdec7e2868 chore(deps): bump golang.org/x/net from 0.31.0 to 0.32.0 (#21069)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.31.0 to 0.32.0.
- [Commits](https://github.com/golang/net/compare/v0.31.0...v0.32.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  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>
2024-12-05 09:16:09 +00:00
dependabot[bot]
9f71ecbf5f chore(deps): bump google.golang.org/grpc from 1.67.1 to 1.68.1 (#21066)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.1 to 1.68.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.67.1...v1.68.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  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>
2024-12-05 14:00:40 +05:30
dependabot[bot]
6ace657e2a chore(deps): bump golang.org/x/crypto from 0.29.0 to 0.30.0 (#21068)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.29.0 to 0.30.0.
- [Commits](https://github.com/golang/crypto/compare/v0.29.0...v0.30.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  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>
2024-12-05 13:59:53 +05:30
dependabot[bot]
0a57d21c3d chore(deps): bump library/golang in /test/container (#21048)
Bumps library/golang from 1.23.3 to 1.23.4.

---
updated-dependencies:
- dependency-name: library/golang
  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>
2024-12-05 13:08:16 +05:30
dependabot[bot]
955858eaad chore(deps): bump library/golang from 1.23.3 to 1.23.4 in /test/remote (#21049)
Bumps library/golang from 1.23.3 to 1.23.4.

---
updated-dependencies:
- dependency-name: library/golang
  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>
2024-12-05 13:07:58 +05:30
dependabot[bot]
e28aa2eb54 chore(deps): bump chromedriver from 131.0.1 to 131.0.2 in /ui-test (#21050)
Bumps [chromedriver](https://github.com/giggio/node-chromedriver) from 131.0.1 to 131.0.2.
- [Commits](https://github.com/giggio/node-chromedriver/compare/131.0.1...131.0.2)

---
updated-dependencies:
- dependency-name: chromedriver
  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>
2024-12-05 13:03:38 +05:30
dependabot[bot]
89f222b6a2 chore(deps-dev): bump dotenv from 16.4.6 to 16.4.7 in /ui-test (#21051)
Bumps [dotenv](https://github.com/motdotla/dotenv) from 16.4.6 to 16.4.7.
- [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md)
- [Commits](https://github.com/motdotla/dotenv/compare/v16.4.6...v16.4.7)

---
updated-dependencies:
- dependency-name: dotenv
  dependency-type: direct:development
  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>
2024-12-05 13:02:52 +05:30
dependabot[bot]
0fbbc0dda9 chore(deps): bump golang.org/x/term from 0.26.0 to 0.27.0 (#21070)
Bumps [golang.org/x/term](https://github.com/golang/term) from 0.26.0 to 0.27.0.
- [Commits](https://github.com/golang/term/compare/v0.26.0...v0.27.0)

---
updated-dependencies:
- dependency-name: golang.org/x/term
  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>
2024-12-05 13:00:10 +05:30
Keith Chong
522d07a8d8 fix: UI: Nothing happens selecting cluster URL/Name dropdown (#13655) (#21028)
Signed-off-by: Keith Chong <kykchong@redhat.com>
2024-12-04 13:15:50 +05:30
Andrii Korotkov
730363f14b fix: Graceful shutdown for the API server (#18642) (#20981)
* fix: Graceful shutdown for the API server (#18642)

Closes #18642

Implements a graceful shutdown the the API server. Without this, ArgoCD API server will eventually return 502 during rolling update. However, healthcheck would return 503 if the server is terminating.

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
Co-authored-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* Init server only once, but keep re-initializing listeners

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

* Check error for SetParamInSettingConfigMap as needed after fresh master

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

* Prevent a data race

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

* Remove unused variable, don't pass lock when not necessary

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

* Try overriding URL instead of additional URLs

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

* Use a more specific url

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>

---------

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
Co-authored-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-12-03 15:32:26 -05:00
dependabot[bot]
523b0e6a78 chore(deps): bump SonarSource/sonarqube-scan-action from 3.1.0 to 4.1.0 (#21034)
* chore(deps): bump SonarSource/sonarqube-scan-action from 3.1.0 to 4.1.0

Bumps [SonarSource/sonarqube-scan-action](https://github.com/sonarsource/sonarqube-scan-action) from 3.1.0 to 4.1.0.
- [Release notes](https://github.com/sonarsource/sonarqube-scan-action/releases)
- [Commits](13990a6956...1b442ee39a)

---
updated-dependencies:
- dependency-name: SonarSource/sonarqube-scan-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

* Apply suggestions from code review

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2024-12-03 17:15:55 +00:00
Andrii Korotkov
975786629f chore: Add support for AdditionalURLs field in server settings query (#21045)
Helps with #18642

Needed for consistency and for future testing in another PR.

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
2024-12-03 16:20:01 +00:00
dependabot[bot]
52dbe514e0 chore(deps-dev): bump dotenv from 16.4.5 to 16.4.6 in /ui-test (#21031)
Bumps [dotenv](https://github.com/motdotla/dotenv) from 16.4.5 to 16.4.6.
- [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md)
- [Commits](https://github.com/motdotla/dotenv/compare/v16.4.5...v16.4.6)

---
updated-dependencies:
- dependency-name: dotenv
  dependency-type: direct:development
  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>
2024-12-03 19:44:50 +05:30
dependabot[bot]
51a7966b92 chore(deps): bump sigs.k8s.io/controller-runtime from 0.19.2 to 0.19.3 (#21032)
Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.19.2 to 0.19.3.
- [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases)
- [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.19.2...v0.19.3)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/controller-runtime
  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>
2024-12-03 19:44:25 +05:30
dudinea
0d7f1f7053 chore: fix tests failing with Kustomize based errors (#21037)
Signed-off-by: Eugene Doudine <eugene.d@trekflow.com>
2024-12-03 12:04:25 +02:00
Andrii Korotkov
b8e118ff7d fix: Bitbucket Cloud PR Author is processed correctly (#20769) (#20990)
Fixes #20769

Author there is a struct, not a string. Use nickname from that struct as an author name.

Let's cherry pick to 2.11-2.13

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
2024-12-03 14:22:22 +05:30
178 changed files with 14429 additions and 2167 deletions

View File

@@ -32,7 +32,7 @@ jobs:
docs: ${{ steps.filter.outputs.docs_any_changed }}
steps:
- uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- uses: tj-actions/changed-files@4edd678ac3f81e2dc578756871e4d00c19191daf # v45.0.4
- uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366 # v45.0.5
id: filter
with:
# Any file which is not under docs/, ui/ or is not a markdown file is counted as a backend file
@@ -57,7 +57,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Download all Go modules
@@ -78,11 +78,11 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Restore go build cache
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -105,7 +105,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Run golangci-lint
@@ -133,7 +133,7 @@ jobs:
- name: Create symlink in GOPATH
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -153,7 +153,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -197,7 +197,7 @@ jobs:
- name: Create symlink in GOPATH
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Install required packages
@@ -217,7 +217,7 @@ jobs:
run: |
echo "/usr/local/bin" >> $GITHUB_PATH
- name: Restore go build cache
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}
@@ -253,7 +253,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: Create symlink in GOPATH
@@ -311,7 +311,7 @@ jobs:
node-version: '22.9.0'
- name: Restore node dependency cache
id: cache-dependencies
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
@@ -351,7 +351,7 @@ jobs:
fetch-depth: 0
- name: Restore node dependency cache
id: cache-dependencies
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: ui/node_modules
key: ${{ runner.os }}-node-dep-v2-${{ hashFiles('**/yarn.lock') }}
@@ -370,11 +370,11 @@ jobs:
path: test-results
- name: combine-go-coverage
# We generate coverage reports for all Argo CD components, but only the applicationset-controller,
# app-controller, and repo-server report contain coverage data. The other components currently don't shut down
# gracefully, so no coverage data is produced. Once those components are fixed, we can add references to their
# coverage output directories.
# app-controller, repo-server, and commit-server report contain coverage data. The other components currently
# don't shut down gracefully, so no coverage data is produced. Once those components are fixed, we can add
# references to their coverage output directories.
run: |
go tool covdata percent -i=test-results,e2e-code-coverage/applicationset-controller,e2e-code-coverage/repo-server,e2e-code-coverage/app-controller -o test-results/full-coverage.out
go tool covdata percent -i=test-results,e2e-code-coverage/applicationset-controller,e2e-code-coverage/repo-server,e2e-code-coverage/app-controller,e2e-code-coverage/commit-server -o test-results/full-coverage.out
- name: Upload code coverage information to codecov.io
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
with:
@@ -393,7 +393,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
uses: SonarSource/sonarqube-scan-action@13990a695682794b53148ff9f6a8b6e22e43955e # v2.2
uses: SonarSource/sonarqube-scan-action@1b442ee39ac3fa7c2acdd410208dcb2bcfaae6c4 # v4.1.0
if: env.sonar_secret != ''
test-e2e:
name: Run end-to-end tests
@@ -432,7 +432,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GOLANG_VERSION }}
- name: GH actions workaround - Kill XSP4 process
@@ -451,7 +451,7 @@ jobs:
sudo chmod go-r $HOME/.kube/config
kubectl version
- name: Restore go build cache
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: ~/.cache/go-build
key: ${{ runner.os }}-go-build-v1-${{ github.run_id }}

View File

@@ -33,7 +33,7 @@ jobs:
# Use correct go version. https://github.com/github/codeql-action/issues/1842#issuecomment-1704398087
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version-file: go.mod

View File

@@ -69,7 +69,7 @@ jobs:
if: ${{ github.ref_type != 'tag'}}
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ inputs.go-version }}

View File

@@ -70,7 +70,7 @@ jobs:
run: git fetch --force --tags
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GOLANG_VERSION }}
@@ -151,7 +151,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Golang
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GOLANG_VERSION }}
@@ -195,7 +195,7 @@ jobs:
echo "hashes=$(sha256sum /tmp/sbom.tar.gz | base64 -w0)" >> "$GITHUB_OUTPUT"
- name: Upload SBOM
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:

View File

@@ -26,6 +26,13 @@ packages:
github.com/argoproj/argo-cd/v2/applicationset/utils:
interfaces:
Renderer:
github.com/argoproj/argo-cd/v2/commitserver/commit:
interfaces:
RepoClientFactory:
github.com/argoproj/argo-cd/v2/commitserver/apiclient:
interfaces:
CommitServiceClient:
Clientset:
github.com/argoproj/argo-cd/v2/controller/cache:
interfaces:
LiveStateCache:

View File

@@ -140,7 +140,8 @@ RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-dex && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-notifications && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-k8s-auth
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-k8s-auth && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-commit-server
USER $ARGOCD_USER_ID
ENTRYPOINT ["/usr/bin/tini", "--"]

View File

@@ -472,6 +472,7 @@ start-e2e-local: mod-vendor-local dep-ui-local cli-local
mkdir -p /tmp/coverage/repo-server
mkdir -p /tmp/coverage/applicationset-controller
mkdir -p /tmp/coverage/notification
mkdir -p /tmp/coverage/commit-server
# set paths for locally managed ssh known hosts and tls certs data
ARGOCD_SSH_DATA_PATH=/tmp/argo-e2e/app/config/ssh \
ARGOCD_TLS_DATA_PATH=/tmp/argo-e2e/app/config/tls \

View File

@@ -4,6 +4,7 @@ dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v2/
redis: hack/start-redis-with-password.sh
repo-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/repo-server} 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}"
commit-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "GOCOVERDIR=${ARGOCD_COVERAGE_DIR:-/tmp/coverage/commit-server} FORCE_LOG_COLORS=1 ARGOCD_BINARY_NAME=argocd-commit-server $COMMAND --loglevel debug --port ${ARGOCD_E2E_COMMITSERVER_PORT:-8086}"
ui: sh -c 'cd ui && ${ARGOCD_E2E_YARN_CMD:-yarn} start'
git-server: test/fixture/testrepos/start-git.sh
helm-registry: test/fixture/testrepos/start-helm-registry.sh

View File

@@ -392,4 +392,5 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Yubo](https://www.yubo.live/)
1. [ZDF](https://www.zdf.de/)
1. [Zimpler](https://www.zimpler.com/)
1. [ZipRecuiter](https://www.ziprecruiter.com/)
1. [ZOZO](https://corp.zozo.com/)

View File

@@ -1783,7 +1783,7 @@ func TestDeleteInCluster(t *testing.T) {
Name: obj.Name,
}, got)
assert.EqualError(t, err, fmt.Sprintf("applications.argoproj.io \"%s\" not found", obj.Name))
assert.EqualError(t, err, fmt.Sprintf("applications.argoproj.io %q not found", obj.Name))
}
}
}
@@ -1894,12 +1894,6 @@ func TestValidateGeneratedApplications(t *testing.T) {
err := v1alpha1.AddToScheme(scheme)
require.NoError(t, err)
// Valid cluster
myCluster := v1alpha1.Cluster{
Server: "https://kubernetes.default.svc",
Name: "my-cluster",
}
// Valid project
myProject := &v1alpha1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "default", Namespace: "namespace"},
@@ -2066,18 +2060,12 @@ func TestValidateGeneratedApplications(t *testing.T) {
objects := append([]runtime.Object{}, secret)
kubeclientset := kubefake.NewSimpleClientset(objects...)
argoDBMock := dbmocks.ArgoDB{}
argoDBMock.On("GetCluster", mock.Anything, "https://kubernetes.default.svc").Return(&myCluster, nil)
argoDBMock.On("ListClusters", mock.Anything).Return(&v1alpha1.ClusterList{Items: []v1alpha1.Cluster{
myCluster,
}}, nil)
r := ApplicationSetReconciler{
Client: client,
Scheme: scheme,
Recorder: record.NewFakeRecorder(1),
Generators: map[string]generators.Generator{},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
ArgoCDNamespace: "namespace",
KubeClientset: kubeclientset,
Metrics: metrics,
@@ -2159,17 +2147,9 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) {
}
kubeclientset := kubefake.NewSimpleClientset()
argoDBMock := dbmocks.ArgoDB{}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &project).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
goodCluster := v1alpha1.Cluster{Server: "https://good-cluster", Name: "good-cluster"}
badCluster := v1alpha1.Cluster{Server: "https://bad-cluster", Name: "bad-cluster"}
argoDBMock.On("GetCluster", mock.Anything, "https://good-cluster").Return(&goodCluster, nil)
argoDBMock.On("GetCluster", mock.Anything, "https://bad-cluster").Return(&badCluster, nil)
argoDBMock.On("ListClusters", mock.Anything).Return(&v1alpha1.ClusterList{Items: []v1alpha1.Cluster{
goodCluster,
}}, nil)
r := ApplicationSetReconciler{
Client: client,
@@ -2179,7 +2159,7 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) {
Generators: map[string]generators.Generator{
"List": generators.NewListGenerator(),
},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
KubeClientset: kubeclientset,
Policy: v1alpha1.ApplicationsSyncPolicySync,
ArgoCDNamespace: "argocd",
@@ -2363,7 +2343,6 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
}
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
argoDBMock := dbmocks.ArgoDB{}
for _, testCase := range testCases {
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&testCase.appset).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).WithStatusSubresource(&testCase.appset).Build()
@@ -2377,7 +2356,7 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
Generators: map[string]generators.Generator{
"List": generators.NewListGenerator(),
},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
KubeClientset: kubeclientset,
Metrics: metrics,
}
@@ -2433,16 +2412,28 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
},
}
kubeclientset := kubefake.NewSimpleClientset()
argoDBMock := dbmocks.ArgoDB{}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster",
Namespace: "argocd",
Labels: map[string]string{
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
},
},
Data: map[string][]byte{
// Since this test requires the cluster to be an invalid destination, we
// always return a cluster named 'my-cluster2' (different from app 'my-cluster', above)
"name": []byte("good-cluster"),
"server": []byte("https://good-cluster"),
"config": []byte("{\"username\":\"foo\",\"password\":\"foo\"}"),
},
}
objects := append([]runtime.Object{}, secret)
kubeclientset := kubefake.NewSimpleClientset(objects...)
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
goodCluster := v1alpha1.Cluster{Server: "https://good-cluster", Name: "good-cluster"}
argoDBMock.On("GetCluster", mock.Anything, "https://good-cluster").Return(&goodCluster, nil)
argoDBMock.On("ListClusters", mock.Anything).Return(&v1alpha1.ClusterList{Items: []v1alpha1.Cluster{
goodCluster,
}}, nil)
r := ApplicationSetReconciler{
Client: client,
@@ -2452,7 +2443,7 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
Generators: map[string]generators.Generator{
"List": generators.NewListGenerator(),
},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
ArgoCDNamespace: "argocd",
KubeClientset: kubeclientset,
Policy: v1alpha1.ApplicationsSyncPolicySync,
@@ -2595,16 +2586,28 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
},
}
kubeclientset := kubefake.NewSimpleClientset()
argoDBMock := dbmocks.ArgoDB{}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "my-cluster",
Namespace: "argocd",
Labels: map[string]string{
argocommon.LabelKeySecretType: argocommon.LabelValueSecretTypeCluster,
},
},
Data: map[string][]byte{
// Since this test requires the cluster to be an invalid destination, we
// always return a cluster named 'my-cluster2' (different from app 'my-cluster', above)
"name": []byte("good-cluster"),
"server": []byte("https://good-cluster"),
"config": []byte("{\"username\":\"foo\",\"password\":\"foo\"}"),
},
}
objects := append([]runtime.Object{}, secret)
kubeclientset := kubefake.NewSimpleClientset(objects...)
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet, &defaultProject).WithStatusSubresource(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
goodCluster := v1alpha1.Cluster{Server: "https://good-cluster", Name: "good-cluster"}
argoDBMock.On("GetCluster", mock.Anything, "https://good-cluster").Return(&goodCluster, nil)
argoDBMock.On("ListClusters", mock.Anything).Return(&v1alpha1.ClusterList{Items: []v1alpha1.Cluster{
goodCluster,
}}, nil)
r := ApplicationSetReconciler{
Client: client,
@@ -2614,7 +2617,7 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
Generators: map[string]generators.Generator{
"List": generators.NewListGenerator(),
},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
ArgoCDNamespace: "argocd",
KubeClientset: kubeclientset,
Policy: v1alpha1.ApplicationsSyncPolicySync,
@@ -2689,7 +2692,7 @@ func TestDeletePerformedWithSyncPolicyCreateDelete(t *testing.T) {
apps := applicationsDeleteSyncPolicyTest(t, applicationsSyncPolicy, 3, true)
assert.Empty(t, apps.Items)
assert.NotNil(t, apps.Items[0].DeletionTimestamp)
}
func TestDeletePerformedWithSyncPolicySync(t *testing.T) {
@@ -2697,7 +2700,7 @@ func TestDeletePerformedWithSyncPolicySync(t *testing.T) {
apps := applicationsDeleteSyncPolicyTest(t, applicationsSyncPolicy, 3, true)
assert.Empty(t, apps.Items)
assert.NotNil(t, apps.Items[0].DeletionTimestamp)
}
func TestDeletePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *testing.T) {
@@ -2705,7 +2708,7 @@ func TestDeletePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *t
apps := applicationsDeleteSyncPolicyTest(t, applicationsSyncPolicy, 3, false)
assert.Empty(t, apps.Items)
assert.NotNil(t, apps.Items[0].DeletionTimestamp)
}
func TestPolicies(t *testing.T) {
@@ -2717,14 +2720,8 @@ func TestPolicies(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "default", Namespace: "argocd"},
Spec: v1alpha1.AppProjectSpec{SourceRepos: []string{"*"}, Destinations: []v1alpha1.ApplicationDestination{{Namespace: "*", Server: "https://kubernetes.default.svc"}}},
}
myCluster := v1alpha1.Cluster{
Server: "https://kubernetes.default.svc",
Name: "my-cluster",
}
kubeclientset := kubefake.NewSimpleClientset()
argoDBMock := dbmocks.ArgoDB{}
argoDBMock.On("GetCluster", mock.Anything, "https://kubernetes.default.svc").Return(&myCluster, nil)
for _, c := range []struct {
name string
@@ -2807,7 +2804,7 @@ func TestPolicies(t *testing.T) {
Generators: map[string]generators.Generator{
"List": generators.NewListGenerator(),
},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
ArgoCDNamespace: "argocd",
KubeClientset: kubeclientset,
Policy: policy,
@@ -2881,7 +2878,6 @@ func TestSetApplicationSetApplicationStatus(t *testing.T) {
require.NoError(t, err)
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
argoDBMock := dbmocks.ArgoDB{}
for _, cc := range []struct {
name string
@@ -2965,7 +2961,7 @@ func TestSetApplicationSetApplicationStatus(t *testing.T) {
Generators: map[string]generators.Generator{
"List": generators.NewListGenerator(),
},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
KubeClientset: kubeclientset,
Metrics: metrics,
}
@@ -3714,14 +3710,13 @@ func TestBuildAppDependencyList(t *testing.T) {
} {
t.Run(cc.name, func(t *testing.T) {
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
argoDBMock := dbmocks.ArgoDB{}
r := ApplicationSetReconciler{
Client: client,
Scheme: scheme,
Recorder: record.NewFakeRecorder(1),
Generators: map[string]generators.Generator{},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
KubeClientset: kubeclientset,
Metrics: metrics,
}
@@ -4381,14 +4376,13 @@ func TestBuildAppSyncMap(t *testing.T) {
} {
t.Run(cc.name, func(t *testing.T) {
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
argoDBMock := dbmocks.ArgoDB{}
r := ApplicationSetReconciler{
Client: client,
Scheme: scheme,
Recorder: record.NewFakeRecorder(1),
Generators: map[string]generators.Generator{},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
KubeClientset: kubeclientset,
Metrics: metrics,
}
@@ -5326,7 +5320,6 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
} {
t.Run(cc.name, func(t *testing.T) {
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
argoDBMock := dbmocks.ArgoDB{}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&cc.appSet).WithStatusSubresource(&cc.appSet).Build()
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
@@ -5336,7 +5329,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
Scheme: scheme,
Recorder: record.NewFakeRecorder(1),
Generators: map[string]generators.Generator{},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
KubeClientset: kubeclientset,
Metrics: metrics,
}
@@ -6075,7 +6068,6 @@ func TestUpdateApplicationSetApplicationStatusProgress(t *testing.T) {
} {
t.Run(cc.name, func(t *testing.T) {
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
argoDBMock := dbmocks.ArgoDB{}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&cc.appSet).WithStatusSubresource(&cc.appSet).Build()
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
@@ -6085,7 +6077,7 @@ func TestUpdateApplicationSetApplicationStatusProgress(t *testing.T) {
Scheme: scheme,
Recorder: record.NewFakeRecorder(1),
Generators: map[string]generators.Generator{},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
KubeClientset: kubeclientset,
Metrics: metrics,
}
@@ -6286,7 +6278,6 @@ func TestUpdateResourceStatus(t *testing.T) {
} {
t.Run(cc.name, func(t *testing.T) {
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
argoDBMock := dbmocks.ArgoDB{}
client := fake.NewClientBuilder().WithScheme(scheme).WithStatusSubresource(&cc.appSet).WithObjects(&cc.appSet).Build()
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
@@ -6296,7 +6287,7 @@ func TestUpdateResourceStatus(t *testing.T) {
Scheme: scheme,
Recorder: record.NewFakeRecorder(1),
Generators: map[string]generators.Generator{},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
KubeClientset: kubeclientset,
Metrics: metrics,
}
@@ -6376,7 +6367,6 @@ func TestResourceStatusAreOrdered(t *testing.T) {
} {
t.Run(cc.name, func(t *testing.T) {
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
argoDBMock := dbmocks.ArgoDB{}
client := fake.NewClientBuilder().WithScheme(scheme).WithStatusSubresource(&cc.appSet).WithObjects(&cc.appSet).Build()
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
@@ -6386,7 +6376,7 @@ func TestResourceStatusAreOrdered(t *testing.T) {
Scheme: scheme,
Recorder: record.NewFakeRecorder(1),
Generators: map[string]generators.Generator{},
ArgoDB: &argoDBMock,
ArgoDB: &dbmocks.ArgoDB{},
KubeClientset: kubeclientset,
Metrics: metrics,
}

View File

@@ -69,9 +69,11 @@ func GenerateApplications(logCtx *log.Entry, applicationSetInfo argov1alpha1.App
res = append(res, *app)
}
}
logCtx.WithField("generator", requestedGenerator).Infof("generated %d applications", len(res))
logCtx.WithField("generator", requestedGenerator).Debugf("apps from generator: %+v", res)
if log.IsLevelEnabled(log.DebugLevel) {
logCtx.WithField("generator", requestedGenerator).Debugf("apps from generator: %+v", res)
} else {
logCtx.Infof("generated %d applications", len(res))
}
}
return res, applicationSetReason, firstError

View File

@@ -48,7 +48,7 @@ func NewClusterGenerator(c client.Client, ctx context.Context, clientset kuberne
// GetRequeueAfter never requeue the cluster generator because the `clusterSecretEventHandler` will requeue the appsets
// when the cluster secrets change
func (g *ClusterGenerator) GetRequeueAfter(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator) time.Duration {
func (g *ClusterGenerator) GetRequeueAfter(_ *argoappsetv1alpha1.ApplicationSetGenerator) time.Duration {
return NoRequeueAfter
}
@@ -57,6 +57,7 @@ func (g *ClusterGenerator) GetTemplate(appSetGenerator *argoappsetv1alpha1.Appli
}
func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator, appSet *argoappsetv1alpha1.ApplicationSet, _ client.Client) ([]map[string]interface{}, error) {
logCtx := log.WithField("applicationset", appSet.GetName()).WithField("namespace", appSet.GetNamespace())
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
}
@@ -79,7 +80,7 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
return nil, nil
}
clusterSecrets, err := g.getSecretsByClusterName(appSetGenerator)
clusterSecrets, err := g.getSecretsByClusterName(logCtx, appSetGenerator)
if err != nil {
return nil, fmt.Errorf("error getting cluster secrets: %w", err)
}
@@ -89,7 +90,7 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
secretsFound := []corev1.Secret{}
isFlatMode := appSetGenerator.Clusters.FlatList
log.Debug("Using flat mode = ", isFlatMode, " for cluster generator")
logCtx.Debugf("Using flat mode = %t for cluster generator", isFlatMode)
clustersParams := make([]map[string]interface{}, 0)
for _, cluster := range clustersFromArgoCD.Items {
@@ -116,7 +117,7 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
res = append(res, params)
}
log.WithField("cluster", "local cluster").Info("matched local cluster")
logCtx.WithField("cluster", "local cluster").Info("matched local cluster")
}
}
@@ -167,7 +168,7 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
res = append(res, params)
}
log.WithField("cluster", cluster.Name).Info("matched cluster secret")
logCtx.WithField("cluster", cluster.Name).Debug("matched cluster secret")
}
if isFlatMode {
@@ -178,8 +179,7 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
return res, nil
}
func (g *ClusterGenerator) getSecretsByClusterName(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator) (map[string]corev1.Secret, error) {
// List all Clusters:
func (g *ClusterGenerator) getSecretsByClusterName(log *log.Entry, appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator) (map[string]corev1.Secret, error) {
clusterSecretList := &corev1.SecretList{}
selector := metav1.AddLabelToSelector(&appSetGenerator.Clusters.Selector, common.LabelKeySecretType, common.LabelValueSecretTypeCluster)
@@ -191,7 +191,7 @@ func (g *ClusterGenerator) getSecretsByClusterName(appSetGenerator *argoappsetv1
if err := g.Client.List(context.Background(), clusterSecretList, client.MatchingLabelsSelector{Selector: secretSelector}); err != nil {
return nil, err
}
log.Debug("clusters matching labels", "count", len(clusterSecretList.Items))
log.Debugf("clusters matching labels: %d", len(clusterSecretList.Items))
res := map[string]corev1.Secret{}

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"github.com/bradleyfalzon/ghinstallation/v2"
"github.com/google/go-github/v63/github"
"github.com/google/go-github/v66/github"
"github.com/argoproj/argo-cd/v2/applicationset/services/github_app_auth"
)

View File

@@ -19,7 +19,7 @@ type BitbucketCloudPullRequest struct {
ID int `json:"id"`
Title string `json:"title"`
Source BitbucketCloudPullRequestSource `json:"source"`
Author string `json:"author"`
Author BitbucketCloudPullRequestAuthor `json:"author"`
}
type BitbucketCloudPullRequestSource struct {
@@ -35,6 +35,11 @@ type BitbucketCloudPullRequestSourceCommit struct {
Hash string `json:"hash"`
}
// Also have display_name and uuid, but don't plan to use them.
type BitbucketCloudPullRequestAuthor struct {
Nickname string `json:"nickname"`
}
type PullRequestResponse struct {
Page int32 `json:"page"`
Size int32 `json:"size"`
@@ -134,7 +139,7 @@ func (b *BitbucketCloudService) List(_ context.Context) ([]*PullRequest, error)
Title: pull.Title,
Branch: pull.Source.Branch.Name,
HeadSHA: pull.Source.Commit.Hash,
Author: pull.Author,
Author: pull.Author.Nickname,
})
}

View File

@@ -38,7 +38,9 @@ func defaultHandlerCloud(t *testing.T) func(http.ResponseWriter, *http.Request)
"hash": "1a8dd249c04a"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`)
@@ -155,7 +157,9 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
"hash": "1a8dd249c04a"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
},
{
"id": 102,
@@ -169,7 +173,9 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
"hash": "4cf807e67a6d"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`, r.Host))
@@ -192,7 +198,9 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
"hash": "6344d9623e3b"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`, r.Host))
@@ -340,7 +348,9 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
"hash": "1a8dd249c04a"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
},
{
"id": 200,
@@ -354,7 +364,9 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
"hash": "4cf807e67a6d"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`, r.Host))
@@ -377,7 +389,9 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
"hash": "6344d9623e3b"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`, r.Host))

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"os"
"github.com/google/go-github/v63/github"
"github.com/google/go-github/v66/github"
"golang.org/x/oauth2"
)

View File

@@ -3,7 +3,7 @@ package pull_request
import (
"testing"
"github.com/google/go-github/v63/github"
"github.com/google/go-github/v66/github"
"github.com/stretchr/testify/require"
)

View File

@@ -6,7 +6,7 @@ import (
"net/http"
"os"
"github.com/google/go-github/v63/github"
"github.com/google/go-github/v66/github"
"golang.org/x/oauth2"
)

View File

@@ -51,9 +51,12 @@ const (
// if we used destination name we infer the server url
// if we used both name and server then we return an invalid spec error
func ValidateDestination(ctx context.Context, dest *appv1.ApplicationDestination, clientset kubernetes.Interface, argoCDNamespace string) error {
if dest.IsServerInferred() && dest.IsNameInferred() {
return fmt.Errorf("application destination can't have both name and server inferred: %s %s", dest.Name, dest.Server)
}
if dest.Name != "" {
if dest.Server == "" {
server, err := getDestinationServer(ctx, dest.Name, clientset, argoCDNamespace)
server, err := getDestinationBy(ctx, dest.Name, clientset, argoCDNamespace, true)
if err != nil {
return fmt.Errorf("unable to find destination server: %w", err)
}
@@ -61,14 +64,25 @@ func ValidateDestination(ctx context.Context, dest *appv1.ApplicationDestination
return fmt.Errorf("application references destination cluster %s which does not exist", dest.Name)
}
dest.SetInferredServer(server)
} else if !dest.IsServerInferred() {
} else if !dest.IsServerInferred() && !dest.IsNameInferred() {
return fmt.Errorf("application destination can't have both name and server defined: %s %s", dest.Name, dest.Server)
}
} else if dest.Server != "" {
if dest.Name == "" {
serverName, err := getDestinationBy(ctx, dest.Server, clientset, argoCDNamespace, false)
if err != nil {
return fmt.Errorf("unable to find destination server: %w", err)
}
if serverName == "" {
return fmt.Errorf("application references destination cluster %s which does not exist", dest.Server)
}
dest.SetInferredName(serverName)
}
}
return nil
}
func getDestinationServer(ctx context.Context, clusterName string, clientset kubernetes.Interface, argoCDNamespace string) (string, error) {
func getDestinationBy(ctx context.Context, cluster string, clientset kubernetes.Interface, argoCDNamespace string, byName bool) (string, error) {
// settingsMgr := settings.NewSettingsManager(context.TODO(), clientset, namespace)
// argoDB := db.NewDB(namespace, settingsMgr, clientset)
// clusterList, err := argoDB.ListClusters(ctx)
@@ -78,14 +92,17 @@ func getDestinationServer(ctx context.Context, clusterName string, clientset kub
}
var servers []string
for _, c := range clusterList.Items {
if c.Name == clusterName {
if byName && c.Name == cluster {
servers = append(servers, c.Server)
}
if !byName && c.Server == cluster {
servers = append(servers, c.Name)
}
}
if len(servers) > 1 {
return "", fmt.Errorf("there are %d clusters with the same name: %v", len(servers), servers)
} else if len(servers) == 0 {
return "", fmt.Errorf("there are no clusters with this name: %s", clusterName)
return "", fmt.Errorf("there are no clusters with this name: %s", cluster)
}
return servers[0], nil
}

View File

@@ -93,7 +93,12 @@ func TestValidateDestination(t *testing.T) {
Namespace: "default",
}
appCond := ValidateDestination(context.Background(), &dest, nil, fakeNamespace)
secret := createClusterSecret("my-secret", "minikube", "https://127.0.0.1:6443")
objects := []runtime.Object{}
objects = append(objects, secret)
kubeclientset := fake.NewSimpleClientset(objects...)
appCond := ValidateDestination(context.Background(), &dest, kubeclientset, fakeNamespace)
require.NoError(t, appCond)
assert.False(t, dest.IsServerInferred())
})

132
assets/swagger.json generated
View File

@@ -4691,6 +4691,12 @@
"clusterSettings": {
"type": "object",
"properties": {
"additionalUrls": {
"type": "array",
"items": {
"type": "string"
}
},
"appLabelKey": {
"type": "string"
},
@@ -6851,6 +6857,9 @@
"source": {
"$ref": "#/definitions/v1alpha1ApplicationSource"
},
"sourceHydrator": {
"$ref": "#/definitions/v1alpha1SourceHydrator"
},
"sources": {
"type": "array",
"title": "Sources is a reference to the location of the application's manifests or chart",
@@ -6908,6 +6917,9 @@
"$ref": "#/definitions/applicationv1alpha1ResourceStatus"
}
},
"sourceHydrator": {
"$ref": "#/definitions/v1alpha1SourceHydratorStatus"
},
"sourceType": {
"type": "string",
"title": "SourceType specifies the type of this application"
@@ -7335,6 +7347,24 @@
}
}
},
"v1alpha1DrySource": {
"description": "DrySource specifies a location for dry \"don't repeat yourself\" manifest source information.",
"type": "object",
"properties": {
"path": {
"type": "string",
"title": "Path is a directory path within the Git repository where the manifests are located"
},
"repoURL": {
"type": "string",
"title": "RepoURL is the URL to the git repository that contains the application manifests"
},
"targetRevision": {
"type": "string",
"title": "TargetRevision defines the revision of the source to hydrate"
}
}
},
"v1alpha1DuckTypeGenerator": {
"description": "DuckType defines a generator to match against clusters registered with ArgoCD.",
"type": "object",
@@ -7505,6 +7535,9 @@
"type": "object",
"title": "HealthStatus contains information about the currently observed health state of an application or resource",
"properties": {
"lastTransitionTime": {
"$ref": "#/definitions/v1Time"
},
"message": {
"type": "string",
"title": "Message is a human-readable informational message describing the health status"
@@ -7586,6 +7619,47 @@
}
}
},
"v1alpha1HydrateOperation": {
"type": "object",
"title": "HydrateOperation contains information about the most recent hydrate operation",
"properties": {
"drySHA": {
"type": "string",
"title": "DrySHA holds the resolved revision (sha) of the dry source as of the most recent reconciliation"
},
"finishedAt": {
"$ref": "#/definitions/v1Time"
},
"hydratedSHA": {
"type": "string",
"title": "HydratedSHA holds the resolved revision (sha) of the hydrated source as of the most recent reconciliation"
},
"message": {
"type": "string",
"title": "Message contains a message describing the current status of the hydrate operation"
},
"phase": {
"type": "string",
"title": "Phase indicates the status of the hydrate operation"
},
"sourceHydrator": {
"$ref": "#/definitions/v1alpha1SourceHydrator"
},
"startedAt": {
"$ref": "#/definitions/v1Time"
}
}
},
"v1alpha1HydrateTo": {
"description": "HydrateTo specifies a location to which hydrated manifests should be pushed as a \"staging area\" before being moved to\nthe SyncSource. The RepoURL and Path are assumed based on the associated SyncSource config in the SourceHydrator.",
"type": "object",
"properties": {
"targetBranch": {
"type": "string",
"title": "TargetBranch is the branch to which hydrated manifests should be committed"
}
}
},
"v1alpha1Info": {
"type": "object",
"properties": {
@@ -9193,6 +9267,50 @@
}
}
},
"v1alpha1SourceHydrator": {
"description": "SourceHydrator specifies a dry \"don't repeat yourself\" source for manifests, a sync source from which to sync\nhydrated manifests, and an optional hydrateTo location to act as a \"staging\" aread for hydrated manifests.",
"type": "object",
"properties": {
"drySource": {
"$ref": "#/definitions/v1alpha1DrySource"
},
"hydrateTo": {
"$ref": "#/definitions/v1alpha1HydrateTo"
},
"syncSource": {
"$ref": "#/definitions/v1alpha1SyncSource"
}
}
},
"v1alpha1SourceHydratorStatus": {
"type": "object",
"title": "SourceHydratorStatus contains information about the current state of source hydration",
"properties": {
"currentOperation": {
"$ref": "#/definitions/v1alpha1HydrateOperation"
},
"lastSuccessfulOperation": {
"$ref": "#/definitions/v1alpha1SuccessfulHydrateOperation"
}
}
},
"v1alpha1SuccessfulHydrateOperation": {
"type": "object",
"title": "SuccessfulHydrateOperation contains information about the most recent successful hydrate operation",
"properties": {
"drySHA": {
"type": "string",
"title": "DrySHA holds the resolved revision (sha) of the dry source as of the most recent reconciliation"
},
"hydratedSHA": {
"type": "string",
"title": "HydratedSHA holds the resolved revision (sha) of the hydrated source as of the most recent reconciliation"
},
"sourceHydrator": {
"$ref": "#/definitions/v1alpha1SourceHydrator"
}
}
},
"v1alpha1SyncOperation": {
"description": "SyncOperation contains details about a sync operation.",
"type": "object",
@@ -9352,6 +9470,20 @@
}
}
},
"v1alpha1SyncSource": {
"description": "SyncSource specifies a location from which hydrated manifests may be synced. RepoURL is assumed based on the\nassociated DrySource config in the SourceHydrator.",
"type": "object",
"properties": {
"path": {
"description": "Path is a directory path within the git repository where hydrated manifests should be committed to and synced\nfrom. If hydrateTo is set, this is just the path from which hydrated manifests will be synced.",
"type": "string"
},
"targetBranch": {
"type": "string",
"title": "TargetBranch is the branch to which hydrated manifests should be committed"
}
}
},
"v1alpha1SyncStatus": {
"type": "object",
"title": "SyncStatus contains information about the currently observed live and desired states of an application",

View File

@@ -62,6 +62,7 @@ func NewCommand() *cobra.Command {
selfHealBackoffTimeoutSeconds int
selfHealBackoffFactor int
selfHealBackoffCapSeconds int
syncTimeout int
statusProcessors int
operationProcessors int
glogLevel int
@@ -189,6 +190,7 @@ func NewCommand() *cobra.Command {
time.Duration(appResyncJitter)*time.Second,
time.Duration(selfHealTimeoutSeconds)*time.Second,
selfHealBackoff,
time.Duration(syncTimeout)*time.Second,
time.Duration(repoErrorGracePeriod)*time.Second,
metricsPort,
metricsCacheExpiration,
@@ -205,7 +207,7 @@ func NewCommand() *cobra.Command {
enableK8sEvent,
)
errors.CheckError(err)
cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer())
cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer(), nil)
stats.RegisterStackDumper()
stats.StartStatsTicker(10 * time.Minute)
@@ -256,6 +258,7 @@ func NewCommand() *cobra.Command {
command.Flags().IntVar(&selfHealBackoffTimeoutSeconds, "self-heal-backoff-timeout-seconds", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_TIMEOUT_SECONDS", 2, 0, math.MaxInt32), "Specifies initial timeout of exponential backoff between self heal attempts")
command.Flags().IntVar(&selfHealBackoffFactor, "self-heal-backoff-factor", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_FACTOR", 3, 0, math.MaxInt32), "Specifies factor of exponential timeout between application self heal attempts")
command.Flags().IntVar(&selfHealBackoffCapSeconds, "self-heal-backoff-cap-seconds", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_BACKOFF_CAP_SECONDS", 300, 0, math.MaxInt32), "Specifies max timeout of exponential backoff between application self heal attempts")
command.Flags().IntVar(&syncTimeout, "sync-timeout", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_SYNC_TIMEOUT", 0, 0, math.MaxInt32), "Specifies the timeout after which a sync would be terminated. 0 means no timeout (default 0).")
command.Flags().Int64Var(&kubectlParallelismLimit, "kubectl-parallelism-limit", env.ParseInt64FromEnv("ARGOCD_APPLICATION_CONTROLLER_KUBECTL_PARALLELISM_LIMIT", 20, 0, math.MaxInt64), "Number of allowed concurrent kubectl fork/execs. Any value less than 1 means no limit.")
command.Flags().BoolVar(&repoServerPlaintext, "repo-server-plaintext", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_PLAINTEXT", false), "Disable TLS on connections to repo server")
command.Flags().BoolVar(&repoServerStrictTLS, "repo-server-strict-tls", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_STRICT_TLS", false), "Whether to use strict validation of the TLS cert presented by the repo server")

View File

@@ -0,0 +1,117 @@
package commands
import (
"fmt"
"net"
"net/http"
"os"
"os/signal"
"sync"
"syscall"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"google.golang.org/grpc/health/grpc_health_v1"
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
"github.com/argoproj/argo-cd/v2/commitserver"
"github.com/argoproj/argo-cd/v2/commitserver/apiclient"
"github.com/argoproj/argo-cd/v2/commitserver/metrics"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/util/askpass"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/util/env"
"github.com/argoproj/argo-cd/v2/util/errors"
"github.com/argoproj/argo-cd/v2/util/healthz"
ioutil "github.com/argoproj/argo-cd/v2/util/io"
)
// NewCommand returns a new instance of an argocd-commit-server command
func NewCommand() *cobra.Command {
var (
listenHost string
listenPort int
metricsPort int
metricsHost string
)
command := &cobra.Command{
Use: "argocd-commit-server",
Short: "Run Argo CD Commit Server",
Long: "Argo CD Commit Server is an internal service which commits and pushes hydrated manifests to git. This command runs Commit Server in the foreground.",
RunE: func(cmd *cobra.Command, args []string) error {
vers := common.GetVersion()
vers.LogStartupInfo(
"Argo CD Commit Server",
map[string]any{
"port": listenPort,
},
)
cli.SetLogFormat(cmdutil.LogFormat)
cli.SetLogLevel(cmdutil.LogLevel)
metricsServer := metrics.NewMetricsServer()
http.Handle("/metrics", metricsServer.GetHandler())
go func() { errors.CheckError(http.ListenAndServe(fmt.Sprintf("%s:%d", metricsHost, metricsPort), nil)) }()
askPassServer := askpass.NewServer(askpass.CommitServerSocketPath)
go func() { errors.CheckError(askPassServer.Run()) }()
server := commitserver.NewServer(askPassServer, metricsServer)
grpc := server.CreateGRPC()
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", listenHost, listenPort))
errors.CheckError(err)
healthz.ServeHealthCheck(http.DefaultServeMux, func(r *http.Request) error {
if val, ok := r.URL.Query()["full"]; ok && len(val) > 0 && val[0] == "true" {
// connect to itself to make sure commit server is able to serve connection
// used by liveness probe to auto restart commit server
conn, err := apiclient.NewConnection(fmt.Sprintf("localhost:%d", listenPort))
if err != nil {
return err
}
defer ioutil.Close(conn)
client := grpc_health_v1.NewHealthClient(conn)
res, err := client.Check(r.Context(), &grpc_health_v1.HealthCheckRequest{})
if err != nil {
return err
}
if res.Status != grpc_health_v1.HealthCheckResponse_SERVING {
return fmt.Errorf("grpc health check status is '%v'", res.Status)
}
return nil
}
return nil
})
// Graceful shutdown code adapted from here: https://gist.github.com/embano1/e0bf49d24f1cdd07cffad93097c04f0a
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
s := <-sigCh
log.Printf("got signal %v, attempting graceful shutdown", s)
grpc.GracefulStop()
wg.Done()
}()
log.Println("starting grpc server")
err = grpc.Serve(listener)
errors.CheckError(err)
wg.Wait()
log.Println("clean shutdown")
return nil
},
}
command.Flags().StringVar(&cmdutil.LogFormat, "logformat", env.StringFromEnv("ARGOCD_COMMIT_SERVER_LOGFORMAT", "text"), "Set the logging format. One of: text|json")
command.Flags().StringVar(&cmdutil.LogLevel, "loglevel", env.StringFromEnv("ARGOCD_COMMIT_SERVER_LOGLEVEL", "info"), "Set the logging level. One of: debug|info|warn|error")
command.Flags().StringVar(&listenHost, "address", env.StringFromEnv("ARGOCD_COMMIT_SERVER_LISTEN_ADDRESS", common.DefaultAddressCommitServer), "Listen on given address for incoming connections")
command.Flags().IntVar(&listenPort, "port", common.DefaultPortCommitServer, "Listen on given port for incoming connections")
command.Flags().StringVar(&metricsHost, "metrics-address", env.StringFromEnv("ARGOCD_COMMIT_SERVER_METRICS_LISTEN_ADDRESS", common.DefaultAddressCommitServerMetrics), "Listen on given address for metrics")
command.Flags().IntVar(&metricsPort, "metrics-port", common.DefaultPortCommitServerMetrics, "Start metrics server on given port")
return command
}

View File

@@ -9,7 +9,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"github.com/argoproj/argo-cd/v2/reposerver/askpass"
"github.com/argoproj/argo-cd/v2/util/askpass"
"github.com/argoproj/argo-cd/v2/util/errors"
grpc_util "github.com/argoproj/argo-cd/v2/util/grpc"
"github.com/argoproj/argo-cd/v2/util/io"

View File

@@ -23,10 +23,10 @@ import (
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/reposerver"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/reposerver/askpass"
reposervercache "github.com/argoproj/argo-cd/v2/reposerver/cache"
"github.com/argoproj/argo-cd/v2/reposerver/metrics"
"github.com/argoproj/argo-cd/v2/reposerver/repository"
"github.com/argoproj/argo-cd/v2/util/askpass"
cacheutil "github.com/argoproj/argo-cd/v2/util/cache"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/util/env"
@@ -130,7 +130,7 @@ func NewCommand() *cobra.Command {
askPassServer := askpass.NewServer(askpass.SocketPath)
metricsServer := metrics.NewMetricsServer()
cacheutil.CollectMetrics(redisClient, metricsServer)
cacheutil.CollectMetrics(redisClient, metricsServer, nil)
server, err := reposerver.NewServer(metricsServer, cache, tlsConfigCustomizer, repository.RepoServerInitConstants{
ParallelismLimit: parallelismLimit,
PauseGenerationAfterFailedGenerationAttempts: pauseGenerationAfterFailedGenerationAttempts,

View File

@@ -258,22 +258,25 @@ func NewCommand() *cobra.Command {
stats.RegisterHeapDumper("memprofile")
argocd := server.NewServer(ctx, argoCDOpts, appsetOpts)
argocd.Init(ctx)
lns, err := argocd.Listen()
errors.CheckError(err)
for {
var closer func()
ctx, cancel := context.WithCancel(ctx)
serverCtx, cancel := context.WithCancel(ctx)
lns, err := argocd.Listen()
errors.CheckError(err)
if otlpAddress != "" {
closer, err = traceutil.InitTracer(ctx, "argocd-server", otlpAddress, otlpInsecure, otlpHeaders, otlpAttrs)
closer, err = traceutil.InitTracer(serverCtx, "argocd-server", otlpAddress, otlpInsecure, otlpHeaders, otlpAttrs)
if err != nil {
log.Fatalf("failed to initialize tracing: %v", err)
}
}
argocd.Run(ctx, lns)
cancel()
argocd.Run(serverCtx, lns)
if closer != nil {
closer()
}
cancel()
if argocd.TerminateRequested() {
break
}
}
},
Example: templates.Examples(`

View File

@@ -680,7 +680,7 @@ func NewGenClusterConfigCommand(pathOpts *clientcmd.PathOptions) *cobra.Command
command.PersistentFlags().StringVar(&pathOpts.LoadingRules.ExplicitPath, pathOpts.ExplicitFileFlag, pathOpts.LoadingRules.ExplicitPath, "use a particular kubeconfig file")
command.Flags().StringVar(&bearerToken, "bearer-token", "", "Authentication token that should be used to access K8S API server")
command.Flags().BoolVar(&generateToken, "generate-bearer-token", false, "Generate authentication token that should be used to access K8S API server")
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "argocd-manager", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default \"%s\" SA will be used", clusterauth.ArgoCDManagerServiceAccount))
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "argocd-manager", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default %q SA will be used", clusterauth.ArgoCDManagerServiceAccount))
command.Flags().StringVar(&clusterOpts.SystemNamespace, "system-namespace", common.DefaultSystemNamespace, "Use different system namespace")
command.Flags().StringVarP(&outputFormat, "output", "o", "yaml", "Output format. One of: json|yaml")
command.Flags().StringArrayVar(&labels, "label", nil, "Set metadata labels (e.g. --label key=value)")

View File

@@ -50,13 +50,13 @@ func NewGenProjectSpecCommand() *cobra.Command {
Short: "Generate declarative config for a project",
Example: templates.Examples(`
# Generate a YAML configuration for a project named "myproject"
argocd admin projects generate-spec myproject
argocd admin proj generate-spec myproject
# Generate a JSON configuration for a project named "anotherproject" and specify an output file
argocd admin projects generate-spec anotherproject --output json --file config.json
argocd admin proj generate-spec anotherproject --output json --file config.json
# Generate a YAML configuration for a project named "someproject" and write it back to the input file
argocd admin projects generate-spec someproject --inline
argocd admin proj generate-spec someproject --inline
`),
Run: func(c *cobra.Command, args []string) {
@@ -155,10 +155,10 @@ func NewUpdatePolicyRuleCommand() *cobra.Command {
Use: "update-role-policy PROJECT_GLOB MODIFICATION ACTION",
Short: "Implement bulk project role update. Useful to back-fill existing project policies or remove obsolete actions.",
Example: ` # Add policy that allows executing any action (action/*) to roles which name matches to *deployer* in all projects
argocd admin projects update-role-policy '*' set 'action/*' --role '*deployer*' --resource applications --scope '*' --permission allow
argocd admin proj update-role-policy '*' set 'action/*' --role '*deployer*' --resource applications --scope '*' --permission allow
# Remove policy that which manages running (action/*) from all roles which name matches *deployer* in all projects
argocd admin projects update-role-policy '*' remove override --role '*deployer*'
argocd admin proj update-role-policy '*' remove override --role '*deployer*'
`,
Run: func(c *cobra.Command, args []string) {
ctx := c.Context()

View File

@@ -192,7 +192,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
}
command.PersistentFlags().StringVar(&pathOpts.LoadingRules.ExplicitPath, pathOpts.ExplicitFileFlag, pathOpts.LoadingRules.ExplicitPath, "use a particular kubeconfig file")
command.Flags().BoolVar(&clusterOpts.Upsert, "upsert", false, "Override an existing cluster with the same name even if the spec differs")
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default \"%s\" SA will be created", clusterauth.ArgoCDManagerServiceAccount))
command.Flags().StringVar(&clusterOpts.ServiceAccount, "service-account", "", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default %q SA will be created", clusterauth.ArgoCDManagerServiceAccount))
command.Flags().StringVar(&clusterOpts.SystemNamespace, "system-namespace", common.DefaultSystemNamespace, "Use different system namespace")
command.Flags().BoolVarP(&skipConfirmation, "yes", "y", false, "Skip explicit confirmation")
command.Flags().StringArrayVar(&labels, "label", nil, "Set metadata labels (e.g. --label key=value)")

View File

@@ -11,6 +11,7 @@ import (
appcontroller "github.com/argoproj/argo-cd/v2/cmd/argocd-application-controller/commands"
applicationset "github.com/argoproj/argo-cd/v2/cmd/argocd-applicationset-controller/commands"
cmpserver "github.com/argoproj/argo-cd/v2/cmd/argocd-cmp-server/commands"
commitserver "github.com/argoproj/argo-cd/v2/cmd/argocd-commit-server/commands"
dex "github.com/argoproj/argo-cd/v2/cmd/argocd-dex/commands"
gitaskpass "github.com/argoproj/argo-cd/v2/cmd/argocd-git-ask-pass/commands"
k8sauth "github.com/argoproj/argo-cd/v2/cmd/argocd-k8s-auth/commands"
@@ -46,6 +47,8 @@ func main() {
case "argocd-cmp-server":
command = cmpserver.NewCommand()
isCLI = true
case "argocd-commit-server":
command = commitserver.NewCommand()
case "argocd-dex":
command = dex.NewCommand()
case "argocd-notifications":

View File

@@ -0,0 +1,49 @@
package apiclient
import (
"fmt"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"github.com/argoproj/argo-cd/v2/util/io"
)
// Clientset represents commit server api clients
type Clientset interface {
NewCommitServerClient() (io.Closer, CommitServiceClient, error)
}
type clientSet struct {
address string
}
// NewCommitServerClient creates new instance of commit server client
func (c *clientSet) NewCommitServerClient() (io.Closer, CommitServiceClient, error) {
conn, err := NewConnection(c.address)
if err != nil {
return nil, nil, fmt.Errorf("failed to open a new connection to commit server: %w", err)
}
return conn, NewCommitServiceClient(conn), nil
}
// NewConnection creates new connection to commit server
func NewConnection(address string) (*grpc.ClientConn, error) {
var opts []grpc.DialOption
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
// TODO: switch to grpc.NewClient.
// nolint:staticcheck
conn, err := grpc.Dial(address, opts...)
if err != nil {
log.Errorf("Unable to connect to commit service with address %s", address)
return nil, err
}
return conn, nil
}
// NewCommitServerClientset creates new instance of commit server Clientset
func NewCommitServerClientset(address string) Clientset {
return &clientSet{address: address}
}

1382
commitserver/apiclient/commit.pb.go generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
// Code generated by mockery v2.43.2. DO NOT EDIT.
package mocks
import (
apiclient "github.com/argoproj/argo-cd/v2/commitserver/apiclient"
io "github.com/argoproj/argo-cd/v2/util/io"
mock "github.com/stretchr/testify/mock"
)
// Clientset is an autogenerated mock type for the Clientset type
type Clientset struct {
mock.Mock
}
// NewCommitServerClient provides a mock function with given fields:
func (_m *Clientset) NewCommitServerClient() (io.Closer, apiclient.CommitServiceClient, error) {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for NewCommitServerClient")
}
var r0 io.Closer
var r1 apiclient.CommitServiceClient
var r2 error
if rf, ok := ret.Get(0).(func() (io.Closer, apiclient.CommitServiceClient, error)); ok {
return rf()
}
if rf, ok := ret.Get(0).(func() io.Closer); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(io.Closer)
}
}
if rf, ok := ret.Get(1).(func() apiclient.CommitServiceClient); ok {
r1 = rf()
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(apiclient.CommitServiceClient)
}
}
if rf, ok := ret.Get(2).(func() error); ok {
r2 = rf()
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// NewClientset creates a new instance of Clientset. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewClientset(t interface {
mock.TestingT
Cleanup(func())
}) *Clientset {
mock := &Clientset{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,69 @@
// Code generated by mockery v2.43.2. DO NOT EDIT.
package mocks
import (
context "context"
apiclient "github.com/argoproj/argo-cd/v2/commitserver/apiclient"
grpc "google.golang.org/grpc"
mock "github.com/stretchr/testify/mock"
)
// CommitServiceClient is an autogenerated mock type for the CommitServiceClient type
type CommitServiceClient struct {
mock.Mock
}
// CommitHydratedManifests provides a mock function with given fields: ctx, in, opts
func (_m *CommitServiceClient) CommitHydratedManifests(ctx context.Context, in *apiclient.CommitHydratedManifestsRequest, opts ...grpc.CallOption) (*apiclient.CommitHydratedManifestsResponse, error) {
_va := make([]interface{}, len(opts))
for _i := range opts {
_va[_i] = opts[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx, in)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for CommitHydratedManifests")
}
var r0 *apiclient.CommitHydratedManifestsResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *apiclient.CommitHydratedManifestsRequest, ...grpc.CallOption) (*apiclient.CommitHydratedManifestsResponse, error)); ok {
return rf(ctx, in, opts...)
}
if rf, ok := ret.Get(0).(func(context.Context, *apiclient.CommitHydratedManifestsRequest, ...grpc.CallOption) *apiclient.CommitHydratedManifestsResponse); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*apiclient.CommitHydratedManifestsResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *apiclient.CommitHydratedManifestsRequest, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewCommitServiceClient creates a new instance of CommitServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewCommitServiceClient(t interface {
mock.TestingT
Cleanup(func())
}) *CommitServiceClient {
mock := &CommitServiceClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,225 @@
package commit
import (
"context"
"fmt"
"os"
"time"
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/v2/commitserver/apiclient"
"github.com/argoproj/argo-cd/v2/commitserver/metrics"
"github.com/argoproj/argo-cd/v2/util/git"
"github.com/argoproj/argo-cd/v2/util/io/files"
)
// Service is the service that handles commit requests.
type Service struct {
gitCredsStore git.CredsStore
metricsServer *metrics.Server
repoClientFactory RepoClientFactory
}
// NewService returns a new instance of the commit service.
func NewService(gitCredsStore git.CredsStore, metricsServer *metrics.Server) *Service {
return &Service{
gitCredsStore: gitCredsStore,
metricsServer: metricsServer,
repoClientFactory: NewRepoClientFactory(gitCredsStore, metricsServer),
}
}
// CommitHydratedManifests handles a commit request. It clones the repository, checks out the sync branch, checks out
// the target branch, clears the repository contents, writes the manifests to the repository, commits the changes, and
// pushes the changes. It returns the hydrated revision SHA and an error if one occurred.
func (s *Service) CommitHydratedManifests(ctx context.Context, r *apiclient.CommitHydratedManifestsRequest) (*apiclient.CommitHydratedManifestsResponse, error) {
// This method is intentionally short. It's a wrapper around handleCommitRequest that adds metrics and logging.
// Keep logic here minimal and put most of the logic in handleCommitRequest.
startTime := time.Now()
// We validate for a nil repo in handleCommitRequest, but we need to check for a nil repo here to get the repo URL
// for metrics.
var repoURL string
if r.Repo != nil {
repoURL = r.Repo.Repo
}
var err error
s.metricsServer.IncPendingCommitRequest(repoURL)
defer func() {
s.metricsServer.DecPendingCommitRequest(repoURL)
commitResponseType := metrics.CommitResponseTypeSuccess
if err != nil {
commitResponseType = metrics.CommitResponseTypeFailure
}
s.metricsServer.IncCommitRequest(repoURL, commitResponseType)
s.metricsServer.ObserveCommitRequestDuration(repoURL, commitResponseType, time.Since(startTime))
}()
logCtx := log.WithFields(log.Fields{"branch": r.TargetBranch, "drySHA": r.DrySha})
out, sha, err := s.handleCommitRequest(logCtx, r)
if err != nil {
logCtx.WithError(err).WithField("output", out).Error("failed to handle commit request")
// No need to wrap this error, sufficient context is build in handleCommitRequest.
return &apiclient.CommitHydratedManifestsResponse{}, err
}
logCtx.Info("Successfully handled commit request")
return &apiclient.CommitHydratedManifestsResponse{
HydratedSha: sha,
}, nil
}
// handleCommitRequest handles the commit request. It clones the repository, checks out the sync branch, checks out the
// target branch, clears the repository contents, writes the manifests to the repository, commits the changes, and pushes
// the changes. It returns the output of the git commands and an error if one occurred.
func (s *Service) handleCommitRequest(logCtx *log.Entry, r *apiclient.CommitHydratedManifestsRequest) (string, string, error) {
if r.Repo == nil {
return "", "", fmt.Errorf("repo is required")
}
if r.Repo.Repo == "" {
return "", "", fmt.Errorf("repo URL is required")
}
if r.TargetBranch == "" {
return "", "", fmt.Errorf("target branch is required")
}
if r.SyncBranch == "" {
return "", "", fmt.Errorf("sync branch is required")
}
logCtx = logCtx.WithField("repo", r.Repo.Repo)
logCtx.Debug("Initiating git client")
gitClient, dirPath, cleanup, err := s.initGitClient(logCtx, r)
if err != nil {
return "", "", fmt.Errorf("failed to init git client: %w", err)
}
defer cleanup()
logCtx.Debugf("Checking out sync branch %s", r.SyncBranch)
var out string
out, err = gitClient.CheckoutOrOrphan(r.SyncBranch, false)
if err != nil {
return out, "", fmt.Errorf("failed to checkout sync branch: %w", err)
}
logCtx.Debugf("Checking out target branch %s", r.TargetBranch)
out, err = gitClient.CheckoutOrNew(r.TargetBranch, r.SyncBranch, false)
if err != nil {
return out, "", fmt.Errorf("failed to checkout target branch: %w", err)
}
logCtx.Debug("Clearing repo contents")
out, err = gitClient.RemoveContents()
if err != nil {
return out, "", fmt.Errorf("failed to clear repo: %w", err)
}
logCtx.Debug("Writing manifests")
err = WriteForPaths(dirPath, r.Repo.Repo, r.DrySha, r.Paths)
if err != nil {
return "", "", fmt.Errorf("failed to write manifests: %w", err)
}
logCtx.Debug("Committing and pushing changes")
out, err = gitClient.CommitAndPush(r.TargetBranch, r.CommitMessage)
if err != nil {
return out, "", fmt.Errorf("failed to commit and push: %w", err)
}
logCtx.Debug("Getting commit SHA")
sha, err := gitClient.CommitSHA()
if err != nil {
return "", "", fmt.Errorf("failed to get commit SHA: %w", err)
}
return "", sha, nil
}
// initGitClient initializes a git client for the given repository and returns the client, the path to the directory where
// the repository is cloned, a cleanup function that should be called when the directory is no longer needed, and an error
// if one occurred.
func (s *Service) initGitClient(logCtx *log.Entry, r *apiclient.CommitHydratedManifestsRequest) (git.Client, string, func(), error) {
dirPath, err := files.CreateTempDir("/tmp/_commit-service")
if err != nil {
return nil, "", nil, fmt.Errorf("failed to create temp dir: %w", err)
}
// Call cleanupOrLog in this function if an error occurs to ensure the temp dir is cleaned up.
cleanupOrLog := func() {
err := os.RemoveAll(dirPath)
if err != nil {
logCtx.WithError(err).Error("failed to cleanup temp dir")
}
}
gitClient, err := s.repoClientFactory.NewClient(r.Repo, dirPath)
if err != nil {
cleanupOrLog()
return nil, "", nil, fmt.Errorf("failed to create git client: %w", err)
}
logCtx.Debugf("Initializing repo %s", r.Repo.Repo)
err = gitClient.Init()
if err != nil {
cleanupOrLog()
return nil, "", nil, fmt.Errorf("failed to init git client: %w", err)
}
logCtx.Debugf("Fetching repo %s", r.Repo.Repo)
err = gitClient.Fetch("")
if err != nil {
cleanupOrLog()
return nil, "", nil, fmt.Errorf("failed to clone repo: %w", err)
}
// FIXME: make it work for GHE
//logCtx.Debugf("Getting user info for repo credentials")
//gitCreds := r.Repo.GetGitCreds(s.gitCredsStore)
//startTime := time.Now()
//authorName, authorEmail, err := gitCreds.GetUserInfo(ctx)
//s.metricsServer.ObserveUserInfoRequestDuration(r.Repo.Repo, getCredentialType(r.Repo), time.Since(startTime))
//if err != nil {
// cleanupOrLog()
// return nil, "", nil, fmt.Errorf("failed to get github app info: %w", err)
//}
var authorName, authorEmail string
if authorName == "" {
authorName = "Argo CD"
}
if authorEmail == "" {
logCtx.Warnf("Author email not available, using 'argo-cd@example.com'.")
authorEmail = "argo-cd@example.com"
}
logCtx.Debugf("Setting author %s <%s>", authorName, authorEmail)
_, err = gitClient.SetAuthor(authorName, authorEmail)
if err != nil {
cleanupOrLog()
return nil, "", nil, fmt.Errorf("failed to set author: %w", err)
}
return gitClient, dirPath, cleanupOrLog, nil
}
type hydratorMetadataFile struct {
RepoURL string `json:"repoURL"`
DrySHA string `json:"drySha"`
Commands []string `json:"commands"`
}
// TODO: make this configurable via ConfigMap.
var manifestHydrationReadmeTemplate = `
# Manifest Hydration
To hydrate the manifests in this repository, run the following commands:
` + "```shell\n" + `
git clone {{ .RepoURL }}
# cd into the cloned directory
git checkout {{ .DrySHA }}
{{ range $command := .Commands -}}
{{ $command }}
{{ end -}}` + "```"

View File

@@ -0,0 +1,50 @@
syntax = "proto3";
option go_package = "github.com/argoproj/argo-cd/v2/commitserver/apiclient";
import "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1/generated.proto";
// CommitHydratedManifestsRequest is the request to commit hydrated manifests to a repository.
message CommitHydratedManifestsRequest {
// Repo contains repository information including, at minimum, the URL of the repository. Generally it will contain
// repo credentials.
github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.Repository repo = 1;
// SyncBranch is the branch Argo CD syncs from, i.e. the hydrated branch.
string syncBranch = 2;
// TargetBranch is the branch Argo CD is committing to, i.e. the branch that will be updated.
string targetBranch = 3;
// DrySha is the commit SHA from the dry branch, i.e. pre-rendered manifest branch.
string drySha = 4;
// CommitMessage is the commit message to use when committing changes.
string commitMessage = 5;
// Paths contains the paths to write hydrated manifests to, along with the manifests and commands to execute.
repeated PathDetails paths = 6;
}
// PathDetails holds information about hydrated manifests to be written to a particular path in the hydrated manifests
// commit.
message PathDetails {
// Path is the path to write the hydrated manifests to.
string path = 1;
// Manifests contains the manifests to write to the path.
repeated HydratedManifestDetails manifests = 2;
// Commands contains the commands executed when hydrating the manifests.
repeated string commands = 3;
}
// ManifestDetails contains the hydrated manifests.
message HydratedManifestDetails {
// ManifestJSON is the hydrated manifest as JSON.
string manifestJSON = 1;
}
// ManifestsResponse is the response to the ManifestsRequest.
message CommitHydratedManifestsResponse {
// HydratedSha is the commit SHA of the hydrated manifests commit.
string hydratedSha = 1;
}
// CommitService is the service for committing hydrated manifests to a repository.
service CommitService {
// Commit commits hydrated manifests to a repository.
rpc CommitHydratedManifests (CommitHydratedManifestsRequest) returns (CommitHydratedManifestsResponse);
}

View File

@@ -0,0 +1,125 @@
package commit
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/argoproj/argo-cd/v2/commitserver/apiclient"
"github.com/argoproj/argo-cd/v2/commitserver/commit/mocks"
"github.com/argoproj/argo-cd/v2/commitserver/metrics"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/git"
gitmocks "github.com/argoproj/argo-cd/v2/util/git/mocks"
)
func Test_CommitHydratedManifests(t *testing.T) {
t.Parallel()
validRequest := &apiclient.CommitHydratedManifestsRequest{
Repo: &v1alpha1.Repository{
Repo: "https://github.com/argoproj/argocd-example-apps.git",
},
TargetBranch: "main",
SyncBranch: "env/test",
CommitMessage: "test commit message",
}
t.Run("missing repo", func(t *testing.T) {
t.Parallel()
service, _ := newServiceWithMocks(t)
request := &apiclient.CommitHydratedManifestsRequest{}
_, err := service.CommitHydratedManifests(context.Background(), request)
require.Error(t, err)
assert.ErrorContains(t, err, "repo is required")
})
t.Run("missing repo URL", func(t *testing.T) {
t.Parallel()
service, _ := newServiceWithMocks(t)
request := &apiclient.CommitHydratedManifestsRequest{
Repo: &v1alpha1.Repository{},
}
_, err := service.CommitHydratedManifests(context.Background(), request)
require.Error(t, err)
assert.ErrorContains(t, err, "repo URL is required")
})
t.Run("missing target branch", func(t *testing.T) {
t.Parallel()
service, _ := newServiceWithMocks(t)
request := &apiclient.CommitHydratedManifestsRequest{
Repo: &v1alpha1.Repository{
Repo: "https://github.com/argoproj/argocd-example-apps.git",
},
}
_, err := service.CommitHydratedManifests(context.Background(), request)
require.Error(t, err)
assert.ErrorContains(t, err, "target branch is required")
})
t.Run("missing sync branch", func(t *testing.T) {
t.Parallel()
service, _ := newServiceWithMocks(t)
request := &apiclient.CommitHydratedManifestsRequest{
Repo: &v1alpha1.Repository{
Repo: "https://github.com/argoproj/argocd-example-apps.git",
},
TargetBranch: "main",
}
_, err := service.CommitHydratedManifests(context.Background(), request)
require.Error(t, err)
assert.ErrorContains(t, err, "sync branch is required")
})
t.Run("failed to create git client", func(t *testing.T) {
t.Parallel()
service, mockRepoClientFactory := newServiceWithMocks(t)
mockRepoClientFactory.On("NewClient", mock.Anything, mock.Anything).Return(nil, assert.AnError).Once()
_, err := service.CommitHydratedManifests(context.Background(), validRequest)
require.Error(t, err)
assert.ErrorIs(t, err, assert.AnError)
})
t.Run("happy path", func(t *testing.T) {
t.Parallel()
service, mockRepoClientFactory := newServiceWithMocks(t)
mockGitClient := gitmocks.NewClient(t)
mockGitClient.On("Init").Return(nil).Once()
mockGitClient.On("Fetch", mock.Anything).Return(nil).Once()
mockGitClient.On("SetAuthor", "Argo CD", "argo-cd@example.com").Return("", nil).Once()
mockGitClient.On("CheckoutOrOrphan", "env/test", false).Return("", nil).Once()
mockGitClient.On("CheckoutOrNew", "main", "env/test", false).Return("", nil).Once()
mockGitClient.On("RemoveContents").Return("", nil).Once()
mockGitClient.On("CommitAndPush", "main", "test commit message").Return("", nil).Once()
mockGitClient.On("CommitSHA").Return("it-worked!", nil).Once()
mockRepoClientFactory.On("NewClient", mock.Anything, mock.Anything).Return(mockGitClient, nil).Once()
resp, err := service.CommitHydratedManifests(context.Background(), validRequest)
require.NoError(t, err)
require.NotNil(t, resp)
assert.Equal(t, "it-worked!", resp.HydratedSha)
})
}
func newServiceWithMocks(t *testing.T) (*Service, *mocks.RepoClientFactory) {
t.Helper()
metricsServer := metrics.NewMetricsServer()
mockCredsStore := git.NoopCredsStore{}
service := NewService(mockCredsStore, metricsServer)
mockRepoClientFactory := mocks.NewRepoClientFactory(t)
service.repoClientFactory = mockRepoClientFactory
return service, mockRepoClientFactory
}

View File

@@ -0,0 +1,23 @@
package commit
import "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
// getCredentialType returns the type of credential used by the repository.
func getCredentialType(repo *v1alpha1.Repository) string {
if repo == nil {
return ""
}
if repo.Password != "" {
return "https"
}
if repo.SSHPrivateKey != "" {
return "ssh"
}
if repo.GithubAppPrivateKey != "" && repo.GithubAppId != 0 && repo.GithubAppInstallationId != 0 {
return "github-app"
}
if repo.GCPServiceAccountKey != "" {
return "cloud-source-repositories"
}
return ""
}

View File

@@ -0,0 +1,62 @@
package commit
import (
"testing"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
func TestRepository_GetCredentialType(t *testing.T) {
tests := []struct {
name string
repo *v1alpha1.Repository
want string
}{
{
name: "Empty Repository",
repo: nil,
want: "",
},
{
name: "HTTPS Repository",
repo: &v1alpha1.Repository{
Repo: "foo",
Password: "some-password",
},
want: "https",
},
{
name: "SSH Repository",
repo: &v1alpha1.Repository{
Repo: "foo",
SSHPrivateKey: "some-key",
},
want: "ssh",
},
{
name: "GitHub App Repository",
repo: &v1alpha1.Repository{
Repo: "foo",
GithubAppPrivateKey: "some-key",
GithubAppId: 1,
GithubAppInstallationId: 1,
},
want: "github-app",
},
{
name: "Google Cloud Repository",
repo: &v1alpha1.Repository{
Repo: "foo",
GCPServiceAccountKey: "some-key",
},
want: "cloud-source-repositories",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getCredentialType(tt.repo); got != tt.want {
t.Errorf("Repository.GetCredentialType() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -0,0 +1,145 @@
package commit
import (
"encoding/json"
"fmt"
"os"
"path"
"text/template"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/argoproj/argo-cd/v2/commitserver/apiclient"
"github.com/argoproj/argo-cd/v2/util/io/files"
)
// WriteForPaths writes the manifests, hydrator.metadata, and README.md files for each path in the provided paths. It
// also writes a root-level hydrator.metadata file containing the repo URL and dry SHA.
func WriteForPaths(rootPath string, repoUrl string, drySha string, paths []*apiclient.PathDetails) error {
// Write the top-level readme.
err := writeMetadata(rootPath, hydratorMetadataFile{DrySHA: drySha, RepoURL: repoUrl})
if err != nil {
return fmt.Errorf("failed to write top-level hydrator metadata: %w", err)
}
for _, p := range paths {
hydratePath := p.Path
if hydratePath == "." {
hydratePath = ""
}
var fullHydratePath string
fullHydratePath, err = files.SecureMkdirAll(rootPath, hydratePath, os.ModePerm)
if err != nil {
return fmt.Errorf("failed to create path: %w", err)
}
// Write the manifests
err = writeManifests(fullHydratePath, p.Manifests)
if err != nil {
return fmt.Errorf("failed to write manifests: %w", err)
}
// Write hydrator.metadata containing information about the hydration process.
hydratorMetadata := hydratorMetadataFile{
Commands: p.Commands,
DrySHA: drySha,
RepoURL: repoUrl,
}
err = writeMetadata(fullHydratePath, hydratorMetadata)
if err != nil {
return fmt.Errorf("failed to write hydrator metadata: %w", err)
}
// Write README
err = writeReadme(fullHydratePath, hydratorMetadata)
if err != nil {
return fmt.Errorf("failed to write readme: %w", err)
}
}
return nil
}
// writeMetadata writes the metadata to the hydrator.metadata file.
func writeMetadata(dirPath string, metadata hydratorMetadataFile) error {
hydratorMetadataJson, err := json.MarshalIndent(metadata, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal hydrator metadata: %w", err)
}
// No need to use SecureJoin here, as the path is already sanitized.
hydratorMetadataPath := path.Join(dirPath, "hydrator.metadata")
err = os.WriteFile(hydratorMetadataPath, hydratorMetadataJson, os.ModePerm)
if err != nil {
return fmt.Errorf("failed to write hydrator metadata: %w", err)
}
return nil
}
// writeReadme writes the readme to the README.md file.
func writeReadme(dirPath string, metadata hydratorMetadataFile) error {
readmeTemplate := template.New("readme")
readmeTemplate, err := readmeTemplate.Parse(manifestHydrationReadmeTemplate)
if err != nil {
return fmt.Errorf("failed to parse readme template: %w", err)
}
// Create writer to template into
// No need to use SecureJoin here, as the path is already sanitized.
readmePath := path.Join(dirPath, "README.md")
readmeFile, err := os.Create(readmePath)
if err != nil && !os.IsExist(err) {
return fmt.Errorf("failed to create README file: %w", err)
}
err = readmeTemplate.Execute(readmeFile, metadata)
closeErr := readmeFile.Close()
if closeErr != nil {
log.WithError(closeErr).Error("failed to close README file")
}
if err != nil {
return fmt.Errorf("failed to execute readme template: %w", err)
}
return nil
}
// writeManifests writes the manifests to the manifest.yaml file, truncating the file if it exists and appending the
// manifests in the order they are provided.
func writeManifests(dirPath string, manifests []*apiclient.HydratedManifestDetails) error {
// If the file exists, truncate it.
// No need to use SecureJoin here, as the path is already sanitized.
manifestPath := path.Join(dirPath, "manifest.yaml")
file, err := os.OpenFile(manifestPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
if err != nil {
return fmt.Errorf("failed to open manifest file: %w", err)
}
defer func() {
err := file.Close()
if err != nil {
log.WithError(err).Error("failed to close file")
}
}()
enc := yaml.NewEncoder(file)
defer func() {
err := enc.Close()
if err != nil {
log.WithError(err).Error("failed to close yaml encoder")
}
}()
enc.SetIndent(2)
for _, m := range manifests {
obj := &unstructured.Unstructured{}
err = json.Unmarshal([]byte(m.ManifestJSON), obj)
if err != nil {
return fmt.Errorf("failed to unmarshal manifest: %w", err)
}
err = enc.Encode(&obj.Object)
if err != nil {
return fmt.Errorf("failed to encode manifest: %w", err)
}
}
return nil
}

View File

@@ -0,0 +1,135 @@
package commit
import (
"encoding/json"
"os"
"path"
"testing"
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/argoproj/argo-cd/v2/commitserver/apiclient"
)
func TestWriteForPaths(t *testing.T) {
dir := t.TempDir()
repoUrl := "https://github.com/example/repo"
drySha := "abc123"
paths := []*apiclient.PathDetails{
{
Path: "path1",
Manifests: []*apiclient.HydratedManifestDetails{
{ManifestJSON: `{"kind":"Pod","apiVersion":"v1"}`},
},
Commands: []string{"command1", "command2"},
},
{
Path: "path2",
Manifests: []*apiclient.HydratedManifestDetails{
{ManifestJSON: `{"kind":"Service","apiVersion":"v1"}`},
},
Commands: []string{"command3"},
},
}
err := WriteForPaths(dir, repoUrl, drySha, paths)
require.NoError(t, err)
// Check if the top-level hydrator.metadata exists and contains the repo URL and dry SHA
topMetadataPath := path.Join(dir, "hydrator.metadata")
topMetadataBytes, err := os.ReadFile(topMetadataPath)
require.NoError(t, err)
var topMetadata hydratorMetadataFile
err = json.Unmarshal(topMetadataBytes, &topMetadata)
require.NoError(t, err)
assert.Equal(t, repoUrl, topMetadata.RepoURL)
assert.Equal(t, drySha, topMetadata.DrySHA)
for _, p := range paths {
fullHydratePath, err := securejoin.SecureJoin(dir, p.Path)
require.NoError(t, err)
// Check if each path directory exists
assert.DirExists(t, fullHydratePath)
// Check if each path contains a hydrator.metadata file and contains the repo URL
metadataPath := path.Join(fullHydratePath, "hydrator.metadata")
metadataBytes, err := os.ReadFile(metadataPath)
require.NoError(t, err)
var readMetadata hydratorMetadataFile
err = json.Unmarshal(metadataBytes, &readMetadata)
require.NoError(t, err)
assert.Equal(t, repoUrl, readMetadata.RepoURL)
// Check if each path contains a README.md file and contains the repo URL
readmePath := path.Join(fullHydratePath, "README.md")
readmeBytes, err := os.ReadFile(readmePath)
require.NoError(t, err)
assert.Contains(t, string(readmeBytes), repoUrl)
// Check if each path contains a manifest.yaml file and contains the word Pod
manifestPath := path.Join(fullHydratePath, "manifest.yaml")
manifestBytes, err := os.ReadFile(manifestPath)
require.NoError(t, err)
assert.Contains(t, string(manifestBytes), "kind")
}
}
func TestWriteMetadata(t *testing.T) {
dir := t.TempDir()
metadata := hydratorMetadataFile{
RepoURL: "https://github.com/example/repo",
DrySHA: "abc123",
}
err := writeMetadata(dir, metadata)
require.NoError(t, err)
metadataPath := path.Join(dir, "hydrator.metadata")
metadataBytes, err := os.ReadFile(metadataPath)
require.NoError(t, err)
var readMetadata hydratorMetadataFile
err = json.Unmarshal(metadataBytes, &readMetadata)
require.NoError(t, err)
assert.Equal(t, metadata, readMetadata)
}
func TestWriteReadme(t *testing.T) {
dir := t.TempDir()
metadata := hydratorMetadataFile{
RepoURL: "https://github.com/example/repo",
DrySHA: "abc123",
}
err := writeReadme(dir, metadata)
require.NoError(t, err)
readmePath := path.Join(dir, "README.md")
readmeBytes, err := os.ReadFile(readmePath)
require.NoError(t, err)
assert.Contains(t, string(readmeBytes), metadata.RepoURL)
}
func TestWriteManifests(t *testing.T) {
dir := t.TempDir()
manifests := []*apiclient.HydratedManifestDetails{
{ManifestJSON: `{"kind":"Pod","apiVersion":"v1"}`},
}
err := writeManifests(dir, manifests)
require.NoError(t, err)
manifestPath := path.Join(dir, "manifest.yaml")
manifestBytes, err := os.ReadFile(manifestPath)
require.NoError(t, err)
assert.Contains(t, string(manifestBytes), "kind")
}

View File

@@ -0,0 +1,59 @@
// Code generated by mockery v2.43.2. DO NOT EDIT.
package mocks
import (
git "github.com/argoproj/argo-cd/v2/util/git"
mock "github.com/stretchr/testify/mock"
v1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
// RepoClientFactory is an autogenerated mock type for the RepoClientFactory type
type RepoClientFactory struct {
mock.Mock
}
// NewClient provides a mock function with given fields: repo, rootPath
func (_m *RepoClientFactory) NewClient(repo *v1alpha1.Repository, rootPath string) (git.Client, error) {
ret := _m.Called(repo, rootPath)
if len(ret) == 0 {
panic("no return value specified for NewClient")
}
var r0 git.Client
var r1 error
if rf, ok := ret.Get(0).(func(*v1alpha1.Repository, string) (git.Client, error)); ok {
return rf(repo, rootPath)
}
if rf, ok := ret.Get(0).(func(*v1alpha1.Repository, string) git.Client); ok {
r0 = rf(repo, rootPath)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(git.Client)
}
}
if rf, ok := ret.Get(1).(func(*v1alpha1.Repository, string) error); ok {
r1 = rf(repo, rootPath)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewRepoClientFactory creates a new instance of RepoClientFactory. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewRepoClientFactory(t interface {
mock.TestingT
Cleanup(func())
}) *RepoClientFactory {
mock := &RepoClientFactory{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,32 @@
package commit
import (
"github.com/argoproj/argo-cd/v2/commitserver/metrics"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/git"
)
// RepoClientFactory is a factory for creating git clients for a repository.
type RepoClientFactory interface {
NewClient(repo *v1alpha1.Repository, rootPath string) (git.Client, error)
}
type repoClientFactory struct {
gitCredsStore git.CredsStore
metricsServer *metrics.Server
}
// NewRepoClientFactory returns a new instance of the repo client factory.
func NewRepoClientFactory(gitCredsStore git.CredsStore, metricsServer *metrics.Server) RepoClientFactory {
return &repoClientFactory{
gitCredsStore: gitCredsStore,
metricsServer: metricsServer,
}
}
// NewClient creates a new git client for the repository.
func (r *repoClientFactory) NewClient(repo *v1alpha1.Repository, rootPath string) (git.Client, error) {
gitCreds := repo.GetGitCreds(r.gitCredsStore)
opts := git.WithEventHandlers(metrics.NewGitClientEventHandlers(r.metricsServer))
return git.NewClientExt(repo.Repo, rootPath, gitCreds, repo.IsInsecure(), repo.IsLFSEnabled(), repo.Proxy, repo.NoProxy, opts)
}

View File

@@ -0,0 +1,34 @@
package metrics
import (
"time"
"github.com/argoproj/argo-cd/v2/util/git"
)
// NewGitClientEventHandlers creates event handlers that update Git related metrics
func NewGitClientEventHandlers(metricsServer *Server) git.EventHandlers {
return git.EventHandlers{
OnFetch: func(repo string) func() {
startTime := time.Now()
metricsServer.IncGitRequest(repo, GitRequestTypeFetch)
return func() {
metricsServer.ObserveGitRequestDuration(repo, GitRequestTypeFetch, time.Since(startTime))
}
},
OnLsRemote: func(repo string) func() {
startTime := time.Now()
metricsServer.IncGitRequest(repo, GitRequestTypeLsRemote)
return func() {
metricsServer.ObserveGitRequestDuration(repo, GitRequestTypeLsRemote, time.Since(startTime))
}
},
OnPush: func(repo string) func() {
startTime := time.Now()
metricsServer.IncGitRequest(repo, GitRequestTypePush)
return func() {
metricsServer.ObserveGitRequestDuration(repo, GitRequestTypePush, time.Since(startTime))
}
},
}
}

View File

@@ -0,0 +1,157 @@
package metrics
import (
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
// Server is a prometheus server which collects application metrics.
type Server struct {
handler http.Handler
commitPendingRequestsGauge *prometheus.GaugeVec
gitRequestCounter *prometheus.CounterVec
gitRequestHistogram *prometheus.HistogramVec
commitRequestHistogram *prometheus.HistogramVec
userInfoRequestHistogram *prometheus.HistogramVec
commitRequestCounter *prometheus.CounterVec
}
// GitRequestType is the type of git request
type GitRequestType string
const (
// GitRequestTypeLsRemote is a request to list remote refs
GitRequestTypeLsRemote = "ls-remote"
// GitRequestTypeFetch is a request to fetch from remote
GitRequestTypeFetch = "fetch"
// GitRequestTypePush is a request to push to remote
GitRequestTypePush = "push"
)
// CommitResponseType is the type of response for a commit request
type CommitResponseType string
const (
// CommitResponseTypeSuccess is a successful commit request
CommitResponseTypeSuccess CommitResponseType = "success"
// CommitResponseTypeFailure is a failed commit request
CommitResponseTypeFailure CommitResponseType = "failure"
)
// NewMetricsServer returns a new prometheus server which collects application metrics.
func NewMetricsServer() *Server {
registry := prometheus.NewRegistry()
registry.MustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))
registry.MustRegister(collectors.NewGoCollector())
commitPendingRequestsGauge := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "argocd_commitserver_commit_pending_request_total",
Help: "Number of pending commit requests",
},
[]string{"repo"},
)
registry.MustRegister(commitPendingRequestsGauge)
gitRequestCounter := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "argocd_commitserver_git_request_total",
Help: "Number of git requests performed by repo server",
},
[]string{"repo", "request_type"},
)
registry.MustRegister(gitRequestCounter)
gitRequestHistogram := prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "argocd_commitserver_git_request_duration_seconds",
Help: "Git requests duration seconds.",
Buckets: []float64{0.1, 0.25, .5, 1, 2, 4, 10, 20},
},
[]string{"repo", "request_type"},
)
registry.MustRegister(gitRequestHistogram)
commitRequestHistogram := prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "argocd_commitserver_commit_request_duration_seconds",
Help: "Commit request duration seconds.",
Buckets: []float64{0.1, 0.25, .5, 1, 2, 4, 10, 20},
},
[]string{"repo", "response_type"},
)
registry.MustRegister(commitRequestHistogram)
userInfoRequestHistogram := prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "argocd_commitserver_userinfo_request_duration_seconds",
Help: "Userinfo request duration seconds.",
Buckets: []float64{0.1, 0.25, .5, 1, 2, 4, 10, 20},
},
[]string{"repo", "credential_type"},
)
registry.MustRegister(userInfoRequestHistogram)
commitRequestCounter := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "argocd_commitserver_commit_request_total",
Help: "Number of commit requests performed handled",
},
[]string{"repo", "response_type"},
)
registry.MustRegister(commitRequestCounter)
return &Server{
handler: promhttp.HandlerFor(registry, promhttp.HandlerOpts{}),
commitPendingRequestsGauge: commitPendingRequestsGauge,
gitRequestCounter: gitRequestCounter,
gitRequestHistogram: gitRequestHistogram,
commitRequestHistogram: commitRequestHistogram,
userInfoRequestHistogram: userInfoRequestHistogram,
commitRequestCounter: commitRequestCounter,
}
}
// GetHandler returns the http.Handler for the prometheus server
func (m *Server) GetHandler() http.Handler {
return m.handler
}
// IncPendingCommitRequest increments the pending commit requests gauge
func (m *Server) IncPendingCommitRequest(repo string) {
m.commitPendingRequestsGauge.WithLabelValues(repo).Inc()
}
// DecPendingCommitRequest decrements the pending commit requests gauge
func (m *Server) DecPendingCommitRequest(repo string) {
m.commitPendingRequestsGauge.WithLabelValues(repo).Dec()
}
// IncGitRequest increments the git requests counter
func (m *Server) IncGitRequest(repo string, requestType GitRequestType) {
m.gitRequestCounter.WithLabelValues(repo, string(requestType)).Inc()
}
// ObserveGitRequestDuration observes the duration of a git request
func (m *Server) ObserveGitRequestDuration(repo string, requestType GitRequestType, duration time.Duration) {
m.gitRequestHistogram.WithLabelValues(repo, string(requestType)).Observe(duration.Seconds())
}
// ObserveCommitRequestDuration observes the duration of a commit request
func (m *Server) ObserveCommitRequestDuration(repo string, rt CommitResponseType, duration time.Duration) {
m.commitRequestHistogram.WithLabelValues(repo, string(rt)).Observe(duration.Seconds())
}
// ObserveUserInfoRequestDuration observes the duration of a userinfo request
func (m *Server) ObserveUserInfoRequestDuration(repo string, credentialType string, duration time.Duration) {
m.userInfoRequestHistogram.WithLabelValues(repo, credentialType).Observe(duration.Seconds())
}
// IncCommitRequest increments the commit request counter
func (m *Server) IncCommitRequest(repo string, rt CommitResponseType) {
m.commitRequestCounter.WithLabelValues(repo, string(rt)).Inc()
}

38
commitserver/server.go Normal file
View File

@@ -0,0 +1,38 @@
package commitserver
import (
"google.golang.org/grpc"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
"github.com/argoproj/argo-cd/v2/commitserver/apiclient"
"github.com/argoproj/argo-cd/v2/commitserver/commit"
"github.com/argoproj/argo-cd/v2/commitserver/metrics"
versionpkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/version"
"github.com/argoproj/argo-cd/v2/server/version"
"github.com/argoproj/argo-cd/v2/util/git"
)
// ArgoCDCommitServer is the server that handles commit requests.
type ArgoCDCommitServer struct {
commitService *commit.Service
}
// NewServer returns a new instance of the commit server.
func NewServer(gitCredsStore git.CredsStore, metricsServer *metrics.Server) *ArgoCDCommitServer {
return &ArgoCDCommitServer{commitService: commit.NewService(gitCredsStore, metricsServer)}
}
// CreateGRPC creates a new gRPC server.
func (a *ArgoCDCommitServer) CreateGRPC() *grpc.Server {
server := grpc.NewServer()
versionpkg.RegisterVersionServiceServer(server, version.NewServer(nil, func() (bool, error) {
return true, nil
}))
apiclient.RegisterCommitServiceServer(server, a.commitService)
healthService := health.NewServer()
grpc_health_v1.RegisterHealthServer(server, healthService)
return server
}

View File

@@ -62,15 +62,19 @@ const (
DefaultPortArgoCDMetrics = 8082
DefaultPortArgoCDAPIServerMetrics = 8083
DefaultPortRepoServerMetrics = 8084
DefaultPortCommitServer = 8086
DefaultPortCommitServerMetrics = 8087
)
// DefaultAddressAPIServer for ArgoCD components
const (
DefaultAddressAdminDashboard = "localhost"
DefaultAddressAPIServer = "0.0.0.0"
DefaultAddressAPIServerMetrics = "0.0.0.0"
DefaultAddressRepoServer = "0.0.0.0"
DefaultAddressRepoServerMetrics = "0.0.0.0"
DefaultAddressAdminDashboard = "localhost"
DefaultAddressAPIServer = "0.0.0.0"
DefaultAddressAPIServerMetrics = "0.0.0.0"
DefaultAddressRepoServer = "0.0.0.0"
DefaultAddressRepoServerMetrics = "0.0.0.0"
DefaultAddressCommitServer = "0.0.0.0"
DefaultAddressCommitServerMetrics = "0.0.0.0"
)
// Default paths on the pod's file system

View File

@@ -131,6 +131,7 @@ type ApplicationController struct {
statusRefreshJitter time.Duration
selfHealTimeout time.Duration
selfHealBackOff *wait.Backoff
syncTimeout time.Duration
db db.ArgoDB
settingsMgr *settings_util.SettingsManager
refreshRequestedApps map[string]CompareWith
@@ -161,6 +162,7 @@ func NewApplicationController(
appResyncJitter time.Duration,
selfHealTimeout time.Duration,
selfHealBackoff *wait.Backoff,
syncTimeout time.Duration,
repoErrorGracePeriod time.Duration,
metricsPort int,
metricsCacheExpiration time.Duration,
@@ -202,6 +204,7 @@ func NewApplicationController(
settingsMgr: settingsMgr,
selfHealTimeout: selfHealTimeout,
selfHealBackOff: selfHealBackoff,
syncTimeout: syncTimeout,
clusterSharding: clusterSharding,
projByNameCache: sync.Map{},
applicationNamespaces: applicationNamespaces,
@@ -377,7 +380,11 @@ func (projCache *appProjCache) GetAppProject(ctx context.Context) (*appv1.AppPro
// getAppProj gets the AppProject for the given Application app.
func (ctrl *ApplicationController) getAppProj(app *appv1.Application) (*appv1.AppProject, error) {
projCache, _ := ctrl.projByNameCache.LoadOrStore(app.Spec.GetProject(), ctrl.newAppProjCache(app.Spec.GetProject()))
projCache, _ := ctrl.projByNameCache.Load(app.Spec.GetProject())
if projCache == nil {
projCache = ctrl.newAppProjCache(app.Spec.GetProject())
ctrl.projByNameCache.Store(app.Spec.GetProject(), projCache)
}
proj, err := projCache.(*appProjCache).GetAppProject(context.TODO())
if err != nil {
if apierr.IsNotFound(err) {
@@ -1373,12 +1380,21 @@ func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Appli
// Get rid of sync results and null out previous operation completion time
state.SyncResult = nil
}
} else if ctrl.syncTimeout != time.Duration(0) && time.Now().After(state.StartedAt.Add(ctrl.syncTimeout)) && !terminating {
state.Phase = synccommon.OperationTerminating
state.Message = "operation is terminating due to timeout"
ctrl.setOperationState(app, state)
logCtx.Infof("Terminating in-progress operation due to timeout. Started at: %v, timeout: %v", state.StartedAt, ctrl.syncTimeout)
} else {
logCtx.Infof("Resuming in-progress operation. phase: %s, message: %s", state.Phase, state.Message)
}
} else {
state = &appv1.OperationState{Phase: synccommon.OperationRunning, Operation: *app.Operation, StartedAt: metav1.Now()}
ctrl.setOperationState(app, state)
if ctrl.syncTimeout != time.Duration(0) {
// Schedule a check during which the timeout would be checked.
ctrl.appOperationQueue.AddAfter(ctrl.toAppKey(app.QualifiedName()), ctrl.syncTimeout)
}
logCtx.Infof("Initialized new operation: %v", *app.Operation)
}
ts.AddCheckpoint("initial_operation_stage_ms")
@@ -1630,9 +1646,11 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
project, hasErrors := ctrl.refreshAppConditions(app)
ts.AddCheckpoint("refresh_app_conditions_ms")
now := metav1.Now()
if hasErrors {
app.Status.Sync.Status = appv1.SyncStatusCodeUnknown
app.Status.Health.Status = health.HealthStatusUnknown
app.Status.Health.LastTransitionTime = &now
patchMs = ctrl.persistAppStatus(origApp, &app.Status)
if err := ctrl.cache.SetAppResourcesTree(app.InstanceName(ctrl.namespace), &appv1.ApplicationTree{}); err != nil {
@@ -1676,7 +1694,6 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
revisions = append(revisions, revision)
sources = append(sources, app.Spec.GetSource())
}
now := metav1.Now()
compareResult, err := ctrl.appStateManager.CompareAppState(app, project, revisions, sources,
refreshType == appv1.RefreshTypeHard,
@@ -2080,7 +2097,7 @@ func (ctrl *ApplicationController) autoSync(app *appv1.Application, syncStatus *
}
// alreadyAttemptedSync returns whether the most recent sync was performed against the
// commitSHA and with the same app source config which are currently set in the app
// commitSHA and with the same app source config which are currently set in the app.
func alreadyAttemptedSync(app *appv1.Application, commitSHA string, commitSHAsMS []string, hasMultipleSources bool, revisionUpdated bool) (bool, synccommon.OperationPhase) {
if app.Status.OperationState == nil || app.Status.OperationState.Operation.Sync == nil || app.Status.OperationState.SyncResult == nil {
return false, ""
@@ -2105,24 +2122,8 @@ func alreadyAttemptedSync(app *appv1.Application, commitSHA string, commitSHAsMS
}
if hasMultipleSources {
// Ignore differences in target revision, since we already just verified commitSHAs are equal,
// and we do not want to trigger auto-sync due to things like HEAD != master
specSources := app.Spec.Sources.DeepCopy()
syncSources := app.Status.OperationState.SyncResult.Sources.DeepCopy()
for _, source := range specSources {
source.TargetRevision = ""
}
for _, source := range syncSources {
source.TargetRevision = ""
}
return reflect.DeepEqual(app.Spec.Sources, app.Status.OperationState.SyncResult.Sources), app.Status.OperationState.Phase
} else {
// Ignore differences in target revision, since we already just verified commitSHAs are equal,
// and we do not want to trigger auto-sync due to things like HEAD != master
specSource := app.Spec.Source.DeepCopy()
specSource.TargetRevision = ""
syncResSource := app.Status.OperationState.SyncResult.Source.DeepCopy()
syncResSource.TargetRevision = ""
return reflect.DeepEqual(app.Spec.GetSource(), app.Status.OperationState.SyncResult.Source), app.Status.OperationState.Phase
}
}

View File

@@ -9,10 +9,12 @@ import (
"time"
clustercache "github.com/argoproj/gitops-engine/pkg/cache"
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/utils/kube/kubetest"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/rest"
"k8s.io/utils/ptr"
@@ -26,6 +28,7 @@ import (
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -90,6 +93,10 @@ func (m *MockKubectl) DeleteResource(ctx context.Context, config *rest.Config, g
}
func newFakeController(data *fakeData, repoErr error) *ApplicationController {
return newFakeControllerWithResync(data, time.Minute, repoErr)
}
func newFakeControllerWithResync(data *fakeData, appResyncPeriod time.Duration, repoErr error) *ApplicationController {
var clust corev1.Secret
err := yaml.Unmarshal([]byte(fakeCluster), &clust)
if err != nil {
@@ -155,11 +162,12 @@ func newFakeController(data *fakeData, repoErr error) *ApplicationController {
1*time.Minute,
),
kubectl,
time.Minute,
appResyncPeriod,
time.Hour,
time.Second,
time.Minute,
nil,
0,
time.Second*10,
common.DefaultPortArgoCDMetrics,
data.metricsCacheExpiration,
@@ -492,10 +500,23 @@ func newFakeApp() *v1alpha1.Application {
return createFakeApp(fakeApp)
}
func newFakeAppWithHealthAndTime(status health.HealthStatusCode, timestamp metav1.Time) *v1alpha1.Application {
return createFakeAppWithHealthAndTime(fakeApp, status, timestamp)
}
func newFakeMultiSourceApp() *v1alpha1.Application {
return createFakeApp(fakeMultiSourceApp)
}
func createFakeAppWithHealthAndTime(testApp string, status health.HealthStatusCode, timestamp metav1.Time) *v1alpha1.Application {
app := createFakeApp(testApp)
app.Status.Health = v1alpha1.HealthStatus{
Status: status,
LastTransitionTime: &timestamp,
}
return app
}
func newFakeAppWithDestMismatch() *v1alpha1.Application {
return createFakeApp(fakeAppWithDestMismatch)
}
@@ -1669,6 +1690,211 @@ func TestUpdateReconciledAt(t *testing.T) {
})
}
func TestUpdateHealthStatusTransitionTime(t *testing.T) {
deployment := kube.MustToUnstructured(&v1.Deployment{
TypeMeta: metav1.TypeMeta{
APIVersion: "apps/v1",
Kind: "Deployment",
},
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
Namespace: "default",
},
})
testCases := []struct {
name string
app *v1alpha1.Application
configMapData map[string]string
expectedStatus health.HealthStatusCode
}{
{
name: "Degraded to Missing",
app: newFakeAppWithHealthAndTime(health.HealthStatusDegraded, testTimestamp),
configMapData: map[string]string{
"resource.customizations": `
apps/Deployment:
health.lua: |
hs = {}
hs.status = "Missing"
hs.message = ""
return hs`,
},
expectedStatus: health.HealthStatusMissing,
},
{
name: "Missing to Progressing",
app: newFakeAppWithHealthAndTime(health.HealthStatusMissing, testTimestamp),
configMapData: map[string]string{
"resource.customizations": `
apps/Deployment:
health.lua: |
hs = {}
hs.status = "Progressing"
hs.message = ""
return hs`,
},
expectedStatus: health.HealthStatusProgressing,
},
{
name: "Progressing to Healthy",
app: newFakeAppWithHealthAndTime(health.HealthStatusProgressing, testTimestamp),
configMapData: map[string]string{
"resource.customizations": `
apps/Deployment:
health.lua: |
hs = {}
hs.status = "Healthy"
hs.message = ""
return hs`,
},
expectedStatus: health.HealthStatusHealthy,
},
{
name: "Healthy to Degraded",
app: newFakeAppWithHealthAndTime(health.HealthStatusHealthy, testTimestamp),
configMapData: map[string]string{
"resource.customizations": `
apps/Deployment:
health.lua: |
hs = {}
hs.status = "Degraded"
hs.message = ""
return hs`,
},
expectedStatus: health.HealthStatusDegraded,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
ctrl := newFakeController(&fakeData{
apps: []runtime.Object{tc.app, &defaultProj},
manifestResponse: &apiclient.ManifestResponse{
Manifests: []string{},
Namespace: test.FakeDestNamespace,
Server: test.FakeClusterURL,
Revision: "abc123",
},
managedLiveObjs: map[kube.ResourceKey]*unstructured.Unstructured{
kube.GetResourceKey(deployment): deployment,
},
configMapData: tc.configMapData,
}, nil)
ctrl.processAppRefreshQueueItem()
apps, err := ctrl.appLister.List(labels.Everything())
require.NoError(t, err)
assert.NotEmpty(t, apps)
assert.Equal(t, tc.expectedStatus, apps[0].Status.Health.Status)
assert.NotEqual(t, testTimestamp, *apps[0].Status.Health.LastTransitionTime)
})
}
}
func TestUpdateHealthStatusProgression(t *testing.T) {
app := newFakeAppWithHealthAndTime(health.HealthStatusDegraded, testTimestamp)
deployment := kube.MustToUnstructured(&v1.Deployment{
TypeMeta: metav1.TypeMeta{
APIVersion: "apps/v1",
Kind: "Deployment",
},
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
Namespace: "default",
},
Status: v1.DeploymentStatus{
ObservedGeneration: 0,
},
})
configMapData := map[string]string{
"resource.customizations": `
apps/Deployment:
health.lua: |
hs = {}
hs.status = ""
hs.message = ""
if obj.metadata ~= nil then
if obj.metadata.labels ~= nil then
current_status = obj.metadata.labels["status"]
if current_status == "Degraded" then
hs.status = "Missing"
elseif current_status == "Missing" then
hs.status = "Progressing"
elseif current_status == "Progressing" then
hs.status = "Healthy"
elseif current_status == "Healthy" then
hs.status = "Degraded"
end
end
end
return hs`,
}
ctrl := newFakeControllerWithResync(&fakeData{
apps: []runtime.Object{app, &defaultProj},
manifestResponse: &apiclient.ManifestResponse{
Manifests: []string{},
Namespace: test.FakeDestNamespace,
Server: test.FakeClusterURL,
Revision: "abc123",
},
managedLiveObjs: map[kube.ResourceKey]*unstructured.Unstructured{
kube.GetResourceKey(deployment): deployment,
},
configMapData: configMapData,
manifestResponses: []*apiclient.ManifestResponse{
{},
{},
{},
{},
},
}, time.Millisecond*10, nil)
testCases := []struct {
name string
initialStatus string
expectedStatus health.HealthStatusCode
}{
{
name: "Degraded to Missing",
initialStatus: "Degraded",
expectedStatus: health.HealthStatusMissing,
},
{
name: "Missing to Progressing",
initialStatus: "Missing",
expectedStatus: health.HealthStatusProgressing,
},
{
name: "Progressing to Healthy",
initialStatus: "Progressing",
expectedStatus: health.HealthStatusHealthy,
},
{
name: "Healthy to Degraded",
initialStatus: "Healthy",
expectedStatus: health.HealthStatusDegraded,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
deployment.SetLabels(map[string]string{"status": tc.initialStatus})
ctrl.processAppRefreshQueueItem()
apps, err := ctrl.appLister.List(labels.Everything())
require.NoError(t, err)
if assert.NotEmpty(t, apps) {
assert.Equal(t, tc.expectedStatus, apps[0].Status.Health.Status)
assert.NotEqual(t, testTimestamp, *apps[0].Status.Health.LastTransitionTime)
}
ctrl.requestAppRefresh(app.Name, nil, nil)
time.Sleep(time.Millisecond * 15)
})
}
}
func TestProjectErrorToCondition(t *testing.T) {
app := newFakeApp()
app.Spec.Project = "wrong project"
@@ -2182,15 +2408,93 @@ func TestAppStatusIsReplaced(t *testing.T) {
func TestAlreadyAttemptSync(t *testing.T) {
app := newFakeApp()
t.Run("same manifest with sync result", func(t *testing.T) {
attempted, _ := alreadyAttemptedSync(app, "sha", []string{}, false, false)
assert.True(t, attempted)
t.Run("no operation state", func(t *testing.T) {
app := app.DeepCopy()
app.Status.OperationState = nil
attempted, _ := alreadyAttemptedSync(app, "", []string{}, false, false)
assert.False(t, attempted)
})
t.Run("different manifest with sync result", func(t *testing.T) {
attempted, _ := alreadyAttemptedSync(app, "sha", []string{}, false, true)
t.Run("no sync operation", func(t *testing.T) {
app := app.DeepCopy()
app.Status.OperationState.Operation.Sync = nil
attempted, _ := alreadyAttemptedSync(app, "", []string{}, false, false)
assert.False(t, attempted)
})
t.Run("no sync result", func(t *testing.T) {
app := app.DeepCopy()
app.Status.OperationState.SyncResult = nil
attempted, _ := alreadyAttemptedSync(app, "", []string{}, false, false)
assert.False(t, attempted)
})
t.Run("single source", func(t *testing.T) {
t.Run("same manifest with sync result", func(t *testing.T) {
attempted, _ := alreadyAttemptedSync(app, "sha", []string{}, false, false)
assert.True(t, attempted)
})
t.Run("same manifest with sync result different targetRevision, same SHA", func(t *testing.T) {
// This test represents the case where the user changed a source's target revision to a new branch, but it
// points to the same revision as the old branch. We currently do not consider this as having been "already
// attempted." In the future we may want to short-circuit the auto-sync in these cases.
app := app.DeepCopy()
app.Status.OperationState.SyncResult.Source = v1alpha1.ApplicationSource{TargetRevision: "branch1"}
app.Spec.Source = &v1alpha1.ApplicationSource{TargetRevision: "branch2"}
app.Status.OperationState.SyncResult.Revision = "sha"
attempted, _ := alreadyAttemptedSync(app, "sha", []string{}, false, false)
assert.False(t, attempted)
})
t.Run("different manifest with sync result, different SHA", func(t *testing.T) {
app := app.DeepCopy()
app.Status.OperationState.SyncResult.Revision = "sha1"
attempted, _ := alreadyAttemptedSync(app, "sha2", []string{}, false, true)
assert.False(t, attempted)
})
t.Run("different manifest with sync result, same SHA", func(t *testing.T) {
app := app.DeepCopy()
app.Status.OperationState.SyncResult.Revision = "sha"
attempted, _ := alreadyAttemptedSync(app, "sha", []string{}, false, true)
assert.True(t, attempted)
})
})
t.Run("multi-source", func(t *testing.T) {
t.Run("same manifest with sync result", func(t *testing.T) {
attempted, _ := alreadyAttemptedSync(app, "", []string{"sha"}, true, false)
assert.True(t, attempted)
})
t.Run("same manifest with sync result, different targetRevision, same SHA", func(t *testing.T) {
// This test represents the case where the user changed a source's target revision to a new branch, but it
// points to the same revision as the old branch. We currently do not consider this as having been "already
// attempted." In the future we may want to short-circuit the auto-sync in these cases.
app := app.DeepCopy()
app.Status.OperationState.SyncResult.Sources = []v1alpha1.ApplicationSource{{TargetRevision: "branch1"}}
app.Spec.Sources = []v1alpha1.ApplicationSource{{TargetRevision: "branch2"}}
app.Status.OperationState.SyncResult.Revisions = []string{"sha"}
attempted, _ := alreadyAttemptedSync(app, "", []string{"sha"}, true, false)
assert.False(t, attempted)
})
t.Run("different manifest with sync result, different SHAs", func(t *testing.T) {
app := app.DeepCopy()
app.Status.OperationState.SyncResult.Revisions = []string{"sha_a_=", "sha_b_1"}
attempted, _ := alreadyAttemptedSync(app, "", []string{"sha_a_2", "sha_b_2"}, true, true)
assert.False(t, attempted)
})
t.Run("different manifest with sync result, same SHAs", func(t *testing.T) {
app := app.DeepCopy()
app.Status.OperationState.SyncResult.Revisions = []string{"sha_a", "sha_b"}
attempted, _ := alreadyAttemptedSync(app, "", []string{"sha_a", "sha_b"}, true, true)
assert.True(t, attempted)
})
})
}
func assertDurationAround(t *testing.T, expected time.Duration, actual time.Duration) {
@@ -2256,3 +2560,54 @@ func TestSelfHealExponentialBackoff(t *testing.T) {
})
}
}
func TestSyncTimeout(t *testing.T) {
testCases := []struct {
delta time.Duration
expectedPhase synccommon.OperationPhase
expectedMessage string
}{{
delta: 2 * time.Minute,
expectedPhase: synccommon.OperationFailed,
expectedMessage: "Operation terminated",
}, {
delta: 30 * time.Second,
expectedPhase: synccommon.OperationSucceeded,
expectedMessage: "successfully synced (no more tasks)",
}}
for i := range testCases {
tc := testCases[i]
t.Run(fmt.Sprintf("test case %d", i), func(t *testing.T) {
app := newFakeApp()
app.Spec.Project = "default"
app.Operation = &v1alpha1.Operation{
Sync: &v1alpha1.SyncOperation{
Revision: "HEAD",
},
}
ctrl := newFakeController(&fakeData{
apps: []runtime.Object{app, &defaultProj},
manifestResponses: []*apiclient.ManifestResponse{{
Manifests: []string{},
}},
}, nil)
ctrl.syncTimeout = time.Minute
app.Status.OperationState = &v1alpha1.OperationState{
Operation: v1alpha1.Operation{
Sync: &v1alpha1.SyncOperation{
Revision: "HEAD",
},
},
Phase: synccommon.OperationRunning,
StartedAt: metav1.NewTime(time.Now().Add(-tc.delta)),
}
ctrl.processRequestedAppOperation(app)
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(app.ObjectMeta.Namespace).Get(context.Background(), app.ObjectMeta.Name, metav1.GetOptions{})
require.NoError(t, err)
require.Equal(t, tc.expectedPhase, app.Status.OperationState.Phase)
require.Equal(t, tc.expectedMessage, app.Status.OperationState.Message)
})
}
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/argoproj/gitops-engine/pkg/sync/ignore"
kubeutil "github.com/argoproj/gitops-engine/pkg/utils/kube"
log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/argoproj/argo-cd/v2/common"
@@ -20,6 +21,7 @@ import (
func setApplicationHealth(resources []managedResource, statuses []appv1.ResourceStatus, resourceOverrides map[string]appv1.ResourceOverride, app *appv1.Application, persistResourceHealth bool) (*appv1.HealthStatus, error) {
var savedErr error
var errCount uint
appHealth := appv1.HealthStatus{Status: health.HealthStatusHealthy}
for i, res := range resources {
if res.Target != nil && hookutil.Skip(res.Target) {
@@ -80,6 +82,13 @@ func setApplicationHealth(resources []managedResource, statuses []appv1.Resource
}
if persistResourceHealth {
app.Status.ResourceHealthSource = appv1.ResourceHealthLocationInline
// if the status didn't change, don't update the timestamp
if app.Status.Health.Status == appHealth.Status && app.Status.Health.LastTransitionTime != nil {
appHealth.LastTransitionTime = app.Status.Health.LastTransitionTime
} else {
now := metav1.Now()
appHealth.LastTransitionTime = &now
}
} else {
app.Status.ResourceHealthSource = appv1.ResourceHealthLocationAppTree
}

View File

@@ -1,8 +1,10 @@
package controller
import (
"fmt"
"os"
"testing"
"time"
"github.com/argoproj/gitops-engine/pkg/health"
synccommon "github.com/argoproj/gitops-engine/pkg/sync/common"
@@ -19,7 +21,16 @@ import (
"github.com/argoproj/argo-cd/v2/util/lua"
)
var app = &appv1.Application{}
var (
app = &appv1.Application{
Status: appv1.ApplicationStatus{
Health: appv1.HealthStatus{
LastTransitionTime: &metav1.Time{Time: time.Date(2020, time.January, 1, 12, 0, 0, 0, time.UTC)},
},
},
}
testTimestamp = metav1.Time{Time: time.Date(2020, time.January, 1, 12, 0, 0, 0, time.UTC)}
)
func initStatuses(resources []managedResource) []appv1.ResourceStatus {
statuses := make([]appv1.ResourceStatus, len(resources))
@@ -56,15 +67,24 @@ func TestSetApplicationHealth(t *testing.T) {
healthStatus, err := setApplicationHealth(resources, resourceStatuses, lua.ResourceHealthOverrides{}, app, true)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusDegraded, healthStatus.Status)
assert.Equal(t, health.HealthStatusHealthy, resourceStatuses[0].Health.Status)
assert.Equal(t, health.HealthStatusDegraded, resourceStatuses[1].Health.Status)
// Health.LastTransitionTime is set only for app health and not at individual resource level
assert.NotNil(t, healthStatus.LastTransitionTime)
assert.Nil(t, resourceStatuses[0].Health.LastTransitionTime)
assert.Nil(t, resourceStatuses[1].Health.LastTransitionTime)
previousLastTransitionTime := healthStatus.LastTransitionTime
app.Status.Health = *healthStatus
// now mark the job as a hook and retry. it should ignore the hook and consider the app healthy
failedJob.SetAnnotations(map[string]string{synccommon.AnnotationKeyHook: "PreSync"})
healthStatus, err = setApplicationHealth(resources, resourceStatuses, nil, app, true)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusHealthy, healthStatus.Status)
// change in health, timestamp should change
assert.NotEqual(t, *previousLastTransitionTime, *healthStatus.LastTransitionTime)
previousLastTransitionTime = healthStatus.LastTransitionTime
app.Status.Health = *healthStatus
// now we set the `argocd.argoproj.io/ignore-healthcheck: "true"` annotation on the job's target.
// The app is considered healthy
@@ -74,6 +94,8 @@ func TestSetApplicationHealth(t *testing.T) {
healthStatus, err = setApplicationHealth(resources, resourceStatuses, nil, app, true)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusHealthy, healthStatus.Status)
// no change in health, timestamp shouldn't change
assert.Equal(t, *previousLastTransitionTime, *healthStatus.LastTransitionTime)
}
func TestSetApplicationHealth_ResourceHealthNotPersisted(t *testing.T) {
@@ -102,6 +124,41 @@ func TestSetApplicationHealth_MissingResource(t *testing.T) {
healthStatus, err := setApplicationHealth(resources, resourceStatuses, lua.ResourceHealthOverrides{}, app, true)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusMissing, healthStatus.Status)
assert.False(t, healthStatus.LastTransitionTime.IsZero())
}
func TestSetApplicationHealth_HealthImproves(t *testing.T) {
testCases := []struct {
oldStatus health.HealthStatusCode
newStatus health.HealthStatusCode
}{
{health.HealthStatusUnknown, health.HealthStatusDegraded},
{health.HealthStatusDegraded, health.HealthStatusProgressing},
{health.HealthStatusMissing, health.HealthStatusProgressing},
{health.HealthStatusProgressing, health.HealthStatusSuspended},
{health.HealthStatusSuspended, health.HealthStatusHealthy},
}
for _, tc := range testCases {
overrides := lua.ResourceHealthOverrides{
lua.GetConfigMapKey(schema.FromAPIVersionAndKind("v1", "Pod")): appv1.ResourceOverride{
HealthLua: fmt.Sprintf("hs = {}\nhs.status = %q\nhs.message = \"\"return hs", tc.newStatus),
},
}
runningPod := resourceFromFile("./testdata/pod-running-restart-always.yaml")
resources := []managedResource{{
Group: "", Version: "v1", Kind: "Pod", Live: &runningPod,
}}
resourceStatuses := initStatuses(resources)
t.Run(string(fmt.Sprintf("%s to %s", tc.oldStatus, tc.newStatus)), func(t *testing.T) {
healthStatus, err := setApplicationHealth(resources, resourceStatuses, overrides, app, true)
require.NoError(t, err)
assert.Equal(t, tc.newStatus, healthStatus.Status)
assert.NotEqual(t, testTimestamp, *healthStatus.LastTransitionTime)
})
}
}
func TestSetApplicationHealth_MissingResourceNoBuiltHealthCheck(t *testing.T) {
@@ -127,6 +184,7 @@ func TestSetApplicationHealth_MissingResourceNoBuiltHealthCheck(t *testing.T) {
}, app, true)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusMissing, healthStatus.Status)
assert.False(t, healthStatus.LastTransitionTime.IsZero())
})
}

View File

@@ -437,6 +437,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
// return unknown comparison result if basic comparison settings cannot be loaded
if err != nil {
now := metav1.Now()
if hasMultipleSources {
return &comparisonResult{
syncStatus: &v1alpha1.SyncStatus{
@@ -444,7 +445,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
Status: v1alpha1.SyncStatusCodeUnknown,
Revisions: revisions,
},
healthStatus: &v1alpha1.HealthStatus{Status: health.HealthStatusUnknown},
healthStatus: &v1alpha1.HealthStatus{Status: health.HealthStatusUnknown, LastTransitionTime: &now},
}, nil
} else {
return &comparisonResult{
@@ -453,7 +454,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
Status: v1alpha1.SyncStatusCodeUnknown,
Revision: revisions[0],
},
healthStatus: &v1alpha1.HealthStatus{Status: health.HealthStatusUnknown},
healthStatus: &v1alpha1.HealthStatus{Status: health.HealthStatusUnknown, LastTransitionTime: &now},
}, nil
}
}

View File

@@ -715,6 +715,44 @@ func TestSetHealth(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, health.HealthStatusHealthy, compRes.healthStatus.Status)
assert.False(t, compRes.healthStatus.LastTransitionTime.IsZero())
}
func TestPreserveStatusTimestamp(t *testing.T) {
timestamp := metav1.Now()
app := newFakeAppWithHealthAndTime(health.HealthStatusHealthy, timestamp)
deployment := kube.MustToUnstructured(&v1.Deployment{
TypeMeta: metav1.TypeMeta{
APIVersion: "apps/v1",
Kind: "Deployment",
},
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
Namespace: "default",
},
})
ctrl := newFakeController(&fakeData{
apps: []runtime.Object{app, &defaultProj},
manifestResponse: &apiclient.ManifestResponse{
Manifests: []string{},
Namespace: test.FakeDestNamespace,
Server: test.FakeClusterURL,
Revision: "abc123",
},
managedLiveObjs: map[kube.ResourceKey]*unstructured.Unstructured{
kube.GetResourceKey(deployment): deployment,
},
}, nil)
sources := make([]argoappv1.ApplicationSource, 0)
sources = append(sources, app.Spec.GetSource())
revisions := make([]string, 0)
revisions = append(revisions, "")
compRes, err := ctrl.appStateManager.CompareAppState(app, &defaultProj, revisions, sources, false, false, nil, false, false)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusHealthy, compRes.healthStatus.Status)
assert.Equal(t, timestamp, *compRes.healthStatus.LastTransitionTime)
}
func TestSetHealthSelfReferencedApp(t *testing.T) {
@@ -752,6 +790,7 @@ func TestSetHealthSelfReferencedApp(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, health.HealthStatusHealthy, compRes.healthStatus.Status)
assert.False(t, compRes.healthStatus.LastTransitionTime.IsZero())
}
func TestSetManagedResourcesWithOrphanedResources(t *testing.T) {
@@ -827,6 +866,7 @@ func TestReturnUnknownComparisonStateOnSettingLoadError(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, health.HealthStatusUnknown, compRes.healthStatus.Status)
assert.False(t, compRes.healthStatus.LastTransitionTime.IsZero())
assert.Equal(t, argoappv1.SyncStatusCodeUnknown, compRes.syncStatus.Status)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

@@ -432,7 +432,7 @@ data:
name: some-cluster
server: https://some-cluster
# The maximum size of the payload that can be sent to the webhook server.
webhook.maxPayloadSizeMB: "1024"
webhook.maxPayloadSizeMB: "50"
# application.sync.impersonation.enabled enables application sync to use a custom service account, via impersonation. This allows decoupling sync from control-plane service account.
application.sync.impersonation.enabled: "false"

View File

@@ -51,6 +51,8 @@ data:
controller.self.heal.timeout.seconds: "2"
controller.self.heal.backoff.factor: "3"
controller.self.heal.backoff.cap.seconds: "300"
# Specifies a sync timeout for applications. "0" means no timeout (default "0")
controller.sync.timeout.seconds: "0"
# Cache expiration for app state (default 1h0m0s)
controller.app.state.cache.expiration: "1h0m0s"

View File

@@ -129,6 +129,20 @@ Scraped at the `argocd-repo-server:8084/metrics` endpoint.
| `argocd_redis_request_total` | counter | Number of Kubernetes requests executed during application reconciliation. |
| `argocd_repo_pending_request_total` | gauge | Number of pending requests requiring repository lock |
## Commit Server Metrics
Metrics about the Commit Server.
Scraped at the `argocd-commit-server:8087/metrics` endpoint.
| Metric | Type | Description |
|---------------------------------------------------------|:---------:|------------------------------------------------------|
| `argocd_commitserver_commit_pending_request_total` | guage | Number of pending commit requests. |
| `argocd_commitserver_git_request_duration_seconds` | histogram | Git requests duration seconds. |
| `argocd_commitserver_git_request_total` | counter | Number of git requests performed by commit server |
| `argocd_commitserver_commit_request_duration_seconds` | histogram | Commit requests duration seconds. |
| `argocd_commitserver_userinfo_request_duration_seconds` | histogram | Userinfo requests duration seconds. |
| `argocd_commitserver_commit_request_total` | counter | Number of commit requests performed by commit server |
## Prometheus Operator
If using Prometheus Operator, the following ServiceMonitor example manifests can be used.

View File

@@ -77,6 +77,7 @@ argocd-application-controller [flags]
--server-side-diff-enabled Feature flag to enable ServerSide diff. Default ("false")
--sharding-method string Enables choice of sharding method. Supported sharding methods are : [legacy, round-robin, consistent-hashing] (default "legacy")
--status-processors int Number of application status processors (default 20)
--sync-timeout int Specifies the timeout after which a sync would be terminated. 0 means no timeout (default 0).
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use

View File

@@ -1,14 +1,23 @@
# Keycloak
Keycloak and ArgoCD integration can be configured in two ways with Client authentication and with PKCE.
# Integrating Keycloak and ArgoCD
If you need to authenticate with __argo-cd command line__, you must choose PKCE way.
* [Keycloak and ArgoCD with Client authentication](#keycloak-and-argocd-with-client-authentication)
* [Keycloak and ArgoCD with PKCE](#keycloak-and-argocd-with-pkce)
## Keycloak and ArgoCD with Client authentication
These instructions will take you through the entire process of getting your ArgoCD application authenticating with Keycloak.
These instructions will take you through the entire process of getting your ArgoCD application authenticating with Keycloak.
You will create a client within Keycloak and configure ArgoCD to use Keycloak for authentication, using groups set in Keycloak
to determine privileges in Argo.
## Creating a new client in Keycloak
### Creating a new client in Keycloak
First we need to setup a new client. Start by logging into your keycloak server, select the realm you want to use (`master` by default)
First we need to setup a new client.
Start by logging into your keycloak server, select the realm you want to use (`master` by default)
and then go to __Clients__ and click the __Create client__ button at the top.
![Keycloak add client](../../assets/keycloak-add-client.png "Keycloak add client")
@@ -19,60 +28,26 @@ Enable the __Client authentication__.
Configure the client by setting the __Root URL__, __Web origins__, __Admin URL__ to the hostname (https://{hostname}).
Also you can set __Home URL__ to your _/applications_ path and __Valid Post logout redirect URIs__ to "+".
Also you can set __Home URL__ to _/applications_ path and __Valid Post logout redirect URIs__ to "https://{hostname}/applications".
The Valid Redirect URIs should be set to https://{hostname}/auth/callback (you can also set the less secure https://{hostname}/* for testing/development purposes,
but it's not recommended in production).
![Keycloak configure client](../../assets/keycloak-configure-client.png "Keycloak configure client")
Make sure to click __Save__. There should be a tab called __Credentials__. You can copy the Secret that we'll use in our ArgoCD
configuration.
Make sure to click __Save__.
There should be a tab called __Credentials__. You can copy the Client Secret that we'll use in our ArgoCD configuration.
![Keycloak client secret](../../assets/keycloak-client-secret.png "Keycloak client secret")
## Configuring the groups claim
In order for ArgoCD to provide the groups the user is in we need to configure a groups claim that can be included in the authentication token.
To do this we'll start by creating a new __Client Scope__ called _groups_.
![Keycloak add scope](../../assets/keycloak-add-scope.png "Keycloak add scope")
Once you've created the client scope you can now add a Token Mapper which will add the groups claim to the token when the client requests
the groups scope. In the Tab "Mappers", click on "Configure a new mapper" and choose __Group Membership__.
Make sure to set the __Name__ as well as the __Token Claim Name__ to _groups_. Also disable the "Full group path".
![Keycloak groups mapper](../../assets/keycloak-groups-mapper.png "Keycloak groups mapper")
We can now configure the client to provide the _groups_ scope. Go back to the client we've created earlier and go to the Tab "Client Scopes".
Click on "Add client scope", choose the _groups_ scope and add it either to the __Default__ or to the __Optional__ Client Scope. If you put it in the Optional
category you will need to make sure that ArgoCD requests the scope in its OIDC configuration. Since we will always want group information, I recommend
using the Default category.
![Keycloak client scope](../../assets/keycloak-client-scope.png "Keycloak client scope")
Create a group called _ArgoCDAdmins_ and have your current user join the group.
![Keycloak user group](../../assets/keycloak-user-group.png "Keycloak user group")
## Configuring ArgoCD OIDC
### Configuring ArgoCD OIDC
Let's start by storing the client secret you generated earlier in the argocd secret _argocd-secret_.
1. First you'll need to encode the client secret in base64: `$ echo -n '83083958-8ec6-47b0-a411-a8c55381fbd2' | base64`
2. Then you can edit the secret and add the base64 value to a new key called _oidc.keycloak.clientSecret_ using `$ kubectl edit secret argocd-secret`.
Your Secret should look something like this:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: argocd-secret
data:
...
oidc.keycloak.clientSecret: ODMwODM5NTgtOGVjNi00N2IwLWE0MTEtYThjNTUzODFmYmQy
...
You can patch it with value copied previously:
```bash
kubectl -n argo-cd patch secret argocd-secret --patch='{"stringData": { "oidc.keycloak.clientSecret": "<REPLACE_WITH_CLIENT_SECRET>" }}'
```
Now we can configure the config map and add the oidc configuration to enable our keycloak authentication.
@@ -103,7 +78,110 @@ Make sure that:
- __clientSecret__ points to the right key you created in the _argocd-secret_ Secret
- __requestedScopes__ contains the _groups_ claim if you didn't add it to the Default scopes
## Configuring ArgoCD Policy
## Keycloak and ArgoCD with PKCE
These instructions will take you through the entire process of getting your ArgoCD application authenticating with Keycloak.
You will create a client within Keycloak and configure ArgoCD to use Keycloak for authentication, using groups set in Keycloak
to determine privileges in Argo.
You will also be able to authenticate using argo-cd command line.
### Creating a new client in Keycloak
First we need to setup a new client.
Start by logging into your keycloak server, select the realm you want to use (`master` by default)
and then go to __Clients__ and click the __Create client__ button at the top.
![Keycloak add client](../../assets/keycloak-add-client.png "Keycloak add client")
Leave default values.
![Keycloak add client Step 2](../../assets/keycloak-add-client-pkce_2.png "Keycloak add client Step 2")
Configure the client by setting the __Root URL__, __Web origins__, __Admin URL__ to the hostname (https://{hostname}).
Also you can set __Home URL__ to _/applications_ path and __Valid Post logout redirect URIs__ to "https://{hostname}/applications".
The Valid Redirect URIs should be set to:
- http://localhost:8085/auth/callback (needed for argo-cd cli, depends on value from [--sso-port](../../user-guide/commands/argocd_login.md))
- https://{hostname}/auth/callback
- https://{hostname}/pkce/verify
![Keycloak configure client](../../assets/keycloak-configure-client-pkce.png "Keycloak configure client")
Make sure to click __Save__.
Now go to a tab called __Advanced__, look for parameter named __Proof Key for Code Exchange Code Challenge Method__ and set it to __S256__
![Keycloak configure client Step 2](../../assets/keycloak-configure-client-pkce_2.png "Keycloak configure client Step 2")
Make sure to click __Save__.
### Configuring ArgoCD OIDC
Now we can configure the config map and add the oidc configuration to enable our keycloak authentication.
You can use `$ kubectl edit configmap argocd-cm`.
Your ConfigMap should look like this:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
data:
url: https://argocd.example.com
oidc.config: |
name: Keycloak
issuer: https://keycloak.example.com/realms/master
clientID: argocd
enablePKCEAuthentication: true
requestedScopes: ["openid", "profile", "email", "groups"]
```
Make sure that:
- __issuer__ ends with the correct realm (in this example _master_)
- __issuer__ on Keycloak releases older than version 17 the URL must include /auth (in this example /auth/realms/master)
- __clientID__ is set to the Client ID you configured in Keycloak
- __enablePKCEAuthentication__ must be set to true to enable correct ArgoCD behaviour with PKCE
- __requestedScopes__ contains the _groups_ claim if you didn't add it to the Default scopes
## Configuring the groups claim
In order for ArgoCD to provide the groups the user is in we need to configure a groups claim that can be included in the authentication token.
To do this we'll start by creating a new __Client Scope__ called _groups_.
![Keycloak add scope](../../assets/keycloak-add-scope.png "Keycloak add scope")
Once you've created the client scope you can now add a Token Mapper which will add the groups claim to the token when the client requests
the groups scope.
In the Tab "Mappers", click on "Configure a new mapper" and choose __Group Membership__.
Make sure to set the __Name__ as well as the __Token Claim Name__ to _groups_. Also disable the "Full group path".
![Keycloak groups mapper](../../assets/keycloak-groups-mapper.png "Keycloak groups mapper")
We can now configure the client to provide the _groups_ scope.
Go back to the client we've created earlier and go to the Tab "Client Scopes".
Click on "Add client scope", choose the _groups_ scope and add it either to the __Default__ or to the __Optional__ Client Scope.
If you put it in the Optional
category you will need to make sure that ArgoCD requests the scope in its OIDC configuration.
Since we will always want group information, I recommend
using the Default category.
![Keycloak client scope](../../assets/keycloak-client-scope.png "Keycloak client scope")
Create a group called _ArgoCDAdmins_ and have your current user join the group.
![Keycloak user group](../../assets/keycloak-user-group.png "Keycloak user group")
## Configuring ArgoCD Policy
Now that we have an authentication that provides groups we want to apply a policy to these groups.
We can modify the _argocd-rbac-cm_ ConfigMap using `$ kubectl edit configmap argocd-rbac-cm`.
@@ -126,8 +204,23 @@ You can now login using our new Keycloak OIDC authentication:
![Keycloak ArgoCD login](../../assets/keycloak-login.png "Keycloak ArgoCD login")
If you have used PKCE method, you can also authenticate using command line:
```bash
argocd login argocd.example.com --sso --grpc-web
```
argocd cli will start to listen on localhost:8085 and open your web browser to allow you to authenticate with Keycloak.
Once done, you should see
![Authentication successful!](../../assets/keycloak-authentication-successful.png "Authentication successful!")
## Troubleshoot
If ArgoCD auth returns 401 or when the login attempt leads to the loop, then restart the argocd-server pod.
```
kubectl rollout restart deployment argocd-server -n argocd
```
If you migrate from Client authentification to PKCE, you can have the following error `invalid_request: Missing parameter: code_challenge_method`.
It could be a redirect issue, try in private browsing or clean browser cookies.

View File

@@ -19,7 +19,7 @@ URL configured in the Git provider should use the `/api/webhook` endpoint of you
(e.g. `https://argocd.example.com/api/webhook`). If you wish to use a shared secret, input an
arbitrary value in the secret. This value will be used when configuring the webhook in the next step.
To prevent DDoS attacks with unauthenticated webhook events (the `/api/webhook` endpoint currently lacks rate limiting protection), it is recommended to limit the payload size. You can achieve this by configuring the `argocd-cm` ConfigMap with the `webhook.maxPayloadSizeMB` attribute. The default value is 1GB.
To prevent DDoS attacks with unauthenticated webhook events (the `/api/webhook` endpoint currently lacks rate limiting protection), it is recommended to limit the payload size. You can achieve this by configuring the `argocd-cm` ConfigMap with the `webhook.maxPayloadSizeMB` attribute. The default value is 50MB.
## Github

View File

@@ -18,7 +18,7 @@ recent minor releases.
| [dex:v2.41.1](master/ghcr.io_dexidp_dex_v2.41.1.html) | 0 | 0 | 0 | 2 |
| [haproxy:2.6.17-alpine](master/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html) | 0 | 0 | 2 | 4 |
| [redis:7.0.15-alpine](master/public.ecr.aws_docker_library_redis_7.0.15-alpine.html) | 0 | 0 | 0 | 1 |
| [argocd:latest](master/quay.io_argoproj_argocd_latest.html) | 0 | 0 | 4 | 9 |
| [argocd:latest](master/quay.io_argoproj_argocd_latest.html) | 0 | 0 | 3 | 10 |
| [redis:7.0.15-alpine](master/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 1 |
| [install.yaml](master/argocd-iac-install.html) | - | - | - | - |
| [namespace-install.yaml](master/argocd-iac-namespace-install.html) | - | - | - | - |
@@ -32,7 +32,7 @@ recent minor releases.
| [dex:v2.41.1](v2.13.1/ghcr.io_dexidp_dex_v2.41.1.html) | 0 | 0 | 0 | 2 |
| [haproxy:2.6.17-alpine](v2.13.1/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html) | 0 | 0 | 2 | 4 |
| [redis:7.0.15-alpine](v2.13.1/public.ecr.aws_docker_library_redis_7.0.15-alpine.html) | 0 | 0 | 0 | 1 |
| [argocd:v2.13.1](v2.13.1/quay.io_argoproj_argocd_v2.13.1.html) | 0 | 0 | 4 | 9 |
| [argocd:v2.13.1](v2.13.1/quay.io_argoproj_argocd_v2.13.1.html) | 0 | 0 | 3 | 10 |
| [redis:7.0.15-alpine](v2.13.1/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 1 |
| [install.yaml](v2.13.1/argocd-iac-install.html) | - | - | - | - |
| [namespace-install.yaml](v2.13.1/argocd-iac-namespace-install.html) | - | - | - | - |
@@ -46,7 +46,7 @@ recent minor releases.
| [dex:v2.38.0](v2.12.7/ghcr.io_dexidp_dex_v2.38.0.html) | 0 | 0 | 6 | 7 |
| [haproxy:2.6.17-alpine](v2.12.7/public.ecr.aws_docker_library_haproxy_2.6.17-alpine.html) | 0 | 0 | 2 | 4 |
| [redis:7.0.15-alpine](v2.12.7/public.ecr.aws_docker_library_redis_7.0.15-alpine.html) | 0 | 0 | 0 | 1 |
| [argocd:v2.12.7](v2.12.7/quay.io_argoproj_argocd_v2.12.7.html) | 0 | 0 | 4 | 10 |
| [argocd:v2.12.7](v2.12.7/quay.io_argoproj_argocd_v2.12.7.html) | 0 | 0 | 3 | 11 |
| [redis:7.0.15-alpine](v2.12.7/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 1 |
| [install.yaml](v2.12.7/argocd-iac-install.html) | - | - | - | - |
| [namespace-install.yaml](v2.12.7/argocd-iac-namespace-install.html) | - | - | - | - |
@@ -59,7 +59,7 @@ recent minor releases.
| [ui/yarn.lock](v2.11.12/argocd-test.html) | 0 | 0 | 1 | 0 |
| [dex:v2.38.0](v2.11.12/ghcr.io_dexidp_dex_v2.38.0.html) | 0 | 0 | 6 | 7 |
| [haproxy:2.6.14-alpine](v2.11.12/haproxy_2.6.14-alpine.html) | 0 | 1 | 7 | 7 |
| [argocd:v2.11.12](v2.11.12/quay.io_argoproj_argocd_v2.11.12.html) | 0 | 0 | 5 | 19 |
| [argocd:v2.11.12](v2.11.12/quay.io_argoproj_argocd_v2.11.12.html) | 0 | 0 | 4 | 20 |
| [redis:7.0.15-alpine](v2.11.12/redis_7.0.15-alpine.html) | 0 | 0 | 0 | 1 |
| [install.yaml](v2.11.12/argocd-iac-install.html) | - | - | - | - |
| [namespace-install.yaml](v2.11.12/argocd-iac-namespace-install.html) | - | - | - | - |

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:23:21 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:23:04 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>
@@ -507,7 +507,7 @@
</li>
<li class="card__meta__item">
Line number: 22702
Line number: 22859
</li>
</ul>
@@ -553,7 +553,7 @@
</li>
<li class="card__meta__item">
Line number: 22383
Line number: 22540
</li>
</ul>
@@ -599,7 +599,7 @@
</li>
<li class="card__meta__item">
Line number: 22470
Line number: 22627
</li>
</ul>
@@ -645,7 +645,7 @@
</li>
<li class="card__meta__item">
Line number: 22498
Line number: 22655
</li>
</ul>
@@ -691,7 +691,7 @@
</li>
<li class="card__meta__item">
Line number: 22528
Line number: 22685
</li>
</ul>
@@ -737,7 +737,7 @@
</li>
<li class="card__meta__item">
Line number: 22546
Line number: 22703
</li>
</ul>
@@ -783,7 +783,7 @@
</li>
<li class="card__meta__item">
Line number: 22564
Line number: 22721
</li>
</ul>
@@ -829,7 +829,7 @@
</li>
<li class="card__meta__item">
Line number: 22586
Line number: 22743
</li>
</ul>
@@ -881,7 +881,7 @@
</li>
<li class="card__meta__item">
Line number: 23677
Line number: 23833
</li>
</ul>
@@ -933,7 +933,7 @@
</li>
<li class="card__meta__item">
Line number: 23984
Line number: 24140
</li>
</ul>
@@ -991,7 +991,7 @@
</li>
<li class="card__meta__item">
Line number: 23196
Line number: 23352
</li>
</ul>
@@ -1049,7 +1049,7 @@
</li>
<li class="card__meta__item">
Line number: 23479
Line number: 23635
</li>
</ul>
@@ -1107,7 +1107,7 @@
</li>
<li class="card__meta__item">
Line number: 23433
Line number: 23589
</li>
</ul>
@@ -1165,7 +1165,7 @@
</li>
<li class="card__meta__item">
Line number: 23541
Line number: 23697
</li>
</ul>
@@ -1223,7 +1223,7 @@
</li>
<li class="card__meta__item">
Line number: 23648
Line number: 23804
</li>
</ul>
@@ -1281,7 +1281,7 @@
</li>
<li class="card__meta__item">
Line number: 23672
Line number: 23828
</li>
</ul>
@@ -1339,7 +1339,7 @@
</li>
<li class="card__meta__item">
Line number: 23984
Line number: 24140
</li>
</ul>
@@ -1397,7 +1397,7 @@
</li>
<li class="card__meta__item">
Line number: 23731
Line number: 23887
</li>
</ul>
@@ -1455,7 +1455,7 @@
</li>
<li class="card__meta__item">
Line number: 24071
Line number: 24227
</li>
</ul>
@@ -1513,7 +1513,7 @@
</li>
<li class="card__meta__item">
Line number: 24463
Line number: 24619
</li>
</ul>
@@ -1565,7 +1565,7 @@
</li>
<li class="card__meta__item">
Line number: 23459
Line number: 23615
</li>
</ul>
@@ -1617,7 +1617,7 @@
</li>
<li class="card__meta__item">
Line number: 23196
Line number: 23352
</li>
</ul>
@@ -1669,7 +1669,7 @@
</li>
<li class="card__meta__item">
Line number: 23433
Line number: 23589
</li>
</ul>
@@ -1721,7 +1721,7 @@
</li>
<li class="card__meta__item">
Line number: 23648
Line number: 23804
</li>
</ul>
@@ -1779,7 +1779,7 @@
</li>
<li class="card__meta__item">
Line number: 23196
Line number: 23352
</li>
</ul>
@@ -1837,7 +1837,7 @@
</li>
<li class="card__meta__item">
Line number: 23433
Line number: 23589
</li>
</ul>
@@ -1895,7 +1895,7 @@
</li>
<li class="card__meta__item">
Line number: 23479
Line number: 23635
</li>
</ul>
@@ -1953,7 +1953,7 @@
</li>
<li class="card__meta__item">
Line number: 23541
Line number: 23697
</li>
</ul>
@@ -2011,7 +2011,7 @@
</li>
<li class="card__meta__item">
Line number: 23648
Line number: 23804
</li>
</ul>
@@ -2069,7 +2069,7 @@
</li>
<li class="card__meta__item">
Line number: 23672
Line number: 23828
</li>
</ul>
@@ -2127,7 +2127,7 @@
</li>
<li class="card__meta__item">
Line number: 23984
Line number: 24140
</li>
</ul>
@@ -2185,7 +2185,7 @@
</li>
<li class="card__meta__item">
Line number: 23731
Line number: 23887
</li>
</ul>
@@ -2243,7 +2243,7 @@
</li>
<li class="card__meta__item">
Line number: 24071
Line number: 24227
</li>
</ul>
@@ -2301,7 +2301,7 @@
</li>
<li class="card__meta__item">
Line number: 24463
Line number: 24619
</li>
</ul>
@@ -2357,7 +2357,7 @@
</li>
<li class="card__meta__item">
Line number: 23355
Line number: 23511
</li>
</ul>
@@ -2413,7 +2413,7 @@
</li>
<li class="card__meta__item">
Line number: 23487
Line number: 23643
</li>
</ul>
@@ -2469,7 +2469,7 @@
</li>
<li class="card__meta__item">
Line number: 23462
Line number: 23618
</li>
</ul>
@@ -2525,7 +2525,7 @@
</li>
<li class="card__meta__item">
Line number: 23580
Line number: 23736
</li>
</ul>
@@ -2581,7 +2581,7 @@
</li>
<li class="card__meta__item">
Line number: 23665
Line number: 23821
</li>
</ul>
@@ -2637,7 +2637,7 @@
</li>
<li class="card__meta__item">
Line number: 23679
Line number: 23835
</li>
</ul>
@@ -2693,7 +2693,7 @@
</li>
<li class="card__meta__item">
Line number: 23991
Line number: 24147
</li>
</ul>
@@ -2749,7 +2749,7 @@
</li>
<li class="card__meta__item">
Line number: 23957
Line number: 24113
</li>
</ul>
@@ -2805,7 +2805,7 @@
</li>
<li class="card__meta__item">
Line number: 24362
Line number: 24518
</li>
</ul>
@@ -2861,7 +2861,7 @@
</li>
<li class="card__meta__item">
Line number: 24684
Line number: 24840
</li>
</ul>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:23:32 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:23:14 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:21:01 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:20:56 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>
@@ -470,7 +470,7 @@
<div class="meta-counts">
<div class="meta-count"><span>7</span> <span>known vulnerabilities</span></div>
<div class="meta-count"><span>26 vulnerable dependency paths</span></div>
<div class="meta-count"><span>2150</span> <span>dependencies</span></div>
<div class="meta-count"><span>2158</span> <span>dependencies</span></div>
</div><!-- .meta-counts -->
</div><!-- .layout-container--short -->
</header><!-- .project__header -->
@@ -504,7 +504,7 @@
<li class="card__meta__item">Introduced through:
github.com/argoproj/argo-cd/v2@0.0.0, github.com/Azure/kubelogin/pkg/token@0.1.4 and others
github.com/argoproj/argo-cd/v2@0.0.0, github.com/Azure/kubelogin/pkg/token@0.1.5 and others
</li>
</ul>
@@ -518,9 +518,9 @@
<span class="list-paths__item__introduced"><em>Introduced through</em>:
github.com/argoproj/argo-cd/v2@0.0.0
<span class="list-paths__item__arrow"></span>
github.com/Azure/kubelogin/pkg/token@0.1.4
github.com/Azure/kubelogin/pkg/token@0.1.5
<span class="list-paths__item__arrow"></span>
github.com/Azure/kubelogin/pkg/internal/token@0.1.4
github.com/Azure/kubelogin/pkg/internal/token@0.1.5
<span class="list-paths__item__arrow"></span>
gopkg.in/retry.v1@1.0.3

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:21:11 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:21:06 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:21:18 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:21:11 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:21:25 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:21:15 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:21:49 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:21:33 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>
@@ -472,7 +472,7 @@
<div class="meta-counts">
<div class="meta-count"><span>20</span> <span>known vulnerabilities</span></div>
<div class="meta-count"><span>100 vulnerable dependency paths</span></div>
<div class="meta-count"><span>2359</span> <span>dependencies</span></div>
<div class="meta-count"><span>2378</span> <span>dependencies</span></div>
</div><!-- .meta-counts -->
</div><!-- .layout-container--short -->
</header><!-- .project__header -->
@@ -707,6 +707,8 @@
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-10041">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-10041</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-10041">https://access.redhat.com/security/cve/CVE-2024-10041</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2319212">https://bugzilla.redhat.com/show_bug.cgi?id=2319212</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9941">https://access.redhat.com/errata/RHSA-2024:9941</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:10379">https://access.redhat.com/errata/RHSA-2024:10379</a></li>
</ul>
<hr/>
@@ -951,170 +953,6 @@
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-PAM-8352843">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--medium" data-snyk-test="medium">
<h2 class="card__title">Information Exposure</h2>
<div class="card__section">
<div class="label label--medium">
<span class="label__text">medium severity</span>
</div>
<hr/>
<ul class="card__meta">
<li class="card__meta__item">
Manifest file: quay.io/argoproj/argocd:latest/argoproj/argocd <span class="list-paths__item__arrow"></span> Dockerfile
</li>
<li class="card__meta__item">
Package Manager: ubuntu:24.04
</li>
<li class="card__meta__item">
Vulnerable module:
libgcrypt20
</li>
<li class="card__meta__item">Introduced through:
docker-image|quay.io/argoproj/argocd@latest and libgcrypt20@1.10.3-2build1
</li>
</ul>
<hr/>
<h3 class="card__section__title">Detailed paths</h3>
<ul class="card__meta__paths">
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
gnupg2/dirmngr@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-agent@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0t64@2.7.14build2
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
gnupg2/gpgv@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
gnupg2/gpgconf@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
adduser@3.137ubuntu1
<span class="list-paths__item__arrow"></span>
shadow/passwd@1:4.13+dfsg1-4ubuntu3.2
<span class="list-paths__item__arrow"></span>
pam/libpam-modules@1.5.3-5ubuntu5.1
<span class="list-paths__item__arrow"></span>
systemd/libsystemd0@255.4-1ubuntu8.4
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
</ul><!-- .list-paths -->
</div><!-- .card__section -->
<hr/>
<!-- Overview -->
<h2 id="nvd-description">NVD Description</h2>
<p><strong><em>Note:</em></strong> <em>Versions mentioned in the description apply only to the upstream <code>libgcrypt20</code> package and not the <code>libgcrypt20</code> package as distributed by <code>Ubuntu</code>.</em>
<em>See <code>How to fix?</code> for <code>Ubuntu:24.04</code> relevant fixed versions and status.</em></p>
<p>A timing-based side-channel flaw was found in libgcrypt&#39;s RSA implementation. This issue may allow a remote attacker to initiate a Bleichenbacher-style attack, which can lead to the decryption of RSA ciphertexts.</p>
<h2 id="remediation">Remediation</h2>
<p>There is no fixed version for <code>Ubuntu:24.04</code> <code>libgcrypt20</code>.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-2236">https://access.redhat.com/security/cve/CVE-2024-2236</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2268268">https://bugzilla.redhat.com/show_bug.cgi?id=2268268</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2245218">https://bugzilla.redhat.com/show_bug.cgi?id=2245218</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9404">https://access.redhat.com/errata/RHSA-2024:9404</a></li>
</ul>
<hr/>
<div class="cta card__cta">
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-LIBGCRYPT20-6693674">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--medium" data-snyk-test="medium">
<h2 class="card__title">CVE-2024-26462</h2>
@@ -2086,6 +1924,170 @@
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-OPENSSL-7838291">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">Information Exposure</h2>
<div class="card__section">
<div class="label label--low">
<span class="label__text">low severity</span>
</div>
<hr/>
<ul class="card__meta">
<li class="card__meta__item">
Manifest file: quay.io/argoproj/argocd:latest/argoproj/argocd <span class="list-paths__item__arrow"></span> Dockerfile
</li>
<li class="card__meta__item">
Package Manager: ubuntu:24.04
</li>
<li class="card__meta__item">
Vulnerable module:
libgcrypt20
</li>
<li class="card__meta__item">Introduced through:
docker-image|quay.io/argoproj/argocd@latest and libgcrypt20@1.10.3-2build1
</li>
</ul>
<hr/>
<h3 class="card__section__title">Detailed paths</h3>
<ul class="card__meta__paths">
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
gnupg2/dirmngr@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-agent@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0t64@2.7.14build2
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
gnupg2/gpgv@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
gnupg2/gpgconf@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@latest
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
adduser@3.137ubuntu1
<span class="list-paths__item__arrow"></span>
shadow/passwd@1:4.13+dfsg1-4ubuntu3.2
<span class="list-paths__item__arrow"></span>
pam/libpam-modules@1.5.3-5ubuntu5.1
<span class="list-paths__item__arrow"></span>
systemd/libsystemd0@255.4-1ubuntu8.4
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
</ul><!-- .list-paths -->
</div><!-- .card__section -->
<hr/>
<!-- Overview -->
<h2 id="nvd-description">NVD Description</h2>
<p><strong><em>Note:</em></strong> <em>Versions mentioned in the description apply only to the upstream <code>libgcrypt20</code> package and not the <code>libgcrypt20</code> package as distributed by <code>Ubuntu</code>.</em>
<em>See <code>How to fix?</code> for <code>Ubuntu:24.04</code> relevant fixed versions and status.</em></p>
<p>A timing-based side-channel flaw was found in libgcrypt&#39;s RSA implementation. This issue may allow a remote attacker to initiate a Bleichenbacher-style attack, which can lead to the decryption of RSA ciphertexts.</p>
<h2 id="remediation">Remediation</h2>
<p>There is no fixed version for <code>Ubuntu:24.04</code> <code>libgcrypt20</code>.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9404">https://access.redhat.com/errata/RHSA-2024:9404</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2268268">https://bugzilla.redhat.com/show_bug.cgi?id=2268268</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-2236">https://access.redhat.com/security/cve/CVE-2024-2236</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2245218">https://bugzilla.redhat.com/show_bug.cgi?id=2245218</a></li>
</ul>
<hr/>
<div class="cta card__cta">
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-LIBGCRYPT20-6693674">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">CVE-2024-26458</h2>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:21:54 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:21:38 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:31:10 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:30:13 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:31:20 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:30:22 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:29:08 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:28:19 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:29:16 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:28:28 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>
@@ -777,15 +777,15 @@
<h2 id="references">References</h2>
<ul>
<li><a href="http://www.openwall.com/lists/oss-security/2024/01/09/1">http://www.openwall.com/lists/oss-security/2024/01/09/1</a></li>
<li><a href="http://www.openwall.com/lists/oss-security/2024/03/11/1">http://www.openwall.com/lists/oss-security/2024/03/11/1</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240216-0009/">https://security.netapp.com/advisory/ntap-20240216-0009/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0008/">https://security.netapp.com/advisory/ntap-20240426-0008/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0013/">https://security.netapp.com/advisory/ntap-20240426-0013/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240503-0011/">https://security.netapp.com/advisory/ntap-20240503-0011/</a></li>
<li><a href="https://github.com/openssl/openssl/commit/050d26383d4e264966fb83428e72d5d48f402d35">https://github.com/openssl/openssl/commit/050d26383d4e264966fb83428e72d5d48f402d35</a></li>
<li><a href="https://github.com/openssl/openssl/commit/5b139f95c9a47a55a0c54100f3837b1eee942b04">https://github.com/openssl/openssl/commit/5b139f95c9a47a55a0c54100f3837b1eee942b04</a></li>
<li><a href="https://github.com/openssl/openssl/commit/f3fc5808fe9ff74042d639839610d03b8fdcc015">https://github.com/openssl/openssl/commit/f3fc5808fe9ff74042d639839610d03b8fdcc015</a></li>
<li><a href="https://www.openssl.org/news/secadv/20240109.txt">https://www.openssl.org/news/secadv/20240109.txt</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240216-0009/">https://security.netapp.com/advisory/ntap-20240216-0009/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0008/">https://security.netapp.com/advisory/ntap-20240426-0008/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0013/">https://security.netapp.com/advisory/ntap-20240426-0013/</a></li>
<li><a href="http://www.openwall.com/lists/oss-security/2024/03/11/1">http://www.openwall.com/lists/oss-security/2024/03/11/1</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240503-0011/">https://security.netapp.com/advisory/ntap-20240503-0011/</a></li>
</ul>
<hr/>
@@ -2817,6 +2817,7 @@
<h2 id="references">References</h2>
<ul>
<li><a href="https://bugs.busybox.net/show_bug.cgi?id=15874">https://bugs.busybox.net/show_bug.cgi?id=15874</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20241206-0007/">https://security.netapp.com/advisory/ntap-20241206-0007/</a></li>
</ul>
<hr/>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:29:22 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:28:32 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>
@@ -1032,15 +1032,15 @@
<h2 id="references">References</h2>
<ul>
<li><a href="http://www.openwall.com/lists/oss-security/2024/01/09/1">http://www.openwall.com/lists/oss-security/2024/01/09/1</a></li>
<li><a href="http://www.openwall.com/lists/oss-security/2024/03/11/1">http://www.openwall.com/lists/oss-security/2024/03/11/1</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240216-0009/">https://security.netapp.com/advisory/ntap-20240216-0009/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0008/">https://security.netapp.com/advisory/ntap-20240426-0008/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0013/">https://security.netapp.com/advisory/ntap-20240426-0013/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240503-0011/">https://security.netapp.com/advisory/ntap-20240503-0011/</a></li>
<li><a href="https://github.com/openssl/openssl/commit/050d26383d4e264966fb83428e72d5d48f402d35">https://github.com/openssl/openssl/commit/050d26383d4e264966fb83428e72d5d48f402d35</a></li>
<li><a href="https://github.com/openssl/openssl/commit/5b139f95c9a47a55a0c54100f3837b1eee942b04">https://github.com/openssl/openssl/commit/5b139f95c9a47a55a0c54100f3837b1eee942b04</a></li>
<li><a href="https://github.com/openssl/openssl/commit/f3fc5808fe9ff74042d639839610d03b8fdcc015">https://github.com/openssl/openssl/commit/f3fc5808fe9ff74042d639839610d03b8fdcc015</a></li>
<li><a href="https://www.openssl.org/news/secadv/20240109.txt">https://www.openssl.org/news/secadv/20240109.txt</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240216-0009/">https://security.netapp.com/advisory/ntap-20240216-0009/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0008/">https://security.netapp.com/advisory/ntap-20240426-0008/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0013/">https://security.netapp.com/advisory/ntap-20240426-0013/</a></li>
<li><a href="http://www.openwall.com/lists/oss-security/2024/03/11/1">http://www.openwall.com/lists/oss-security/2024/03/11/1</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240503-0011/">https://security.netapp.com/advisory/ntap-20240503-0011/</a></li>
</ul>
<hr/>
@@ -1325,6 +1325,7 @@
<h2 id="references">References</h2>
<ul>
<li><a href="https://bugs.busybox.net/show_bug.cgi?id=15874">https://bugs.busybox.net/show_bug.cgi?id=15874</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20241206-0007/">https://security.netapp.com/advisory/ntap-20241206-0007/</a></li>
</ul>
<hr/>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:29:44 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:28:51 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>
@@ -872,6 +872,8 @@
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-10041">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-10041</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-10041">https://access.redhat.com/security/cve/CVE-2024-10041</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2319212">https://bugzilla.redhat.com/show_bug.cgi?id=2319212</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9941">https://access.redhat.com/errata/RHSA-2024:9941</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:10379">https://access.redhat.com/errata/RHSA-2024:10379</a></li>
</ul>
<hr/>
@@ -1106,220 +1108,6 @@
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2204-PAM-8352842">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--medium" data-snyk-test="medium">
<h2 class="card__title">Information Exposure</h2>
<div class="card__section">
<div class="label label--medium">
<span class="label__text">medium severity</span>
</div>
<hr/>
<ul class="card__meta">
<li class="card__meta__item">
Manifest file: quay.io/argoproj/argocd:v2.11.12/argoproj/argocd <span class="list-paths__item__arrow"></span> Dockerfile
</li>
<li class="card__meta__item">
Package Manager: ubuntu:22.04
</li>
<li class="card__meta__item">
Vulnerable module:
libgcrypt20
</li>
<li class="card__meta__item">Introduced through:
docker-image|quay.io/argoproj/argocd@v2.11.12 and libgcrypt20@1.9.4-3ubuntu3
</li>
</ul>
<hr/>
<h3 class="card__section__title">Detailed paths</h3>
<ul class="card__meta__paths">
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/dirmngr@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
apt@2.4.13
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0@2.4.13
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
apt@2.4.13
<span class="list-paths__item__arrow"></span>
gnupg2/gpgv@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpgconf@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg-utils@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-agent@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-wks-client@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-wks-server@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpgsm@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
apt@2.4.13
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0@2.4.13
<span class="list-paths__item__arrow"></span>
systemd/libsystemd0@249.11-0ubuntu3.12
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
</ul><!-- .list-paths -->
</div><!-- .card__section -->
<hr/>
<!-- Overview -->
<h2 id="nvd-description">NVD Description</h2>
<p><strong><em>Note:</em></strong> <em>Versions mentioned in the description apply only to the upstream <code>libgcrypt20</code> package and not the <code>libgcrypt20</code> package as distributed by <code>Ubuntu</code>.</em>
<em>See <code>How to fix?</code> for <code>Ubuntu:22.04</code> relevant fixed versions and status.</em></p>
<p>A timing-based side-channel flaw was found in libgcrypt&#39;s RSA implementation. This issue may allow a remote attacker to initiate a Bleichenbacher-style attack, which can lead to the decryption of RSA ciphertexts.</p>
<h2 id="remediation">Remediation</h2>
<p>There is no fixed version for <code>Ubuntu:22.04</code> <code>libgcrypt20</code>.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-2236">https://access.redhat.com/security/cve/CVE-2024-2236</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2268268">https://bugzilla.redhat.com/show_bug.cgi?id=2268268</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2245218">https://bugzilla.redhat.com/show_bug.cgi?id=2245218</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9404">https://access.redhat.com/errata/RHSA-2024:9404</a></li>
</ul>
<hr/>
<div class="cta card__cta">
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2204-LIBGCRYPT20-6411451">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--medium" data-snyk-test="medium">
<h2 class="card__title">CVE-2024-26462</h2>
@@ -3631,6 +3419,220 @@
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2204-LIBZSTD-3368800">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">Information Exposure</h2>
<div class="card__section">
<div class="label label--low">
<span class="label__text">low severity</span>
</div>
<hr/>
<ul class="card__meta">
<li class="card__meta__item">
Manifest file: quay.io/argoproj/argocd:v2.11.12/argoproj/argocd <span class="list-paths__item__arrow"></span> Dockerfile
</li>
<li class="card__meta__item">
Package Manager: ubuntu:22.04
</li>
<li class="card__meta__item">
Vulnerable module:
libgcrypt20
</li>
<li class="card__meta__item">Introduced through:
docker-image|quay.io/argoproj/argocd@v2.11.12 and libgcrypt20@1.9.4-3ubuntu3
</li>
</ul>
<hr/>
<h3 class="card__section__title">Detailed paths</h3>
<ul class="card__meta__paths">
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/dirmngr@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
apt@2.4.13
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0@2.4.13
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
apt@2.4.13
<span class="list-paths__item__arrow"></span>
gnupg2/gpgv@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpgconf@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg-utils@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-agent@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-wks-client@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-wks-server@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
gnupg2/gnupg@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpgsm@2.2.27-3ubuntu2.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.11.12
<span class="list-paths__item__arrow"></span>
apt@2.4.13
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0@2.4.13
<span class="list-paths__item__arrow"></span>
systemd/libsystemd0@249.11-0ubuntu3.12
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.9.4-3ubuntu3
</span>
</li>
</ul><!-- .list-paths -->
</div><!-- .card__section -->
<hr/>
<!-- Overview -->
<h2 id="nvd-description">NVD Description</h2>
<p><strong><em>Note:</em></strong> <em>Versions mentioned in the description apply only to the upstream <code>libgcrypt20</code> package and not the <code>libgcrypt20</code> package as distributed by <code>Ubuntu</code>.</em>
<em>See <code>How to fix?</code> for <code>Ubuntu:22.04</code> relevant fixed versions and status.</em></p>
<p>A timing-based side-channel flaw was found in libgcrypt&#39;s RSA implementation. This issue may allow a remote attacker to initiate a Bleichenbacher-style attack, which can lead to the decryption of RSA ciphertexts.</p>
<h2 id="remediation">Remediation</h2>
<p>There is no fixed version for <code>Ubuntu:22.04</code> <code>libgcrypt20</code>.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9404">https://access.redhat.com/errata/RHSA-2024:9404</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2268268">https://bugzilla.redhat.com/show_bug.cgi?id=2268268</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-2236">https://access.redhat.com/security/cve/CVE-2024-2236</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2245218">https://bugzilla.redhat.com/show_bug.cgi?id=2245218</a></li>
</ul>
<hr/>
<div class="cta card__cta">
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2204-LIBGCRYPT20-6411451">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">Integer Overflow or Wraparound</h2>
@@ -5105,7 +5107,7 @@
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">CVE-2024-9681</h2>
<h2 class="card__title">Insufficient Comparison</h2>
<div class="card__section">
<div class="label label--low">

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:29:49 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:28:55 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:28:35 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:27:55 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:28:46 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:28:04 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:26:24 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:25:56 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:26:34 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:26:04 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>
@@ -777,15 +777,15 @@
<h2 id="references">References</h2>
<ul>
<li><a href="http://www.openwall.com/lists/oss-security/2024/01/09/1">http://www.openwall.com/lists/oss-security/2024/01/09/1</a></li>
<li><a href="http://www.openwall.com/lists/oss-security/2024/03/11/1">http://www.openwall.com/lists/oss-security/2024/03/11/1</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240216-0009/">https://security.netapp.com/advisory/ntap-20240216-0009/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0008/">https://security.netapp.com/advisory/ntap-20240426-0008/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0013/">https://security.netapp.com/advisory/ntap-20240426-0013/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240503-0011/">https://security.netapp.com/advisory/ntap-20240503-0011/</a></li>
<li><a href="https://github.com/openssl/openssl/commit/050d26383d4e264966fb83428e72d5d48f402d35">https://github.com/openssl/openssl/commit/050d26383d4e264966fb83428e72d5d48f402d35</a></li>
<li><a href="https://github.com/openssl/openssl/commit/5b139f95c9a47a55a0c54100f3837b1eee942b04">https://github.com/openssl/openssl/commit/5b139f95c9a47a55a0c54100f3837b1eee942b04</a></li>
<li><a href="https://github.com/openssl/openssl/commit/f3fc5808fe9ff74042d639839610d03b8fdcc015">https://github.com/openssl/openssl/commit/f3fc5808fe9ff74042d639839610d03b8fdcc015</a></li>
<li><a href="https://www.openssl.org/news/secadv/20240109.txt">https://www.openssl.org/news/secadv/20240109.txt</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240216-0009/">https://security.netapp.com/advisory/ntap-20240216-0009/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0008/">https://security.netapp.com/advisory/ntap-20240426-0008/</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240426-0013/">https://security.netapp.com/advisory/ntap-20240426-0013/</a></li>
<li><a href="http://www.openwall.com/lists/oss-security/2024/03/11/1">http://www.openwall.com/lists/oss-security/2024/03/11/1</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20240503-0011/">https://security.netapp.com/advisory/ntap-20240503-0011/</a></li>
</ul>
<hr/>
@@ -2817,6 +2817,7 @@
<h2 id="references">References</h2>
<ul>
<li><a href="https://bugs.busybox.net/show_bug.cgi?id=15874">https://bugs.busybox.net/show_bug.cgi?id=15874</a></li>
<li><a href="https://security.netapp.com/advisory/ntap-20241206-0007/">https://security.netapp.com/advisory/ntap-20241206-0007/</a></li>
</ul>
<hr/>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:26:39 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:26:08 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:26:44 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:26:12 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:27:07 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:26:30 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>
@@ -707,6 +707,8 @@
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-10041">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-10041</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-10041">https://access.redhat.com/security/cve/CVE-2024-10041</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2319212">https://bugzilla.redhat.com/show_bug.cgi?id=2319212</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9941">https://access.redhat.com/errata/RHSA-2024:9941</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:10379">https://access.redhat.com/errata/RHSA-2024:10379</a></li>
</ul>
<hr/>
@@ -951,170 +953,6 @@
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-PAM-8352843">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--medium" data-snyk-test="medium">
<h2 class="card__title">Information Exposure</h2>
<div class="card__section">
<div class="label label--medium">
<span class="label__text">medium severity</span>
</div>
<hr/>
<ul class="card__meta">
<li class="card__meta__item">
Manifest file: quay.io/argoproj/argocd:v2.12.7/argoproj/argocd <span class="list-paths__item__arrow"></span> Dockerfile
</li>
<li class="card__meta__item">
Package Manager: ubuntu:24.04
</li>
<li class="card__meta__item">
Vulnerable module:
libgcrypt20
</li>
<li class="card__meta__item">Introduced through:
docker-image|quay.io/argoproj/argocd@v2.12.7 and libgcrypt20@1.10.3-2build1
</li>
</ul>
<hr/>
<h3 class="card__section__title">Detailed paths</h3>
<ul class="card__meta__paths">
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
gnupg2/dirmngr@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-agent@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0t64@2.7.14build2
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
gnupg2/gpgv@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
gnupg2/gpgconf@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
adduser@3.137ubuntu1
<span class="list-paths__item__arrow"></span>
shadow/passwd@1:4.13+dfsg1-4ubuntu3.2
<span class="list-paths__item__arrow"></span>
pam/libpam-modules@1.5.3-5ubuntu5.1
<span class="list-paths__item__arrow"></span>
systemd/libsystemd0@255.4-1ubuntu8.4
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
</ul><!-- .list-paths -->
</div><!-- .card__section -->
<hr/>
<!-- Overview -->
<h2 id="nvd-description">NVD Description</h2>
<p><strong><em>Note:</em></strong> <em>Versions mentioned in the description apply only to the upstream <code>libgcrypt20</code> package and not the <code>libgcrypt20</code> package as distributed by <code>Ubuntu</code>.</em>
<em>See <code>How to fix?</code> for <code>Ubuntu:24.04</code> relevant fixed versions and status.</em></p>
<p>A timing-based side-channel flaw was found in libgcrypt&#39;s RSA implementation. This issue may allow a remote attacker to initiate a Bleichenbacher-style attack, which can lead to the decryption of RSA ciphertexts.</p>
<h2 id="remediation">Remediation</h2>
<p>There is no fixed version for <code>Ubuntu:24.04</code> <code>libgcrypt20</code>.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-2236">https://access.redhat.com/security/cve/CVE-2024-2236</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2268268">https://bugzilla.redhat.com/show_bug.cgi?id=2268268</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2245218">https://bugzilla.redhat.com/show_bug.cgi?id=2245218</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9404">https://access.redhat.com/errata/RHSA-2024:9404</a></li>
</ul>
<hr/>
<div class="cta card__cta">
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-LIBGCRYPT20-6693674">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--medium" data-snyk-test="medium">
<h2 class="card__title">CVE-2024-26462</h2>
@@ -2196,6 +2034,170 @@
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-OPENSSL-7838291">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">Information Exposure</h2>
<div class="card__section">
<div class="label label--low">
<span class="label__text">low severity</span>
</div>
<hr/>
<ul class="card__meta">
<li class="card__meta__item">
Manifest file: quay.io/argoproj/argocd:v2.12.7/argoproj/argocd <span class="list-paths__item__arrow"></span> Dockerfile
</li>
<li class="card__meta__item">
Package Manager: ubuntu:24.04
</li>
<li class="card__meta__item">
Vulnerable module:
libgcrypt20
</li>
<li class="card__meta__item">Introduced through:
docker-image|quay.io/argoproj/argocd@v2.12.7 and libgcrypt20@1.10.3-2build1
</li>
</ul>
<hr/>
<h3 class="card__section__title">Detailed paths</h3>
<ul class="card__meta__paths">
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
gnupg2/dirmngr@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-agent@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0t64@2.7.14build2
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
gnupg2/gpgv@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
gnupg2/gpgconf@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.12.7
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
adduser@3.137ubuntu1
<span class="list-paths__item__arrow"></span>
shadow/passwd@1:4.13+dfsg1-4ubuntu3.2
<span class="list-paths__item__arrow"></span>
pam/libpam-modules@1.5.3-5ubuntu5.1
<span class="list-paths__item__arrow"></span>
systemd/libsystemd0@255.4-1ubuntu8.4
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
</ul><!-- .list-paths -->
</div><!-- .card__section -->
<hr/>
<!-- Overview -->
<h2 id="nvd-description">NVD Description</h2>
<p><strong><em>Note:</em></strong> <em>Versions mentioned in the description apply only to the upstream <code>libgcrypt20</code> package and not the <code>libgcrypt20</code> package as distributed by <code>Ubuntu</code>.</em>
<em>See <code>How to fix?</code> for <code>Ubuntu:24.04</code> relevant fixed versions and status.</em></p>
<p>A timing-based side-channel flaw was found in libgcrypt&#39;s RSA implementation. This issue may allow a remote attacker to initiate a Bleichenbacher-style attack, which can lead to the decryption of RSA ciphertexts.</p>
<h2 id="remediation">Remediation</h2>
<p>There is no fixed version for <code>Ubuntu:24.04</code> <code>libgcrypt20</code>.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9404">https://access.redhat.com/errata/RHSA-2024:9404</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2268268">https://bugzilla.redhat.com/show_bug.cgi?id=2268268</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-2236">https://access.redhat.com/security/cve/CVE-2024-2236</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2245218">https://bugzilla.redhat.com/show_bug.cgi?id=2245218</a></li>
</ul>
<hr/>
<div class="cta card__cta">
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-LIBGCRYPT20-6693674">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">CVE-2024-26458</h2>
@@ -3072,7 +3074,7 @@
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">CVE-2024-9681</h2>
<h2 class="card__title">Insufficient Comparison</h2>
<div class="card__section">
<div class="label label--low">

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:27:13 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:26:35 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:25:52 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:25:26 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:26:02 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:25:35 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:23:46 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:23:27 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:23:53 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:23:34 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:23:58 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:23:37 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following path:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:24:02 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:23:41 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:24:22 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:23:59 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>
@@ -707,6 +707,8 @@
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-10041">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-10041</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-10041">https://access.redhat.com/security/cve/CVE-2024-10041</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2319212">https://bugzilla.redhat.com/show_bug.cgi?id=2319212</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9941">https://access.redhat.com/errata/RHSA-2024:9941</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:10379">https://access.redhat.com/errata/RHSA-2024:10379</a></li>
</ul>
<hr/>
@@ -951,170 +953,6 @@
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-PAM-8352843">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--medium" data-snyk-test="medium">
<h2 class="card__title">Information Exposure</h2>
<div class="card__section">
<div class="label label--medium">
<span class="label__text">medium severity</span>
</div>
<hr/>
<ul class="card__meta">
<li class="card__meta__item">
Manifest file: quay.io/argoproj/argocd:v2.13.1/argoproj/argocd <span class="list-paths__item__arrow"></span> Dockerfile
</li>
<li class="card__meta__item">
Package Manager: ubuntu:24.04
</li>
<li class="card__meta__item">
Vulnerable module:
libgcrypt20
</li>
<li class="card__meta__item">Introduced through:
docker-image|quay.io/argoproj/argocd@v2.13.1 and libgcrypt20@1.10.3-2build1
</li>
</ul>
<hr/>
<h3 class="card__section__title">Detailed paths</h3>
<ul class="card__meta__paths">
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
gnupg2/dirmngr@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-agent@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0t64@2.7.14build2
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
gnupg2/gpgv@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
gnupg2/gpgconf@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
adduser@3.137ubuntu1
<span class="list-paths__item__arrow"></span>
shadow/passwd@1:4.13+dfsg1-4ubuntu3.2
<span class="list-paths__item__arrow"></span>
pam/libpam-modules@1.5.3-5ubuntu5.1
<span class="list-paths__item__arrow"></span>
systemd/libsystemd0@255.4-1ubuntu8.4
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
</ul><!-- .list-paths -->
</div><!-- .card__section -->
<hr/>
<!-- Overview -->
<h2 id="nvd-description">NVD Description</h2>
<p><strong><em>Note:</em></strong> <em>Versions mentioned in the description apply only to the upstream <code>libgcrypt20</code> package and not the <code>libgcrypt20</code> package as distributed by <code>Ubuntu</code>.</em>
<em>See <code>How to fix?</code> for <code>Ubuntu:24.04</code> relevant fixed versions and status.</em></p>
<p>A timing-based side-channel flaw was found in libgcrypt&#39;s RSA implementation. This issue may allow a remote attacker to initiate a Bleichenbacher-style attack, which can lead to the decryption of RSA ciphertexts.</p>
<h2 id="remediation">Remediation</h2>
<p>There is no fixed version for <code>Ubuntu:24.04</code> <code>libgcrypt20</code>.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-2236">https://access.redhat.com/security/cve/CVE-2024-2236</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2268268">https://bugzilla.redhat.com/show_bug.cgi?id=2268268</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2245218">https://bugzilla.redhat.com/show_bug.cgi?id=2245218</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9404">https://access.redhat.com/errata/RHSA-2024:9404</a></li>
</ul>
<hr/>
<div class="cta card__cta">
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-LIBGCRYPT20-6693674">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--medium" data-snyk-test="medium">
<h2 class="card__title">CVE-2024-26462</h2>
@@ -2086,6 +1924,170 @@
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-OPENSSL-7838291">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">Information Exposure</h2>
<div class="card__section">
<div class="label label--low">
<span class="label__text">low severity</span>
</div>
<hr/>
<ul class="card__meta">
<li class="card__meta__item">
Manifest file: quay.io/argoproj/argocd:v2.13.1/argoproj/argocd <span class="list-paths__item__arrow"></span> Dockerfile
</li>
<li class="card__meta__item">
Package Manager: ubuntu:24.04
</li>
<li class="card__meta__item">
Vulnerable module:
libgcrypt20
</li>
<li class="card__meta__item">Introduced through:
docker-image|quay.io/argoproj/argocd@v2.13.1 and libgcrypt20@1.10.3-2build1
</li>
</ul>
<hr/>
<h3 class="card__section__title">Detailed paths</h3>
<ul class="card__meta__paths">
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
gnupg2/dirmngr@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg-agent@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
apt/libapt-pkg6.0t64@2.7.14build2
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
gnupg2/gpgv@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
gnupg2/gpg@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
gnupg2/gpgconf@2.4.4-2ubuntu17
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
<li>
<span class="list-paths__item__introduced"><em>Introduced through</em>:
docker-image|quay.io/argoproj/argocd@v2.13.1
<span class="list-paths__item__arrow"></span>
apt@2.7.14build2
<span class="list-paths__item__arrow"></span>
adduser@3.137ubuntu1
<span class="list-paths__item__arrow"></span>
shadow/passwd@1:4.13+dfsg1-4ubuntu3.2
<span class="list-paths__item__arrow"></span>
pam/libpam-modules@1.5.3-5ubuntu5.1
<span class="list-paths__item__arrow"></span>
systemd/libsystemd0@255.4-1ubuntu8.4
<span class="list-paths__item__arrow"></span>
libgcrypt20@1.10.3-2build1
</span>
</li>
</ul><!-- .list-paths -->
</div><!-- .card__section -->
<hr/>
<!-- Overview -->
<h2 id="nvd-description">NVD Description</h2>
<p><strong><em>Note:</em></strong> <em>Versions mentioned in the description apply only to the upstream <code>libgcrypt20</code> package and not the <code>libgcrypt20</code> package as distributed by <code>Ubuntu</code>.</em>
<em>See <code>How to fix?</code> for <code>Ubuntu:24.04</code> relevant fixed versions and status.</em></p>
<p>A timing-based side-channel flaw was found in libgcrypt&#39;s RSA implementation. This issue may allow a remote attacker to initiate a Bleichenbacher-style attack, which can lead to the decryption of RSA ciphertexts.</p>
<h2 id="remediation">Remediation</h2>
<p>There is no fixed version for <code>Ubuntu:24.04</code> <code>libgcrypt20</code>.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236">http://people.ubuntu.com/~ubuntu-security/cve/CVE-2024-2236</a></li>
<li><a href="https://access.redhat.com/errata/RHSA-2024:9404">https://access.redhat.com/errata/RHSA-2024:9404</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2268268">https://bugzilla.redhat.com/show_bug.cgi?id=2268268</a></li>
<li><a href="https://access.redhat.com/security/cve/CVE-2024-2236">https://access.redhat.com/security/cve/CVE-2024-2236</a></li>
<li><a href="https://bugzilla.redhat.com/show_bug.cgi?id=2245218">https://bugzilla.redhat.com/show_bug.cgi?id=2245218</a></li>
</ul>
<hr/>
<div class="cta card__cta">
<p><a href="https://snyk.io/vuln/SNYK-UBUNTU2404-LIBGCRYPT20-6693674">More about this vulnerability</a></p>
</div>
</div><!-- .card -->
<div class="card card--vuln disclosure--not-new severity--low" data-snyk-test="low">
<h2 class="card__title">CVE-2024-26458</h2>

View File

@@ -456,7 +456,7 @@
<div class="header-wrap">
<h1 class="project__header__title">Snyk test report</h1>
<p class="timestamp">November 24th 2024, 12:24:27 am (UTC+00:00)</p>
<p class="timestamp">December 8th 2024, 12:24:03 am (UTC+00:00)</p>
</div>
<div class="source-panel">
<span>Scanned the following paths:</span>

View File

@@ -12,13 +12,13 @@ argocd admin proj generate-spec PROJECT [flags]
```
# Generate a YAML configuration for a project named "myproject"
argocd admin projects generate-spec myproject
argocd admin proj generate-spec myproject
# Generate a JSON configuration for a project named "anotherproject" and specify an output file
argocd admin projects generate-spec anotherproject --output json --file config.json
argocd admin proj generate-spec anotherproject --output json --file config.json
# Generate a YAML configuration for a project named "someproject" and write it back to the input file
argocd admin projects generate-spec someproject --inline
argocd admin proj generate-spec someproject --inline
```
### Options

View File

@@ -12,10 +12,10 @@ argocd admin proj update-role-policy PROJECT_GLOB MODIFICATION ACTION [flags]
```
# Add policy that allows executing any action (action/*) to roles which name matches to *deployer* in all projects
argocd admin projects update-role-policy '*' set 'action/*' --role '*deployer*' --resource applications --scope '*' --permission allow
argocd admin proj update-role-policy '*' set 'action/*' --role '*deployer*' --resource applications --scope '*' --permission allow
# Remove policy that which manages running (action/*) from all roles which name matches *deployer* in all projects
argocd admin projects update-role-policy '*' remove override --role '*deployer*'
argocd admin proj update-role-policy '*' remove override --role '*deployer*'
```

View File

@@ -2,7 +2,31 @@
Sync windows are configurable windows of time where syncs will either be blocked or allowed. These are defined
by a kind, which can be either `allow` or `deny`, a `schedule` in cron format and a duration along with one or
more of either `applications`, `namespaces` and `clusters`. Wildcards are supported. These windows affect the running
more of either `applications`, `namespaces` and `clusters`. Wildcards are supported.
## Relationship between Sync Windows and Applications
The relationship between Sync Windows and Application resources is many-to-many. This means that an Application resource
may be affected by multiple Sync Windows, and that a single Sync Window definition may apply to multiple Application
resources.
The relationship between Sync Window and Application is established as part of the definition of Sync Window.
Sync Window definition includes a section defining the Application resources to which it applies. There
are three mechanisms for selecting the Application resources to which a Sync Window applies:
- By name of Application resource
- By cluster into which resources are installed by Application resource. This is specified by `Application.spec.destination.name` and `.server` fields
- By namespace into which resources are installed by Application resource. This is specified by `Application.spec.destination.namespace` field.
All three mechanisms allow usage of wildcards. The mechanisms are not mutually exclusive, and all three of them can be used in single
Sync Window definition.
When multiple selection mechanisms are used, they are effectively `ORed`, meaning that if any of the selector selects the Application,
then the Application is affected by the Sync Window.
## Effect of Sync Windows
These windows affect the running
of both manual and automated syncs but allow an override for manual syncs which is useful if you are only interested
in preventing automated syncs or if you need to temporarily override a window to perform a sync.

View File

@@ -2883,7 +2883,7 @@
"datasource": {
"uid": "$datasource"
},
"expr": "go_memstats_heap_alloc_bytes{job=\"argocd-repo-server-metrics\",namespace=~\"$namespace\"}",
"expr": "go_memstats_heap_alloc_bytes{job=\"argocd-server-metrics\",namespace=~\"$namespace\"}",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{pod}}",
@@ -2968,7 +2968,7 @@
"datasource": {
"uid": "$datasource"
},
"expr": "go_goroutines{job=\"argocd-repo-server-metrics\",namespace=~\"$namespace\"}",
"expr": "go_goroutines{job=\"argocd-server-metrics\",namespace=~\"$namespace\"}",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{pod}}",
@@ -3270,7 +3270,7 @@
"datasource": {
"uid": "$datasource"
},
"expr": "go_gc_duration_seconds{job=\"argocd-repo-server-metrics\", quantile=\"1\", namespace=~\"$namespace\"}",
"expr": "go_gc_duration_seconds{job=\"argocd-server-metrics\", quantile=\"1\", namespace=~\"$namespace\"}",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "{{pod}}",

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