Compare commits

..

50 Commits

Author SHA1 Message Date
github-actions[bot]
a14b0125fe Bump version to 3.0.3 on release-3.0 branch (#23087)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: crenshaw-dev <350466+crenshaw-dev@users.noreply.github.com>
2025-05-21 14:18:58 -04:00
Peter Jiang
866db14e30 chore: bump gitops-engine ssd fix (#23071)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2025-05-20 21:09:18 -04:00
gcp-cherry-pick-bot[bot]
af3d9266a8 fix: Account for batch event processing in e2e tests (cherry-pick #22356) (#23070)
Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
Co-authored-by: Andrii Korotkov <137232734+andrii-korotkov-verkada@users.noreply.github.com>
2025-05-20 20:09:04 -04:00
Alexandre Gaudreault
ddd6df5d44 fix: infinite reconciliation loop when app is in error (#23067)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-20 16:12:00 -04:00
gcp-cherry-pick-bot[bot]
927ed3504e fix: remove default spec.preserveUnknownFields ignoreDifference for CRD (cherry-pick #22948) (#23044)
Signed-off-by: mikutas <23391543+mikutas@users.noreply.github.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Takumi Sue <23391543+mikutas@users.noreply.github.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-20 09:43:08 -04:00
gcp-cherry-pick-bot[bot]
b1cafa9d76 docs: fix jsonpath in 2.14-3.0 upgrade doc (cherry-pick #23045) (#23046)
Signed-off-by: Cyril Gaudin <cyril.gaudin@camunda.com>
Co-authored-by: Cyril Gaudin <cyril.gaudin@gmail.com>
2025-05-19 09:58:23 -07:00
github-actions[bot]
8a7c0f0c86 Bump version to 3.0.2 on release-3.0 branch (#23039)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <19544836+reggie-k@users.noreply.github.com>
2025-05-19 16:41:34 +03:00
Regina Voloshin
3fb34b99de fix(haproxy): setting maxconn in haproxy config cherry-pick (#15319) (#18283) (#23037)
Signed-off-by: Timothy Griffiths <griffiths.timothy@gmail.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Timothy Griffiths <griffiths.timothy@gmail.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-05-19 14:48:47 +02:00
Oleksandr Saulyak
90e9d1a5ad fix: settings request doesn't return default tracking method (#22965) (cherry-pick) (#23034)
Signed-off-by: oleksandr-codefresh <oleksandr.saulyak@octopus.com>
2025-05-19 11:07:32 +03:00
gcp-cherry-pick-bot[bot]
cca991a018 fix(test): broken e2e test (cherry-pick #22975) (#23017)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-16 10:00:08 -07:00
gcp-cherry-pick-bot[bot]
3d37cfac04 docs(server): no resource health when using the list api (cherry-pick #22954) (#22972)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-05-14 11:40:19 -04:00
github-actions[bot]
2bcef48772 Bump version to 3.0.1 on release-3.0 branch (#22968)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <19544836+reggie-k@users.noreply.github.com>
2025-05-14 17:59:45 +03:00
gcp-cherry-pick-bot[bot]
cb5d6f5ef7 fix(health): handle nil lastTransitionTime (#22897) (cherry-pick #22900) (#22908)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-05-09 10:46:00 -04:00
gcp-cherry-pick-bot[bot]
2913d5fcb5 fix: Race condition in nativeGitClient.LsFiles (issue #21754) (cherry-pick #22878) (#22906)
Signed-off-by: Mathieu Agar <magar@mirakl.com>
Co-authored-by: Mathieu Agar <magar@mirakl.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-05-08 08:01:31 -07:00
gcp-cherry-pick-bot[bot]
edd2358f79 fix(docs): upgrading 3.0 docs (cherry-pick #22891) (#22894)
Signed-off-by: Joerg Heyduk <joerg@heyduk.org>
Co-authored-by: jheyduk <jheyduk@users.noreply.github.com>
2025-05-07 09:06:07 -04:00
github-actions[bot]
e98f483bfd Bump version to 3.0.0 on release-3.0 branch (#22880)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <19544836+reggie-k@users.noreply.github.com>
2025-05-06 14:20:53 +03:00
github-actions[bot]
e2250bad87 Bump version to 3.0.0-rc6 on release-3.0 branch (#22861)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <19544836+reggie-k@users.noreply.github.com>
2025-05-04 11:43:11 +03:00
gcp-cherry-pick-bot[bot]
a444a05e8f fix: AppSet PullRequest and SCM generators get 401 from GitHub without tokenRef (cherry-pick #22737) (#22744)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
Co-authored-by: Regina Voloshin <regina.voloshin@codefresh.io>
2025-05-02 18:25:24 -04:00
gcp-cherry-pick-bot[bot]
f075c5acd3 fix: Only port-forward to ready pods (#10610) (cherry-pick #22794) (#22825)
Signed-off-by: Mike Bryant <mike.bryant@mettle.co.uk>
Co-authored-by: Mike Bryant <mike.bryant@mettle.co.uk>
2025-05-02 18:24:25 -04:00
github-actions[bot]
f58b8070f1 Bump version to 3.0.0-rc5 on release-3.0 branch (#22830)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <19544836+reggie-k@users.noreply.github.com>
2025-04-30 08:38:01 +03:00
gcp-cherry-pick-bot[bot]
b2e875323c fix: do not normalize resource tracking on live crds (cherry-pick #22722) - cherry-pick 3.0 (#22735)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-04-28 17:22:08 -04:00
gcp-cherry-pick-bot[bot]
6fea008447 fix: remove project from cache key for project scoped credentials (cherry-pick #22712) (#22817)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
Co-authored-by: Peter Jiang <35584807+pjiang-dev@users.noreply.github.com>
2025-04-28 16:47:01 -04:00
Regina Voloshin
ffbf9d5911 fix: AppSet PullRequest and SCM generators get 401 from GitHub without tokenRef (manually signed off cherry-pick #22737) (#22763)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
2025-04-28 11:24:02 +03:00
gcp-cherry-pick-bot[bot]
ebeae20ff4 fix(ui): fix bearerToken validate in helm connect page (cherry-pick #22791) (#22798)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
Co-authored-by: Linghao Su <linghao.su@daocloud.io>
2025-04-25 08:35:07 -07:00
github-actions[bot]
3ae374ce22 Bump version to 3.0.0-rc4 on release-3.0 branch (#22756)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: crenshaw-dev <350466+crenshaw-dev@users.noreply.github.com>
2025-04-22 08:25:30 -07:00
gcp-cherry-pick-bot[bot]
3d2c010dbe feat(hydrator): handle sourceHydrator fields from webhook (#19397) (cherry-pick #22485) (#22753)
Signed-off-by: daengdaengLee <gunho1020@gmail.com>
Signed-off-by: Alexy Mantha <alexy@mantha.dev>
Co-authored-by: Alexy Mantha <alexy.mantha@goto.com>
Co-authored-by: Kunho Lee <gunho1020@gmail.com>
2025-04-22 08:21:13 -07:00
gcp-cherry-pick-bot[bot]
b6e6104dbc fix(ui): avoid spurious error on hydration (#22506) (cherry-pick #22711) (#22715)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-04-17 16:40:54 -07:00
gcp-cherry-pick-bot[bot]
a8ce6772b8 fix(controller): always set health.status.lastTransitionTime (#22665) (cherry-pick #22666) (#22667)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-04-14 12:50:58 -07:00
gcp-cherry-pick-bot[bot]
5d131c5251 fix: do not exclude APIService resources (cherry-pick #22586) (#22587)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-04-07 12:24:48 +01:00
gcp-cherry-pick-bot[bot]
d6a04a3642 fix: Check for semver constraint matching in application webhook handler (cherry-pick #21648) (#22507)
Signed-off-by: eadred <eadred77@googlemail.com>
Co-authored-by: Eadred <eadred77@googlemail.com>
2025-03-27 11:27:26 -04:00
github-actions[bot]
4f37dd880a Bump version to 3.0.0-rc3 on release-3.0 branch (#22468)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: crenshaw-dev <350466+crenshaw-dev@users.noreply.github.com>
2025-03-24 15:38:58 -04:00
Michael Crenshaw
20f0fc6786 chore(deps): bump github.com/golang-jwt/jwt to 4.5.2/5.2.2 (#22464)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-24 14:06:45 -04:00
github-actions[bot]
4ced513335 Bump version to 3.0.0-rc2 on release-3.0 branch (#22411)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: crenshaw-dev <350466+crenshaw-dev@users.noreply.github.com>
2025-03-19 13:04:03 -04:00
gcp-cherry-pick-bot[bot]
0d2471b3f9 fix: Enable service account token automount for haproxy (#22226) (cherry-pick #22353) (#22406)
Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
Co-authored-by: Andrii Korotkov <137232734+andrii-korotkov-verkada@users.noreply.github.com>
2025-03-19 10:53:20 -04:00
gcp-cherry-pick-bot[bot]
226a670fe6 chore(ci): improve previous-version script readability, fix bug (cherry-pick #22378) (#22381)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-17 15:18:27 -04:00
gcp-cherry-pick-bot[bot]
2933154a5c fix(ci): get correct previous version, fail workflow if not (cherry-pick #22376) (#22377)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-17 20:01:18 +02:00
github-actions[bot]
ba866bfc16 Bump version to 3.0.0-rc1 on release-3.0 branch (#22374)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <19544836+reggie-k@users.noreply.github.com>
2025-03-17 17:48:35 +02:00
gcp-cherry-pick-bot[bot]
6e4c8fd53d fix(ci): use tags instead of branches (cherry-pick #22372) (#22373)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-17 17:43:57 +02:00
gcp-cherry-pick-bot[bot]
15046b992e fix(ci): handle major versions in compatibility table generator (cherry-pick #22370) (#22371)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-17 17:17:55 +02:00
Cheng Fang
8545d214b6 fix(docs): update --auth-token description in argocd_appset_update.md to account for environment variable (#22350)
Signed-off-by: Cheng Fang <cfang@redhat.com>
2025-03-16 16:49:50 -04:00
Andrii Korotkov
bfd72b42df fix: Revert "fix: Race condition occurs during initial sharding (#22264)" (#22354)
Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
2025-03-14 17:00:08 -07:00
Peter Jiang
f044200d9e chore: bump gitops-engine (#22335)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2025-03-14 16:52:00 -04:00
Linghao Su
0fab3cfeec feat(ui): support display sync wave (#20614)
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
2025-03-14 12:05:32 -04:00
dependabot[bot]
c8e1de6146 chore(deps): bump github.com/Azure/kubelogin from 0.1.8 to 0.1.9 (#22308)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 11:30:06 -04:00
dependabot[bot]
de40dc2334 chore(deps): bump github.com/coreos/go-oidc/v3 from 3.12.0 to 3.13.0 (#22347)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 10:12:11 -04:00
Dan Garfield
9f8d68f07b docs: various wording fixes for 3.0 migration guide (#22343)
Signed-off-by: Dan Garfield <dan@codefresh.io>
2025-03-14 10:08:26 -04:00
Alexandre Gaudreault
fe598a831e chore!: add 60s default jitter (#22342)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-03-13 22:01:12 +00:00
Michael Crenshaw
aeb0002877 chore: set default tracking to annotation (#22289)
Signed-off-by: Yuan Tang <terrytangyuan@gmail.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Yuan Tang <terrytangyuan@gmail.com>
2025-03-13 17:40:51 -04:00
Michael Crenshaw
910b9518e4 feat(controller): enable batch event processing by default (#22338)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-03-13 17:40:31 -04:00
Marco Franssen
2ce593b5de chore: Optimize Docker image layers (#21525)
Signed-off-by: Marco Franssen <marco.franssen@gmail.com>
2025-03-13 15:24:45 -04:00
110 changed files with 1237 additions and 575 deletions

View File

@@ -77,7 +77,8 @@ jobs:
- name: Set GORELEASER_PREVIOUS_TAG # Workaround, GoReleaser uses 'git-describe' to determine a previous tag. Our tags are created in release branches.
run: |
set -xue
echo "GORELEASER_PREVIOUS_TAG=$(go run hack/get-previous-release/get-previous-version-for-release-notes.go ${{ github.ref_name }})" >> $GITHUB_ENV
GORELEASER_PREVIOUS_TAG=$(go run hack/get-previous-release/get-previous-version-for-release-notes.go ${{ github.ref_name }}) || exit 1
echo "GORELEASER_PREVIOUS_TAG=$GORELEASER_PREVIOUS_TAG" >> $GITHUB_ENV
- name: Set environment variables for ldflags
id: set_ldflag

View File

@@ -6,6 +6,8 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:80dd3c3b9c6cecb9f1667e9290b
####################################################################################################
FROM docker.io/library/golang:1.24.1@sha256:c5adecdb7b3f8c5ca3c88648a861882849cc8b02fed68ece31e25de88ad13418 AS builder
WORKDIR /tmp
RUN echo 'deb http://archive.debian.org/debian buster-backports main' >> /etc/apt/sources.list
RUN apt-get update && apt-get install --no-install-recommends -y \
@@ -23,8 +25,6 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /tmp
COPY hack/install.sh hack/tool-versions.sh ./
COPY hack/installers installers
@@ -40,8 +40,8 @@ LABEL org.opencontainers.image.source="https://github.com/argoproj/argo-cd"
USER root
ENV ARGOCD_USER_ID=999
ENV DEBIAN_FRONTEND=noninteractive
ENV ARGOCD_USER_ID=999 \
DEBIAN_FRONTEND=noninteractive
RUN groupadd -g $ARGOCD_USER_ID argocd && \
useradd -r -u $ARGOCD_USER_ID -g argocd argocd && \
@@ -55,11 +55,13 @@ RUN groupadd -g $ARGOCD_USER_ID argocd && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY hack/gpg-wrapper.sh /usr/local/bin/gpg-wrapper.sh
COPY hack/git-verify-wrapper.sh /usr/local/bin/git-verify-wrapper.sh
COPY hack/gpg-wrapper.sh \
hack/git-verify-wrapper.sh \
entrypoint.sh \
/usr/local/bin/
COPY --from=builder /usr/local/bin/helm /usr/local/bin/helm
COPY --from=builder /usr/local/bin/kustomize /usr/local/bin/kustomize
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
# keep uid_entrypoint.sh for backward compatibility
RUN ln -s /usr/local/bin/entrypoint.sh /usr/local/bin/uid_entrypoint.sh
@@ -111,13 +113,13 @@ RUN go mod download
# Perform the build
COPY . .
COPY --from=argocd-ui /src/dist/app /go/src/github.com/argoproj/argo-cd/ui/dist/app
ARG TARGETOS
ARG TARGETARCH
ARG TARGETOS \
TARGETARCH
# These build args are optional; if not specified the defaults will be taken from the Makefile
ARG GIT_TAG
ARG BUILD_DATE
ARG GIT_TREE_STATE
ARG GIT_COMMIT
ARG GIT_TAG \
BUILD_DATE \
GIT_TREE_STATE \
GIT_COMMIT
RUN GIT_COMMIT=$GIT_COMMIT \
GIT_TREE_STATE=$GIT_TREE_STATE \
GIT_TAG=$GIT_TAG \
@@ -130,6 +132,7 @@ RUN GIT_COMMIT=$GIT_COMMIT \
# Final image
####################################################################################################
FROM argocd-base
ENTRYPOINT ["/usr/bin/tini", "--"]
COPY --from=argocd-build /go/src/github.com/argoproj/argo-cd/dist/argocd* /usr/local/bin/
USER root
@@ -144,4 +147,3 @@ RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-commit-server
USER $ARGOCD_USER_ID
ENTRYPOINT ["/usr/bin/tini", "--"]

View File

@@ -486,6 +486,7 @@ start-e2e-local: mod-vendor-local dep-ui-local cli-local
ARGOCD_APPLICATIONSET_CONTROLLER_ALLOWED_SCM_PROVIDERS=http://127.0.0.1:8341,http://127.0.0.1:8342,http://127.0.0.1:8343,http://127.0.0.1:8344 \
ARGOCD_E2E_TEST=true \
ARGOCD_HYDRATOR_ENABLED=true \
ARGOCD_CLUSTER_CACHE_EVENTS_PROCESSING_INTERVAL=1ms \
goreman -f $(ARGOCD_PROCFILE) start ${ARGOCD_START}
ls -lrt /tmp/coverage

View File

@@ -1 +1 @@
3.0.0
3.0.3

View File

@@ -26,7 +26,11 @@ func NewGithubService(token, url, owner, repo string, labels []string) (PullRequ
httpClient := &http.Client{}
var client *github.Client
if url == "" {
client = github.NewClient(httpClient).WithAuthToken(token)
if token == "" {
client = github.NewClient(httpClient)
} else {
client = github.NewClient(httpClient).WithAuthToken(token)
}
} else {
var err error
client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url)

View File

@@ -25,7 +25,11 @@ func NewGithubProvider(organization string, token string, url string, allBranche
httpClient := &http.Client{}
var client *github.Client
if url == "" {
client = github.NewClient(httpClient).WithAuthToken(token)
if token == "" {
client = github.NewClient(httpClient)
} else {
client = github.NewClient(httpClient).WithAuthToken(token)
}
} else {
var err error
client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url)

View File

@@ -44,9 +44,13 @@ const (
// CLIName is the name of the CLI
cliName = common.ApplicationController
// Default time in seconds for application resync period
defaultAppResyncPeriod = 180
defaultAppResyncPeriod = 120
// Default time in seconds for application resync period jitter
defaultAppResyncPeriodJitter = 60
// Default time in seconds for application hard resync period
defaultAppHardResyncPeriod = 0
// Default time in seconds for ignoring consecutive errors when comminicating with repo-server
defaultRepoErrorGracePeriod = defaultAppResyncPeriod + defaultAppResyncPeriodJitter
)
func NewCommand() *cobra.Command {
@@ -252,8 +256,8 @@ func NewCommand() *cobra.Command {
clientConfig = cli.AddKubectlFlagsToCmd(&command)
command.Flags().Int64Var(&appResyncPeriod, "app-resync", int64(env.ParseDurationFromEnv("ARGOCD_RECONCILIATION_TIMEOUT", defaultAppResyncPeriod*time.Second, 0, math.MaxInt64).Seconds()), "Time period in seconds for application resync.")
command.Flags().Int64Var(&appHardResyncPeriod, "app-hard-resync", int64(env.ParseDurationFromEnv("ARGOCD_HARD_RECONCILIATION_TIMEOUT", defaultAppHardResyncPeriod*time.Second, 0, math.MaxInt64).Seconds()), "Time period in seconds for application hard resync.")
command.Flags().Int64Var(&appResyncJitter, "app-resync-jitter", int64(env.ParseDurationFromEnv("ARGOCD_RECONCILIATION_JITTER", 0*time.Second, 0, math.MaxInt64).Seconds()), "Maximum time period in seconds to add as a delay jitter for application resync.")
command.Flags().Int64Var(&repoErrorGracePeriod, "repo-error-grace-period-seconds", int64(env.ParseDurationFromEnv("ARGOCD_REPO_ERROR_GRACE_PERIOD_SECONDS", defaultAppResyncPeriod*time.Second, 0, math.MaxInt64).Seconds()), "Grace period in seconds for ignoring consecutive errors while communicating with repo server.")
command.Flags().Int64Var(&appResyncJitter, "app-resync-jitter", int64(env.ParseDurationFromEnv("ARGOCD_RECONCILIATION_JITTER", defaultAppResyncPeriodJitter*time.Second, 0, math.MaxInt64).Seconds()), "Maximum time period in seconds to add as a delay jitter for application resync.")
command.Flags().Int64Var(&repoErrorGracePeriod, "repo-error-grace-period-seconds", int64(env.ParseDurationFromEnv("ARGOCD_REPO_ERROR_GRACE_PERIOD_SECONDS", defaultRepoErrorGracePeriod*time.Second, 0, math.MaxInt64).Seconds()), "Grace period in seconds for ignoring consecutive errors while communicating with repo server.")
command.Flags().StringVar(&repoServerAddress, "repo-server", env.StringFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER", common.DefaultRepoServerAddr), "Repo server address.")
command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", env.ParseNumFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS", 60, 0, math.MaxInt64), "Repo server RPC call timeout seconds.")
command.Flags().StringVar(&commitServerAddress, "commit-server", env.StringFromEnv("ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER", common.DefaultCommitServerAddr), "Commit server address.")

View File

@@ -886,6 +886,9 @@ func (ctrl *ApplicationController) Run(ctx context.Context, statusProcessors int
ctrl.RegisterClusterSecretUpdater(ctx)
ctrl.metricsServer.RegisterClustersInfoSource(ctx, ctrl.stateCache, ctrl.db, ctrl.metricsClusterLabels)
go ctrl.appInformer.Run(ctx.Done())
go ctrl.projInformer.Run(ctx.Done())
if ctrl.dynamicClusterDistributionEnabled {
// only start deployment informer if dynamic distribution is enabled
go ctrl.deploymentInformer.Informer().Run(ctx.Done())
@@ -904,9 +907,6 @@ func (ctrl *ApplicationController) Run(ctx context.Context, statusProcessors int
}
}
go ctrl.appInformer.Run(ctx.Done())
go ctrl.projInformer.Run(ctx.Done())
errors.CheckError(ctrl.stateCache.Init())
if !cache.WaitForCacheSync(ctx.Done(), ctrl.appInformer.HasSynced, ctrl.projInformer.HasSynced) {
@@ -1681,11 +1681,9 @@ 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 {
@@ -1782,6 +1780,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
ts.AddCheckpoint("auto_sync_ms")
if app.Status.ReconciledAt == nil || comparisonLevel >= CompareWithLatest {
now := metav1.Now()
app.Status.ReconciledAt = &now
}
app.Status.Sync = *compareResult.syncStatus
@@ -2012,9 +2011,15 @@ func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, new
ctrl.logAppEvent(context.TODO(), orig, argo.EventInfo{Reason: argo.EventReasonResourceUpdated, Type: corev1.EventTypeNormal}, message)
}
if orig.Status.Health.Status != newStatus.Health.Status {
now := metav1.Now()
newStatus.Health.LastTransitionTime = &now
message := fmt.Sprintf("Updated health status: %s -> %s", orig.Status.Health.Status, newStatus.Health.Status)
ctrl.logAppEvent(context.TODO(), orig, argo.EventInfo{Reason: argo.EventReasonResourceUpdated, Type: corev1.EventTypeNormal}, message)
} else {
// make sure the last transition time is the same and populated if the health is the same
newStatus.Health.LastTransitionTime = orig.Status.Health.LastTransitionTime
}
var newAnnotations map[string]string
if orig.GetAnnotations() != nil {
newAnnotations = make(map[string]string)

View File

@@ -1826,7 +1826,7 @@ apps/Deployment:
hs = {}
hs.status = ""
hs.message = ""
if obj.metadata ~= nil then
if obj.metadata.labels ~= nil then
current_status = obj.metadata.labels["status"]

View File

@@ -126,7 +126,7 @@ func init() {
clusterCacheListSemaphoreSize = env.ParseInt64FromEnv(EnvClusterCacheListSemaphore, clusterCacheListSemaphoreSize, 0, math.MaxInt64)
clusterCacheAttemptLimit = int32(env.ParseNumFromEnv(EnvClusterCacheAttemptLimit, int(clusterCacheAttemptLimit), 1, math.MaxInt32))
clusterCacheRetryUseBackoff = env.ParseBoolFromEnv(EnvClusterCacheRetryUseBackoff, false)
clusterCacheBatchEventsProcessing = env.ParseBoolFromEnv(EnvClusterCacheBatchEventsProcessing, false)
clusterCacheBatchEventsProcessing = env.ParseBoolFromEnv(EnvClusterCacheBatchEventsProcessing, true)
clusterCacheEventsProcessingInterval = env.ParseDurationFromEnv(EnvClusterCacheEventsProcessingInterval, clusterCacheEventsProcessingInterval, 0, math.MaxInt64)
}
@@ -242,6 +242,10 @@ func (c *liveStateCache) loadCacheSettings() (*cacheSettings, error) {
if err != nil {
return nil, err
}
trackingMethod, err := c.settingsMgr.GetTrackingMethod()
if err != nil {
return nil, err
}
installationID, err := c.settingsMgr.GetInstallationID()
if err != nil {
return nil, err
@@ -267,7 +271,7 @@ func (c *liveStateCache) loadCacheSettings() (*cacheSettings, error) {
ResourcesFilter: resourcesFilter,
}
return &cacheSettings{clusterSettings, appInstanceLabelKey, argo.GetTrackingMethod(c.settingsMgr), installationID, resourceUpdatesOverrides, ignoreResourceUpdatesEnabled}, nil
return &cacheSettings{clusterSettings, appInstanceLabelKey, appv1.TrackingMethod(trackingMethod), installationID, resourceUpdatesOverrides, ignoreResourceUpdatesEnabled}, nil
}
func asResourceNode(r *clustercache.Resource) appv1.ResourceNode {

View File

@@ -8,7 +8,6 @@ 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/v3/common"
@@ -22,7 +21,9 @@ func setApplicationHealth(resources []managedResource, statuses []appv1.Resource
var savedErr error
var errCount uint
appHealth := appv1.HealthStatus{Status: health.HealthStatusHealthy}
appHealth := app.Status.Health.DeepCopy()
appHealth.Status = health.HealthStatusHealthy
for i, res := range resources {
if res.Target != nil && hookutil.Skip(res.Target) {
continue
@@ -82,18 +83,11 @@ 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
}
if savedErr != nil && errCount > 1 {
savedErr = fmt.Errorf("see application-controller logs for %d other errors; most recent error was: %w", errCount-1, savedErr)
}
return &appHealth, savedErr
return appHealth, savedErr
}

View File

@@ -73,7 +73,6 @@ func TestSetApplicationHealth(t *testing.T) {
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
@@ -81,9 +80,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)
// change in health, timestamp should change
assert.NotEqual(t, *previousLastTransitionTime, *healthStatus.LastTransitionTime)
previousLastTransitionTime = healthStatus.LastTransitionTime
// timestamp should be the same in case health did not change
assert.Equal(t, app.Status.Health.LastTransitionTime, healthStatus.LastTransitionTime)
app.Status.Health = *healthStatus
// now we set the `argocd.argoproj.io/ignore-healthcheck: "true"` annotation on the job's target.
@@ -94,8 +92,7 @@ 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)
assert.Equal(t, app.Status.Health.LastTransitionTime, healthStatus.LastTransitionTime)
}
func TestSetApplicationHealth_ResourceHealthNotPersisted(t *testing.T) {
@@ -109,6 +106,7 @@ func TestSetApplicationHealth_ResourceHealthNotPersisted(t *testing.T) {
healthStatus, err := setApplicationHealth(resources, resourceStatuses, lua.ResourceHealthOverrides{}, app, false)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusDegraded, healthStatus.Status)
assert.NotNil(t, healthStatus.LastTransitionTime)
assert.Nil(t, resourceStatuses[0].Health)
}
@@ -124,7 +122,7 @@ 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())
assert.Equal(t, app.Status.Health.LastTransitionTime, healthStatus.LastTransitionTime)
}
func TestSetApplicationHealth_HealthImproves(t *testing.T) {
@@ -156,7 +154,7 @@ func TestSetApplicationHealth_HealthImproves(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)
assert.Equal(t, app.Status.Health.LastTransitionTime, healthStatus.LastTransitionTime)
})
}
}
@@ -173,6 +171,7 @@ func TestSetApplicationHealth_MissingResourceNoBuiltHealthCheck(t *testing.T) {
healthStatus, err := setApplicationHealth(resources, resourceStatuses, lua.ResourceHealthOverrides{}, app, true)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusHealthy, healthStatus.Status)
assert.Equal(t, app.Status.Health.LastTransitionTime, healthStatus.LastTransitionTime)
assert.Equal(t, health.HealthStatusMissing, resourceStatuses[0].Health.Status)
})
@@ -184,7 +183,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())
assert.Equal(t, app.Status.Health.LastTransitionTime, healthStatus.LastTransitionTime)
})
}

View File

@@ -163,6 +163,11 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp
return nil, nil, false, fmt.Errorf("failed to get Helm settings: %w", err)
}
trackingMethod, err := m.settingsMgr.GetTrackingMethod()
if err != nil {
return nil, nil, false, fmt.Errorf("failed to get trackingMethod: %w", err)
}
installationID, err := m.settingsMgr.GetInstallationID()
if err != nil {
return nil, nil, false, fmt.Errorf("failed to get installation ID: %w", err)
@@ -249,7 +254,7 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp
ApplicationSource: &source,
KubeVersion: serverVersion,
ApiVersions: apiVersions,
TrackingMethod: string(argo.GetTrackingMethod(m.settingsMgr)),
TrackingMethod: trackingMethod,
RefSources: refSources,
HasMultipleSources: app.Spec.HasMultipleSources(),
InstallationID: installationID,
@@ -286,7 +291,7 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp
ApiVersions: apiVersions,
VerifySignature: verifySignature,
HelmRepoCreds: permittedHelmCredentials,
TrackingMethod: string(argo.GetTrackingMethod(m.settingsMgr)),
TrackingMethod: trackingMethod,
EnabledSourceTypes: enabledSourceTypes,
HelmOptions: helmOptions,
HasMultipleSources: app.Spec.HasMultipleSources(),
@@ -435,24 +440,28 @@ func normalizeClusterScopeTracking(targetObjs []*unstructured.Unstructured, info
// getComparisonSettings will return the system level settings related to the
// diff/normalization process.
func (m *appStateManager) getComparisonSettings() (string, map[string]v1alpha1.ResourceOverride, *settings.ResourcesFilter, string, error) {
func (m *appStateManager) getComparisonSettings() (string, map[string]v1alpha1.ResourceOverride, *settings.ResourcesFilter, string, string, error) {
resourceOverrides, err := m.settingsMgr.GetResourceOverrides()
if err != nil {
return "", nil, nil, "", err
return "", nil, nil, "", "", err
}
appLabelKey, err := m.settingsMgr.GetAppInstanceLabelKey()
if err != nil {
return "", nil, nil, "", err
return "", nil, nil, "", "", err
}
resFilter, err := m.settingsMgr.GetResourcesFilter()
if err != nil {
return "", nil, nil, "", err
return "", nil, nil, "", "", err
}
installationID, err := m.settingsMgr.GetInstallationID()
if err != nil {
return "", nil, nil, "", err
return "", nil, nil, "", "", err
}
return appLabelKey, resourceOverrides, resFilter, installationID, nil
trackingMethod, err := m.settingsMgr.GetTrackingMethod()
if err != nil {
return "", nil, nil, "", "", err
}
return appLabelKey, resourceOverrides, resFilter, installationID, trackingMethod, nil
}
// verifyGnuPGSignature verifies the result of a GnuPG operation for a given git
@@ -503,13 +512,12 @@ func isManagedNamespace(ns *unstructured.Unstructured, app *v1alpha1.Application
// revision and overrides in the app spec.
func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1alpha1.AppProject, revisions []string, sources []v1alpha1.ApplicationSource, noCache bool, noRevisionCache bool, localManifests []string, hasMultipleSources bool, rollback bool) (*comparisonResult, error) {
ts := stats.NewTimingStats()
appLabelKey, resourceOverrides, resFilter, installationID, err := m.getComparisonSettings()
appLabelKey, resourceOverrides, resFilter, installationID, trackingMethod, err := m.getComparisonSettings()
ts.AddCheckpoint("settings_ms")
// return unknown comparison result if basic comparison settings cannot be loaded
if err != nil {
now := metav1.Now()
if hasMultipleSources {
return &comparisonResult{
syncStatus: &v1alpha1.SyncStatus{
@@ -517,7 +525,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
Status: v1alpha1.SyncStatusCodeUnknown,
Revisions: revisions,
},
healthStatus: &v1alpha1.HealthStatus{Status: health.HealthStatusUnknown, LastTransitionTime: &now},
healthStatus: &v1alpha1.HealthStatus{Status: health.HealthStatusUnknown},
}, nil
}
return &comparisonResult{
@@ -526,7 +534,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
Status: v1alpha1.SyncStatusCodeUnknown,
Revision: revisions[0],
},
healthStatus: &v1alpha1.HealthStatus{Status: health.HealthStatusUnknown, LastTransitionTime: &now},
healthStatus: &v1alpha1.HealthStatus{Status: health.HealthStatusUnknown},
}, nil
}
@@ -615,10 +623,8 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
infoProvider = &resourceInfoProviderStub{}
}
trackingMethod := argo.GetTrackingMethod(m.settingsMgr)
err = normalizeClusterScopeTracking(targetObjs, infoProvider, func(u *unstructured.Unstructured) error {
return m.resourceTracking.SetAppInstance(u, appLabelKey, app.InstanceName(m.namespace), app.Spec.Destination.Namespace, trackingMethod, installationID)
return m.resourceTracking.SetAppInstance(u, appLabelKey, app.InstanceName(m.namespace), app.Spec.Destination.Namespace, v1alpha1.TrackingMethod(trackingMethod), installationID)
})
if err != nil {
msg := "Failed to normalize cluster-scoped resource tracking: " + err.Error()
@@ -685,7 +691,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
for _, liveObj := range liveObjByKey {
if liveObj != nil {
appInstanceName := m.resourceTracking.GetAppName(liveObj, appLabelKey, trackingMethod, installationID)
appInstanceName := m.resourceTracking.GetAppName(liveObj, appLabelKey, v1alpha1.TrackingMethod(trackingMethod), installationID)
if appInstanceName != "" && appInstanceName != app.InstanceName(m.namespace) {
fqInstanceName := strings.ReplaceAll(appInstanceName, "_", "/")
conditions = append(conditions, v1alpha1.ApplicationCondition{
@@ -824,7 +830,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
}
gvk := obj.GroupVersionKind()
isSelfReferencedObj := m.isSelfReferencedObj(liveObj, targetObj, app.GetName(), trackingMethod, installationID)
isSelfReferencedObj := m.isSelfReferencedObj(liveObj, targetObj, app.GetName(), v1alpha1.TrackingMethod(trackingMethod), installationID)
resState := v1alpha1.ResourceStatus{
Namespace: obj.GetNamespace(),
@@ -1148,7 +1154,7 @@ func (m *appStateManager) isSelfReferencedObj(live, config *unstructured.Unstruc
// If tracking method doesn't contain required metadata for this check,
// we are not able to determine and just assume the object to be managed.
if trackingMethod == argo.TrackingMethodLabel {
if trackingMethod == v1alpha1.TrackingMethodLabel {
return true
}

View File

@@ -31,7 +31,6 @@ import (
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
"github.com/argoproj/argo-cd/v3/test"
"github.com/argoproj/argo-cd/v3/util/argo"
)
// TestCompareAppStateEmpty tests comparison when both git and live have no objects
@@ -719,7 +718,7 @@ func TestSetHealth(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, health.HealthStatusHealthy, compRes.healthStatus.Status)
assert.False(t, compRes.healthStatus.LastTransitionTime.IsZero())
assert.Equal(t, app.Status.Health.LastTransitionTime, compRes.healthStatus.LastTransitionTime)
}
func TestPreserveStatusTimestamp(t *testing.T) {
@@ -794,7 +793,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())
assert.Equal(t, app.Status.Health.LastTransitionTime, compRes.healthStatus.LastTransitionTime)
}
func TestSetManagedResourcesWithOrphanedResources(t *testing.T) {
@@ -870,7 +869,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, app.Status.Health.LastTransitionTime, compRes.healthStatus.LastTransitionTime)
assert.Equal(t, v1alpha1.SyncStatusCodeUnknown, compRes.syncStatus.Status)
}
@@ -1415,8 +1414,8 @@ func TestIsLiveResourceManaged(t *testing.T) {
configObj := managedObj.DeepCopy()
// then
assert.True(t, manager.isSelfReferencedObj(managedObj, configObj, appName, argo.TrackingMethodLabel, ""))
assert.True(t, manager.isSelfReferencedObj(managedObj, configObj, appName, argo.TrackingMethodAnnotation, ""))
assert.True(t, manager.isSelfReferencedObj(managedObj, configObj, appName, v1alpha1.TrackingMethodLabel, ""))
assert.True(t, manager.isSelfReferencedObj(managedObj, configObj, appName, v1alpha1.TrackingMethodAnnotation, ""))
})
t.Run("will return true if tracked with label", func(t *testing.T) {
// given
@@ -1424,43 +1423,43 @@ func TestIsLiveResourceManaged(t *testing.T) {
configObj := managedObjWithLabel.DeepCopy()
// then
assert.True(t, manager.isSelfReferencedObj(managedObjWithLabel, configObj, appName, argo.TrackingMethodLabel, ""))
assert.True(t, manager.isSelfReferencedObj(managedObjWithLabel, configObj, appName, v1alpha1.TrackingMethodLabel, ""))
})
t.Run("will handle if trackingId has wrong resource name and config is nil", func(t *testing.T) {
// given
t.Parallel()
// then
assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongName, nil, appName, argo.TrackingMethodLabel, ""))
assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongName, nil, appName, argo.TrackingMethodAnnotation, ""))
assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongName, nil, appName, v1alpha1.TrackingMethodLabel, ""))
assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongName, nil, appName, v1alpha1.TrackingMethodAnnotation, ""))
})
t.Run("will handle if trackingId has wrong resource group and config is nil", func(t *testing.T) {
// given
t.Parallel()
// then
assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongGroup, nil, appName, argo.TrackingMethodLabel, ""))
assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongGroup, nil, appName, argo.TrackingMethodAnnotation, ""))
assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongGroup, nil, appName, v1alpha1.TrackingMethodLabel, ""))
assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongGroup, nil, appName, v1alpha1.TrackingMethodAnnotation, ""))
})
t.Run("will handle if trackingId has wrong kind and config is nil", func(t *testing.T) {
// given
t.Parallel()
// then
assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongKind, nil, appName, argo.TrackingMethodLabel, ""))
assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongKind, nil, appName, argo.TrackingMethodAnnotation, ""))
assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongKind, nil, appName, v1alpha1.TrackingMethodLabel, ""))
assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongKind, nil, appName, v1alpha1.TrackingMethodAnnotation, ""))
})
t.Run("will handle if trackingId has wrong namespace and config is nil", func(t *testing.T) {
// given
t.Parallel()
// then
assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongNamespace, nil, appName, argo.TrackingMethodLabel, ""))
assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongNamespace, nil, appName, argo.TrackingMethodAnnotationAndLabel, ""))
assert.True(t, manager.isSelfReferencedObj(unmanagedObjWrongNamespace, nil, appName, v1alpha1.TrackingMethodLabel, ""))
assert.False(t, manager.isSelfReferencedObj(unmanagedObjWrongNamespace, nil, appName, v1alpha1.TrackingMethodAnnotationAndLabel, ""))
})
t.Run("will return true if live is nil", func(t *testing.T) {
t.Parallel()
assert.True(t, manager.isSelfReferencedObj(nil, nil, appName, argo.TrackingMethodAnnotation, ""))
assert.True(t, manager.isSelfReferencedObj(nil, nil, appName, v1alpha1.TrackingMethodAnnotation, ""))
})
t.Run("will handle upgrade in desired state APIGroup", func(t *testing.T) {
@@ -1470,7 +1469,7 @@ func TestIsLiveResourceManaged(t *testing.T) {
delete(config.GetAnnotations(), common.AnnotationKeyAppInstance)
// then
assert.True(t, manager.isSelfReferencedObj(managedWrongAPIGroup, config, appName, argo.TrackingMethodAnnotation, ""))
assert.True(t, manager.isSelfReferencedObj(managedWrongAPIGroup, config, appName, v1alpha1.TrackingMethodAnnotation, ""))
})
}

View File

@@ -309,7 +309,11 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
log.Errorf("Could not get installation ID: %v", err)
return
}
trackingMethod := argo.GetTrackingMethod(m.settingsMgr)
trackingMethod, err := m.settingsMgr.GetTrackingMethod()
if err != nil {
log.Errorf("Could not get trackingMethod: %v", err)
return
}
impersonationEnabled, err := m.settingsMgr.IsImpersonationEnabled()
if err != nil {
@@ -360,7 +364,7 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
return (len(syncOp.Resources) == 0 ||
isPostDeleteHook(target) ||
argo.ContainsSyncResource(key.Name, key.Namespace, schema.GroupVersionKind{Kind: key.Kind, Group: key.Group}, syncOp.Resources)) &&
m.isSelfReferencedObj(live, target, app.GetName(), trackingMethod, installationID)
m.isSelfReferencedObj(live, target, app.GetName(), v1alpha1.TrackingMethod(trackingMethod), installationID)
}),
sync.WithManifestValidation(!syncOp.SyncOptions.HasOption(common.SyncOptionsDisableValidation)),
sync.WithSyncWaveHook(delayBetweenSyncWaves),

View File

@@ -147,7 +147,7 @@ See [#1482](https://github.com/argoproj/argo-cd/issues/1482).
## How often does Argo CD check for changes to my Git or Helm repository ?
The default polling interval is 3 minutes (180 seconds) with a configurable jitter.
The default maximum polling interval is 3 minutes (120 seconds + 60 seconds jitter).
You can change the setting by updating the `timeout.reconciliation` value and the `timeout.reconciliation.jitter` in the [argocd-cm](https://github.com/argoproj/argo-cd/blob/2d6ce088acd4fb29271ffb6f6023dbb27594d59b/docs/operator-manual/argocd-cm.yaml#L279-L282) config map. If there are any Git changes, Argo CD will only update applications with the [auto-sync setting](user-guide/auto_sync.md) enabled. If you set it to `0` then Argo CD will stop polling Git repositories automatically and you can only use alternative methods such as [webhooks](operator-manual/webhook.md) and/or manual syncs for deploying applications.

View File

@@ -280,9 +280,9 @@ data:
# You can change the resource tracking method Argo CD uses by changing the
# setting application.resourceTrackingMethod to the desired method.
# The following methods are available:
# - label : Uses the application.instanceLabelKey label for tracking
# - annotation : Uses an annotation with additional metadata for tracking instead of the label
# - annotation+label : Also uses an annotation for tracking, but additionally labels the resource with the application name
# - label : Uses the application.instanceLabelKey label for tracking
application.resourceTrackingMethod: annotation
# Optional installation id. Allows to have multiple installations of Argo CD in the same cluster.
@@ -325,17 +325,18 @@ data:
# at the bottom of the page. Change the value as needed.
# ui.bannerposition: "bottom"
# Application reconciliation timeout is the max amount of time required to discover if a new manifests version got
# published to the repository. Reconciliation by timeout is disabled if timeout is set to 0. Three minutes by default.
# Application reconciliation timeout is the amount of time spent before Argo tries to discover if a new manifests version got
# published to the repository. Reconciliation by timeout is disabled if timeout is set to 0. Two minutes by default with additional jitter.
# > Note: The argocd-repo-server deployment and the argocd-application-controller statefulset (or deployment, if
# configured) must be manually restarted after changing the setting.
timeout.reconciliation: 180s
timeout.reconciliation: 120s
# With a large number of applications, the periodic refresh for each application can cause a spike in the refresh queue
# and can cause a spike in the repo-server component. To avoid this, you can set a jitter to the sync timeout, which will
# spread out the refreshes and give time to the repo-server to catch up. The jitter is the maximum duration that can be
# added to the sync timeout. So, if the sync timeout is 3 minutes and the jitter is 1 minute, then the actual timeout will
# be between 3 and 4 minutes. Disabled when the value is 0, defaults to 0.
timeout.reconciliation.jitter: "0"
# be between 3 and 4 minutes. Disabled when the value is 0, defaults to 1 minute.
timeout.reconciliation.jitter: 60s
# cluster.inClusterEnabled indicates whether to allow in-cluster server address. This is enabled by default.
cluster.inClusterEnabled: "true"

View File

@@ -93,7 +93,7 @@ data:
controller.profile.enabled: "false"
# Enables batch-processing mode in the controller's cluster cache. This can help improve performance for clusters that
# have high "churn," i.e. lots of resource modifications.
controller.cluster.cache.batch.events.processing: "false"
controller.cluster.cache.batch.events.processing: "true"
# This sets the interval at which the controller's cluster cache processes a batch of cluster events. A lower value
# will increase the speed at which Argo CD becomes aware of external cluster state. A higher value will reduce cluster
# cache lock contention and better handle high-churn clusters.

View File

@@ -132,8 +132,8 @@ stringData:
* `ARGOCD_CLUSTER_CACHE_BATCH_EVENTS_PROCESSING` - environment variable that enables the controller to collect events
for Kubernetes resources and process them in a batch. This is useful when the cluster contains a large number of resources,
and the controller is overwhelmed by the number of events. The default value is `false`, which means that the controller
processes events one by one.
and the controller is overwhelmed by the number of events. The default value is `true`. `false` would mean that the controller
would process events one by one.
* `ARGOCD_CLUSTER_CACHE_EVENTS_PROCESSING_INTERVAL` - environment variable controlling the interval for processing events in a batch.
The valid value is in the format of Go time duration string, e.g. `1ms`, `1s`, `1m`, `1h`. The default value is `100ms`.

View File

@@ -16,8 +16,8 @@ argocd-application-controller [flags]
```
--app-hard-resync int Time period in seconds for application hard resync.
--app-resync int Time period in seconds for application resync. (default 180)
--app-resync-jitter int Maximum time period in seconds to add as a delay jitter for application resync.
--app-resync int Time period in seconds for application resync. (default 120)
--app-resync-jitter int Maximum time period in seconds to add as a delay jitter for application resync. (default 60)
--app-state-cache-expiration duration Cache expiration for app state (default 1h0m0s)
--application-namespaces strings List of additional namespaces that applications are allowed to be reconciled from
--as string Username to impersonate for the operation

View File

@@ -1,2 +1,5 @@
This page is populated for released Argo CD versions. Use the version selector to view this table for a specific
version.
| Argo CD version | Kubernetes versions |
|-----------------|---------------------|
| 3.0 | v1.32, v1.31, v1.30, v1.29 |
| 2.14 | v1.31, v1.30, v1.29, v1.28 |
| 2.13 | v1.30, v1.29, v1.28, v1.27 |

View File

@@ -1,22 +1,21 @@
# v2.14 to 3.0
Argo CD 3.0 is meant to be a low-risk upgrade, containing some minor breaking changes. For each change, the next
Argo CD 3.0 is meant to be a low-risk upgrade containing only minor breaking changes. For each change, the next
section will describe how to quickly determine if you are impacted, how to remediate the breaking change, and (if
applicable) how to opt out of the change.
applicable) restore Argo CD 2.x default behavior.
Once 3.0 is released, no more 2.x minor versions will be released. We will continue to cut patch releases for the two
most recent minor versions (so 2.14 until 3.2 is released, and 2.13 until 3.1 is released).
most recent minor versions (so 2.14 until 3.2 is released and 2.13 until 3.1 is released).
## Breaking Changes
### Fine-Grained RBAC for application `update` and `delete` sub-resources
The default behavior of fine-grained policies have changed so they do not apply to sub-resources anymore.
Prior to v3, when `update` or `delete` actions were allowed on an application, it gave the permission to
update and delete the application itself and any of its sub-resources.
The default behavior of fine-grained policies have changed so they no longer apply to sub-resources.
Prior to v3, policies granting `update` or `delete` to an application also applied to any of its sub-resources.
Starting with v3, the `update` or `delete` actions only apply on the application. New policies must be defined
to allow the `update/*` or `delete/*` actions on the application to give permissions on sub-resources.
Starting with v3, the `update` or `delete` actions only apply to the application itself. New policies must be defined
to allow the `update/*` or `delete/*` actions on an Application's managed resources.
The v2 behavior can be preserved by setting the config value `server.rbac.disableApplicationFineGrainedRBACInheritance`
to `false` in the Argo CD ConfigMap `argocd-cm`.
@@ -36,35 +35,37 @@ Starting from 3.0, this flag is removed and the logs RBAC is enforced by default
#### Detection
Users who have `server.rbac.log.enforce.enable: "true"` in their `argocd-cm` ConfigMap, are unaffected by this change.
Users who have `server.rbac.log.enforce.enable: "true"` in their `argocd-cm` ConfigMap, are unaffected by this change.
Users who have `policy.default: role:readonly` or `policy.default: role:admin` in their `argocd-rbac-cm` ConfigMap, are unaffected.
Users who have `policy.default: role:readonly` or `policy.default: role:admin` in their `argocd-rbac-cm` ConfigMap, are unaffected.
Users who don't have a `policy.default` in their `argocd-rbac-cm` ConfigMap, and either have `server.rbac.log.enforce.enable` set to `false` or don't have this setting at all in their `argocd-cm` ConfigMap are affected and should perform the below remediation steps.
Users who don't have a `policy.default` in their `argocd-rbac-cm` ConfigMap, and either have `server.rbac.log.enforce.enable` set to `false` or don't have this setting at all in their `argocd-cm` ConfigMap are affected and should perform the below remediation steps.
After the upgrade, it is recommended to remove the setting `server.rbac.log.enforce.enable` from `argocd-cm` ConfigMap, if it was there before the upgrade.
After the upgrade, it is recommended to remove the setting `server.rbac.log.enforce.enable` from `argocd-cm` ConfigMap, if it was there before the upgrade.
#### Remediation
##### Quick remediation (global change)
For users with an existing default policy with a custom role, add this policy to `policy.csv` for your custom role: `p, role:<YOUR_DEFAULT_ROLE>, logs, get, */*, allow`.
For users without a default policy, add this policy to `policy.csv`: `p, role:global-log-viewer, logs, get, */*, allow` and add the default policy for this role: `policy.default: role:global-log-viewer`
##### Quick remediation (global change)
For users with an existing default policy with a custom role, add this policy to `policy.csv` for your custom role: `p, role:<YOUR_DEFAULT_ROLE>, logs, get, */*, allow`.
For users without a default policy, add this policy to `policy.csv`: `p, role:global-log-viewer, logs, get, */*, allow` and add the default policy for this role: `policy.default: role:global-log-viewer`
##### Recommended remediation (per-policy change)
Explicitly add a `logs, get` policy to every role that has a policy for `applications, get` or for `applications, *`.
This is the recommended way for maintaining the principle of least-privilege.
Similarly to the way you currently manage the access to Applications, the access to logs can be either granted on a Project scope level (Project resource) or on the `argocd-rbac-cm` ConfigMap level.
See this [example](../upgrading/2.3-2.4.md#example-1) for more details.
Explicitly add a `logs, get` policy to every role that has a policy for `applications, get` or for `applications, *`.
This is the recommended way to maintain the principle of least privilege.
Similar to the way access to Applications are currently managed, access to logs can be either granted on a Project scope level (Project resource) or on the `argocd-rbac-cm` ConfigMap level.
See this [example](../upgrading/2.3-2.4.md#example-1) for more details.
### Default `resource.exclusions` configurations
Argo CD manifest now contains a default configuration for `resource.exclusions` in the `argocd-cm` to exclude resources that
are known to be created by controller and not usually managed in Git. The exclusions contains high volume and high churn objects
are known to be created by controllers and not usually managed in Git. The exclusions contain high volume and high churn objects
which we exclude for performance reasons, reducing connections and load to the K8s API servers of managed clusters.
The excluded Kinds are:
- **Kubernetes Resources**: `Endpoints`, `EndpointSlice`, `APIService`, `Lease`, `SelfSubjectReview`, `TokenReview`, `LocalSubjectAccessReview`, `SelfSubjectAccessReview`, `SelfSubjectRulesReview`, `SubjectAccessReview`, `CertificateSigningRequest`, `PolicyReport` and `ClusterPolicyReport`.
- **Kubernetes Resources**: `Endpoints`, `EndpointSlice`, `Lease`, `SelfSubjectReview`, `TokenReview`, `LocalSubjectAccessReview`, `SelfSubjectAccessReview`, `SelfSubjectRulesReview`, `SubjectAccessReview`, `CertificateSigningRequest`, `PolicyReport` and `ClusterPolicyReport`.
- **Cert Manager**: `CertificateRequest`.
- **Kyverno**: `EphemeralReport`, `ClusterEphemeralReport`, `AdmissionReport`, `ClusterAdmissionReport`, `BackgroundScanReport`, `ClusterBackgroundScanReport` and `UpdateRequest`.
- **Cilium**: `CiliumIdentity`, `CiliumEndpoint` and `CiliumEndpointSlice`.
@@ -134,7 +135,7 @@ been deprecated for some time and is no longer available in Argo CD 3.0.
To check whether you have any repositories configured in argocd-cm, run the following command:
```shell
kubectl get cm argocd-cm -o=jsonpath="[{.data.repositories}, {.data['repository.credentials']}, {.data['helm.repositories']}]"
kubectl get cm argocd-cm -o=jsonpath="[{.data.repositories}, {.data['repository\.credentials']}, {.data['helm\.repositories']}]"
```
If you have no repositories configured in argocd-cm, the output will be `[, , ]`, and you are not impacted by this
@@ -217,16 +218,70 @@ spec:
namespace: guestbook
```
### Upgraded Helm version with breaking changes
Helm was upgraded to 3.17.1.
This may require changing your `values.yaml` files for subcharts, if the `values.yaml` contain a section with a `null` object.
See related issue in [Helm GitHub repository](https://github.com/helm/helm/issues/12469)
See Helm 3.17.1 [release notes](https://github.com/helm/helm/releases/tag/v3.17.1)
Example of such a [problem and resolution](https://github.com/argoproj/argo-cd/pull/22035/files)
### Upgraded Helm version with breaking changes
Helm was upgraded to 3.17.1.
This may require changing your `values.yaml` files for subcharts, if the `values.yaml` contain a section with a `null` object.
See related issue in [Helm GitHub repository](https://github.com/helm/helm/issues/12469)
See Helm 3.17.1 [release notes](https://github.com/helm/helm/releases/tag/v3.17.1)
Example of such a [problem and resolution](https://github.com/argoproj/argo-cd/pull/22035/files)
Explanation:
- Prior to Helm 3.17.1, `null` object in `values.yaml` resulted in a warning: `cannot overwrite table with non table` upon performing `helm template`, and the resulting K8s object was not overridden with the invalid `null` value.
- In Helm 3.17.1, this behavior changed and `null` object in `values.yaml` still results in this warning upon performing `helm template`, but the resulting K8s object will be overridden with the invalid `null` value.
- To resolve the issue, identify `values.yaml` with `null` object values, and remove those `null` values.
- To resolve the issue, identify `values.yaml` with `null` object values, and remove those `null` values.
### Use Annotation-Based Tracking by Default
The default behavior for [tracking resources](../../user-guide/resource_tracking.md) has changed to use annotation-based
tracking instead of label-based tracking. Annotation-based tracking is more reliable and less prone to errors caused by
external code copying tracking labels from one resource to another.
#### Detection
To detect if you are impacted, check the `argocd-cm` ConfigMap for the `application.resourceTrackingMethod` field. If it
unset or is set to `label`, you are using label-based tracking. If it is set to `annotation`, you are already using
annotation-based tracking and are not impacted by this change.
```sh
kubectl get cm argocd-cm -n argocd -o jsonpath='{.data.application\.resourceTrackingMethod}'
```
#### Remediation
For most users, it is safe to upgrade to Argo CD 3.0 and use annotation-based tracking. Labels will be replaced with
annotations on the next sync. Applications will not be marked as out-of-sync if labels are not present on the
resources.
!!! warning "Potential for orphaned resources"
There is a known edge case when switching from label-based tracking to annotation-based tracking that may cause
resources to be orphaned. If the first sync operation after switching to annotation-based tracking includes a
resource being deleted, Argo CD will fail to recognize that the resource is managed by the Application and will not
delete it. To avoid this edge case, it is recommended to perform a sync operation on your Applications, even if
they are not out of sync, so that orphan resource detection will work as expected on the next sync.
Some users rely on label-based tracking to track resources that are not managed by Argo CD. They may set annotations
to have Argo CD ignore the resource as extraneous or to disable pruning. If you are using label-based tracking to track
resources that are not managed by Argo CD, you will need to construct tracking annotations instead of tracking labels
and apply them to the relevant resources. The format of the tracking annotation is:
```yaml
argocd.argoproj.io/tracking-id: <app name>:<resource group>/<resource kind>:<resource namespace>/<resource name>
```
For cluster-scoped resources, the namespace is set to the value in the Application's `spec.destination.namespace` field.
!!! warning
Manually constructing and applying tracking labels and annotations is not an officially supported feature, and Argo
CD's behavior may change in the future. It is recommended to manage resources with Argo CD via GitOps.
#### Opting Out
If you are not ready to use annotation-based tracking, you can opt out of this change by setting the
`application.resourceTrackingMethod` field in the `argocd-cm` ConfigMap to `label`. There are no current plans to remove
label-based tracking.
## Other changes
@@ -264,6 +319,7 @@ Example of a status field in the Application CR persisting health:
status:
health:
status: Healthy
lastTransitionTime: '2025-01-01T00:00:00Z'
resources:
- group: apps
health:
@@ -283,6 +339,7 @@ Example of a status field in the Application CR _not_ persisting health:
status:
health:
status: Healthy
lastTransitionTime: '2025-01-01T00:00:00Z'
resourceHealthSource: appTree
resources:
- group: apps
@@ -316,6 +373,9 @@ kubectl get applications.argoproj.io <my app> -n argocd -o jsonpath='{.status.re
Any tools or CLI commands parsing the `.status.resources[].health` need to be updated to use the argocd cli/API to get the health status.
!!! note
The application list API (argocd app list) no longer returns the individual health status of resources.
```sh
argocd app get <my app> -o json
```
@@ -342,8 +402,8 @@ spec:
By default, the existing system-level `ignoreDifferences` customizations will be added to ignore resource updates as well.
Logically, if a field is configured to be ignore for the difference, there is no reason to gnerate the diff for the application
whenever that field changes.
Logically, if differences to a field are configured to be ignored, there is no reason to generate the diff for the application
when that field changes.
To disable this behavior and preserve the v2 default, the `ignoreDifferencesOnResourceUpdates` can be set to false:
@@ -377,4 +437,30 @@ data:
ignoreResourceStatusField: crd
```
More details for ignored resource updates in the [Diffing customization](../../user-guide/diffing.md) documentation.
### Removing default ignores of `preserveUnknownFields` for CRD
The `spec.preserveUnknownFields` has been deprecated in favor of `x-kubernetes-preserve-unknown-fields: true` in the CRD v1.
This means that CRD deployed with Argo CD containing `spec.preserveUnknownFields: false` will be out of sync. To address this problem,
the `preserveUnknownFields` field can be removed from the CRD spec.
Until this is completed, if you want your Application not to be out of sync, you can add the following configuration to the Application manifest.
```yaml
spec:
ignoreDifferences:
- group: apiextensions.k8s.io
kind: CustomResourceDefinition
jsonPointers:
- /spec/preserveUnknownFields
```
You can also configure it globally in the `argocd-cm` ConfigMap.
```yaml
resource.customizations.ignoreDifferences.apiextensions.k8s.io_CustomResourceDefinition: |
jsonPointers:
- /spec/preserveUnknownFields
```
More details for ignored resource updates in the [Diffing customization](../../user-guide/diffing.md) documentation.

View File

@@ -96,4 +96,4 @@ which is controlled by `--self-heal-timeout-seconds` flag of `argocd-application
and parameters had failed.
* Rollback cannot be performed against an application with automated sync enabled.
* The automatic sync interval is determined by [the `timeout.reconciliation` value in the `argocd-cm` ConfigMap](../faq.md#how-often-does-argo-cd-check-for-changes-to-my-git-or-helm-repository), which defaults to `180s` (3 minutes).
* The automatic sync interval is determined by [the `timeout.reconciliation` value in the `argocd-cm` ConfigMap](../faq.md#how-often-does-argo-cd-check-for-changes-to-my-git-or-helm-repository), which defaults to `120s` with added jitter of `60s` for a maximum period of 3 minutes.

View File

@@ -52,4 +52,4 @@ argocd app wait guestbook
If [automated synchronization](auto_sync.md) is configured for the application, this step is
unnecessary. The controller will automatically detect the new config (fast tracked using a
[webhook](../operator-manual/webhook.md), or polled every 3 minutes), and automatically sync the new manifests.
[webhook](../operator-manual/webhook.md), or polled at least every 3 minutes by default), and automatically sync the new manifests.

View File

@@ -2,7 +2,7 @@
## argocd appset generate
Generate apps from ApplicationSet rendered templates and display the output.
Generate apps of ApplicationSet rendered templates
```
argocd appset generate [flags]

View File

@@ -24,7 +24,7 @@ argocd appset update [flags]
### Options inherited from parent commands
```
--auth-token string Authentication token
--auth-token string Authentication token; set this or the ARGOCD_AUTH_TOKEN environment variable
--client-crt string Client certificate file
--client-crt-key string Client certificate key file
--config string Path to Argo CD config (default "/home/user/.config/argocd/config")

View File

@@ -1,8 +1,46 @@
# Resource Tracking
## Tracking Kubernetes resources by annotation
Argo CD can be instructed to use the following methods for tracking:
1. `annotation` (default) - Argo CD uses the `argocd.argoproj.io/tracking-id` annotation to track application resources. Use this when you don't need to maintain both the label and the annotation.
1. `annotation+label` - Argo CD uses the `app.kubernetes.io/instance` label but only for informational purposes. The label is not used for tracking purposes, and the value is still truncated if longer than 63 characters. The annotation `argocd.argoproj.io/tracking-id` is used instead to track application resources. Use this for resources that you manage with Argo CD, but still need compatibility with other tools that require the instance label.
1. `label` - Argo CD uses the `app.kubernetes.io/instance` label
Here is an example of using the annotation method for tracking resources:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
namespace: default
annotations:
argocd.argoproj.io/tracking-id: my-app:apps/Deployment:default/my-deployment
```
The advantages of using the tracking id annotation is that there are no clashes any
more with other Kubernetes tools and Argo CD is never confused about the owner of a resource. The `annotation+label` can also be used if you want other tools to understand resources managed by Argo CD.
### Installation ID
If you are managing one cluster using multiple Argo CD instances, you will need to set `installationID` in the Argo CD ConfigMap. This will prevent conflicts between
the different Argo CD instances:
* Each managed resource will have the annotation `argocd.argoproj.io/installation-id: <installation-id>`
* It is possible to have applications with the same name in Argo CD instances without causing conflicts.
### Non self-referencing annotations
When using the tracking method `annotation` or `annotation+label`, Argo CD will consider the resource properties in the annotation (name, namespace, group and kind) to determine whether the resource should be compared against the desired state. If the tracking annotation does not reference the resource it is applied to, the resource will neither affect the application's sync status nor be marked for pruning.
This allows other kubernetes tools (e.g. [HNC](https://github.com/kubernetes-sigs/hierarchical-namespaces)) to copy a resource to a different namespace without impacting the Argo CD application's sync status. Copied resources will be visible on the UI at top level. They will have no sync status and won't impact the application's sync status.
## Tracking Kubernetes resources by label
Argo CD identifies resources it manages by setting the application instance label to the name of the managing Application on all resources that are managed (i.e. reconciled from Git). The default label used is the well-known label `app.kubernetes.io/instance`.
In this mode, Argo CD identifies resources it manages by setting the application instance label to the name of the managing Application on all resources that are managed (i.e. reconciled from Git). The default label used is the well-known label `app.kubernetes.io/instance`.
Example:
@@ -40,44 +78,6 @@ data:
application.instanceLabelKey: argocd.argoproj.io/instance
```
## Additional tracking methods via an annotation
>v2.2
To offer more flexible options for tracking resources and solve some of the issues outlined in the previous section Argo CD can be instructed to use the following methods for tracking:
1. `label` (default) - Argo CD uses the `app.kubernetes.io/instance` label
1. `annotation+label` - Argo CD uses the `app.kubernetes.io/instance` label but only for informational purposes. The label is not used for tracking purposes, and the value is still truncated if longer than 63 characters. The annotation `argocd.argoproj.io/tracking-id` is used instead to track application resources. Use this for resources that you manage with Argo CD, but still need compatibility with other tools that require the instance label.
1. `annotation` - Argo CD uses the `argocd.argoproj.io/tracking-id` annotation to track application resources. Use this when you don't need to maintain both the label and the annotation.
Here is an example of using the annotation method for tracking resources:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
namespace: default
annotations:
argocd.argoproj.io/tracking-id: my-app:apps/Deployment:default/nginx-deployment
```
The advantages of using the tracking id annotation is that there are no clashes any
more with other Kubernetes tools and Argo CD is never confused about the owner of a resource. The `annotation+label` can also be used if you want other tools to understand resources managed by Argo CD.
### Installation ID
If you are managing one cluster using multiple Argo CD instances, you will need to set `installationID` in the Argo CD ConfigMap. This will prevent conflicts between
the different Argo CD instances:
* Each managed resource will have the annotation `argocd.argoproj.io/tracking-id: <installation-id>`
* It is possible to have applications with the same name in Argo CD instances without causing conflicts.
### Non self-referencing annotations
When using the tracking method `annotation` or `annotation+label`, Argo CD will consider the resource properties in the annotation (name, namespace, group and kind) to determine whether the resource should be compared against the desired state. If the tracking annotation does not reference the resource it is applied to, the resource will neither affect the application's sync status nor be marked for pruning.
This allows other kubernetes tools (e.g. [HNC](https://github.com/kubernetes-sigs/hierarchical-namespaces)) to copy a resource to a different namespace without impacting the Argo CD application's sync status. Copied resources will be visible on the UI at top level. They will have no sync status and won't impact the application's sync status.
## Choosing a tracking method
To actually select your preferred tracking method edit the `resourceTrackingMethod` value contained inside the `argocd-cm` configmap.
@@ -93,8 +93,8 @@ metadata:
data:
application.resourceTrackingMethod: annotation
```
Possible values are `label`, `annotation+label` and `annotation` as described in the previous section.
Possible values are `label`, `annotation+label` and `annotation` as described above.
Note that once you change the value you need to sync your applications again (or wait for the sync mechanism to kick-in) in order to apply your changes.
You can revert to a previous choice, by changing again the configmap.
You can revert to a previous choice, by changing the configmap again.

15
go.mod
View File

@@ -7,12 +7,12 @@ require (
dario.cat/mergo v1.0.1
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2
github.com/Azure/kubelogin v0.1.8
github.com/Azure/kubelogin v0.1.9
github.com/Masterminds/semver/v3 v3.3.1
github.com/Masterminds/sprig/v3 v3.3.0
github.com/TomOnTime/utfutil v1.0.0
github.com/alicebob/miniredis/v2 v2.34.0
github.com/argoproj/gitops-engine v0.7.1-0.20250305152649-acb47d5407b6
github.com/argoproj/gitops-engine v0.7.1-0.20250520182409-89c110b5952e
github.com/argoproj/notifications-engine v0.4.1-0.20250309174002-87bf0576a872
github.com/argoproj/pkg v0.13.7-0.20250305113207-cbc37dc61de5
github.com/aws/aws-sdk-go v1.55.6
@@ -23,7 +23,7 @@ require (
github.com/casbin/govaluate v1.3.0
github.com/cespare/xxhash/v2 v2.3.0
github.com/chainguard-dev/git-urls v1.0.2
github.com/coreos/go-oidc/v3 v3.12.0
github.com/coreos/go-oidc/v3 v3.13.0
github.com/cyphar/filepath-securejoin v0.4.1
github.com/dlclark/regexp2 v1.11.5
github.com/dustin/go-humanize v1.0.1
@@ -42,7 +42,7 @@ require (
github.com/gobwas/glob v0.2.3
github.com/gogits/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/gogo/protobuf v1.3.2
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/golang/protobuf v1.5.4
github.com/google/btree v1.1.3
github.com/google/go-cmp v0.7.0
@@ -90,7 +90,7 @@ require (
go.uber.org/automaxprocs v1.6.0
golang.org/x/crypto v0.36.0
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
golang.org/x/net v0.37.0
golang.org/x/net v0.38.0
golang.org/x/oauth2 v0.28.0
golang.org/x/sync v0.12.0
golang.org/x/term v0.30.0
@@ -107,7 +107,7 @@ require (
k8s.io/client-go v0.32.2
k8s.io/code-generator v0.32.2
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7
k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9
k8s.io/kubectl v0.32.2
k8s.io/utils v0.0.0-20241210054802-24370beab758
layeh.com/gopher-json v0.0.0-20190114024228-97fed8db8427
@@ -185,7 +185,7 @@ require (
github.com/go-openapi/strfmt v0.23.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/validate v0.24.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/glog v1.2.4 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
@@ -287,6 +287,7 @@ require (
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/kustomize/api v0.18.0 // indirect
sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
)
replace (

35
go.sum
View File

@@ -70,8 +70,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/Azure/kubelogin v0.1.8 h1:G5lQO7TPmD0TPdfW41sOnhqPfywc+oVl4ERd88llAko=
github.com/Azure/kubelogin v0.1.8/go.mod h1:QdijBoCq0W24IEdGNB7lwI+SWI32w9nMo6GFjJQGd5k=
github.com/Azure/kubelogin v0.1.9 h1:OwaVyCyf4rtm9UYOISoe3y5KmWIPA5Z1u9s2MVnpIfQ=
github.com/Azure/kubelogin v0.1.9/go.mod h1:3snUrz9Ykw4hU/zZmzHsDo02ALe5nY43J6wFWn3pk7Y=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 h1:H5xDQaE3XowWfhZRUpnfC+rGZMEVoSiji+b+/HFAPU4=
@@ -114,8 +114,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/appscode/go v0.0.0-20191119085241-0887d8ec2ecc/go.mod h1:OawnOmAL4ZX3YaPdN+8HTNwBveT1jMsqP74moa9XUbE=
github.com/argoproj/gitops-engine v0.7.1-0.20250305152649-acb47d5407b6 h1:3H0jvRZDjQHgZ7bMpeXmSn6/NTBIhzGEdSbFJvwr1+c=
github.com/argoproj/gitops-engine v0.7.1-0.20250305152649-acb47d5407b6/go.mod h1:KMB51dChCgd0J96CcqAVfCtSyNzqncQgWakdi++ZIg4=
github.com/argoproj/gitops-engine v0.7.1-0.20250520182409-89c110b5952e h1:65x5+7Vz3HPjFoj7+mFyCckgHrAhPwy4rnDp/AveD18=
github.com/argoproj/gitops-engine v0.7.1-0.20250520182409-89c110b5952e/go.mod h1:duVhxDW7M7M7+19IBCVth2REOS11gmqzTWwj4u8N7aQ=
github.com/argoproj/notifications-engine v0.4.1-0.20250309174002-87bf0576a872 h1:ADGAdyN9ty0+RmTT/yn+xV9vwkqvLn9O1ccqeP0Zeas=
github.com/argoproj/notifications-engine v0.4.1-0.20250309174002-87bf0576a872/go.mod h1:d1RazGXWvKRFv9//rg4MRRR7rbvbE7XLgTSMT5fITTE=
github.com/argoproj/pkg v0.13.7-0.20250305113207-cbc37dc61de5 h1:YBoLSjpoaJXaXAldVvBRKJuOPvIXz9UOv6S96gMJM/Q=
@@ -201,8 +201,8 @@ github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZ
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo=
github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
github.com/coreos/go-oidc/v3 v3.13.0 h1:M66zd0pcc5VxvBNM4pB331Wrsanby+QomQYjN8HamW8=
github.com/coreos/go-oidc/v3 v3.13.0/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -362,10 +362,10 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc=
github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
@@ -858,8 +858,8 @@ go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwE
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -979,8 +979,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1323,8 +1323,8 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-aggregator v0.32.2 h1:kg9pke+i2qRbJwX1UKwZV4fsCRvmbaCEFk38R4FqHmw=
k8s.io/kube-aggregator v0.32.2/go.mod h1:rRm+xY1yIFIt3zBc727nG5SBLYywywD87klfIAw+7+c=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9 h1:t0huyHnz6HsokckRxAF1bY0cqPFwzINKCL7yltEjZQc=
k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
k8s.io/kubectl v0.32.2 h1:TAkag6+XfSBgkqK9I7ZvwtF0WVtUAvK8ZqTt+5zi1Us=
k8s.io/kubectl v0.32.2/go.mod h1:+h/NQFSPxiDZYX/WZaWw9fwYezGLISP0ud8nQKg+3g8=
k8s.io/kubernetes v1.32.2 h1:mShetlA102UpjRVSGzB+5vjJwy8oPy8FMWrkTH5f37o=
@@ -1348,8 +1348,9 @@ sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo
sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U=
sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E=
sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016 h1:kXv6kKdoEtedwuqMmkqhbkgvYKeycVbC8+iPCP9j5kQ=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -6,7 +6,6 @@ import (
"os"
"os/exec"
"regexp"
"strconv"
"strings"
)
@@ -52,61 +51,59 @@ func extractPatchAndRC(tag string) (string, string, error) {
return patch, rc, nil
}
func findPreviousTag(proposedTag string, tags []string) (string, error) {
var previousTag string
proposedMajor := semver.Major(proposedTag)
proposedMinor := semver.MajorMinor(proposedTag)
proposedPatch, proposedRC, err := extractPatchAndRC(proposedTag)
if err != nil {
return "", err
}
// If the current tag is a .0 patch release or a 1 release candidate, adjust to the previous minor release series.
if (proposedPatch == "0" && proposedRC == "0") || proposedRC == "1" {
proposedMinorInt, err := strconv.Atoi(strings.TrimPrefix(proposedMinor, proposedMajor+"."))
if err != nil {
return "", fmt.Errorf("invalid minor version: %v", err)
}
if proposedMinorInt > 0 {
proposedMinor = fmt.Sprintf("%s.%d", proposedMajor, proposedMinorInt-1)
}
}
func removeInvalidTags(tags []string) []string {
var validTags []string
for _, tag := range tags {
if tag == proposedTag {
continue
}
tagMajor := semver.Major(tag)
tagMinor := semver.MajorMinor(tag)
tagPatch, tagRC, err := extractPatchAndRC(tag)
if err != nil {
continue
}
// Only bother considering tags with the same major and minor version.
if tagMajor == proposedMajor && tagMinor == proposedMinor {
// If it's a non-RC release...
if proposedRC == "0" {
// Only consider non-RC tags.
if tagRC == "0" {
if semver.Compare(tag, previousTag) > 0 {
previousTag = tag
}
}
} else {
if tagRC != "0" && tagPatch == proposedPatch {
if semver.Compare(tag, previousTag) > 0 {
previousTag = tag
}
} else if tagRC == "0" {
if semver.Compare(tag, previousTag) > 0 {
previousTag = tag
}
}
}
if _, _, err := extractPatchAndRC(tag); err == nil {
validTags = append(validTags, tag)
}
}
return validTags
}
func removeNewerOrEqualTags(proposedTag string, tags []string) []string {
var validTags []string
for _, tag := range tags {
if semver.Compare(tag, proposedTag) < 0 {
validTags = append(validTags, tag)
}
}
return validTags
}
func removeTagsFromSameMinorSeries(proposedTag string, tags []string) []string {
var validTags []string
proposedMinor := semver.MajorMinor(proposedTag)
for _, tag := range tags {
if semver.MajorMinor(tag) != proposedMinor {
validTags = append(validTags, tag)
}
}
return validTags
}
func getMostRecentTag(tags []string) string {
var mostRecentTag string
for _, tag := range tags {
if mostRecentTag == "" || semver.Compare(tag, mostRecentTag) > 0 {
mostRecentTag = tag
}
}
return mostRecentTag
}
func findPreviousTag(proposedTag string, tags []string) (string, error) {
tags = removeInvalidTags(tags)
tags = removeNewerOrEqualTags(proposedTag, tags)
proposedPatch, proposedRC, _ := extractPatchAndRC(proposedTag) // Ignore the error, we already filtered out invalid tags.
if proposedRC == "0" && proposedPatch == "0" {
// If we're cutting the first patch of a new minor release series, don't consider tags in the same minor release
// series. We want to compare to the latest tag in the previous minor release series.
tags = removeTagsFromSameMinorSeries(proposedTag, tags)
}
previousTag := getMostRecentTag(tags)
if previousTag == "" {
return "", fmt.Errorf("no matching tag found for tags: " + strings.Join(tags, ", "))
}

View File

@@ -76,6 +76,13 @@ func TestFindPreviousTagRules(t *testing.T) {
{"Rule 3: 1 release candidate", "v2.14.0-rc1", "v2.13.0-rc3", false},
// Rule 4: If we're releasing a non-1 release candidate, get the most recent rc tag on the current minor release series.
{"Rule 4: non-1 release candidate", "v2.13.0-rc4", "v2.13.0-rc3", false},
// Rule 5: If we're releasing a major version RC, get the most recent tag on the previous major release series.
{"Rule 5: major version RC", "v3.0.0-rc1", "v2.13.0-rc3", false},
// Rule 6: If we're releasing a major version, get the most recent tag on the previous major release series,
// even if it's an RC.
{"Rule 6: major version", "v3.0.0", "v2.13.0-rc3", false},
// Rule 7: If the proposed tag already exists, don't return it.
{"Rule 7: proposed tag already exists", "v2.12.5", "v2.12.4", false},
}
for _, test := range tests {

View File

@@ -7,8 +7,9 @@ argocd_minor_version=$(git rev-parse --abbrev-ref HEAD | sed 's/release-//')
argocd_major_version_num=$(echo "$argocd_minor_version" | sed -E 's/\.[0-9]+//')
argocd_minor_version_num=$(echo "$argocd_minor_version" | sed -E 's/[0-9]+\.//')
for n in 0 1 2; do
minor_version_num=$((argocd_minor_version_num - n))
minor_version_decrement=0
for _ in {1..3}; do
minor_version_num=$((argocd_minor_version_num - minor_version_decrement))
minor_version="${argocd_major_version_num}.${minor_version_num}"
git checkout "release-$minor_version" > /dev/null || exit 1
@@ -19,9 +20,22 @@ for n in 0 1 2; do
jq --arg minor_version "$minor_version" --raw-input --slurp --raw-output \
'split("\n")[:-1] | map(sub("\\.[0-9]+$"; "")) | join(", ") | "| \($minor_version) | \(.) |"')
out+="$line\n"
minor_version_decrement=$((minor_version_decrement + 1))
# If we're at minor version 0, there's no further version back in this series. Instead, move to the latest version in
# the previous major release series.
if [ "$argocd_minor_version_num" -eq 0 ]; then
argocd_major_version_num=$((argocd_major_version_num - 1))
# Get the latest minor version in the previous series.
argocd_minor_version_num=$(git tag -l "v$argocd_major_version_num.*" | sort -V | tail -n 1 | sed -E 's/\.[0-9]+$//' | sed -E 's/^v[0-9]+\.//')
# Don't decrement the minor version, since we're switching to the previous major release series. We want the latest
# minor version in that series.
minor_version_decrement=0
fi
done
git checkout "release-$argocd_minor_version"
printf "$out" > docs/operator-manual/tested-kubernetes-versions.md

View File

@@ -70,10 +70,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:

View File

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

View File

@@ -24217,10 +24217,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -24613,7 +24609,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -24889,7 +24885,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -25162,7 +25158,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25214,7 +25210,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -25544,7 +25540,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -24208,10 +24208,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -24581,7 +24577,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -24701,7 +24697,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -24974,7 +24970,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25026,7 +25022,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -25356,7 +25352,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -12,4 +12,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: latest
newTag: v3.0.3

View File

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

View File

@@ -701,6 +701,10 @@ data:
stats enable
stats uri /stats
stats refresh 10s
# Additional configuration
global
maxconn 4096
haproxy_init.sh: |
HAPROXY_CONF=/data/haproxy.cfg
cp /readonly/haproxy.cfg "$HAPROXY_CONF"
@@ -1092,7 +1096,7 @@ spec:
prometheus.io/port: "9101"
prometheus.io/scrape: "true"
prometheus.io/path: "/metrics"
checksum/config: e34e8124c38bcfd2f16e75620bbde30158686692b13bc449eecc44c51b207d54
checksum/config: cd6508bdf9819601c454d0cc491fb77a209e3a88761d92514d105b6681829953
spec:
# Needed when using unmodified rbac-setup.yml
@@ -1101,7 +1105,7 @@ spec:
fsGroup: 99
runAsNonRoot: true
runAsUser: 99
automountServiceAccountToken: false
automountServiceAccountToken: true
nodeSelector:
{}
tolerations:

View File

@@ -21,6 +21,11 @@ redis-ha:
checkInterval: 3s
metrics:
enabled: true
extraConfig: |
global
maxconn 4096
serviceAccount:
automountToken: true
image:
tag: 7.2.7-alpine
sentinel:

View File

@@ -24626,10 +24626,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -25043,7 +25039,8 @@ data:
1\n use-server R2 if { srv_is_up(R2) } { nbsrv(check_if_redis_is_master_2) ge
2 }\n server R2 argocd-redis-ha-announce-2:6379 check inter 3s fall 1 rise 1\nfrontend
stats\n mode http\n bind :9101 \n http-request use-service prometheus-exporter
if { path /metrics }\n stats enable\n stats uri /stats\n stats refresh 10s\n"
if { path /metrics }\n stats enable\n stats uri /stats\n stats refresh 10s\n#
Additional configuration\nglobal\n maxconn 4096\n"
haproxy_init.sh: |
HAPROXY_CONF=/data/haproxy.cfg
cp /readonly/haproxy.cfg "$HAPROXY_CONF"
@@ -25978,7 +25975,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -26277,7 +26274,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -26373,7 +26370,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -26433,7 +26430,7 @@ spec:
template:
metadata:
annotations:
checksum/config: e34e8124c38bcfd2f16e75620bbde30158686692b13bc449eecc44c51b207d54
checksum/config: cd6508bdf9819601c454d0cc491fb77a209e3a88761d92514d105b6681829953
prometheus.io/path: /metrics
prometheus.io/port: "9101"
prometheus.io/scrape: "true"
@@ -26448,7 +26445,7 @@ spec:
matchLabels:
app.kubernetes.io/name: argocd-redis-ha-haproxy
topologyKey: kubernetes.io/hostname
automountServiceAccountToken: false
automountServiceAccountToken: true
containers:
- env:
- name: AUTH
@@ -26497,7 +26494,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -26796,7 +26793,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -26848,7 +26845,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -27222,7 +27219,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -27588,7 +27585,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -24617,10 +24617,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -25034,7 +25030,8 @@ data:
1\n use-server R2 if { srv_is_up(R2) } { nbsrv(check_if_redis_is_master_2) ge
2 }\n server R2 argocd-redis-ha-announce-2:6379 check inter 3s fall 1 rise 1\nfrontend
stats\n mode http\n bind :9101 \n http-request use-service prometheus-exporter
if { path /metrics }\n stats enable\n stats uri /stats\n stats refresh 10s\n"
if { path /metrics }\n stats enable\n stats uri /stats\n stats refresh 10s\n#
Additional configuration\nglobal\n maxconn 4096\n"
haproxy_init.sh: |
HAPROXY_CONF=/data/haproxy.cfg
cp /readonly/haproxy.cfg "$HAPROXY_CONF"
@@ -25948,7 +25945,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -26091,7 +26088,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -26187,7 +26184,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -26247,7 +26244,7 @@ spec:
template:
metadata:
annotations:
checksum/config: e34e8124c38bcfd2f16e75620bbde30158686692b13bc449eecc44c51b207d54
checksum/config: cd6508bdf9819601c454d0cc491fb77a209e3a88761d92514d105b6681829953
prometheus.io/path: /metrics
prometheus.io/port: "9101"
prometheus.io/scrape: "true"
@@ -26262,7 +26259,7 @@ spec:
matchLabels:
app.kubernetes.io/name: argocd-redis-ha-haproxy
topologyKey: kubernetes.io/hostname
automountServiceAccountToken: false
automountServiceAccountToken: true
containers:
- env:
- name: AUTH
@@ -26311,7 +26308,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -26610,7 +26607,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -26662,7 +26659,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -27036,7 +27033,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -27402,7 +27399,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -513,10 +513,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -930,7 +926,8 @@ data:
1\n use-server R2 if { srv_is_up(R2) } { nbsrv(check_if_redis_is_master_2) ge
2 }\n server R2 argocd-redis-ha-announce-2:6379 check inter 3s fall 1 rise 1\nfrontend
stats\n mode http\n bind :9101 \n http-request use-service prometheus-exporter
if { path /metrics }\n stats enable\n stats uri /stats\n stats refresh 10s\n"
if { path /metrics }\n stats enable\n stats uri /stats\n stats refresh 10s\n#
Additional configuration\nglobal\n maxconn 4096\n"
haproxy_init.sh: |
HAPROXY_CONF=/data/haproxy.cfg
cp /readonly/haproxy.cfg "$HAPROXY_CONF"
@@ -1865,7 +1862,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -2164,7 +2161,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -2260,7 +2257,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2320,7 +2317,7 @@ spec:
template:
metadata:
annotations:
checksum/config: e34e8124c38bcfd2f16e75620bbde30158686692b13bc449eecc44c51b207d54
checksum/config: cd6508bdf9819601c454d0cc491fb77a209e3a88761d92514d105b6681829953
prometheus.io/path: /metrics
prometheus.io/port: "9101"
prometheus.io/scrape: "true"
@@ -2335,7 +2332,7 @@ spec:
matchLabels:
app.kubernetes.io/name: argocd-redis-ha-haproxy
topologyKey: kubernetes.io/hostname
automountServiceAccountToken: false
automountServiceAccountToken: true
containers:
- env:
- name: AUTH
@@ -2384,7 +2381,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -2683,7 +2680,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2735,7 +2732,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -3109,7 +3106,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -3475,7 +3472,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -504,10 +504,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -921,7 +917,8 @@ data:
1\n use-server R2 if { srv_is_up(R2) } { nbsrv(check_if_redis_is_master_2) ge
2 }\n server R2 argocd-redis-ha-announce-2:6379 check inter 3s fall 1 rise 1\nfrontend
stats\n mode http\n bind :9101 \n http-request use-service prometheus-exporter
if { path /metrics }\n stats enable\n stats uri /stats\n stats refresh 10s\n"
if { path /metrics }\n stats enable\n stats uri /stats\n stats refresh 10s\n#
Additional configuration\nglobal\n maxconn 4096\n"
haproxy_init.sh: |
HAPROXY_CONF=/data/haproxy.cfg
cp /readonly/haproxy.cfg "$HAPROXY_CONF"
@@ -1835,7 +1832,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1978,7 +1975,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -2074,7 +2071,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2134,7 +2131,7 @@ spec:
template:
metadata:
annotations:
checksum/config: e34e8124c38bcfd2f16e75620bbde30158686692b13bc449eecc44c51b207d54
checksum/config: cd6508bdf9819601c454d0cc491fb77a209e3a88761d92514d105b6681829953
prometheus.io/path: /metrics
prometheus.io/port: "9101"
prometheus.io/scrape: "true"
@@ -2149,7 +2146,7 @@ spec:
matchLabels:
app.kubernetes.io/name: argocd-redis-ha-haproxy
topologyKey: kubernetes.io/hostname
automountServiceAccountToken: false
automountServiceAccountToken: true
containers:
- env:
- name: AUTH
@@ -2198,7 +2195,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -2497,7 +2494,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2549,7 +2546,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2923,7 +2920,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -3289,7 +3286,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -24577,10 +24577,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -25073,7 +25069,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -25372,7 +25368,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -25468,7 +25464,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -25570,7 +25566,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -25843,7 +25839,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25895,7 +25891,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -26267,7 +26263,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -26633,7 +26629,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

20
manifests/install.yaml generated
View File

@@ -24568,10 +24568,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -25041,7 +25037,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -25184,7 +25180,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -25280,7 +25276,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -25382,7 +25378,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -25655,7 +25651,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25707,7 +25703,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -26079,7 +26075,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -26445,7 +26441,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -464,10 +464,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -960,7 +956,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1259,7 +1255,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1355,7 +1351,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1457,7 +1453,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -1730,7 +1726,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1782,7 +1778,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2154,7 +2150,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2520,7 +2516,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -455,10 +455,6 @@ data:
- Endpoints
- EndpointSlice
### Internal Kubernetes resources excluded reduce the number of watched events
- apiGroups:
- apiregistration.k8s.io
kinds:
- APIService
- apiGroups:
- coordination.k8s.io
kinds:
@@ -928,7 +924,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1071,7 +1067,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1167,7 +1163,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1269,7 +1265,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -1542,7 +1538,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1594,7 +1590,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1966,7 +1962,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2332,7 +2328,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v3.0.3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -130,6 +130,7 @@ nav:
- operator-manual/server-commands/additional-configuration-method.md
- Upgrading:
- operator-manual/upgrading/overview.md
- operator-manual/upgrading/2.14-3.0.md
- operator-manual/upgrading/2.13-2.14.md
- operator-manual/upgrading/2.12-2.13.md
- operator-manual/upgrading/2.11-2.12.md

View File

@@ -102,6 +102,12 @@ func (id IgnoreDifferences) Equals(other IgnoreDifferences) bool {
type TrackingMethod string
const (
TrackingMethodAnnotation TrackingMethod = "annotation"
TrackingMethodLabel TrackingMethod = "label"
TrackingMethodAnnotationAndLabel TrackingMethod = "annotation+label"
)
// ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state.
type ResourceIgnoreDifferences struct {
Group string `json:"group,omitempty" protobuf:"bytes,1,opt,name=group"`

View File

@@ -18,7 +18,6 @@ import (
appv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
"github.com/argoproj/argo-cd/v3/util/argo"
cacheutil "github.com/argoproj/argo-cd/v3/util/cache"
"github.com/argoproj/argo-cd/v3/util/env"
"github.com/argoproj/argo-cd/v3/util/hash"
@@ -305,7 +304,7 @@ func manifestCacheKey(revision string, appSrc *appv1.ApplicationSource, srcRefs
func trackingKey(appLabelKey string, trackingMethod string) string {
trackingKey := appLabelKey
if text.FirstNonEmpty(trackingMethod, string(argo.TrackingMethodLabel)) != string(argo.TrackingMethodLabel) {
if text.FirstNonEmpty(trackingMethod, string(appv1.TrackingMethodLabel)) != string(appv1.TrackingMethodLabel) {
trackingKey = trackingMethod + ":" + trackingKey
}
return trackingKey
@@ -399,7 +398,7 @@ func (c *Cache) DeleteManifests(revision string, appSrc *appv1.ApplicationSource
func appDetailsCacheKey(revision string, appSrc *appv1.ApplicationSource, srcRefs appv1.RefTargetRevisionMapping, trackingMethod appv1.TrackingMethod, refSourceCommitSHAs ResolvedRevisions) string {
if trackingMethod == "" {
trackingMethod = argo.TrackingMethodLabel
trackingMethod = appv1.TrackingMethodLabel
}
return fmt.Sprintf("appdetails|%s|%d|%s", revision, appSourceKey(appSrc, srcRefs, refSourceCommitSHAs), trackingMethod)
}

View File

@@ -338,7 +338,7 @@ func (s *Service) runRepoOperation(
if source.IsHelm() {
if settings.noCache {
err = helmClient.CleanChartCache(source.Chart, revision, repo.Project)
err = helmClient.CleanChartCache(source.Chart, revision)
if err != nil {
return err
}
@@ -347,7 +347,7 @@ func (s *Service) runRepoOperation(
if source.Helm != nil {
helmPassCredentials = source.Helm.PassCredentials
}
chartPath, closer, err := helmClient.ExtractChart(source.Chart, revision, repo.Project, helmPassCredentials, s.initConstants.HelmManifestMaxExtractedSize, s.initConstants.DisableHelmManifestMaxExtractedSize)
chartPath, closer, err := helmClient.ExtractChart(source.Chart, revision, helmPassCredentials, s.initConstants.HelmManifestMaxExtractedSize, s.initConstants.DisableHelmManifestMaxExtractedSize)
if err != nil {
return err
}
@@ -1155,7 +1155,7 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie
referencedSource := getReferencedSource(p.Path, q.RefSources)
if referencedSource != nil {
// If the $-prefixed path appears to reference another source, do env substitution _after_ resolving the source
resolvedPath, err = getResolvedRefValueFile(p.Path, env, q.GetValuesFileSchemes(), referencedSource.Repo.Repo, gitRepoPaths, referencedSource.Repo.Project)
resolvedPath, err = getResolvedRefValueFile(p.Path, env, q.GetValuesFileSchemes(), referencedSource.Repo.Repo, gitRepoPaths)
if err != nil {
return nil, "", fmt.Errorf("error resolving set-file path: %w", err)
}
@@ -1276,7 +1276,7 @@ func getResolvedValueFiles(
referencedSource := getReferencedSource(rawValueFile, refSources)
if referencedSource != nil {
// If the $-prefixed path appears to reference another source, do env substitution _after_ resolving that source.
resolvedPath, err = getResolvedRefValueFile(rawValueFile, env, allowedValueFilesSchemas, referencedSource.Repo.Repo, gitRepoPaths, referencedSource.Repo.Project)
resolvedPath, err = getResolvedRefValueFile(rawValueFile, env, allowedValueFilesSchemas, referencedSource.Repo.Repo, gitRepoPaths)
if err != nil {
return nil, fmt.Errorf("error resolving value file path: %w", err)
}
@@ -1309,15 +1309,9 @@ func getResolvedRefValueFile(
allowedValueFilesSchemas []string,
refSourceRepo string,
gitRepoPaths io.TempPaths,
project string,
) (pathutil.ResolvedFilePath, error) {
pathStrings := strings.Split(rawValueFile, "/")
keyData, err := json.Marshal(map[string]string{"url": git.NormalizeGitURL(refSourceRepo), "project": project})
if err != nil {
return "", err
}
repoPath := gitRepoPaths.GetPathIfExists(string(keyData))
repoPath := gitRepoPaths.GetPathIfExists(git.NormalizeGitURL(refSourceRepo))
if repoPath == "" {
return "", fmt.Errorf("failed to find repo %q", refSourceRepo)
}
@@ -2353,7 +2347,7 @@ func (s *Service) GetRevisionChartDetails(_ context.Context, q *apiclient.RepoSe
if err != nil {
return nil, fmt.Errorf("helm client error: %w", err)
}
chartPath, closer, err := helmClient.ExtractChart(q.Name, revision, q.Repo.Project, false, s.initConstants.HelmManifestMaxExtractedSize, s.initConstants.DisableHelmManifestMaxExtractedSize)
chartPath, closer, err := helmClient.ExtractChart(q.Name, revision, false, s.initConstants.HelmManifestMaxExtractedSize, s.initConstants.DisableHelmManifestMaxExtractedSize)
if err != nil {
return nil, fmt.Errorf("error extracting chart: %w", err)
}
@@ -2383,11 +2377,7 @@ func fileParameters(q *apiclient.RepoServerAppDetailsQuery) []v1alpha1.HelmFileP
}
func (s *Service) newClient(repo *v1alpha1.Repository, opts ...git.ClientOpts) (git.Client, error) {
keyData, err := json.Marshal(map[string]string{"url": git.NormalizeGitURL(repo.Repo), "project": repo.Project})
if err != nil {
return nil, err
}
repoPath, err := s.gitRepoPaths.GetPath(string(keyData))
repoPath, err := s.gitRepoPaths.GetPath(git.NormalizeGitURL(repo.Repo))
if err != nil {
return nil, err
}

View File

@@ -126,10 +126,10 @@ func newServiceWithMocks(t *testing.T, root string, signed bool) (*Service, *git
chart: {{Version: "1.0.0"}, {Version: version}},
oobChart: {{Version: "1.0.0"}, {Version: version}},
}}, nil)
helmClient.On("ExtractChart", chart, version, "", false, int64(0), false).Return("./testdata/my-chart", io.NopCloser, nil)
helmClient.On("ExtractChart", oobChart, version, "", false, int64(0), false).Return("./testdata2/out-of-bounds-chart", io.NopCloser, nil)
helmClient.On("CleanChartCache", chart, version, "").Return(nil)
helmClient.On("CleanChartCache", oobChart, version, "").Return(nil)
helmClient.On("ExtractChart", chart, version, false, int64(0), false).Return("./testdata/my-chart", io.NopCloser, nil)
helmClient.On("ExtractChart", oobChart, version, false, int64(0), false).Return("./testdata2/out-of-bounds-chart", io.NopCloser, nil)
helmClient.On("CleanChartCache", chart, version).Return(nil)
helmClient.On("CleanChartCache", oobChart, version).Return(nil)
helmClient.On("DependencyBuild").Return(nil)
paths.On("Add", mock.Anything, mock.Anything).Return(root, nil)
@@ -3270,8 +3270,7 @@ func Test_getResolvedValueFiles(t *testing.T) {
tempDir := t.TempDir()
paths := io.NewRandomizedTempPaths(tempDir)
key, _ := json.Marshal(map[string]string{"url": git.NormalizeGitURL("https://github.com/org/repo1"), "project": ""})
paths.Add(string(key), path.Join(tempDir, "repo1"))
paths.Add(git.NormalizeGitURL("https://github.com/org/repo1"), path.Join(tempDir, "repo1"))
testCases := []struct {
name string

View File

@@ -7,8 +7,18 @@ if obj.status == nil or obj.status.conditions == nil then
end
-- Sort conditions by lastTransitionTime, from old to new.
-- Ensure that conditions with nil lastTransitionTime are always sorted after those with non-nil values.
table.sort(obj.status.conditions, function(a, b)
return a.lastTransitionTime < b.lastTransitionTime
-- Nil values are considered "less than" non-nil values.
-- This means that conditions with nil lastTransitionTime will be sorted to the end.
if a.lastTransitionTime == nil then
return false
elseif b.lastTransitionTime == nil then
return true
else
-- If both have non-nil lastTransitionTime, compare them normally.
return a.lastTransitionTime < b.lastTransitionTime
end
end)
for _, condition in ipairs(obj.status.conditions) do

View File

@@ -14,4 +14,8 @@ tests:
- healthStatus:
status: Degraded
message: "Has Errors: Waiting for foo/keycloak-1 due to CrashLoopBackOff: back-off 10s"
inputPath: testdata/degraded.yaml
inputPath: testdata/degraded.yaml
- healthStatus:
status: Healthy
message: ""
inputPath: testdata/nil_last_transition_time.yaml

View File

@@ -0,0 +1,13 @@
apiVersion: k8s.keycloak.org/v1alpha1
kind: Keycloak
metadata:
name: keycloak-23
namespace: keycloak
status:
conditions:
- type: Ready
status: "True"
lastTransitionTime: "2025-05-06T12:00:00Z" # Non-nil lastTransitionTime
- type: HasErrors
status: "False"
lastTransitionTime: null # Nil lastTransitionTime

View File

@@ -528,6 +528,10 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
if err != nil {
return fmt.Errorf("error getting installation ID: %w", err)
}
trackingMethod, err := s.settingsMgr.GetTrackingMethod()
if err != nil {
return fmt.Errorf("error getting trackingMethod from settings: %w", err)
}
manifestInfo, err := client.GenerateManifest(ctx, &apiclient.ManifestRequest{
Repo: repo,
@@ -542,7 +546,7 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
ApiVersions: argo.APIResourcesToStrings(apiResources, true),
HelmRepoCreds: helmCreds,
HelmOptions: helmOptions,
TrackingMethod: string(argo.GetTrackingMethod(s.settingsMgr)),
TrackingMethod: trackingMethod,
EnabledSourceTypes: enableGenerateManifests,
ProjectName: proj.Name,
ProjectSourceRepos: proj.Spec.SourceRepos,
@@ -613,6 +617,11 @@ func (s *Server) GetManifestsWithFiles(stream application.ApplicationService_Get
return fmt.Errorf("error getting app instance label key from settings: %w", err)
}
trackingMethod, err := s.settingsMgr.GetTrackingMethod()
if err != nil {
return fmt.Errorf("error getting trackingMethod from settings: %w", err)
}
config, err := s.getApplicationClusterConfig(ctx, a)
if err != nil {
return fmt.Errorf("error getting application cluster config: %w", err)
@@ -662,7 +671,7 @@ func (s *Server) GetManifestsWithFiles(stream application.ApplicationService_Get
ApiVersions: argo.APIResourcesToStrings(apiResources, true),
HelmRepoCreds: helmCreds,
HelmOptions: helmOptions,
TrackingMethod: string(argo.GetTrackingMethod(s.settingsMgr)),
TrackingMethod: trackingMethod,
EnabledSourceTypes: enableGenerateManifests,
ProjectName: proj.Name,
ProjectSourceRepos: proj.Spec.SourceRepos,
@@ -777,6 +786,10 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*v1a
if err != nil {
return fmt.Errorf("error getting kustomize settings: %w", err)
}
trackingMethod, err := s.settingsMgr.GetTrackingMethod()
if err != nil {
return fmt.Errorf("error getting trackingMethod from settings: %w", err)
}
kustomizeOptions, err := kustomizeSettings.GetOptions(a.Spec.GetSource())
if err != nil {
return fmt.Errorf("error getting kustomize settings options: %w", err)
@@ -788,7 +801,7 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*v1a
KustomizeOptions: kustomizeOptions,
Repos: helmRepos,
NoCache: true,
TrackingMethod: string(argo.GetTrackingMethod(s.settingsMgr)),
TrackingMethod: trackingMethod,
EnabledSourceTypes: enabledSourceTypes,
HelmOptions: helmOptions,
})

View File

@@ -1009,7 +1009,7 @@ func TestDuplicatedClusterResourcesAnnotationTracking(t *testing.T) {
// (i.e. resources where metadata.namespace is set). Before the bugfix, this test would fail with a diff in the
// tracking annotation.
Given(t).
SetTrackingMethod(string(argo.TrackingMethodAnnotation)).
SetTrackingMethod(string(TrackingMethodAnnotation)).
Path("duplicated-resources").
When().
CreateApp().
@@ -1262,6 +1262,7 @@ definitions:
result = {}
result[1] = impactedResource1
obj.metadata.labels = {}
obj.metadata.labels["aKey"] = 'aValue'
impactedResource2 = {}
impactedResource2.operation = "patch"
@@ -2599,7 +2600,7 @@ func TestSwitchTrackingMethod(t *testing.T) {
ctx := Given(t)
ctx.
SetTrackingMethod(string(argo.TrackingMethodAnnotation)).
SetTrackingMethod(string(TrackingMethodAnnotation)).
Path("deployment").
When().
CreateApp().
@@ -2636,7 +2637,7 @@ func TestSwitchTrackingMethod(t *testing.T) {
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(HealthIs(health.HealthStatusHealthy)).
When().
SetTrackingMethod(string(argo.TrackingMethodLabel)).
SetTrackingMethod(string(TrackingMethodLabel)).
Sync().
Then().
Expect(OperationPhaseIs(OperationSucceeded)).
@@ -2691,6 +2692,7 @@ func TestSwitchTrackingMethod(t *testing.T) {
func TestSwitchTrackingLabel(t *testing.T) {
ctx := Given(t)
require.NoError(t, fixture.SetTrackingMethod(string(TrackingMethodLabel)))
ctx.
Path("deployment").
When().
@@ -2784,7 +2786,7 @@ func TestSwitchTrackingLabel(t *testing.T) {
func TestAnnotationTrackingExtraResources(t *testing.T) {
ctx := Given(t)
require.NoError(t, fixture.SetTrackingMethod(string(argo.TrackingMethodAnnotation)))
require.NoError(t, fixture.SetTrackingMethod(string(TrackingMethodAnnotation)))
ctx.
Path("deployment").
When().
@@ -2950,7 +2952,7 @@ data:
func TestInstallationID(t *testing.T) {
ctx := Given(t)
ctx.
SetTrackingMethod(string(argo.TrackingMethodAnnotation)).
SetTrackingMethod(string(TrackingMethodAnnotation)).
And(func() {
_, err := fixture.KubeClientset.CoreV1().ConfigMaps(fixture.DeploymentNamespace()).Create(
t.Context(), &corev1.ConfigMap{
@@ -3027,3 +3029,46 @@ func TestDeletionConfirmation(t *testing.T) {
When().ConfirmDeletion().
Then().Expect(DoesNotExist())
}
func TestLastTransitionTimeUnchangedError(t *testing.T) {
// Ensure that, if the health status hasn't changed, the lastTransitionTime is not updated.
ctx := Given(t)
ctx.
Path(guestbookPath).
When().
And(func() {
// Manually create an application with an outdated reconciledAt field
manifest := fmt.Sprintf(`
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: %s
spec:
project: default
source:
repoURL: %s
path: guestbook
targetRevision: HEAD
destination:
server: https://non-existent-cluster
namespace: default
status:
reconciledAt: "2023-01-01T00:00:00Z"
health:
status: Unknown
lastTransitionTime: "2023-01-01T00:00:00Z"
`, ctx.AppName(), fixture.RepoURL(fixture.RepoURLTypeFile))
_, err := fixture.RunWithStdin(manifest, "", "kubectl", "apply", "-n", fixture.ArgoCDNamespace, "-f", "-")
require.NoError(t, err)
}).
Refresh(RefreshTypeNormal).
Then().
And(func(app *Application) {
// Verify the health status is still Unknown
assert.Equal(t, health.HealthStatusUnknown, app.Status.Health.Status)
// Verify the lastTransitionTime has not been updated
assert.Equal(t, "2023-01-01T00:00:00Z", app.Status.Health.LastTransitionTime.UTC().Format(time.RFC3339))
})
}

View File

@@ -65,7 +65,7 @@ func TestMultiSourceAppWithHelmExternalValueFiles(t *testing.T) {
RepoURL: RepoURL(RepoURLTypeFile),
Ref: "values",
}, {
RepoURL: "https://github.com/argoproj/argocd-example-apps.git",
RepoURL: RepoURL(RepoURLTypeFile),
TargetRevision: "HEAD",
Path: "helm-guestbook",
Helm: &ApplicationSourceHelm{
@@ -107,9 +107,13 @@ func TestMultiSourceAppWithHelmExternalValueFiles(t *testing.T) {
for _, r := range app.Status.Resources {
statusByName[r.Name] = r.Status
}
// check if the app has 3 resources, guestbook and 2 pods
assert.Len(t, statusByName, 1)
assert.Equal(t, SyncStatusCodeSynced, statusByName["helm-guestbook"])
assert.Equal(t, SyncStatusCodeSynced, statusByName["guestbook-ui"])
// Confirm that the deployment has 3 replicas.
output, err := Run("", "kubectl", "get", "deployment", "guestbook-ui", "-n", DeploymentNamespace(), "-o", "jsonpath={.spec.replicas}")
require.NoError(t, err)
assert.Equal(t, "3", output, "Expected 3 replicas for the helm-guestbook deployment")
})
}

View File

@@ -11,7 +11,6 @@ import (
. "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
. "github.com/argoproj/argo-cd/v3/test/e2e/fixture"
. "github.com/argoproj/argo-cd/v3/test/e2e/fixture/app"
"github.com/argoproj/argo-cd/v3/util/argo"
)
func TestClusterRoleBinding(t *testing.T) {
@@ -30,7 +29,7 @@ func TestClusterRoleBinding(t *testing.T) {
assert.Empty(t, diffOutput)
}).
When().
SetTrackingMethod(string(argo.TrackingMethodAnnotation)).
SetTrackingMethod(string(TrackingMethodAnnotation)).
Sync().
Then().
Expect(OperationPhaseIs(OperationSucceeded)).

View File

@@ -18,7 +18,6 @@ import (
"k8s.io/client-go/tools/clientcmd"
"github.com/argoproj/argo-cd/v3/common"
"github.com/argoproj/argo-cd/v3/util/argo"
"github.com/argoproj/argo-cd/v3/util/clusterauth"
"github.com/argoproj/gitops-engine/pkg/health"
@@ -54,7 +53,7 @@ func TestDeployment(t *testing.T) {
func TestDeploymentWithAnnotationTrackingMode(t *testing.T) {
ctx := Given(t)
require.NoError(t, SetTrackingMethod(string(argo.TrackingMethodAnnotation)))
require.NoError(t, SetTrackingMethod(string(TrackingMethodAnnotation)))
ctx.
Path("deployment").
When().
@@ -77,7 +76,7 @@ func TestDeploymentWithAnnotationTrackingMode(t *testing.T) {
func TestDeploymentWithLabelTrackingMode(t *testing.T) {
ctx := Given(t)
require.NoError(t, SetTrackingMethod(string(argo.TrackingMethodLabel)))
require.NoError(t, SetTrackingMethod(string(TrackingMethodLabel)))
ctx.
Path("deployment").
When().
@@ -115,10 +114,9 @@ func TestDeploymentWithoutTrackingMode(t *testing.T) {
And(func(_ *Application) {
out, err := RunCli("app", "manifests", ctx.AppName())
require.NoError(t, err)
assert.Contains(t, out, fmt.Sprintf(`labels:
app: nginx
app.kubernetes.io/instance: %s
`, ctx.AppName()))
assert.Contains(t, out, fmt.Sprintf(`annotations:
argocd.argoproj.io/tracking-id: %s:apps/Deployment:%s/nginx-deployment
`, ctx.AppName(), DeploymentNamespace()))
})
}

View File

@@ -1,6 +1,8 @@
package project
import (
"time"
"github.com/stretchr/testify/require"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
@@ -81,5 +83,6 @@ func (a *Actions) runCli(args ...string) {
func (a *Actions) Then() *Consequences {
a.context.t.Helper()
time.Sleep(fixture.WhenThenSleepInterval)
return &Consequences{a.context, a}
}

View File

@@ -3,6 +3,7 @@ package project
import (
"context"
"errors"
"time"
"github.com/stretchr/testify/require"
@@ -64,5 +65,6 @@ func (c *Consequences) Given() *Context {
}
func (c *Consequences) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return c.actions
}

View File

@@ -2,6 +2,7 @@ package project
import (
"testing"
"time"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
"github.com/argoproj/argo-cd/v3/util/env"
@@ -45,5 +46,6 @@ func (c *Context) And(block func()) *Context {
}
func (c *Context) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return &Actions{context: c}
}

View File

@@ -1,6 +1,8 @@
package admin
import (
"time"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
)
@@ -63,5 +65,6 @@ func (a *Actions) runCliWithStdin(stdin string, args ...string) {
func (a *Actions) Then() *Consequences {
a.context.t.Helper()
time.Sleep(fixture.WhenThenSleepInterval)
return &Consequences{a.context, a}
}

View File

@@ -1,6 +1,9 @@
package admin
import (
"time"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
. "github.com/argoproj/argo-cd/v3/test/e2e/fixture/admin/utils"
)
@@ -33,5 +36,6 @@ func (c *Consequences) Given() *Context {
}
func (c *Consequences) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return c.actions
}

View File

@@ -2,6 +2,7 @@ package admin
import (
"testing"
"time"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
"github.com/argoproj/argo-cd/v3/util/env"
@@ -39,5 +40,6 @@ func (c *Context) And(block func()) *Context {
}
func (c *Context) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return &Actions{context: c}
}

View File

@@ -6,6 +6,7 @@ import (
"os"
"slices"
"strconv"
"time"
rbacv1 "k8s.io/api/rbac/v1"
@@ -492,6 +493,7 @@ func (a *Actions) And(block func()) *Actions {
func (a *Actions) Then() *Consequences {
a.context.t.Helper()
time.Sleep(fixture.WhenThenSleepInterval)
return &Consequences{a.context, a, 15}
}

View File

@@ -101,6 +101,7 @@ func (c *Consequences) Given() *Context {
}
func (c *Consequences) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return c.actions
}

View File

@@ -11,7 +11,6 @@ import (
"github.com/argoproj/argo-cd/v3/test/e2e/fixture/certs"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture/gpgkeys"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture/repos"
"github.com/argoproj/argo-cd/v3/util/argo"
"github.com/argoproj/argo-cd/v3/util/env"
"github.com/argoproj/argo-cd/v3/util/settings"
)
@@ -88,7 +87,7 @@ func GivenWithSameState(t *testing.T) *Context {
timeout: timeout,
project: "default",
prune: true,
trackingMethod: argo.TrackingMethodLabel,
trackingMethod: v1alpha1.TrackingMethodLabel,
}
}
@@ -349,6 +348,7 @@ func (c *Context) And(block func()) *Context {
}
func (c *Context) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return &Actions{context: c}
}

View File

@@ -61,6 +61,7 @@ func (a *Actions) And(block func()) *Actions {
func (a *Actions) Then() *Consequences {
a.context.t.Helper()
time.Sleep(fixture.WhenThenSleepInterval)
return &Consequences{a.context, a}
}

View File

@@ -71,6 +71,7 @@ func (c *Consequences) Given() *Context {
}
func (c *Consequences) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return c.actions
}

View File

@@ -29,6 +29,7 @@ func Given(t *testing.T) *Context {
}
func (c *Context) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return &Actions{context: c}
}

View File

@@ -5,6 +5,7 @@ import (
"errors"
"log"
"strings"
"time"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
@@ -131,6 +132,7 @@ func (a *Actions) DeleteByServer() *Actions {
func (a *Actions) Then() *Consequences {
a.context.t.Helper()
time.Sleep(fixture.WhenThenSleepInterval)
return &Consequences{a.context, a}
}

View File

@@ -3,6 +3,7 @@ package cluster
import (
"context"
"errors"
"time"
clusterpkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/cluster"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
@@ -54,5 +55,6 @@ func (c *Consequences) Given() *Context {
}
func (c *Consequences) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return c.actions
}

View File

@@ -2,6 +2,7 @@ package cluster
import (
"testing"
"time"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
"github.com/argoproj/argo-cd/v3/util/env"
@@ -59,6 +60,7 @@ func (c *Context) And(block func()) *Context {
}
func (c *Context) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return &Actions{context: c}
}

View File

@@ -66,6 +66,9 @@ const (
PluginSockFilePath = "/app/config/plugin"
E2ETestPrefix = "e2e-test-"
// Account for batch events processing (set to 1ms in e2e tests)
WhenThenSleepInterval = 5 * time.Millisecond
)
const (

View File

@@ -1,6 +1,8 @@
package notification
import (
"time"
"github.com/stretchr/testify/require"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
@@ -24,6 +26,7 @@ func (a *Actions) SetParamInNotificationConfigMap(key, value string) *Actions {
func (a *Actions) Then() *Consequences {
a.context.t.Helper()
time.Sleep(fixture.WhenThenSleepInterval)
return &Consequences{a.context, a}
}

View File

@@ -2,6 +2,7 @@ package notification
import (
"context"
"time"
"github.com/argoproj/argo-cd/v3/pkg/apiclient/notification"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
@@ -53,6 +54,7 @@ func (c *Consequences) listTemplates() (*notification.TemplateList, error) {
}
func (c *Consequences) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return c.actions
}

View File

@@ -2,6 +2,7 @@ package notification
import (
"testing"
"time"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
)
@@ -23,5 +24,6 @@ func (c *Context) And(block func()) *Context {
}
func (c *Context) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return &Actions{context: c}
}

View File

@@ -3,6 +3,7 @@ package project
import (
"context"
"strings"
"time"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -112,6 +113,7 @@ func (a *Actions) And(block func()) *Actions {
func (a *Actions) Then() *Consequences {
a.context.t.Helper()
time.Sleep(fixture.WhenThenSleepInterval)
return &Consequences{a.context, a}
}

View File

@@ -2,6 +2,7 @@ package project
import (
"context"
"time"
"github.com/argoproj/argo-cd/v3/pkg/apiclient/project"
@@ -43,5 +44,6 @@ func (c *Consequences) Given() *Context {
}
func (c *Consequences) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return c.actions
}

View File

@@ -2,6 +2,7 @@ package project
import (
"testing"
"time"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
"github.com/argoproj/argo-cd/v3/util/env"
@@ -68,5 +69,6 @@ func (c *Context) And(block func()) *Context {
}
func (c *Context) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return &Actions{context: c}
}

View File

@@ -2,6 +2,7 @@ package repos
import (
"log"
"time"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
)
@@ -77,6 +78,7 @@ func (a *Actions) Project(project string) *Actions {
func (a *Actions) Then() *Consequences {
a.context.t.Helper()
time.Sleep(fixture.WhenThenSleepInterval)
return &Consequences{a.context, a}
}

View File

@@ -3,6 +3,7 @@ package repos
import (
"context"
"errors"
"time"
repositorypkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/repository"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
@@ -54,5 +55,6 @@ func (c *Consequences) Given() *Context {
}
func (c *Consequences) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return c.actions
}

View File

@@ -2,6 +2,7 @@ package repos
import (
"testing"
"time"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
"github.com/argoproj/argo-cd/v3/util/env"
@@ -54,6 +55,7 @@ func (c *Context) And(block func()) *Context {
}
func (c *Context) When() *Actions {
time.Sleep(fixture.WhenThenSleepInterval)
return &Actions{context: c}
}

View File

@@ -544,8 +544,9 @@ func TestHelmRepoDiffLocal(t *testing.T) {
"--key-file", "../fixture/certs/argocd-test-client.key",
"--ca-file", "../fixture/certs/argocd-test-ca.crt",
))
diffOutput := errors.NewHandler(t).FailOnErr(fixture.RunCli("app", "diff", app.Name, "--local", "testdata/helm")).(string)
diffOutput, err := fixture.RunCli("app", "diff", app.Name, "--local", "testdata/helm")
assert.Empty(t, diffOutput)
assert.NoError(t, err)
})
}

View File

@@ -232,3 +232,41 @@ func TestGetRepoCLIOutput(t *testing.T) {
git https://github.com/argoproj/argo-cd.git false false false false Successful argo-project`, output)
})
}
func TestCreateRepoWithSameURLInTwoProjects(t *testing.T) {
projectFixture.Given(t).
When().
Name("project-one").
Create().
Then()
projectFixture.Given(t).
When().
Name("project-two").
Create().
Then()
path := "https://github.com/argoproj/argo-cd.git"
// Create repository in first project
repoFixture.GivenWithSameState(t).
When().
Path(path).
Project("project-one").
Create().
Then().
And(func(r *Repository, _ error) {
assert.Equal(t, r.Repo, path)
})
// Create repository with same URL in second project
repoFixture.GivenWithSameState(t).
When().
Path(path).
Project("project-two").
Create().
Then().
And(func(r *Repository, _ error) {
assert.Equal(t, r.Repo, path)
})
}

View File

@@ -0,0 +1,3 @@
apiVersion: v2
version: 1.0.0
name: helm-guestbook

View File

@@ -0,0 +1,23 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: guestbook-ui
labels:
test: "true"
spec:
replicas: {{ .Values.replicas }}
revisionHistoryLimit: 3
selector:
matchLabels:
app: guestbook-ui
template:
metadata:
labels:
app: guestbook-ui
spec:
containers:
- image: quay.io/argoprojlabs/argocd-e2e-container:0.2
imagePullPolicy: IfNotPresent
name: guestbook-ui
ports:
- containerPort: 80

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: guestbook-ui
spec:
ports:
- port: 80
targetPort: 80
selector:
app: guestbook-ui

View File

@@ -0,0 +1 @@
replicas: 1

View File

@@ -15,7 +15,7 @@ interface Props {
application: models.Application;
operationState: models.OperationState;
}
const buildResourceUniqueId = (res: Omit<models.ResourceRef, 'uid'>) => `${res.group}-${res.kind}-${res.version}-${res.namespace}-${res.name}`;
const buildResourceUniqueId = (res: Omit<models.ResourceRef, 'uid'>) => `${res.group || ''}-${res.kind || ''}-${res.version || ''}-${res.namespace || ''}-${res.name}`;
const FilterableMessageStatuses = ['Changed', 'Unchanged'];
const Filter = (props: {filters: string[]; setFilters: (f: string[]) => void; options: string[]; title: string; style?: React.CSSProperties}) => {
@@ -158,13 +158,20 @@ export const ApplicationOperationState: React.StatelessComponent<Props> = ({appl
// const hookPhases = ['Running', 'Terminating', 'Failed', 'Error', 'Succeeded'];
const resourceHealth = application.status.resources.reduce(
(acc, res) => {
if (res.health) {
acc[buildResourceUniqueId(res)] = res.health;
}
acc[buildResourceUniqueId(res)] = {
health: res.health,
syncWave: res.syncWave
};
return acc;
},
{} as Record<string, models.HealthStatus>
{} as Record<
string,
{
health: models.HealthStatus;
syncWave: number;
}
>
);
const combinedHealthSyncResult: models.SyncResourceResult[] = syncResult?.resources?.map(syncResultItem => {
@@ -176,10 +183,12 @@ export const ApplicationOperationState: React.StatelessComponent<Props> = ({appl
...syncResultItem
};
if (healthStatus) {
syncResultWithHealth.health = healthStatus;
if (healthStatus?.health) {
syncResultWithHealth.health = healthStatus.health;
}
syncResultWithHealth.syncWave = healthStatus?.syncWave;
return syncResultWithHealth;
});
let filtered: models.SyncResourceResult[] = [];
@@ -242,7 +251,8 @@ export const ApplicationOperationState: React.StatelessComponent<Props> = ({appl
<div className='argo-table-list'>
<div className='argo-table-list__head'>
<div className='row'>
<div className='columns large-2 show-for-large application-operation-state__icons_container_padding'>KIND</div>
<div className='columns large-1 show-for-large application-operation-state__icons_container_padding'>SYNC WAVE</div>
<div className='columns large-1 show-for-large application-operation-state__icons_container_padding'>KIND</div>
<div className='columns large-1 show-for-large'>NAMESPACE</div>
<div className='columns large-2 small-2'>NAME</div>
<div className='columns large-1 small-2'>STATUS</div>
@@ -255,10 +265,13 @@ export const ApplicationOperationState: React.StatelessComponent<Props> = ({appl
filtered.map((resource, i) => (
<div className='argo-table-list__row' key={i}>
<div className='row'>
<div className='columns large-2 show-for-large application-operation-state__icons_container_padding'>
<div className='columns large-1 show-for-large application-operation-state__icons_container_padding' style={{textAlign: 'center'}}>
<div className='application-operation-state__icons_container'>
{resource.hookType && <i title='Resource lifecycle hook' className='fa fa-anchor' />}
</div>
{resource.syncWave || '0'}
</div>
<div className='columns large-1 show-for-large'>
<span title={getKind(resource)}>{getKind(resource)}</span>
</div>
<div className='columns large-1 show-for-large' title={resource.namespace}>

View File

@@ -117,13 +117,15 @@ export const ApplicationStatusPanel = ({application, showDiff, showOperation, sh
<div className='application-status-panel__item-name'>{application.status.sourceHydrator.currentOperation.message}</div>
)}
<div className='application-status-panel__item-name'>
<RevisionMetadataPanel
appName={application.metadata.name}
appNamespace={application.metadata.namespace}
type={''}
revision={application.status.sourceHydrator.currentOperation.drySHA}
versionId={utils.getAppCurrentVersion(application)}
/>
{application.status.sourceHydrator.currentOperation.drySHA && (
<RevisionMetadataPanel
appName={application.metadata.name}
appNamespace={application.metadata.namespace}
type={''}
revision={application.status.sourceHydrator.currentOperation.drySHA}
versionId={utils.getAppCurrentVersion(application)}
/>
)}
</div>
</div>
)}

View File

@@ -219,7 +219,7 @@ export class ReposList extends React.Component<
tlsClientCertKey: !validURLValues.tlsClientCertKey && validURLValues.tlsClientCertData && 'TLS client cert key is required if TLS client cert is given.',
bearerToken:
(validURLValues.password && validURLValues.bearerToken && 'Either the password or the bearer token must be set, but not both.') ||
(validURLValues.type != 'git' && 'Bearer token is only supported for Git BitBucket Data Center repositories.')
(validURLValues.bearerToken && validURLValues.type != 'git' && 'Bearer token is only supported for Git BitBucket Data Center repositories.')
};
case ConnectionMethod.GITHUBAPP:
const githubAppValues = params as NewGitHubAppRepoParams;

View File

@@ -129,6 +129,7 @@ export interface ResourceResult {
export type SyncResourceResult = ResourceResult & {
health?: HealthStatus;
syncWave?: number;
};
export const AnnotationRefreshKey = 'argocd.argoproj.io/refresh';

View File

@@ -773,6 +773,15 @@ func verifyGenerateManifests(
continue
}
trackingMethod, err := settingsMgr.GetTrackingMethod()
if err != nil {
conditions = append(conditions, argoappv1.ApplicationCondition{
Type: argoappv1.ApplicationConditionInvalidSpecError,
Message: fmt.Sprintf("Error getting trackingMethod: %v", err),
})
continue
}
verifySignature := false
if len(proj.Spec.SignatureKeys) > 0 && gpg.IsGPGEnabled() {
verifySignature = true
@@ -798,7 +807,7 @@ func verifyGenerateManifests(
ApiVersions: apiVersions,
HelmOptions: helmOptions,
HelmRepoCreds: repositoryCredentials,
TrackingMethod: string(GetTrackingMethod(settingsMgr)),
TrackingMethod: trackingMethod,
EnabledSourceTypes: enableGenerateManifests,
NoRevisionCache: true,
HasMultipleSources: app.Spec.HasMultipleSources(),

View File

@@ -6,18 +6,12 @@ import (
"regexp"
"strings"
kubeutil "github.com/argoproj/gitops-engine/pkg/utils/kube"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/argoproj/argo-cd/v3/common"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v3/util/kube"
"github.com/argoproj/argo-cd/v3/util/settings"
)
const (
TrackingMethodAnnotation v1alpha1.TrackingMethod = "annotation"
TrackingMethodLabel v1alpha1.TrackingMethod = "label"
TrackingMethodAnnotationAndLabel v1alpha1.TrackingMethod = "annotation+label"
)
var (
@@ -51,17 +45,8 @@ func NewResourceTracking() ResourceTracking {
return &resourceTracking{}
}
// GetTrackingMethod retrieve tracking method from settings
func GetTrackingMethod(settingsMgr *settings.SettingsManager) v1alpha1.TrackingMethod {
tm, err := settingsMgr.GetTrackingMethod()
if err != nil || tm == "" {
return TrackingMethodLabel
}
return v1alpha1.TrackingMethod(tm)
}
func IsOldTrackingMethod(trackingMethod string) bool {
return trackingMethod == "" || trackingMethod == string(TrackingMethodLabel)
return trackingMethod == "" || trackingMethod == string(v1alpha1.TrackingMethodLabel)
}
func (rt *resourceTracking) getAppInstanceValue(un *unstructured.Unstructured, installationID string) *AppInstanceValue {
@@ -89,22 +74,18 @@ func (rt *resourceTracking) GetAppName(un *unstructured.Unstructured, key string
return ""
}
switch trackingMethod {
case TrackingMethodLabel:
case v1alpha1.TrackingMethodLabel:
label, err := kube.GetAppInstanceLabel(un, key)
if err != nil {
return ""
}
return label
case TrackingMethodAnnotationAndLabel:
case v1alpha1.TrackingMethodAnnotationAndLabel:
return retrieveAppInstanceValue()
case TrackingMethodAnnotation:
case v1alpha1.TrackingMethodAnnotation:
return retrieveAppInstanceValue()
default:
label, err := kube.GetAppInstanceLabel(un, key)
if err != nil {
return ""
}
return label
return retrieveAppInstanceValue()
}
}
@@ -113,7 +94,7 @@ func (rt *resourceTracking) GetAppName(un *unstructured.Unstructured, key string
// not be parsed, it returns nil.
func (rt *resourceTracking) GetAppInstance(un *unstructured.Unstructured, trackingMethod v1alpha1.TrackingMethod, instanceID string) *AppInstanceValue {
switch trackingMethod {
case TrackingMethodAnnotation, TrackingMethodAnnotationAndLabel:
case v1alpha1.TrackingMethodAnnotation, v1alpha1.TrackingMethodAnnotationAndLabel:
return rt.getAppInstanceValue(un, instanceID)
default:
return nil
@@ -155,15 +136,15 @@ func (rt *resourceTracking) SetAppInstance(un *unstructured.Unstructured, key, v
return kube.SetAppInstanceAnnotation(un, common.AnnotationKeyAppInstance, rt.BuildAppInstanceValue(appInstanceValue))
}
switch trackingMethod {
case TrackingMethodLabel:
case v1alpha1.TrackingMethodLabel:
err := kube.SetAppInstanceLabel(un, key, val)
if err != nil {
return fmt.Errorf("failed to set app instance label: %w", err)
}
return nil
case TrackingMethodAnnotation:
case v1alpha1.TrackingMethodAnnotation:
return setAppInstanceAnnotation()
case TrackingMethodAnnotationAndLabel:
case v1alpha1.TrackingMethodAnnotationAndLabel:
err := setAppInstanceAnnotation()
if err != nil {
return err
@@ -185,11 +166,7 @@ func (rt *resourceTracking) SetAppInstance(un *unstructured.Unstructured, key, v
}
return nil
default:
err := kube.SetAppInstanceLabel(un, key, val)
if err != nil {
return fmt.Errorf("failed to set app instance label: %w", err)
}
return nil
return setAppInstanceAnnotation()
}
}
@@ -240,6 +217,11 @@ func (rt *resourceTracking) Normalize(config, live *unstructured.Unstructured, l
return nil
}
if kubeutil.IsCRD(live) {
// CRDs don't get tracking annotations.
return nil
}
annotation, err := kube.GetAppInstanceAnnotation(config, common.AnnotationKeyAppInstance)
if err != nil {
return err

View File

@@ -12,6 +12,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/argoproj/argo-cd/v3/common"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
)
func TestSetAppInstanceLabel(t *testing.T) {
@@ -24,9 +25,9 @@ func TestSetAppInstanceLabel(t *testing.T) {
resourceTracking := NewResourceTracking()
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel, "")
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", v1alpha1.TrackingMethodLabel, "")
require.NoError(t, err)
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodLabel, "")
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, v1alpha1.TrackingMethodLabel, "")
assert.Equal(t, "my-app", app)
}
@@ -40,10 +41,10 @@ func TestSetAppInstanceAnnotation(t *testing.T) {
resourceTracking := NewResourceTracking()
err = resourceTracking.SetAppInstance(&obj, common.AnnotationKeyAppInstance, "my-app", "", TrackingMethodAnnotation, "")
err = resourceTracking.SetAppInstance(&obj, common.AnnotationKeyAppInstance, "my-app", "", v1alpha1.TrackingMethodAnnotation, "")
require.NoError(t, err)
app := resourceTracking.GetAppName(&obj, common.AnnotationKeyAppInstance, TrackingMethodAnnotation, "")
app := resourceTracking.GetAppName(&obj, common.AnnotationKeyAppInstance, v1alpha1.TrackingMethodAnnotation, "")
assert.Equal(t, "my-app", app)
}
@@ -56,10 +57,10 @@ func TestSetAppInstanceAnnotationAndLabel(t *testing.T) {
resourceTracking := NewResourceTracking()
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodAnnotationAndLabel, "")
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app", "", v1alpha1.TrackingMethodAnnotationAndLabel, "")
require.NoError(t, err)
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel, "")
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, v1alpha1.TrackingMethodAnnotationAndLabel, "")
assert.Equal(t, "my-app", app)
}
@@ -72,11 +73,11 @@ func TestSetAppInstanceAnnotationAndLabelLongName(t *testing.T) {
resourceTracking := NewResourceTracking()
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", "", TrackingMethodAnnotationAndLabel, "")
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", "", v1alpha1.TrackingMethodAnnotationAndLabel, "")
require.NoError(t, err)
// the annotation should still work, so the name from GetAppName should not be truncated
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel, "")
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, v1alpha1.TrackingMethodAnnotationAndLabel, "")
assert.Equal(t, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", app)
// the label should be truncated to 63 characters
@@ -92,11 +93,11 @@ func TestSetAppInstanceAnnotationAndLabelLongNameBadEnding(t *testing.T) {
resourceTracking := NewResourceTracking()
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", "", TrackingMethodAnnotationAndLabel, "")
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", "", v1alpha1.TrackingMethodAnnotationAndLabel, "")
require.NoError(t, err)
// the annotation should still work, so the name from GetAppName should not be truncated
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel, "")
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, v1alpha1.TrackingMethodAnnotationAndLabel, "")
assert.Equal(t, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", app)
// the label should be truncated to 63 characters, AND the hyphen should be removed
@@ -112,7 +113,7 @@ func TestSetAppInstanceAnnotationAndLabelOutOfBounds(t *testing.T) {
resourceTracking := NewResourceTracking()
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "----------------------------------------------------------------", "", TrackingMethodAnnotationAndLabel, "")
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "----------------------------------------------------------------", "", v1alpha1.TrackingMethodAnnotationAndLabel, "")
// this should error because it can't truncate to a valid value
assert.EqualError(t, err, "failed to set app instance label: unable to truncate label to not end with a special character")
}
@@ -127,7 +128,7 @@ func TestSetAppInstanceAnnotationNotFound(t *testing.T) {
resourceTracking := NewResourceTracking()
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotation, "")
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, v1alpha1.TrackingMethodAnnotation, "")
assert.Equal(t, "", app)
}
@@ -186,15 +187,15 @@ func TestResourceIdNormalizer_Normalize(t *testing.T) {
// live object is a resource that has old style tracking label
liveObj := sampleResource(t)
err := rt.SetAppInstance(liveObj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel, "")
err := rt.SetAppInstance(liveObj, common.LabelKeyAppInstance, "my-app", "", v1alpha1.TrackingMethodLabel, "")
require.NoError(t, err)
// config object is a resource that has new style tracking annotation
configObj := sampleResource(t)
err = rt.SetAppInstance(configObj, common.AnnotationKeyAppInstance, "my-app2", "", TrackingMethodAnnotation, "")
err = rt.SetAppInstance(configObj, common.AnnotationKeyAppInstance, "my-app2", "", v1alpha1.TrackingMethodAnnotation, "")
require.NoError(t, err)
_ = rt.Normalize(configObj, liveObj, common.LabelKeyAppInstance, string(TrackingMethodAnnotation))
_ = rt.Normalize(configObj, liveObj, common.LabelKeyAppInstance, string(v1alpha1.TrackingMethodAnnotation))
// the normalization should affect add the new style annotation and drop old tracking label from live object
annotation, err := kube.GetAppInstanceAnnotation(configObj, common.AnnotationKeyAppInstance)
@@ -204,22 +205,66 @@ func TestResourceIdNormalizer_Normalize(t *testing.T) {
assert.False(t, hasOldLabel)
}
func TestResourceIdNormalizer_NormalizeCRD(t *testing.T) {
rt := NewResourceTracking()
// live object is a CRD resource
liveObj := &unstructured.Unstructured{
Object: map[string]any{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "CustomResourceDefinition",
"metadata": map[string]any{
"name": "crontabs.stable.example.com",
"labels": map[string]any{
common.LabelKeyAppInstance: "my-app",
},
},
"spec": map[string]any{
"group": "stable.example.com",
"scope": "Namespaced",
},
},
}
// config object is a CRD resource
configObj := &unstructured.Unstructured{
Object: map[string]any{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "CustomResourceDefinition",
"metadata": map[string]any{
"name": "crontabs.stable.example.com",
"labels": map[string]any{
common.LabelKeyAppInstance: "my-app",
},
},
"spec": map[string]any{
"group": "stable.example.com",
"scope": "Namespaced",
},
},
}
require.NoError(t, rt.Normalize(configObj, liveObj, common.LabelKeyAppInstance, string(v1alpha1.TrackingMethodAnnotation)))
// the normalization should not apply any changes to the live object
require.NotContains(t, liveObj.GetAnnotations(), common.AnnotationKeyAppInstance)
}
func TestResourceIdNormalizer_Normalize_ConfigHasOldLabel(t *testing.T) {
rt := NewResourceTracking()
// live object is a resource that has old style tracking label
liveObj := sampleResource(t)
err := rt.SetAppInstance(liveObj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel, "")
err := rt.SetAppInstance(liveObj, common.LabelKeyAppInstance, "my-app", "", v1alpha1.TrackingMethodLabel, "")
require.NoError(t, err)
// config object is a resource that has new style tracking annotation
configObj := sampleResource(t)
err = rt.SetAppInstance(configObj, common.AnnotationKeyAppInstance, "my-app2", "", TrackingMethodAnnotation, "")
err = rt.SetAppInstance(configObj, common.AnnotationKeyAppInstance, "my-app2", "", v1alpha1.TrackingMethodAnnotation, "")
require.NoError(t, err)
err = rt.SetAppInstance(configObj, common.LabelKeyAppInstance, "my-app", "", TrackingMethodLabel, "")
err = rt.SetAppInstance(configObj, common.LabelKeyAppInstance, "my-app", "", v1alpha1.TrackingMethodLabel, "")
require.NoError(t, err)
_ = rt.Normalize(configObj, liveObj, common.LabelKeyAppInstance, string(TrackingMethodAnnotation))
_ = rt.Normalize(configObj, liveObj, common.LabelKeyAppInstance, string(v1alpha1.TrackingMethodAnnotation))
// the normalization should affect add the new style annotation and drop old tracking label from live object
annotation, err := kube.GetAppInstanceAnnotation(configObj, common.AnnotationKeyAppInstance)
@@ -230,5 +275,5 @@ func TestResourceIdNormalizer_Normalize_ConfigHasOldLabel(t *testing.T) {
}
func TestIsOldTrackingMethod(t *testing.T) {
assert.True(t, IsOldTrackingMethod(string(TrackingMethodLabel)))
assert.True(t, IsOldTrackingMethod(string(v1alpha1.TrackingMethodLabel)))
}

View File

@@ -424,11 +424,14 @@ func (m *nativeGitClient) Fetch(revision string) error {
func (m *nativeGitClient) LsFiles(path string, enableNewGitFileGlobbing bool) ([]string, error) {
if enableNewGitFileGlobbing {
// This is the new way with safer globbing
err := os.Chdir(m.root)
// evaluating the root path for symlinks
realRoot, err := filepath.EvalSymlinks(m.root)
if err != nil {
return nil, err
}
allFiles, err := doublestar.FilepathGlob(path)
// searching for the pattern inside the root path
allFiles, err := doublestar.FilepathGlob(filepath.Join(realRoot, path))
if err != nil {
return nil, err
}
@@ -442,10 +445,16 @@ func (m *nativeGitClient) LsFiles(path string, enableNewGitFileGlobbing bool) ([
if err != nil {
return nil, err
}
if strings.HasPrefix(absPath, m.root) {
files = append(files, file)
if strings.HasPrefix(absPath, realRoot) {
// removing the repository root prefix from the file path
relativeFile, err := filepath.Rel(realRoot, file)
if err != nil {
return nil, err
}
files = append(files, relativeFile)
} else {
log.Warnf("Absolute path for %s is outside of repository, removing it", file)
log.Warnf("Absolute path for %s is outside of repository, ignoring it", file)
}
}
return files, nil

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