Compare commits

..

16 Commits

Author SHA1 Message Date
Alexander Matyushentsev
24834112d6 Update manifests to v1.4.3 2020-04-15 09:35:12 -07:00
Alexander Matyushentsev
48cced9d92 Update manifests to v1.4.2 2020-01-23 16:48:25 -08:00
Alexander Matyushentsev
bc77ea70c4 fix: correctly replace cache in namespace isolation mode (#3023) 2020-01-23 16:20:40 -08:00
Alexander Matyushentsev
f8721a7360 Update manifests to v1.4.1 2020-01-22 14:44:13 -08:00
Alexander Matyushentsev
8ada07e0f5 fix: run dep ensure (#3018) 2020-01-22 14:43:38 -08:00
Alexander Matyushentsev
de8ae9c617 fix: impossible to config RBAC if group name includes ',' (#3013)
* fix:  impossible to config RBAC if group name includes ','

* apply reviewer notes
2020-01-22 11:47:31 -08:00
Alexander Matyushentsev
2d029488ab Update manifests to v1.4.0 2020-01-17 21:32:51 -08:00
Alexander Matyushentsev
3771486c14 feat: upgrade dex to v2.21.0 (#2985) 2020-01-15 14:07:44 -08:00
Alexander Matyushentsev
97922f0439 fix: sync apps panel fails with 'No App Selected' message if name contains '.' (#2983) 2020-01-15 14:07:39 -08:00
Alexander Matyushentsev
141ef96a44 docs: add notifications.md with recommandation about notifications (#2979)
* docs: add demo argocd/grafana links

* docs: add notifications.md with recommandation about notifications
2020-01-15 14:07:34 -08:00
Paul Brit
92824215f8 docs: Fix a broken link to Helm Hooks (#2970) 2020-01-15 14:07:30 -08:00
Alexander Matyushentsev
f74640d95c fix: fix nil pointer dereference in CreateRepositoryCredentials method (#2975) 2020-01-15 14:07:27 -08:00
Alexander Matyushentsev
5c0ebb59d2 fix: remove 'total' suffix from gauge prom metric (#2976) 2020-01-15 14:07:23 -08:00
Alexander Matyushentsev
6d65d01757 fix: fix rendering CRD acronym (#2978) 2020-01-15 14:07:20 -08:00
Alexander Matyushentsev
36bbc29891 docs: v1.3 and v1.4 changelog (#2952) 2020-01-15 14:07:17 -08:00
Alexander Matyushentsev
5af52f6698 Update manifests to v1.4.0-rc1 2020-01-13 09:03:55 -08:00
259 changed files with 2770 additions and 11626 deletions

View File

@@ -25,13 +25,13 @@ commands:
install_golang:
steps:
- run:
name: Install Golang v1.14
name: Install Golang v1.12.6
command: |
go get golang.org/dl/go1.14
[ -e /home/circleci/sdk/go1.14 ] || go1.14 download
go get golang.org/dl/go1.12.6
[ -e /home/circleci/sdk/go1.12.6 ] || go1.12.6 download
go env
echo "export GOPATH=/home/circleci/.go_workspace" | tee -a $BASH_ENV
echo "export PATH=/home/circleci/sdk/go1.14/bin:\$PATH" | tee -a $BASH_ENV
echo "export PATH=/home/circleci/sdk/go1.12.6/bin:\$PATH" | tee -a $BASH_ENV
save_go_cache:
steps:
- save_cache:
@@ -39,7 +39,7 @@ commands:
# https://circleci.com/docs/2.0/language-go/
paths:
- /home/circleci/.cache/go-build
- /home/circleci/sdk/go1.14
- /home/circleci/sdk/go1.12.6
restore_go_cache:
steps:
- restore_cache:
@@ -62,7 +62,7 @@ jobs:
- save_cache:
key: codegen-v1-{{ checksum "Gopkg.lock" }}-{{ checksum "hack/installers/install-codegen-go-tools.sh" }}
paths: [vendor, /tmp/dl, /go/pkg]
- run: helm2 init --client-only
- run: helm init --client-only
- run: make codegen-local
- run:
name: Check nothing has changed
@@ -85,10 +85,10 @@ jobs:
- install_golang
- checkout
- restore_cache:
key: test-dl-v2
- run: sudo ./hack/install.sh kubectl-linux kubectx-linux dep-linux ksonnet-linux helm-linux helm2-linux kustomize-linux
key: test-dl-v1
- run: sudo ./hack/install.sh kubectl-linux kubectx-linux dep-linux ksonnet-linux helm-linux kustomize-linux
- save_cache:
key: test-dl-v2
key: test-dl-v1
paths: [/tmp/dl]
- configure_git
- run: go get github.com/jstemmer/go-junit-report
@@ -128,11 +128,11 @@ jobs:
- install_golang
- checkout
- restore_cache:
keys: [e2e-dl-v2]
- run: sudo ./hack/install.sh kubectx-linux dep-linux ksonnet-linux helm-linux helm2-linux kustomize-linux
keys: [e2e-dl-v1]
- run: sudo ./hack/install.sh kubectx-linux dep-linux ksonnet-linux helm-linux kustomize-linux
- run: go get github.com/jstemmer/go-junit-report
- save_cache:
key: e2e-dl-v2
key: e2e-dl-v10
paths: [/tmp/dl]
- restore_vendor
- run: dep ensure -v

View File

@@ -3,5 +3,5 @@ Checklist:
* [ ] Either (a) I've created an [enhancement proposal](https://github.com/argoproj/argo-cd/issues/new/choose) and discussed it with the community, (b) this is a bug fix, or (c) this does not need to be in the release notes.
* [ ] The title of the PR states what changed and the related issues number (used for the release note).
* [ ] I've updated both the CLI and UI to expose my feature, or I plan to submit a second PR with them.
* [ ] Optional. My organization is added to USERS.md.
* [ ] Optional. My organization is added to the README.
* [ ] I've signed the CLA and my build is green ([troubleshooting builds](https://argoproj.github.io/argo-cd/developer-guide/ci/)).

View File

@@ -16,7 +16,7 @@ jobs:
python-version: 3.x
- name: build
run: |
pip install mkdocs==1.0.4 mkdocs_material==4.1.1
pip install mkdocs mkdocs_material
mkdocs build
mkdir ./site/.circleci && echo '{version: 2, jobs: {build: {branches: {ignore: gh-pages}}}}' > ./site/.circleci/config.yml
- name: deploy

View File

@@ -1,57 +0,0 @@
name: Image
on:
push:
branches:
- master
jobs:
publish:
runs-on: ubuntu-latest
env:
GOPATH: /home/runner/work/argo-cd/argo-cd
steps:
- uses: actions/setup-go@v1
with:
go-version: '1.14'
- uses: actions/checkout@master
with:
path: src/github.com/argoproj/argo-cd
- uses: actions/cache@v1
with:
path: src/github.com/argoproj/argo-cd/vendor
key: ${{ runner.os }}-go-dep-${{ hashFiles('**/Gopkg.lock') }}
# download dependencies
- run: mkdir -p $GITHUB_WORKSPACE/bin && curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
working-directory: src/github.com/argoproj/argo-cd
- run: $GOPATH/bin/dep ensure -v
working-directory: ./src/github.com/argoproj/argo-cd
# get image tag
- run: echo ::set-output name=tag::$(cat ./VERSION)-${GITHUB_SHA::8}
working-directory: ./src/github.com/argoproj/argo-cd
id: image
# build
- run: make image DEV_IMAGE=true DOCKER_PUSH=false IMAGE_NAMESPACE=docker.pkg.github.com/argoproj/argo-cd IMAGE_TAG=${{ steps.image.outputs.tag }}
working-directory: ./src/github.com/argoproj/argo-cd
# publish
- run: |
docker login docker.pkg.github.com --username $USERNAME --password $PASSWORD
docker push docker.pkg.github.com/argoproj/argo-cd/argocd:${{ steps.image.outputs.tag }}
env:
USERNAME: ${{ secrets.USERNAME }}
PASSWORD: ${{ secrets.TOKEN }}
# deploy
- run: git clone "https://$TOKEN@github.com/argoproj/argoproj-deployments"
env:
TOKEN: ${{ secrets.TOKEN }}
- run: |
docker run -v $(pwd):/src -w /src --rm -t lyft/kustomizer:v3.3.0 kustomize edit set image argoproj/argocd=docker.pkg.github.com/argoproj/argo-cd/argocd:${{ steps.image.outputs.tag }}
git config --global user.email 'ci@argoproj.com'
git config --global user.name 'CI'
git diff --exit-code && echo 'Already deployed' || (git commit -am 'Upgrade argocd to ${{ steps.image.outputs.tag }}' && git push)
working-directory: argoproj-deployments/argocd
# TODO: clean up old images once github supports it: https://github.community/t5/How-to-use-Git-and-GitHub/Deleting-images-from-Github-Package-Registry/m-p/41202/thread-id/9811

View File

@@ -1,101 +1,6 @@
# Changelog
## v1.5.0 (Not released)
#### Helm Integration Enhancements - Helm 3 Support And More
Introduced native support Helm3 charts. For backward compatibility Helm 2 charts are still rendered using Helm 2 CLI. Argo CD inspects the
Charts.yaml file and choose the right binary based on `apiVersion` value.
Following enhancement were implemented in addition to Helm 3:
* The `--api-version` flag is passed to the `helm template` command during manifest generation.
* The `--set-file` flag can be specified in the application specification.
* Fixed bug that prevents automatically update Helm chart when new version is published (#3193)
#### Local accounts
The local accounts had been introduced additional to `admin` user and SSO integration. The feature is useful for creating authentication
tokens with limited permissions to automate Argo CD management. Local accounts also could be used small by teams when SSO integration is overkill.
This enhancement also allows to disable admin user and enforce only SSO logins.
#### Enhancements
* feat: support helm3 (#2383) (#3178)
* feat: Argo CD Service Account / Local Users #3185
* feat: Disable Admin Login (fixes #3019) (#3179)
* feat(ui): add docs to sync policy options present in create application panel (Close #3098) (#3203)
* feat: add "service-account" flag to "cluster add" command (#3183) (#3184)
* feat: Supports the validate-false option at an app level. Closes #1063 (#2542)
* feat: add dest cluster and namespace in the Events (#3093)
* feat: Rollback disables auto sync issue #2441 (#2591)
* feat: allow ssh and http repository references in bitbucketserver webhook #2773 (#3036)
* feat: Add helm --set-file support (#2751)
* feat: Include resource group for Event's InvolvedObject.APIVersion
* feat: Add argocd cmd for Windows #2121 (#3015)
#### Bug Fixes
- fix: app reconciliation fails with panic: index out of (#3233)
- fix: upgrade argoproj/pkg version to fix leaked sensitive information in logs (#3230)
- fix: set MaxCallSendMsgSize to MaxGRPCMessageSize for the GRPC caller (#3117)
- fix: stop caching helm index (#3193)
- fix: dex proxy should forward request to dex preserving the basehref (#3165)
- fix: set default login redirect to baseHRef (#3164)
- fix: don't double-prepend basehref to redirect URLs (fixes #3137)
- fix: ui referring to /api/version using absolute path (#3092)
- fix: Unhang UI on long app info items by using more sane URL match pattern (#3159)
- fix: Allow multiple hostnames per SSH known hosts entry and also allow IPv6 (#2814) (#3074)
- fix: argocd-util backup produced truncated backups. import app status (#3096)
- fix: upgrade redis-ha chart and enable haproxy (#3147)
- fix: make dex server deployment init container resilient to restarts (#3136)
- fix: reduct secret values of manifests stored in git (#3088)
- fix: labels not being deleted via UI (#3081)
- fix: HTTP|HTTPS|NO_PROXY env variable reading #3055 (#3063)
- fix: Correct usage text for repo add command regarding insecure repos (#3068)
- fix: Ensure SSH private key is written out with a final newline character (#2890) (#3064)
- fix: Handle SSH URLs in 'git@server:org/repo' notation correctly (#3062)
- fix sso condition when several sso connectors has been configured (#3057)
- fix: Fix bug where the same pointer is used. (#3059)
- fix: Opening in new tab bad key binding on Linux (#3020)
- fix: K8s secrets for repository credential templates are not deleted when credential template is deleted (#3028)
- fix: SSH credential template not working #3016
- fix: Unable to parse kubectl pre-release version strings (#3034)
- fix: Jsonnet TLA parameters of same type are overwritten (#3022)
- fix: Replace aws-iam-authenticator to support IRSA (#3010)
- fix: Hide bindPW in dex config (#3025)
- fix: SSH repo URL with a user different from `git` is not matched correctly when resolving a webhook (#2988)
- fix: JWT invalid => Password for superuser has changed since token issued (#2108)
#### Contributors
* alexandrfox
* alexec
* alexmt
* bergur88
* CBytelabs
* dbeal-wiser
* dnascimento
* Elgarni
* eSamS
* gpaul
* jannfis
* jdmulloy
* machgo
* masa213f
* matthyx
* rayanebel
* shelby-moore
* tomcruise81
* wecger
* zeph
## v1.4.2 (2020-01-24)
- fix: correctly replace cache in namespace isolation mode (#3023)
## v1.4.1 (2020-01-23)
- fix: impossible to config RBAC if group name includes ',' (#3013)
## v1.4.0 (2020-01-17)
## v1.4.0 (Not Released)
The v1.4.0 is a stability release that brings multiple bug fixes, security, performance enhancements, and multiple usability improvements.
@@ -216,55 +121,18 @@ an in-flight state for all Kubernetes resources including `Deployment`, `PVC`, `
#### Contributors
* Aalok Ahluwalia
* Aananth K
* Abhishek Jaisingh
* Adam Johnson
* Alan Tang
* Alex Collins
* Alexander Matyushentsev
* Andrew Waters
* Byungjin Park
* Christine Banek
* Daniel Helfand
* David Hong
* David J. M. Karlsen
* David Maciel
* Devan Goodwin
* Devin Stein
* dthomson25
* Gene Liverman
* Gregor Krmelj
* Guido Maria Serra
* Ilir Bekteshi
* Imran Ismail
* INOUE BANJI
* Isaac Gaskin
* jannfis
* Jeff Hastings
* Jesse Suen
* John Girvan
* Konstantin
* Lev Aminov
* Manatsawin Hanmongkolchai
* Marco Schmid
* Masayuki Ishii
* Michael Bridgen
* Naoki Oketani
* niqdev
* nitinpatil1992
* Olivier Boukili
* Olivier Lemasle
* Omer Kahani
* Paul Brit
* Qingbo Zhou
* Saradhi Sreegiriraju
* Scott Cabrinha
* shlo
* Simon Behar
* stgarf
* Yujun Zhang
* Zoltán Reegn
* [@abhishekjiitr](https://github.com/abhishekjiitr)
* [@adamjohnson01](https://github.com/adamjohnson01)
* [@alexec](https://github.com/alexec)
* [@alexmt](https://github.com/alexmt)
* [@binoue](https://github.com/binoue)
* [@cabrinha](https://github.com/cabrinha)
* [@cbanek](https://github.com/cbanek)
* [@dgoodwin](https://github.com/dgoodwin)
* [@jannfis](https://github.com/jannfis)
* [@jessesuen](https://github.com/jessesuen)
* [@masa213f](https://github.com/masa213f)
* [@whs](https://github.com/whs)
## v1.3.4 (2019-12-05)
- #2819 Fixes logging of tracing option in CLI
@@ -410,10 +278,6 @@ There may be instances when you want to control the times during which an Argo C
- Application controller `kubectl-parallelism-limit` flag is broken (#2673)
- Annoying toolbar flickering (#2691)
## v1.2.5 (2019-10-29)
- Issue #2339 - Don't update `status.reconciledAt` unless compared with latest git version (#2581)
## v1.2.4 (2019-10-23)
- Issue #2185 - Manual sync don't trigger hooks (#2477)

View File

@@ -4,7 +4,7 @@ ARG BASE_IMAGE=debian:10-slim
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
# Also used as the image in CI jobs so needs all dependencies
####################################################################################################
FROM golang:1.14.0 as builder
FROM golang:1.12.6 as builder
RUN echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
@@ -30,9 +30,9 @@ RUN ./install.sh dep-linux
RUN ./install.sh packr-linux
RUN ./install.sh kubectl-linux
RUN ./install.sh ksonnet-linux
RUN ./install.sh helm2-linux
RUN ./install.sh helm-linux
RUN ./install.sh kustomize-linux
RUN ./install.sh aws-iam-authenticator-linux
####################################################################################################
# Argo CD Base - used as the base for both the release and dev argocd images
@@ -50,17 +50,16 @@ RUN groupadd -g 999 argocd && \
chmod g=u /home/argocd && \
chmod g=u /etc/passwd && \
apt-get update && \
apt-get install -y git git-lfs python3-pip && \
apt-get install -y git git-lfs && \
apt-get clean && \
pip3 install awscli==1.17.7 && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY hack/git-ask-pass.sh /usr/local/bin/git-ask-pass.sh
COPY --from=builder /usr/local/bin/ks /usr/local/bin/ks
COPY --from=builder /usr/local/bin/helm2 /usr/local/bin/helm2
COPY --from=builder /usr/local/bin/helm /usr/local/bin/helm
COPY --from=builder /usr/local/bin/kubectl /usr/local/bin/kubectl
COPY --from=builder /usr/local/bin/kustomize /usr/local/bin/kustomize
COPY --from=builder /usr/local/bin/aws-iam-authenticator /usr/local/bin/aws-iam-authenticator
# script to add current (possibly arbitrary) user to /etc/passwd at runtime
# (if it's not already there, to be openshift friendly)
COPY uid_entrypoint.sh /usr/local/bin/uid_entrypoint.sh
@@ -97,7 +96,7 @@ RUN NODE_ENV='production' yarn build
####################################################################################################
# Argo CD Build stage which performs the actual build of Argo CD binaries
####################################################################################################
FROM golang:1.14.0 as argocd-build
FROM golang:1.12.6 as argocd-build
COPY --from=builder /usr/local/bin/dep /usr/local/bin/dep
COPY --from=builder /usr/local/bin/packr /usr/local/bin/packr
@@ -116,8 +115,7 @@ RUN cd ${GOPATH}/src/dummy && \
WORKDIR /go/src/github.com/argoproj/argo-cd
COPY . .
RUN make cli server controller repo-server argocd-util && \
make CLI_NAME=argocd-darwin-amd64 GOOS=darwin cli && \
make CLI_NAME=argocd-windows-amd64.exe GOOS=windows cli
make CLI_NAME=argocd-darwin-amd64 GOOS=darwin cli
####################################################################################################
@@ -126,3 +124,4 @@ RUN make cli server controller repo-server argocd-util && \
FROM argocd-base
COPY --from=argocd-build /go/src/github.com/argoproj/argo-cd/dist/argocd* /usr/local/bin/
COPY --from=argocd-ui ./src/dist/app /shared/app

25
Gopkg.lock generated
View File

@@ -66,19 +66,16 @@
[[projects]]
branch = "master"
digest = "1:fbe4779f247babd0b21e2283d419f848a8dab42c0f6bbdeb88d83f190f52c159"
digest = "1:52905b00a73cda93a2ce8c5fa35185daed673d59e39576e81ad6ab6fb7076b3c"
name = "github.com/argoproj/pkg"
packages = [
"errors",
"exec",
"grpc/http",
"kubeclientmetrics",
"rand",
"stats",
"time",
]
pruneopts = ""
revision = "f46beff7cd548bafc0264b95a4efed645fb1862c"
revision = "02a6aac40ac4cd23de448afe7a1ec0ba4b6d2b96"
[[projects]]
digest = "1:d8a2bb36a048d1571bcc1aee208b61f39dc16c6c53823feffd37449dde162507"
@@ -518,14 +515,6 @@
pruneopts = ""
revision = "c34317bd91bf98fab745d77b03933cf8769299fe"
[[projects]]
digest = "1:ad92aa49f34cbc3546063c7eb2cabb55ee2278b72842eda80e2a20a8a06a8d73"
name = "github.com/google/uuid"
packages = ["."]
pruneopts = ""
revision = "0cd6bf5da1e1c83f8b45653022c74f71af0538a4"
version = "v1.1.1"
[[projects]]
digest = "1:2a131706ff80636629ab6373f2944569b8252ecc018cda8040931b05d32e3c16"
name = "github.com/googleapis/gnostic"
@@ -961,15 +950,15 @@
version = "v0.1"
[[projects]]
digest = "1:cc4eb6813da8d08694e557fcafae8fcc24f47f61a0717f952da130ca9a486dfc"
digest = "1:c587772fb8ad29ad4db67575dad25ba17a51f072ff18a22b4f0257a4d9c24f75"
name = "github.com/stretchr/testify"
packages = [
"assert",
"mock",
]
pruneopts = ""
revision = "3ebf1ddaeb260c4b1ae502a01c7844fa8c1fa0e9"
version = "v1.5.1"
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
version = "v1.2.2"
[[projects]]
digest = "1:51cf0fca93f4866709ceaf01b750e51d997c299a7bd2edf7ccd79e3b428754ae"
@@ -1941,9 +1930,6 @@
"github.com/TomOnTime/utfutil",
"github.com/argoproj/pkg/errors",
"github.com/argoproj/pkg/exec",
"github.com/argoproj/pkg/grpc/http",
"github.com/argoproj/pkg/kubeclientmetrics",
"github.com/argoproj/pkg/stats",
"github.com/argoproj/pkg/time",
"github.com/casbin/casbin",
"github.com/casbin/casbin/model",
@@ -1970,7 +1956,6 @@
"github.com/golang/protobuf/ptypes/empty",
"github.com/google/go-jsonnet",
"github.com/google/shlex",
"github.com/google/uuid",
"github.com/grpc-ecosystem/go-grpc-middleware",
"github.com/grpc-ecosystem/go-grpc-middleware/auth",
"github.com/grpc-ecosystem/go-grpc-middleware/logging",

View File

@@ -86,7 +86,7 @@ required = [
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.5.1"
version = "1.2.2"
[[constraint]]
name = "github.com/gobuffalo/packr"
@@ -115,7 +115,3 @@ required = [
[[override]]
name = "github.com/evanphx/json-patch"
version = "v4.1.0"
[[constraint]]
name = "github.com/google/uuid"
version = "1.1.1"

View File

@@ -9,7 +9,7 @@ GIT_COMMIT=$(shell git rev-parse HEAD)
GIT_TAG=$(shell if [ -z "`git status --porcelain`" ]; then git describe --exact-match --tags HEAD 2>/dev/null; fi)
GIT_TREE_STATE=$(shell if [ -z "`git status --porcelain`" ]; then echo "clean" ; else echo "dirty"; fi)
PACKR_CMD=$(shell if [ "`which packr`" ]; then echo "packr"; else echo "go run vendor/github.com/gobuffalo/packr/packr/main.go"; fi)
VOLUME_MOUNT=$(shell if [[ selinuxenabled -eq 0 ]]; then echo ":Z"; elif [[ $(go env GOOS)=="darwin" ]]; then echo ":delegated"; else echo ""; fi)
VOLUME_MOUNT=$(shell [[ $(go env GOOS)=="darwin" ]] && echo ":delegated" || echo "")
define run-in-dev-tool
docker run --rm -it -u $(shell id -u) -e HOME=/home/user -v ${CURRENT_DIR}:/go/src/github.com/argoproj/argo-cd${VOLUME_MOUNT} -w /go/src/github.com/argoproj/argo-cd argocd-dev-tools bash -c "GOPATH=/go $(1)"
@@ -38,8 +38,6 @@ endif
ifneq (${GIT_TAG},)
IMAGE_TAG=${GIT_TAG}
LDFLAGS += -X ${PACKAGE}.gitTag=${GIT_TAG}
else
IMAGE_TAG?=latest
endif
ifeq (${DOCKER_PUSH},true)
@@ -83,7 +81,6 @@ release-cli: clean-debug image
docker create --name tmp-argocd-linux $(IMAGE_PREFIX)argocd:$(IMAGE_TAG)
docker cp tmp-argocd-linux:/usr/local/bin/argocd ${DIST_DIR}/argocd-linux-amd64
docker cp tmp-argocd-linux:/usr/local/bin/argocd-darwin-amd64 ${DIST_DIR}/argocd-darwin-amd64
docker cp tmp-argocd-linux:/usr/local/bin/argocd-windows-amd64.exe ${DIST_DIR}/argocd-windows-amd64.exe
docker rm tmp-argocd-linux
.PHONY: argocd-util
@@ -137,7 +134,6 @@ image: packr
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 dist/packr build -v -i -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd-util ./cmd/argocd-util
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 dist/packr build -v -i -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd ./cmd/argocd
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 dist/packr build -v -i -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd-darwin-amd64 ./cmd/argocd
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 dist/packr build -v -i -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd-windows-amd64.exe ./cmd/argocd
cp Dockerfile.dev dist
docker build -t $(IMAGE_PREFIX)argocd:$(IMAGE_TAG) -f dist/Dockerfile.dev dist
else
@@ -166,9 +162,7 @@ install-lint-tools:
.PHONY: lint
lint:
golangci-lint --version
# NOTE: If you get a "Killed" OOM message, try reducing the value of GOGC
# See https://github.com/golangci/golangci-lint#memory-usage-of-golangci-lint
GOGC=100 golangci-lint run --fix --verbose
golangci-lint run --fix --verbose
.PHONY: build
build:
@@ -176,12 +170,11 @@ build:
.PHONY: test
test:
./hack/test.sh -coverprofile=coverage.out `go list ./... | grep -v 'test/e2e'`
./hack/test.sh -coverprofile=coverage.out `go list ./... | grep -v 'test/e2e'`
.PHONY: test-e2e
test-e2e:
# NO_PROXY ensures all tests don't go out through a proxy if one is configured on the test system
NO_PROXY=* ./hack/test.sh -timeout 15m -v ./test/e2e
./hack/test.sh -timeout 15m ./test/e2e
.PHONY: start-e2e
start-e2e: cli
@@ -196,7 +189,7 @@ start-e2e: cli
ARGOCD_TLS_DATA_PATH=/tmp/argo-e2e/app/config/tls \
ARGOCD_E2E_DISABLE_AUTH=false \
ARGOCD_ZJWT_FEATURE_FLAG=always \
goreman start ${ARGOCD_START}
goreman start
# Cleans VSCode debug.test files from sub-dirs to prevent them from being included in packr boxes
.PHONY: clean-debug
@@ -215,7 +208,7 @@ start:
kubectl create ns argocd || true
kubens argocd
ARGOCD_ZJWT_FEATURE_FLAG=always \
goreman start ${ARGOCD_START}
goreman start
.PHONY: pre-commit
pre-commit: dep-ensure codegen build lint test
@@ -244,4 +237,4 @@ lint-docs:
.PHONY: publish-docs
publish-docs: lint-docs
mkdocs gh-deploy
mkdocs gh-deploy

4
OWNERS
View File

@@ -3,8 +3,10 @@ owners:
- alexmt
- jessesuen
reviewers:
- jannfis
approvers:
- alexec
- alexmt
- jannfis
- jessesuen

View File

@@ -12,12 +12,62 @@ Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.
## Why Argo CD?
1. Application definitions, configurations, and environments should be declarative and version controlled.
1. Application deployment and lifecycle management should be automated, auditable, and easy to understand.
Application definitions, configurations, and environments should be declarative and version controlled.
Application deployment and lifecycle management should be automated, auditable, and easy to understand.
## Who uses Argo CD?
[Official Argo CD user list](USERS.md)
Organizations below are **officially** using Argo CD. Please send a PR with your organization name if you are using Argo CD.
1. [127Labs](https://127labs.com/)
1. [Adevinta](https://www.adevinta.com/)
1. [ANSTO - Australian Synchrotron](https://www.synchrotron.org.au/)
1. [ARZ Allgemeines Rechenzentrum GmbH ](https://www.arz.at/)
1. [Baloise](https://www.baloise.com)
1. [BioBox Analytics](https://biobox.io)
1. [CARFAX](https://www.carfax.com)
1. [Celonis](https://www.celonis.com/)
1. [Codility](https://www.codility.com/)
1. [Commonbond](https://commonbond.co/)
1. [CyberAgent](https://www.cyberagent.co.jp/en/)
1. [Cybozu](https://cybozu-global.com)
1. [EDF Renewables](https://www.edf-re.com/)
1. [Elium](https://www.elium.com)
1. [END.](https://www.endclothing.com/)
1. [Fave](https://myfave.com)
1. [Future PLC](https://www.futureplc.com/)
1. [GMETRI](https://gmetri.com/)
1. [hipages](https://hipages.com.au/)
1. [Intuit](https://www.intuit.com/)
1. [KintoHub](https://www.kintohub.com/)
1. [KompiTech GmbH](https://www.kompitech.com/)
1. [Lytt](https://www.lytt.co/)
1. [Major League Baseball](https://mlb.com)
1. [Mambu](https://www.mambu.com/)
1. [Max Kelsen](https://www.maxkelsen.com/)
1. [Mirantis](https://mirantis.com/)
1. [OpenSaaS Studio](https://opensaas.studio)
1. [Optoro](https://www.optoro.com/)
1. [Peloton Interactive](https://www.onepeloton.com/)
1. [Pipefy](https://www.pipefy.com/)
1. [Riskified](https://www.riskified.com/)
1. [Red Hat](https://www.redhat.com/)
1. [Saildrone](https://www.saildrone.com/)
1. [Saloodo! GmbH](https://www.saloodo.com)
1. [Syncier](https://syncier.com/)
1. [Tesla](https://tesla.com/)
1. [Tiger Analytics](https://www.tigeranalytics.com/)
1. [tZERO](https://www.tzero.com/)
1. [Ticketmaster](https://ticketmaster.com)
1. [Twilio SendGrid](https://sendgrid.com)
1. [Yieldlab](https://www.yieldlab.de/)
1. [UBIO](https://ub.io/)
1. [Universidad Mesoamericana](https://www.umes.edu.gt/)
1. [Viaduct](https://www.viaduct.ai/)
1. [Volvo Cars](https://www.volvocars.com/)
1. [Walkbase](https://www.walkbase.com/)
## Documentation

View File

@@ -1,58 +0,0 @@
## Who uses Argo CD?
As the Argo Community grows, we'd like to keep track of our users. Please send a PR with your organization name if you are using Argo CD.
Currently, the following organizations are **officially** using Argo CD:
1. [127Labs](https://127labs.com/)
1. [Adevinta](https://www.adevinta.com/)
1. [ANSTO - Australian Synchrotron](https://www.synchrotron.org.au/)
1. [ARZ Allgemeines Rechenzentrum GmbH ](https://www.arz.at/)
1. [Baloise](https://www.baloise.com)
1. [BioBox Analytics](https://biobox.io)
1. [CARFAX](https://www.carfax.com)
1. [Celonis](https://www.celonis.com/)
1. [Codility](https://www.codility.com/)
1. [Commonbond](https://commonbond.co/)
1. [CyberAgent](https://www.cyberagent.co.jp/en/)
1. [Cybozu](https://cybozu-global.com)
1. [EDF Renewables](https://www.edf-re.com/)
1. [Elium](https://www.elium.com)
1. [END.](https://www.endclothing.com/)
1. [Fave](https://myfave.com)
1. [Future PLC](https://www.futureplc.com/)
1. [GMETRI](https://gmetri.com/)
1. [hipages](https://hipages.com.au/)
1. [Intuit](https://www.intuit.com/)
1. [KintoHub](https://www.kintohub.com/)
1. [KompiTech GmbH](https://www.kompitech.com/)
1. [Lytt](https://www.lytt.co/)
1. [Major League Baseball](https://mlb.com)
1. [Mambu](https://www.mambu.com/)
1. [Max Kelsen](https://www.maxkelsen.com/)
1. [Mirantis](https://mirantis.com/)
1. [MOO Print](https://www.moo.com/)
1. [OpenSaaS Studio](https://opensaas.studio)
1. [Optoro](https://www.optoro.com/)
1. [Peloton Interactive](https://www.onepeloton.com/)
1. [Pipefy](https://www.pipefy.com/)
1. [Prudential](https://prudential.com.sg)
1. [Red Hat](https://www.redhat.com/)
1. [Robotinfra](https://www.robotinfra.com)
1. [Riskified](https://www.riskified.com/)
1. [Saildrone](https://www.saildrone.com/)
1. [Saloodo! GmbH](https://www.saloodo.com)
1. [Syncier](https://syncier.com/)
1. [Tesla](https://tesla.com/)
1. [ThousandEyes](https://www.thousandeyes.com/)
1. [Ticketmaster](https://ticketmaster.com)
1. [Tiger Analytics](https://www.tigeranalytics.com/)
1. [Twilio SendGrid](https://sendgrid.com)
1. [tZERO](https://www.tzero.com/)
1. [UBIO](https://ub.io/)
1. [Universidad Mesoamericana](https://www.umes.edu.gt/)
1. [Viaduct](https://www.viaduct.ai/)
1. [Volvo Cars](https://www.volvocars.com/)
1. [Walkbase](https://www.walkbase.com/)
1. [Whitehat Berlin](https://whitehat.berlin) by Guido Maria Serra +Fenaroli
1. [Yieldlab](https://www.yieldlab.de/)

View File

@@ -1 +1 @@
1.5.2
1.4.3

View File

@@ -1,24 +1,22 @@
<svg width="131" height="20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<filter id="dropShadow">
<feDropShadow dx="0.2" dy="0.4" stdDeviation="0.2" flood-color="#333" flood-opacity="0.5"/>
</filter>
</defs>
<clipPath id="roundedCorners">
<rect width="100%" height="100%" rx="3" opacity="1" />
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="131" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="a">
<rect width="131" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#roundedCorners)">
<rect id="leftRect" fill="#555" x="0" y="0" width="74" height="20" />
<rect id="rightRect" fill="#4c1" x="74" y="0" width="57" height="20" />
<rect id="revisionRect" fill="#4c1" x="131" y="0" width="62" height="20" display="none"/>
<g clip-path="url(#a)">
<path id="leftPath" fill="#555" d="M0 0h74v20H0z"/>
<path id="rightPath" fill="#4c1" d="M74 0h57v20H74z"/>
<path fill="url(#b)" d="M0 0h131v20H0z"/>
</g>
<g fill="#fff" style="filter: url(#dropShadow);" text-anchor="middle" font-family="DejaVu Sans, sans-serif" font-size="90">
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="90">
<image x="5" y="3" width="14" height="14" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAeCAYAAADU8sWcAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAABPAAAATwFjiv3XAAACC2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjE8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlBob3RvbWV0cmljSW50ZXJwcmV0YXRpb24+MjwvdGlmZjpQaG90b21ldHJpY0ludGVycHJldGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KD0UqkwAACpZJREFUSA11VnmQFcUZ//qY4527by92WWTXwHKqEJDDg0MQUioKSWopK4oaS9RAlMofUSPGbFlBSaViKomgQSNmIdECkUS8ophdozEJArKoKCsgIFlY2Pu9N29mero7X78FxCR2Vb8309PTv+/4fb9vCHz1II2Nm+jmzYul2bJsdlMyO7LyPGlZtYqQck1ZHCgwLZWiROeJgB7bDzpYb/7o0y/emzXv4Pts8+ZGBUC0uf/vQf57wdw3NTVRnOYFfXvj6pJcadkUmbDGRoxVSEItSYAQQrUmRBP81VoRpkFTJUMuZA/3g/28q3dn89b7u885D4348vgf8NPAxY033LJmSlDizlSOU94f6UhoHaZdC/3QCHWON2gDYBhAYyRAWgyD4QSi1815f29++vv/+CoD2Lm2nAFGl8mndzyxMMgk5/iW6xzPi/xVk+oyE8+vLNt14FR/0uYW14ox0IwUJ4ZAaUpAaaBEYByiyLbikWWNnnThvPIxu+L717auVeb81tbWsyk4C34u8I3LnlhcSCameMzykg7TwzOJGIYWQj+M+voLYcSo/hxY1E65FECUq4G4RFP0nSjMCMVAIIKUnOHkw90L6qq/vXvbh02trV8yoBh2E0NMY9GiG+58fIGXTF6epyw7JOnamZQbz/tCnDrVVzgqqdwTT0ZTdWDN0wPpMh3ZPZqHLSw98C7Y4RwtnAodsTwGAg0ppkcxrlkYJFID+Z0bn/zelsFImzQRXfScNJFiOG689dcT/FT6GzlqedVJTHRpPH6yz/PyfTlx2IrLCpvSdWrv5OXkX9fOJB/Mnaz3XzItap+yMDoyZgEE7F1SceIghryeRNwnTBkEqhRIxiLF6bCpDXNybW2v/ruxcTzbt2+zZmfCvWT+zxNhbek3cxaPlyYsXVWSSHT25rxC3o+OWK6aDn7sZ3r79ZNY28w45Esxuhw5RjmVvEQPlIwgR8bOiE7VdrPaA2+TeGEEhFbhtAEmG5pzk5WqqbWTPv7jC8sLpgxNSRWZrUeWTAgor7EY9ytTiURvzg8GskGU5xxKkc33yDcX1yc7x3ijLxF+zZgoEljgCrSiXOWIG/WGrjifHxl1V9iyeKwW1lHNo5SKmDmcYinivwhjVpkor55sQj9+/D4MO9bpLW8RN6zJzMvbPDUkHaecE368N1+IUUJfIm5hPf1w2kTedlm/LgntmqEWEQGT3ScJYUh2NIxiiWupSUFasor1VgzXvPATfv6BC3Roq0E9MLqAXKQcAe1rqi/dv+q3DwQUw6djY6tiAaG1jLEw7nAn64WhcStPqZqpA6chap8aage077GwbQcJDx8Awq3T3DHlbeijUHWwytHFuuizCTergdQ+YocxLRHVPNcESRAJxqo60nbSvExvvvWx23MCVvucDyRt5hitwDRHHG09pZiaT7MlSUdUhtQGZttYRdwA4WnFQjFnDA4LX7UdIlgMYpaouBgGMnuBKVN/ZhgBRCMVynNAHOfRm777q4UcrW3EZxcEnD/kclYlpVaFKFIZrIRtluvdls/G9InnLZ9fpLXoJjwZAzZkDJ5mjkIj8HTCKETH9oD0eoikMSDQ5cTrLrUg4QoaFlxUH5MdYy6yAFAaYBHed6ODkMPOkMcFZggZKa0SkaL/jMeDpq5D1Vez9693V/wNUg1jQRY8yLX8BcSba8AaOgyBOdqtQBz7DNj8lZCeNY9SN6aiD3bTOc89s2iliDVvKa3uGxf6doQAxYE2oBbm0HQPG5IxqKhOg9ZpSSQj+pDU+jv5t7913spV5c70GcqLJwgMGw6ZJUuBLbgHPW0D4rgQdewDvnAllN58B0D918AvzVBn3jWi/p4Hq2/s+et1URgBRlVRMGVvBtITfwyuyYPAoIRmWSIrEqjZW1Ml/qN7dtRWzptfBzXDoaeri6TicWhes8Zsg9iMOaAyU0D3fw4qdSEkrryquP77xx+HZCwG3T09HEZfCBUXTxh125H9VZ9SHp1OfZF4aEWI9MM1AhmiVCmaIwV6a2F5ge2q8s7OBB8ytPiOZduw6pFHYOS4cUUQGsNWXj4MVLYdaGU9UAQ0o2H8eHh49WpAITReKqdmGC0PsvF2JB4Gu+i5RqKg5JSi82mOnu9GYGEhwbFjSOXadJII7Pa6Ed3hwU8igAU8lU7D/ffdZ1pFEUT19YI+sR9oZgLIjo8h6usDu2oIzJpxOc4ZphKQtoqFxw6LzxIV/RMxkabSUPAJRz3A5oc50x9T7Lf3xkR0R0xGSS+IRIFQOUUUkqvGXdR5tGXnLmjbYXI0OLCJykIBvFe2ABVHgCQqgMpjkH9xE9IY7cSgGd0w+8mOVjiy68DOh+sauusiwSM8F11nlhCm39/SvP7ux4qNZVfba/0TJ183Is9opWtxEXe5E/cC+Y5bf+CilmczqaC/JigEOjjYTrwtzwB8tAn4kJFGMIEmy0B98gb4B7tAYimHncd19ObLrP25rW0/rb76pQqsoKTEkKJgoT64biCObVx35xvGGz67qYW3Nl0RWYH/ftxmo7pyfpSoKFFjEiLxhE73jXaueHXlGw+PZ68rS8pQ01QlodUjTqcAfcQo8qGjQB36EwQfbFAuF8wjZbmNtStefZ4nC0uibKIHez92AeZEUln5wocGuLGxyUbg2cVEFp5a9pFz11MH/ZCP6M0V8gmbxWZL35K2paFmUmjDgCXAMQkjqv8wgFMGBFVSCw8g1wWsrB5IBrTDAvB0eaAkhVHCeGzSQDUm3bE9/1hs/d7dBhy5aSqAaNNWN6Mvdn9+e0KGfl8hZCd6vBwqABmISKSkCgkqr/a6QMWrwLpsKaYWhfrwi1ikfWBNvQmUhXItAlznICMlcopFFNXcEA25wBw/EIms2L4O1onZs5u46abFUsILDWhAc/OKo7H+/OtuEFqaUcsmIE8CR47zEMsSuJvRQcceODVmOqR/uAHKftAC6R+9AKcmzgVxci9qexwLTIDZ34+MR6FVErXECXw7kc+3/G7j8gPG0dbWJmQnum1+zDj3U2rJ0rWzvFRynu/YskMTb5vetmwI7xyeg7R0g072ynEGwa0PwZTRDbDn0GGI1j0Ii2pCKPCyqJTl+eei9tOl5Kr1eU2seuG5ZMBv2fjUIMkQymAWC6jouQE3jdlYZa43PLnsLbcn++eYVwi6FCQktTCEmO3QAx2rhOllAl6bOwsahg2FDTMvhRklWVSUMkxcWEyHJFbUqyCW9AtRSV//K18AF4XmbOWeBTegCF78ujTXf3hm+XvTeo49G8/67Sg+A0a0OGc6CDzIlFbDL3+8GPYuuxLWP7AYysprIQx9YNjdzAglyVkD3qGvd3dsWvv0infM2qBj53zr49rZsJsNZwa2WeTTFxtP3L1oe1VCzh3AWqOM2FJJsFBwbMuCUAgQyAqGrVVJ7Zdwyz2RZS/X/GbrguJ5eNYgyhfnncH5v+DmYcft18Y1T5S7fl9jPMN+4aM6IpeQPmgxThNA5AnuJFhIeI2tHafiNqEUW1XQL+8NrfRznENP1drNuTOA5/5/KezmAZ4zaJBSdVaUvQk5PsNTeqfrMsKQOui5LGKibBAjmKgSRk/RIMlc8BiWCLbI95Dx05jybrMkfsh+xfgPf+hH0AC4OlsAAAAASUVORK5CYII="/>
<text id="leftText" x="435" y="140" transform="scale(.1)" textLength="470"></text>
<text id="rightText" x="995" y="140" transform="scale(.1)" textLength="470"></text>
<text id="revisionText" x="1550" y="140" font-family="monospace" transform="scale(.1)" font-size="110" display="none"></text>
</g>
<text id="leftText1" x="435" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470"></text>
<text id="leftText2" x="435" y="140" transform="scale(.1)" textLength="470"></text>
<text id="rightText1" x="995" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="470"></text>
<text id="rightText1" x="995" y="140" transform="scale(.1)" textLength="470"></text></g>
</svg>

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -11,7 +11,6 @@ p, role:readonly, certificates, get, *, allow
p, role:readonly, clusters, get, *, allow
p, role:readonly, repositories, get, *, allow
p, role:readonly, projects, get, *, allow
p, role:readonly, accounts, get, *, allow
p, role:admin, applications, create, */*, allow
p, role:admin, applications, update, */*, allow
@@ -31,7 +30,6 @@ p, role:admin, repositories, delete, *, allow
p, role:admin, projects, create, *, allow
p, role:admin, projects, update, *, allow
p, role:admin, projects, delete, *, allow
p, role:admin, accounts, update, *, allow
g, role:admin, role:readonly
g, admin, role:admin
1 # Built-in policy which defines two roles: role:readonly and role:admin,
11 p, role:readonly, repositories, get, *, allow
12 p, role:readonly, projects, get, *, allow
13 p, role:readonly, accounts, get, *, allow p, role:admin, applications, create, */*, allow
p, role:admin, applications, create, */*, allow
14 p, role:admin, applications, update, */*, allow
15 p, role:admin, applications, delete, */*, allow
16 p, role:admin, applications, sync, */*, allow
30 p, role:admin, projects, delete, *, allow
31 p, role:admin, accounts, update, *, allow g, role:admin, role:readonly
32 g, role:admin, role:readonly g, admin, role:admin
g, admin, role:admin
33
34
35

View File

@@ -16,22 +16,6 @@
"version": "version not set"
},
"paths": {
"/api/v1/account": {
"get": {
"tags": [
"AccountService"
],
"operationId": "ListAccounts",
"responses": {
"200": {
"description": "(empty)",
"schema": {
"$ref": "#/definitions/accountAccountsList"
}
}
}
}
},
"/api/v1/account/can-i/{resource}/{action}/{subresource}": {
"get": {
"tags": [
@@ -95,99 +79,13 @@
}
}
},
"/api/v1/account/{name}": {
"get": {
"tags": [
"AccountService"
],
"operationId": "GetAccount",
"parameters": [
{
"type": "string",
"name": "name",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "(empty)",
"schema": {
"$ref": "#/definitions/accountAccount"
}
}
}
}
},
"/api/v1/account/{name}/token": {
"post": {
"tags": [
"AccountService"
],
"operationId": "CreateTokenMixin9",
"parameters": [
{
"type": "string",
"name": "name",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/accountCreateTokenRequest"
}
}
],
"responses": {
"200": {
"description": "(empty)",
"schema": {
"$ref": "#/definitions/accountCreateTokenResponse"
}
}
}
}
},
"/api/v1/account/{name}/token/{id}": {
"delete": {
"tags": [
"AccountService"
],
"operationId": "DeleteTokenMixin9",
"parameters": [
{
"type": "string",
"name": "name",
"in": "path",
"required": true
},
{
"type": "string",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "(empty)",
"schema": {
"$ref": "#/definitions/accountEmptyResponse"
}
}
}
}
},
"/api/v1/applications": {
"get": {
"tags": [
"ApplicationService"
],
"summary": "List returns list of applications",
"operationId": "List",
"operationId": "ListMixin8",
"parameters": [
{
"type": "string",
@@ -237,7 +135,7 @@
"ApplicationService"
],
"summary": "Create creates an application",
"operationId": "Create",
"operationId": "CreateMixin8",
"parameters": [
{
"name": "body",
@@ -264,7 +162,7 @@
"ApplicationService"
],
"summary": "Update updates an application",
"operationId": "Update",
"operationId": "UpdateMixin8",
"parameters": [
{
"type": "string",
@@ -395,7 +293,7 @@
"ApplicationService"
],
"summary": "Get returns an application by name",
"operationId": "Get",
"operationId": "GetMixin8",
"parameters": [
{
"type": "string",
@@ -445,7 +343,7 @@
"ApplicationService"
],
"summary": "Delete deletes an application",
"operationId": "Delete",
"operationId": "DeleteMixin8",
"parameters": [
{
"type": "string",
@@ -1084,7 +982,7 @@
"ClusterService"
],
"summary": "List returns list of clusters",
"operationId": "ListMixin4",
"operationId": "List",
"parameters": [
{
"type": "string",
@@ -1106,7 +1004,7 @@
"ClusterService"
],
"summary": "Create creates a cluster",
"operationId": "CreateMixin4",
"operationId": "Create",
"parameters": [
{
"name": "body",
@@ -1133,7 +1031,7 @@
"ClusterService"
],
"summary": "Update updates a cluster",
"operationId": "UpdateMixin4",
"operationId": "Update",
"parameters": [
{
"type": "string",
@@ -1166,7 +1064,7 @@
"ClusterService"
],
"summary": "Get returns a cluster by server address",
"operationId": "GetMixin4",
"operationId": "GetMixin2",
"parameters": [
{
"type": "string",
@@ -1189,7 +1087,7 @@
"ClusterService"
],
"summary": "Delete deletes a cluster",
"operationId": "DeleteMixin4",
"operationId": "Delete",
"parameters": [
{
"type": "string",
@@ -1239,7 +1137,7 @@
"ProjectService"
],
"summary": "List returns list of projects",
"operationId": "ListMixin5",
"operationId": "ListMixin6",
"parameters": [
{
"type": "string",
@@ -1261,7 +1159,7 @@
"ProjectService"
],
"summary": "Create a new project.",
"operationId": "CreateMixin5",
"operationId": "CreateMixin6",
"parameters": [
{
"name": "body",
@@ -1288,7 +1186,7 @@
"ProjectService"
],
"summary": "Get returns a project by name",
"operationId": "GetMixin5",
"operationId": "GetMixin6",
"parameters": [
{
"type": "string",
@@ -1311,7 +1209,7 @@
"ProjectService"
],
"summary": "Delete deletes a project",
"operationId": "DeleteMixin5",
"operationId": "DeleteMixin6",
"parameters": [
{
"type": "string",
@@ -1386,7 +1284,7 @@
"ProjectService"
],
"summary": "Update updates a project",
"operationId": "UpdateMixin5",
"operationId": "UpdateMixin6",
"parameters": [
{
"type": "string",
@@ -1905,7 +1803,7 @@
"SettingsService"
],
"summary": "Get returns Argo CD settings",
"operationId": "GetMixin7",
"operationId": "Get",
"responses": {
"200": {
"description": "(empty)",
@@ -1987,41 +1885,6 @@
}
},
"definitions": {
"accountAccount": {
"type": "object",
"properties": {
"capabilities": {
"type": "array",
"items": {
"type": "string"
}
},
"enabled": {
"type": "boolean",
"format": "boolean"
},
"name": {
"type": "string"
},
"tokens": {
"type": "array",
"items": {
"$ref": "#/definitions/accountToken"
}
}
}
},
"accountAccountsList": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/accountAccount"
}
}
}
},
"accountCanIResponse": {
"type": "object",
"properties": {
@@ -2030,55 +1893,12 @@
}
}
},
"accountCreateTokenRequest": {
"type": "object",
"properties": {
"expiresIn": {
"type": "string",
"format": "int64",
"title": "expiresIn represents a duration in seconds"
},
"name": {
"type": "string"
}
}
},
"accountCreateTokenResponse": {
"type": "object",
"properties": {
"token": {
"type": "string"
}
}
},
"accountEmptyResponse": {
"type": "object"
},
"accountToken": {
"type": "object",
"properties": {
"expiresAt": {
"type": "string",
"format": "int64"
},
"id": {
"type": "string"
},
"issuedAt": {
"type": "string",
"format": "int64"
}
}
},
"accountUpdatePasswordRequest": {
"type": "object",
"properties": {
"currentPassword": {
"type": "string"
},
"name": {
"type": "string"
},
"newPassword": {
"type": "string"
}
@@ -2372,10 +2192,6 @@
},
"url": {
"type": "string"
},
"userLoginsDisabled": {
"type": "boolean",
"format": "boolean"
}
}
},
@@ -2485,13 +2301,6 @@
"type": "object",
"title": "HelmAppSpec contains helm app name in source repo",
"properties": {
"fileParameters": {
"type": "array",
"title": "helm file parameters",
"items": {
"$ref": "#/definitions/v1alpha1HelmFileParameter"
}
},
"name": {
"type": "string"
},
@@ -3309,13 +3118,6 @@
"type": "object",
"title": "ApplicationSourceHelm holds helm specific options",
"properties": {
"fileParameters": {
"type": "array",
"title": "FileParameters are file parameters to the helm template",
"items": {
"$ref": "#/definitions/v1alpha1HelmFileParameter"
}
},
"parameters": {
"type": "array",
"title": "Parameters are parameters to the helm template",
@@ -3674,20 +3476,6 @@
}
}
},
"v1alpha1HelmFileParameter": {
"type": "object",
"title": "HelmFileParameter is a file parameter to a helm template",
"properties": {
"name": {
"type": "string",
"title": "Name is the name of the helm parameter"
},
"path": {
"type": "string",
"title": "Path is the path value for the helm parameter"
}
}
},
"v1alpha1HelmParameter": {
"type": "object",
"title": "HelmParameter is a parameter to a helm template",
@@ -3791,29 +3579,11 @@
"description": "Operation contains requested operation parameters.",
"type": "object",
"properties": {
"initiatedBy": {
"$ref": "#/definitions/v1alpha1OperationInitiator"
},
"sync": {
"$ref": "#/definitions/v1alpha1SyncOperation"
}
}
},
"v1alpha1OperationInitiator": {
"type": "object",
"title": "OperationInitiator holds information about the operation initiator",
"properties": {
"automated": {
"description": "Automated is set to true if operation was initiated automatically by the application controller.",
"type": "boolean",
"format": "boolean"
},
"username": {
"description": "Name of a user who started operation.",
"type": "string"
}
}
},
"v1alpha1OperationState": {
"description": "OperationState contains information about state of currently performing operation on application.",
"type": "object",
@@ -4417,13 +4187,6 @@
"source": {
"$ref": "#/definitions/v1alpha1ApplicationSource"
},
"syncOptions": {
"type": "array",
"title": "SyncOptions provide per-sync sync-options, e.g. Validate=false",
"items": {
"type": "string"
}
},
"syncStrategy": {
"$ref": "#/definitions/v1alpha1SyncStrategy"
}
@@ -4470,13 +4233,6 @@
"properties": {
"automated": {
"$ref": "#/definitions/v1alpha1SyncPolicyAutomated"
},
"syncOptions": {
"type": "array",
"title": "Options allow youe to specify whole app sync-options",
"items": {
"type": "string"
}
}
}
},

View File

@@ -6,7 +6,6 @@ import (
"os"
"time"
"github.com/argoproj/pkg/stats"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"k8s.io/client-go/kubernetes"
@@ -20,13 +19,13 @@ import (
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/controller"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/reposerver/apiclient"
appstatecache "github.com/argoproj/argo-cd/util/cache/appstate"
"github.com/argoproj/argo-cd/util/cli"
"github.com/argoproj/argo-cd/util/kube"
"github.com/argoproj/argo-cd/util/settings"
"github.com/argoproj/argo-cd/util/stats"
)
const (
@@ -60,7 +59,8 @@ func newCommand() *cobra.Command {
config, err := clientConfig.ClientConfig()
errors.CheckError(err)
errors.CheckError(v1alpha1.SetK8SConfigDefaults(config))
config.QPS = common.K8sClientConfigQPS
config.Burst = common.K8sClientConfigBurst
kubeClient := kubernetes.NewForConfigOrDie(config)
appClient := appclientset.NewForConfigOrDie(config)
@@ -92,8 +92,7 @@ func newCommand() *cobra.Command {
kubectlParallelismLimit)
errors.CheckError(err)
vers := common.GetVersion()
log.Infof("Application Controller (version: %s, built: %s) starting (namespace: %s)", vers.Version, vers.BuildDate, namespace)
log.Infof("Application Controller (version: %s) starting (namespace: %s)", common.GetVersion(), namespace)
stats.RegisterStackDumper()
stats.StartStatsTicker(10 * time.Minute)
stats.RegisterHeapDumper("memprofile")

View File

@@ -7,7 +7,6 @@ import (
"os"
"time"
"github.com/argoproj/pkg/stats"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -17,6 +16,7 @@ import (
reposervercache "github.com/argoproj/argo-cd/reposerver/cache"
"github.com/argoproj/argo-cd/reposerver/metrics"
"github.com/argoproj/argo-cd/util/cli"
"github.com/argoproj/argo-cd/util/stats"
"github.com/argoproj/argo-cd/util/tls"
)

View File

@@ -4,19 +4,18 @@ import (
"context"
"time"
"github.com/argoproj/pkg/stats"
"github.com/spf13/cobra"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/reposerver/apiclient"
"github.com/argoproj/argo-cd/server"
servercache "github.com/argoproj/argo-cd/server/cache"
"github.com/argoproj/argo-cd/util/cli"
"github.com/argoproj/argo-cd/util/stats"
"github.com/argoproj/argo-cd/util/tls"
)
@@ -49,7 +48,8 @@ func NewCommand() *cobra.Command {
config, err := clientConfig.ClientConfig()
errors.CheckError(err)
errors.CheckError(v1alpha1.SetK8SConfigDefaults(config))
config.QPS = common.K8sClientConfigQPS
config.Burst = common.K8sClientConfigBurst
namespace, _, err := clientConfig.Namespace()
errors.CheckError(err)

View File

@@ -26,6 +26,7 @@ import (
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/cli"
"github.com/argoproj/argo-cd/util/db"
"github.com/argoproj/argo-cd/util/dex"
@@ -108,7 +109,7 @@ func NewRunDexCommand() *cobra.Command {
} else {
err = ioutil.WriteFile("/tmp/dex.yaml", dexCfgBytes, 0644)
errors.CheckError(err)
log.Debug(redactor(string(dexCfgBytes)))
log.Info(redactor(string(dexCfgBytes)))
cmd = exec.Command("dex", "serve", "/tmp/dex.yaml")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
@@ -384,14 +385,8 @@ func NewExportCommand() *cobra.Command {
} else {
f, err := os.Create(out)
errors.CheckError(err)
bw := bufio.NewWriter(f)
writer = bw
defer func() {
err = bw.Flush()
errors.CheckError(err)
err = f.Close()
errors.CheckError(err)
}()
defer util.Close(f)
writer = bufio.NewWriter(f)
}
acdClients := newArgoCDClientsets(config, namespace)
@@ -545,21 +540,10 @@ func specsEqual(left, right unstructured.Unstructured) bool {
leftData, _, _ := unstructured.NestedMap(left.Object, "data")
rightData, _, _ := unstructured.NestedMap(right.Object, "data")
return reflect.DeepEqual(leftData, rightData)
case "AppProject":
case "AppProject", "Application":
leftSpec, _, _ := unstructured.NestedMap(left.Object, "spec")
rightSpec, _, _ := unstructured.NestedMap(right.Object, "spec")
return reflect.DeepEqual(leftSpec, rightSpec)
case "Application":
leftSpec, _, _ := unstructured.NestedMap(left.Object, "spec")
rightSpec, _, _ := unstructured.NestedMap(right.Object, "spec")
leftStatus, _, _ := unstructured.NestedMap(left.Object, "status")
rightStatus, _, _ := unstructured.NestedMap(right.Object, "status")
// reconciledAt and observedAt are constantly changing and we ignore any diff there
delete(leftStatus, "reconciledAt")
delete(rightStatus, "reconciledAt")
delete(leftStatus, "observedAt")
delete(rightStatus, "observedAt")
return reflect.DeepEqual(leftSpec, rightSpec) && reflect.DeepEqual(leftStatus, rightStatus)
}
return false
}
@@ -574,13 +558,8 @@ func updateLive(bak, live *unstructured.Unstructured) *unstructured.Unstructured
switch live.GetKind() {
case "Secret", "ConfigMap":
newLive.Object["data"] = bak.Object["data"]
case "AppProject":
case "AppProject", "Application":
newLive.Object["spec"] = bak.Object["spec"]
case "Application":
newLive.Object["spec"] = bak.Object["spec"]
if _, ok := bak.Object["status"]; ok {
newLive.Object["status"] = bak.Object["status"]
}
}
return newLive
}
@@ -661,7 +640,7 @@ func redactor(dirtyString string) string {
err := yaml.Unmarshal([]byte(dirtyString), &config)
errors.CheckError(err)
iterateStringFields(config, func(name string, val string) string {
if name == "clientSecret" || name == "secret" || name == "bindPW" {
if name == "clientSecret" || name == "secret" {
return "********"
} else {
return val

View File

@@ -18,13 +18,6 @@ connectors:
id: github
name: GitHub
type: github
- config:
bindDN: uid=serviceaccount,cn=users,dc=example,dc=com
bindPW: theSecret
host: ldap.example.com:636
id: ldap
name: LDAP
type: ldap
grpc:
addr: 0.0.0.0:5557
issuer: https://argocd.example.com/api/dex
@@ -56,13 +49,6 @@ var expectedRedaction = `connectors:
id: github
name: GitHub
type: github
- config:
bindDN: uid=serviceaccount,cn=users,dc=example,dc=com
bindPW: '********'
host: ldap.example.com:636
id: ldap
name: LDAP
type: ldap
grpc:
addr: 0.0.0.0:5557
issuer: https://argocd.example.com/api/dex

View File

@@ -5,12 +5,9 @@ import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"text/tabwriter"
"time"
"syscall"
timeutil "github.com/argoproj/pkg/time"
"github.com/ghodss/yaml"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -24,7 +21,6 @@ import (
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/cli"
"github.com/argoproj/argo-cd/util/localconfig"
sessionutil "github.com/argoproj/argo-cd/util/session"
)
func NewAccountCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
@@ -39,16 +35,11 @@ func NewAccountCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
command.AddCommand(NewAccountUpdatePasswordCommand(clientOpts))
command.AddCommand(NewAccountGetUserInfoCommand(clientOpts))
command.AddCommand(NewAccountCanICommand(clientOpts))
command.AddCommand(NewAccountListCommand(clientOpts))
command.AddCommand(NewAccountGenerateTokenCommand(clientOpts))
command.AddCommand(NewAccountGetCommand(clientOpts))
command.AddCommand(NewAccountDeleteTokenCommand(clientOpts))
return command
}
func NewAccountUpdatePasswordCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
account string
currentPassword string
newPassword string
)
@@ -60,20 +51,14 @@ func NewAccountUpdatePasswordCommand(clientOpts *argocdclient.ClientOptions) *co
c.HelpFunc()(c, args)
os.Exit(1)
}
acdClient := argocdclient.NewClientOrDie(clientOpts)
conn, usrIf := acdClient.NewAccountClientOrDie()
defer util.Close(conn)
userInfo := getCurrentAccount(acdClient)
if userInfo.Iss == sessionutil.SessionManagerClaimsIssuer && currentPassword == "" {
if currentPassword == "" {
fmt.Print("*** Enter current password: ")
password, err := terminal.ReadPassword(int(os.Stdin.Fd()))
password, err := terminal.ReadPassword(syscall.Stdin)
errors.CheckError(err)
currentPassword = string(password)
fmt.Print("\n")
}
if newPassword == "" {
var err error
newPassword, err = cli.ReadAndConfirmPassword()
@@ -83,37 +68,37 @@ func NewAccountUpdatePasswordCommand(clientOpts *argocdclient.ClientOptions) *co
updatePasswordRequest := accountpkg.UpdatePasswordRequest{
NewPassword: newPassword,
CurrentPassword: currentPassword,
Name: account,
}
acdClient := argocdclient.NewClientOrDie(clientOpts)
conn, usrIf := acdClient.NewAccountClientOrDie()
defer util.Close(conn)
ctx := context.Background()
_, err := usrIf.UpdatePassword(ctx, &updatePasswordRequest)
errors.CheckError(err)
fmt.Printf("Password updated\n")
if account == "" || account == userInfo.Username {
// Get a new JWT token after updating the password
localCfg, err := localconfig.ReadLocalConfig(clientOpts.ConfigPath)
errors.CheckError(err)
configCtx, err := localCfg.ResolveContext(clientOpts.Context)
errors.CheckError(err)
claims, err := configCtx.User.Claims()
errors.CheckError(err)
tokenString := passwordLogin(acdClient, claims.Subject, newPassword)
localCfg.UpsertUser(localconfig.User{
Name: localCfg.CurrentContext,
AuthToken: tokenString,
})
err = localconfig.WriteLocalConfig(*localCfg, clientOpts.ConfigPath)
errors.CheckError(err)
fmt.Printf("Context '%s' updated\n", localCfg.CurrentContext)
}
// Get a new JWT token after updating the password
localCfg, err := localconfig.ReadLocalConfig(clientOpts.ConfigPath)
errors.CheckError(err)
configCtx, err := localCfg.ResolveContext(clientOpts.Context)
errors.CheckError(err)
claims, err := configCtx.User.Claims()
errors.CheckError(err)
tokenString := passwordLogin(acdClient, claims.Subject, newPassword)
localCfg.UpsertUser(localconfig.User{
Name: localCfg.CurrentContext,
AuthToken: tokenString,
})
err = localconfig.WriteLocalConfig(*localCfg, clientOpts.ConfigPath)
errors.CheckError(err)
fmt.Printf("Context '%s' updated\n", localCfg.CurrentContext)
},
}
command.Flags().StringVar(&currentPassword, "current-password", "", "current password you wish to change")
command.Flags().StringVar(&newPassword, "new-password", "", "new password you want to update to")
command.Flags().StringVar(&account, "account", "", "an account name that should be updated. Defaults to current user account")
return command
}
@@ -174,7 +159,7 @@ argocd account can-i sync applications '*'
argocd account can-i update projects 'default'
# Can I create a cluster?
argocd account can-i create clusters '*'
argocd account can-i create cluster '*'
Actions: %v
Resources: %v
@@ -199,199 +184,3 @@ Resources: %v
},
}
}
func printAccountNames(accounts []*accountpkg.Account) {
for _, p := range accounts {
fmt.Println(p.Name)
}
}
func printAccountsTable(items []*accountpkg.Account) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintf(w, "NAME\tENABLED\tCAPABILITIES\n")
for _, a := range items {
fmt.Fprintf(w, "%s\t%v\t%s\n", a.Name, a.Enabled, strings.Join(a.Capabilities, ", "))
}
_ = w.Flush()
}
func NewAccountListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
output string
)
cmd := &cobra.Command{
Use: "list",
Short: "List accounts",
Example: "argocd account list",
Run: func(c *cobra.Command, args []string) {
conn, client := argocdclient.NewClientOrDie(clientOpts).NewAccountClientOrDie()
defer util.Close(conn)
ctx := context.Background()
response, err := client.ListAccounts(ctx, &accountpkg.ListAccountRequest{})
errors.CheckError(err)
switch output {
case "yaml", "json":
err := PrintResourceList(response.Items, output, false)
errors.CheckError(err)
case "name":
printAccountNames(response.Items)
case "wide", "":
printAccountsTable(response.Items)
default:
errors.CheckError(fmt.Errorf("unknown output format: %s", output))
}
},
}
cmd.Flags().StringVarP(&output, "output", "o", "wide", "Output format. One of: json|yaml|wide|name")
return cmd
}
func getCurrentAccount(clientset argocdclient.Client) session.GetUserInfoResponse {
conn, client := clientset.NewSessionClientOrDie()
defer util.Close(conn)
userInfo, err := client.GetUserInfo(context.Background(), &session.GetUserInfoRequest{})
errors.CheckError(err)
return *userInfo
}
func NewAccountGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
output string
account string
)
cmd := &cobra.Command{
Use: "get",
Short: "Get account details",
Example: `# Get the currently logged in account details
argocd account get
# Get details for an account by name
argocd account get --account <account-name>`,
Run: func(c *cobra.Command, args []string) {
clientset := argocdclient.NewClientOrDie(clientOpts)
if account == "" {
account = getCurrentAccount(clientset).Username
}
conn, client := clientset.NewAccountClientOrDie()
defer util.Close(conn)
acc, err := client.GetAccount(context.Background(), &accountpkg.GetAccountRequest{Name: account})
errors.CheckError(err)
switch output {
case "yaml", "json":
err := PrintResourceList(acc, output, true)
errors.CheckError(err)
case "name":
fmt.Println(acc.Name)
case "wide", "":
printAccountDetails(acc)
default:
errors.CheckError(fmt.Errorf("unknown output format: %s", output))
}
},
}
cmd.Flags().StringVarP(&output, "output", "o", "wide", "Output format. One of: json|yaml|wide|name")
cmd.Flags().StringVarP(&account, "account", "a", "", "Account name. Defaults to the current account.")
return cmd
}
func printAccountDetails(acc *accountpkg.Account) {
fmt.Printf(printOpFmtStr, "Name:", acc.Name)
fmt.Printf(printOpFmtStr, "Enabled:", strconv.FormatBool(acc.Enabled))
fmt.Printf(printOpFmtStr, "Capabilities:", strings.Join(acc.Capabilities, ", "))
fmt.Println("\nTokens:")
if len(acc.Tokens) == 0 {
fmt.Println("NONE")
} else {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintf(w, "ID\tISSUED AT\tEXPIRING AT\n")
for _, t := range acc.Tokens {
expiresAtFormatted := "never"
if t.ExpiresAt > 0 {
expiresAt := time.Unix(t.ExpiresAt, 0)
expiresAtFormatted = expiresAt.Format(time.RFC3339)
if expiresAt.Before(time.Now()) {
expiresAtFormatted = fmt.Sprintf("%s (expired)", expiresAtFormatted)
}
}
fmt.Fprintf(w, "%s\t%s\t%s\n", t.Id, time.Unix(t.IssuedAt, 0).Format(time.RFC3339), expiresAtFormatted)
}
_ = w.Flush()
}
}
func NewAccountGenerateTokenCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
account string
expiresIn string
)
cmd := &cobra.Command{
Use: "generate-token",
Short: "Generate account token",
Example: `# Generate token for the currently logged in account
argocd account generate-token
# Generate token for the account with the specified name
argocd account generate-token --account <account-name>`,
Run: func(c *cobra.Command, args []string) {
clientset := argocdclient.NewClientOrDie(clientOpts)
conn, client := clientset.NewAccountClientOrDie()
defer util.Close(conn)
if account == "" {
account = getCurrentAccount(clientset).Username
}
expiresIn, err := timeutil.ParseDuration(expiresIn)
errors.CheckError(err)
response, err := client.CreateToken(context.Background(), &accountpkg.CreateTokenRequest{
Name: account,
ExpiresIn: int64(expiresIn.Seconds()),
})
errors.CheckError(err)
fmt.Println(response.Token)
},
}
cmd.Flags().StringVarP(&account, "account", "a", "", "Account name. Defaults to the current account.")
cmd.Flags().StringVarP(&expiresIn, "expires-in", "e", "0s", "Duration before the token will expire. (Default: No expiration)")
return cmd
}
func NewAccountDeleteTokenCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
account string
)
cmd := &cobra.Command{
Use: "delete-token",
Short: "Deletes account token",
Example: `# Delete token of the currently logged in account
argocd account delete-token ID
# Delete token of the account with the specified name
argocd account generate-token --account <account-name>`,
Run: func(c *cobra.Command, args []string) {
if len(args) != 1 {
c.HelpFunc()(c, args)
os.Exit(1)
}
id := args[0]
clientset := argocdclient.NewClientOrDie(clientOpts)
conn, client := clientset.NewAccountClientOrDie()
defer util.Close(conn)
if account == "" {
account = getCurrentAccount(clientset).Username
}
_, err := client.DeleteToken(context.Background(), &accountpkg.DeleteTokenRequest{Name: account, Id: id})
errors.CheckError(err)
},
}
cmd.Flags().StringVarP(&account, "account", "a", "", "Account name. Defaults to the current account.")
return cmd
}

View File

@@ -496,8 +496,6 @@ func setAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, ap
setHelmOpt(&spec.Source, helmOpts{helmSets: appOpts.helmSets})
case "helm-set-string":
setHelmOpt(&spec.Source, helmOpts{helmSetStrings: appOpts.helmSetStrings})
case "helm-set-file":
setHelmOpt(&spec.Source, helmOpts{helmSetFiles: appOpts.helmSetFiles})
case "directory-recurse":
spec.Source.Directory = &argoappv1.ApplicationSourceDirectory{Recurse: appOpts.directoryRecurse}
case "config-management-plugin":
@@ -525,36 +523,14 @@ func setAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, ap
case "sync-policy":
switch appOpts.syncPolicy {
case "automated":
if spec.SyncPolicy == nil {
spec.SyncPolicy = &argoappv1.SyncPolicy{}
spec.SyncPolicy = &argoappv1.SyncPolicy{
Automated: &argoappv1.SyncPolicyAutomated{},
}
spec.SyncPolicy.Automated = &argoappv1.SyncPolicyAutomated{}
case "none":
if spec.SyncPolicy != nil {
spec.SyncPolicy.Automated = nil
}
if spec.SyncPolicy.IsZero() {
spec.SyncPolicy = nil
}
spec.SyncPolicy = nil
default:
log.Fatalf("Invalid sync-policy: %s", appOpts.syncPolicy)
}
case "sync-option":
if spec.SyncPolicy == nil {
spec.SyncPolicy = &argoappv1.SyncPolicy{}
}
for _, option := range appOpts.syncOptions {
// `!` means remove the option
if strings.HasPrefix(option, "!") {
option = strings.TrimPrefix(option, "!")
spec.SyncPolicy.SyncOptions = spec.SyncPolicy.SyncOptions.RemoveOption(option)
} else {
spec.SyncPolicy.SyncOptions = spec.SyncPolicy.SyncOptions.AddOption(option)
}
}
if spec.SyncPolicy.IsZero() {
spec.SyncPolicy = nil
}
}
})
if flags.Changed("auto-prune") {
@@ -610,7 +586,6 @@ type helmOpts struct {
releaseName string
helmSets []string
helmSetStrings []string
helmSetFiles []string
}
func setHelmOpt(src *argoappv1.ApplicationSource, opts helmOpts) {
@@ -637,13 +612,6 @@ func setHelmOpt(src *argoappv1.ApplicationSource, opts helmOpts) {
}
src.Helm.AddParameter(*p)
}
for _, text := range opts.helmSetFiles {
p, err := argoappv1.NewHelmFileParameter(text)
if err != nil {
log.Fatal(err)
}
src.Helm.AddFileParameter(*p)
}
if src.Helm.IsZero() {
src.Helm = nil
}
@@ -653,8 +621,31 @@ func setJsonnetOpt(src *argoappv1.ApplicationSource, tlaParameters []string, cod
if src.Directory == nil {
src.Directory = &argoappv1.ApplicationSourceDirectory{}
}
for _, j := range tlaParameters {
src.Directory.Jsonnet.TLAs = append(src.Directory.Jsonnet.TLAs, argoappv1.NewJsonnetVar(j, code))
if len(tlaParameters) != 0 {
tlas := make([]argoappv1.JsonnetVar, len(tlaParameters))
for index, paramStr := range tlaParameters {
parts := strings.SplitN(paramStr, "=", 2)
if len(parts) != 2 {
log.Fatalf("Expected parameter of the form: param=value. Received: %s", paramStr)
break
}
tlas[index] = argoappv1.JsonnetVar{
Name: parts[0],
Value: parts[1],
Code: code}
}
var existingTLAs []argoappv1.JsonnetVar
for i := range src.Directory.Jsonnet.TLAs {
if src.Directory.Jsonnet.TLAs[i].Code != code {
existingTLAs = append(existingTLAs, src.Directory.Jsonnet.TLAs[i])
}
}
src.Directory.Jsonnet.TLAs = append(existingTLAs, tlas...)
}
if src.Directory.IsZero() {
src.Directory = nil
}
}
@@ -681,10 +672,8 @@ type appOptions struct {
releaseName string
helmSets []string
helmSetStrings []string
helmSetFiles []string
project string
syncPolicy string
syncOptions []string
autoPrune bool
selfHeal bool
namePrefix string
@@ -712,10 +701,8 @@ func addAppFlags(command *cobra.Command, opts *appOptions) {
command.Flags().StringVar(&opts.releaseName, "release-name", "", "Helm release-name")
command.Flags().StringArrayVar(&opts.helmSets, "helm-set", []string{}, "Helm set values on the command line (can be repeated to set several values: --helm-set key1=val1 --helm-set key2=val2)")
command.Flags().StringArrayVar(&opts.helmSetStrings, "helm-set-string", []string{}, "Helm set STRING values on the command line (can be repeated to set several values: --helm-set-string key1=val1 --helm-set-string key2=val2)")
command.Flags().StringArrayVar(&opts.helmSetFiles, "helm-set-file", []string{}, "Helm set values from respective files specified via the command line (can be repeated to set several values: --helm-set-file key1=path1 --helm-set-file key2=path2)")
command.Flags().StringVar(&opts.project, "project", "", "Application project name")
command.Flags().StringVar(&opts.syncPolicy, "sync-policy", "", "Set the sync policy (one of: automated, none)")
command.Flags().StringArrayVar(&opts.syncOptions, "sync-option", []string{}, "Add or remove a sync options, e.g add `Prune=false`. Remove using `!` prefix, e.g. `!Prune=false`")
command.Flags().BoolVar(&opts.autoPrune, "auto-prune", false, "Set automatic pruning when sync is automated")
command.Flags().BoolVar(&opts.selfHeal, "self-heal", false, "Set self healing when sync is automated")
command.Flags().StringVar(&opts.namePrefix, "nameprefix", "", "Kustomize nameprefix")

View File

@@ -3,7 +3,6 @@ package commands
import (
"testing"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
@@ -35,70 +34,4 @@ func Test_setHelmOpt(t *testing.T) {
setHelmOpt(&src, helmOpts{helmSetStrings: []string{"foo=bar"}})
assert.Equal(t, []v1alpha1.HelmParameter{{Name: "foo", Value: "bar", ForceString: true}}, src.Helm.Parameters)
})
t.Run("HelmSetFiles", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setHelmOpt(&src, helmOpts{helmSetFiles: []string{"foo=bar"}})
assert.Equal(t, []v1alpha1.HelmFileParameter{{Name: "foo", Path: "bar"}}, src.Helm.FileParameters)
})
}
func Test_setJsonnetOpt(t *testing.T) {
t.Run("TlaSets", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setJsonnetOpt(&src, []string{"foo=bar"}, false)
assert.Equal(t, []v1alpha1.JsonnetVar{{Name: "foo", Value: "bar"}}, src.Directory.Jsonnet.TLAs)
setJsonnetOpt(&src, []string{"bar=baz"}, false)
assert.Equal(t, []v1alpha1.JsonnetVar{{Name: "foo", Value: "bar"}, {Name: "bar", Value: "baz"}}, src.Directory.Jsonnet.TLAs)
})
t.Run("ExtSets", func(t *testing.T) {
src := v1alpha1.ApplicationSource{}
setJsonnetOptExtVar(&src, []string{"foo=bar"}, false)
assert.Equal(t, []v1alpha1.JsonnetVar{{Name: "foo", Value: "bar"}}, src.Directory.Jsonnet.ExtVars)
setJsonnetOptExtVar(&src, []string{"bar=baz"}, false)
assert.Equal(t, []v1alpha1.JsonnetVar{{Name: "foo", Value: "bar"}, {Name: "bar", Value: "baz"}}, src.Directory.Jsonnet.ExtVars)
})
}
type appOptionsFixture struct {
spec *v1alpha1.ApplicationSpec
command *cobra.Command
options *appOptions
}
func (f *appOptionsFixture) SetFlag(key, value string) error {
err := f.command.Flags().Set(key, value)
if err != nil {
return err
}
_ = setAppSpecOptions(f.command.Flags(), f.spec, f.options)
return err
}
func newAppOptionsFixture() *appOptionsFixture {
fixture := &appOptionsFixture{
spec: &v1alpha1.ApplicationSpec{},
command: &cobra.Command{},
options: &appOptions{},
}
addAppFlags(fixture.command, fixture.options)
return fixture
}
func Test_setAppSpecOptions(t *testing.T) {
f := newAppOptionsFixture()
t.Run("SyncPolicy", func(t *testing.T) {
assert.NoError(t, f.SetFlag("sync-policy", "automated"))
assert.NotNil(t, f.spec.SyncPolicy.Automated)
assert.NoError(t, f.SetFlag("sync-policy", "none"))
assert.Nil(t, f.spec.SyncPolicy)
})
t.Run("SyncOptions", func(t *testing.T) {
assert.NoError(t, f.SetFlag("sync-option", "a=1"))
assert.True(t, f.spec.SyncPolicy.SyncOptions.HasOption("a=1"))
// remove the options using !
assert.NoError(t, f.SetFlag("sync-option", "!a=1"))
assert.Nil(t, f.spec.SyncPolicy)
})
}

View File

@@ -174,20 +174,18 @@ func NewCertAddSSHCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
}
for _, knownHostsEntry := range sshKnownHostsLists {
_, certSubType, certData, err := certutil.TokenizeSSHKnownHostsEntry(knownHostsEntry)
hostname, certSubType, certData, err := certutil.TokenizeSSHKnownHostsEntry(knownHostsEntry)
errors.CheckError(err)
hostnameList, _, err := certutil.KnownHostsLineToPublicKey(knownHostsEntry)
_, _, err = certutil.KnownHostsLineToPublicKey(knownHostsEntry)
errors.CheckError(err)
// Each key could be valid for multiple hostnames
for _, hostname := range hostnameList {
certificate := appsv1.RepositoryCertificate{
ServerName: hostname,
CertType: "ssh",
CertSubType: certSubType,
CertData: certData,
}
certificates = append(certificates, certificate)
certificate := appsv1.RepositoryCertificate{
ServerName: hostname,
CertType: "ssh",
CertSubType: certSubType,
CertData: certData,
}
certificates = append(certificates, certificate)
}
certList := &appsv1.RepositoryCertificateList{Items: certificates}

View File

@@ -60,7 +60,6 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
var (
inCluster bool
upsert bool
serviceAccount string
awsRoleArn string
awsClusterName string
systemNamespace string
@@ -102,11 +101,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
// Install RBAC resources for managing the cluster
clientset, err := kubernetes.NewForConfig(conf)
errors.CheckError(err)
if serviceAccount != "" {
managerBearerToken, err = clusterauth.GetServiceAccountBearerToken(clientset, systemNamespace, serviceAccount)
} else {
managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, systemNamespace, namespaces)
}
managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, systemNamespace, namespaces)
errors.CheckError(err)
}
conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie()
@@ -127,8 +122,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
command.PersistentFlags().StringVar(&pathOpts.LoadingRules.ExplicitPath, pathOpts.ExplicitFileFlag, pathOpts.LoadingRules.ExplicitPath, "use a particular kubeconfig file")
command.Flags().BoolVar(&inCluster, "in-cluster", false, "Indicates Argo CD resides inside this cluster and should connect using the internal k8s hostname (kubernetes.default.svc)")
command.Flags().BoolVar(&upsert, "upsert", false, "Override an existing cluster with the same name even if the spec differs")
command.Flags().StringVar(&serviceAccount, "service-account", "", fmt.Sprintf("System namespace service account to use for kubernetes resource management. If not set then default \"%s\" SA will be created", clusterauth.ArgoCDManagerServiceAccount))
command.Flags().StringVar(&awsClusterName, "aws-cluster-name", "", "AWS Cluster name if set then aws cli eks token command will be used to access cluster")
command.Flags().StringVar(&awsClusterName, "aws-cluster-name", "", "AWS Cluster name if set then aws-iam-authenticator will be used to access cluster")
command.Flags().StringVar(&awsRoleArn, "aws-role-arn", "", "Optional AWS role arn. If set then AWS IAM Authenticator assume a role to perform cluster operations instead of the default AWS credential provider chain.")
command.Flags().StringVar(&systemNamespace, "system-namespace", common.DefaultSystemNamespace, "Use different system namespace")
command.Flags().StringArrayVar(&namespaces, "namespace", nil, "List of namespaces which are allowed to manage")

View File

@@ -52,10 +52,7 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
// For better readability and easier formatting
var repoAddExamples = ` # Add a Git repository via SSH using a private key for authentication, ignoring the server's host key:
argocd repo add git@git.example.com:repos/repo --insecure-ignore-host-key --ssh-private-key-path ~/id_rsa
# Add a Git repository via SSH on a non-default port - need to use ssh:// style URLs here
argocd repo add ssh://git@git.example.com:2222/repos/repo --ssh-private-key-path ~/id_rsa
argocd repo add git@git.example.com:repos/repo --insecure-ignore-host-key --ssh-private-key-path ~/id_rsa
# Add a private Git repository via HTTPS using username/password and TLS client certificates:
argocd repo add https://git.example.com/repos/repo --username git --password secret --tls-client-cert-path ~/mycert.crt --tls-client-cert-key-path ~/mycert.key
@@ -177,7 +174,7 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
command.Flags().StringVar(&sshPrivateKeyPath, "ssh-private-key-path", "", "path to the private ssh key (e.g. ~/.ssh/id_rsa)")
command.Flags().StringVar(&tlsClientCertPath, "tls-client-cert-path", "", "path to the TLS client cert (must be PEM format)")
command.Flags().StringVar(&tlsClientCertKeyPath, "tls-client-cert-key-path", "", "path to the TLS client cert's key path (must be PEM format)")
command.Flags().BoolVar(&insecureIgnoreHostKey, "insecure-ignore-host-key", false, "disables SSH strict host key checking (deprecated, use --insecure-skip-server-verification instead)")
command.Flags().BoolVar(&insecureIgnoreHostKey, "insecure-ignore-host-key", false, "disables SSH strict host key checking (deprecated, use --insecure-skip-server-validation instead)")
command.Flags().BoolVar(&insecureSkipServerVerification, "insecure-skip-server-verification", false, "disables server certificate and host key checks")
command.Flags().BoolVar(&enableLfs, "enable-lfs", false, "enable git-lfs (Large File Support) on this repository")
command.Flags().BoolVar(&upsert, "upsert", false, "Override an existing repository with the same name even if the spec differs")

View File

@@ -19,7 +19,7 @@ import (
"github.com/argoproj/argo-cd/util/git"
)
// NewRepoCredsCommand returns a new instance of an `argocd repocreds` command
// NewRepoCredsCommand returns a new instance of an `argocd repo` command
func NewRepoCredsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var command = &cobra.Command{
Use: "repocreds",
@@ -36,7 +36,7 @@ func NewRepoCredsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
return command
}
// NewRepoCredsAddCommand returns a new instance of an `argocd repocreds add` command
// NewRepoCredsAddCommand returns a new instance of an `argocd repo add` command
func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
repo appsv1.RepoCreds
@@ -50,8 +50,8 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma
var repocredsAddExamples = ` # Add credentials with user/pass authentication to use for all repositories under https://git.example.com/repos
argocd repocreds add https://git.example.com/repos/ --username git --password secret
# Add credentials with SSH private key authentication to use for all repositories under ssh://git@git.example.com/repos
argocd repocreds add ssh://git@git.example.com/repos/ --ssh-private-key-path ~/.ssh/id_rsa
# Add credentials with SSH private key authentication to use for all repositories under https://git.example.com/repos
argocd repocreds add https://git.example.com/repos/ --ssh-private-key-path ~/.ssh/id_rsa
`
var command = &cobra.Command{
@@ -131,7 +131,7 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma
return command
}
// NewRepoCredsRemoveCommand returns a new instance of an `argocd repocreds rm` command
// NewRepoCredsRemoveCommand returns a new instance of an `argocd repo list` command
func NewRepoCredsRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var command = &cobra.Command{
Use: "rm CREDSURL",
@@ -172,7 +172,7 @@ func printRepoCredsUrls(repos []appsv1.RepoCreds) {
}
}
// NewRepoCredsListCommand returns a new instance of an `argocd repo list` command
// NewRepoCredsListCommand returns a new instance of an `argocd repo rm` command
func NewRepoCredsListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
output string

View File

@@ -1,11 +1,5 @@
package common
import (
"os"
"strconv"
"time"
)
// Default service addresses and URLS of Argo CD internal services
const (
// DefaultRepoServerAddr is the gRPC address of the Argo CD repo server
@@ -44,6 +38,8 @@ const (
// Default paths on the pod's file system
const (
// The default base path where application config is located
DefaultPathAppConfig = "/app/config"
// The default path where TLS certificates for repositories are located
DefaultPathTLSConfig = "/app/config/tls"
// The default path where SSH known hosts are stored
@@ -66,8 +62,10 @@ const (
AuthCookieName = "argocd.token"
// RevisionHistoryLimit is the max number of successful sync to keep in history
RevisionHistoryLimit = 10
// ChangePasswordSSOTokenMaxAge is the max token age for password change operation
ChangePasswordSSOTokenMaxAge = time.Minute * 5
// K8sClientConfigQPS controls the QPS to be used in K8s REST client configs
K8sClientConfigQPS = 25
// K8sClientConfigBurst controls the burst to be used in K8s REST client configs
K8sClientConfigBurst = 50
)
// Dex related constants
@@ -140,12 +138,6 @@ const (
EnvGitAttemptsCount = "ARGOCD_GIT_ATTEMPTS_COUNT"
// Overrides git submodule support, true by default
EnvGitSubmoduleEnabled = "ARGOCD_GIT_MODULES_ENABLED"
// EnvK8sClientQPS is the QPS value used for the kubernetes client (default: 50)
EnvK8sClientQPS = "ARGOCD_K8S_CLIENT_QPS"
// EnvK8sClientBurst is the burst value used for the kubernetes client (default: twice the client QPS)
EnvK8sClientBurst = "ARGOCD_K8S_CLIENT_BURST"
// EnvK8sClientMaxIdleConnections is the number of max idle connections in K8s REST client HTTP transport (default: 500)
EnvK8sClientMaxIdleConnections = "ARGOCD_K8S_CLIENT_MAX_IDLE_CONNECTIONS"
)
const (
@@ -157,33 +149,3 @@ const (
// Number should be bumped in case of backward incompatible change to make sure cache is invalidated after upgrade.
CacheVersion = "1.0.0"
)
var (
// K8sClientConfigQPS controls the QPS to be used in K8s REST client configs
K8sClientConfigQPS float32 = 50
// K8sClientConfigBurst controls the burst to be used in K8s REST client configs
K8sClientConfigBurst int = 100
// K8sMaxIdleConnections controls the number of max idle connections in K8s REST client HTTP transport
K8sMaxIdleConnections = 500
)
func init() {
if envQPS := os.Getenv(EnvK8sClientQPS); envQPS != "" {
if qps, err := strconv.ParseFloat(envQPS, 32); err != nil {
K8sClientConfigQPS = float32(qps)
}
}
if envBurst := os.Getenv(EnvK8sClientBurst); envBurst != "" {
if burst, err := strconv.Atoi(envBurst); err != nil {
K8sClientConfigBurst = burst
}
} else {
K8sClientConfigBurst = 2 * int(K8sClientConfigQPS)
}
if envMaxConn := os.Getenv(EnvK8sClientMaxIdleConnections); envMaxConn != "" {
if maxConn, err := strconv.Atoi(envMaxConn); err != nil {
K8sMaxIdleConnections = maxConn
}
}
}

View File

@@ -821,20 +821,22 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
return
}
app := origApp.DeepCopy()
logCtx := log.WithFields(log.Fields{"application": app.Name})
startTime := time.Now()
defer func() {
reconcileDuration := time.Since(startTime)
ctrl.metricsServer.IncReconcile(origApp, reconcileDuration)
logCtx.WithFields(log.Fields{
"time_ms": reconcileDuration.Milliseconds(),
logCtx := log.WithFields(log.Fields{
"application": origApp.Name,
"time_ms": reconcileDuration.Seconds() * 1e3,
"level": comparisonLevel,
"dest-server": origApp.Spec.Destination.Server,
"dest-namespace": origApp.Spec.Destination.Namespace,
}).Info("Reconciliation completed")
})
logCtx.Info("Reconciliation completed")
}()
app := origApp.DeepCopy()
logCtx := log.WithFields(log.Fields{"application": app.Name})
if comparisonLevel == ComparisonWithNothing {
managedResources := make([]*appv1.ResourceDiff, 0)
if err := ctrl.cache.GetAppManagedResources(app.Name, &managedResources); err != nil {
@@ -886,9 +888,6 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
observedAt := metav1.Now()
compareResult := ctrl.appStateManager.CompareAppState(app, project, revision, app.Spec.Source, refreshType == appv1.RefreshTypeHard, localManifests)
for k, v := range compareResult.timings {
logCtx = logCtx.WithField(k, v.Milliseconds())
}
ctrl.normalizeApplication(origApp, app)
@@ -913,7 +912,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
)
}
} else {
logCtx.Info("Sync prevented by sync window")
logCtx.Infof("Sync prevented by sync window")
}
if app.Status.ReconciledAt == nil || comparisonLevel == CompareWithLatest {
@@ -1081,30 +1080,14 @@ func (ctrl *ApplicationController) autoSync(app *appv1.Application, syncStatus *
return nil
}
if !app.Spec.SyncPolicy.Automated.Prune {
requirePruneOnly := true
for _, r := range resources {
if r.Status != appv1.SyncStatusCodeSynced && !r.RequiresPruning {
requirePruneOnly = false
break
}
}
if requirePruneOnly {
logCtx.Infof("Skipping auto-sync: need to prune extra resources only but automated prune is disabled")
return nil
}
}
desiredCommitSHA := syncStatus.Revision
alreadyAttempted, attemptPhase := alreadyAttemptedSync(app, desiredCommitSHA)
selfHeal := app.Spec.SyncPolicy.Automated.SelfHeal
op := appv1.Operation{
Sync: &appv1.SyncOperation{
Revision: desiredCommitSHA,
Prune: app.Spec.SyncPolicy.Automated.Prune,
SyncOptions: app.Spec.SyncPolicy.SyncOptions,
Revision: desiredCommitSHA,
Prune: app.Spec.SyncPolicy.Automated.Prune,
},
InitiatedBy: appv1.OperationInitiator{Automated: true},
}
// It is possible for manifests to remain OutOfSync even after a sync/kubectl apply (e.g.
// auto-sync with pruning disabled). We need to ensure that we do not keep Syncing an

View File

@@ -111,7 +111,7 @@ func newFakeController(data *fakeData) *ApplicationController {
ctrl.stateCache = &mockStateCache
mockStateCache.On("IsNamespaced", mock.Anything, mock.Anything).Return(true, nil)
mockStateCache.On("GetManagedLiveObjs", mock.Anything, mock.Anything).Return(data.managedLiveObjs, nil)
mockStateCache.On("GetVersionsInfo", mock.Anything).Return("v1.2.3", nil, nil)
mockStateCache.On("GetServerVersion", mock.Anything).Return("v1.2.3", nil)
response := make(map[kube.ResourceKey]argoappv1.ResourceNode)
for k, v := range data.namespacedResources {
response[k] = v.ResourceNode
@@ -228,7 +228,7 @@ func TestAutoSync(t *testing.T) {
Status: argoappv1.SyncStatusCodeOutOfSync,
Revision: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
}
cond := ctrl.autoSync(app, &syncStatus, []argoappv1.ResourceStatus{{Name: "guestbook", Kind: kube.DeploymentKind, Status: argoappv1.SyncStatusCodeOutOfSync}})
cond := ctrl.autoSync(app, &syncStatus, []argoappv1.ResourceStatus{})
assert.Nil(t, cond)
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get("my-app", metav1.GetOptions{})
assert.NoError(t, err)
@@ -240,7 +240,7 @@ func TestAutoSync(t *testing.T) {
func TestSkipAutoSync(t *testing.T) {
// Verify we skip when we previously synced to it in our most recent history
// Set current to 'aaaaa', desired to 'aaaa' and mark system OutOfSync
t.Run("PreviouslySyncedToRevision", func(t *testing.T) {
{
app := newFakeApp()
ctrl := newFakeController(&fakeData{apps: []runtime.Object{app}})
syncStatus := argoappv1.SyncStatus{
@@ -252,10 +252,10 @@ func TestSkipAutoSync(t *testing.T) {
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get("my-app", metav1.GetOptions{})
assert.NoError(t, err)
assert.Nil(t, app.Operation)
})
}
// Verify we skip when we are already Synced (even if revision is different)
t.Run("AlreadyInSyncedState", func(t *testing.T) {
{
app := newFakeApp()
ctrl := newFakeController(&fakeData{apps: []runtime.Object{app}})
syncStatus := argoappv1.SyncStatus{
@@ -267,10 +267,10 @@ func TestSkipAutoSync(t *testing.T) {
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get("my-app", metav1.GetOptions{})
assert.NoError(t, err)
assert.Nil(t, app.Operation)
})
}
// Verify we skip when auto-sync is disabled
t.Run("AutoSyncIsDisabled", func(t *testing.T) {
{
app := newFakeApp()
app.Spec.SyncPolicy = nil
ctrl := newFakeController(&fakeData{apps: []runtime.Object{app}})
@@ -283,10 +283,10 @@ func TestSkipAutoSync(t *testing.T) {
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get("my-app", metav1.GetOptions{})
assert.NoError(t, err)
assert.Nil(t, app.Operation)
})
}
// Verify we skip when application is marked for deletion
t.Run("ApplicationIsMarkedForDeletion", func(t *testing.T) {
{
app := newFakeApp()
now := metav1.Now()
app.DeletionTimestamp = &now
@@ -300,11 +300,11 @@ func TestSkipAutoSync(t *testing.T) {
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get("my-app", metav1.GetOptions{})
assert.NoError(t, err)
assert.Nil(t, app.Operation)
})
}
// Verify we skip when previous sync attempt failed and return error condition
// Set current to 'aaaaa', desired to 'bbbbb' and add 'bbbbb' to failure history
t.Run("PreviousSyncAttemptFailed", func(t *testing.T) {
{
app := newFakeApp()
app.Status.OperationState = &argoappv1.OperationState{
Operation: argoappv1.Operation{
@@ -321,28 +321,12 @@ func TestSkipAutoSync(t *testing.T) {
Status: argoappv1.SyncStatusCodeOutOfSync,
Revision: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
}
cond := ctrl.autoSync(app, &syncStatus, []argoappv1.ResourceStatus{{Name: "guestbook", Kind: kube.DeploymentKind, Status: argoappv1.SyncStatusCodeOutOfSync}})
cond := ctrl.autoSync(app, &syncStatus, []argoappv1.ResourceStatus{})
assert.NotNil(t, cond)
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get("my-app", metav1.GetOptions{})
assert.NoError(t, err)
assert.Nil(t, app.Operation)
})
t.Run("NeedsToPruneResourcesOnlyButAutomatedPruneDisabled", func(t *testing.T) {
app := newFakeApp()
ctrl := newFakeController(&fakeData{apps: []runtime.Object{app}})
syncStatus := argoappv1.SyncStatus{
Status: argoappv1.SyncStatusCodeOutOfSync,
Revision: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
}
cond := ctrl.autoSync(app, &syncStatus, []argoappv1.ResourceStatus{
{Name: "guestbook", Kind: kube.DeploymentKind, Status: argoappv1.SyncStatusCodeOutOfSync, RequiresPruning: true},
})
assert.Nil(t, cond)
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get("my-app", metav1.GetOptions{})
assert.NoError(t, err)
assert.Nil(t, app.Operation)
})
}
}
// TestAutoSyncIndicateError verifies we skip auto-sync and return error condition if previous sync failed
@@ -373,7 +357,7 @@ func TestAutoSyncIndicateError(t *testing.T) {
Source: *app.Spec.Source.DeepCopy(),
},
}
cond := ctrl.autoSync(app, &syncStatus, []argoappv1.ResourceStatus{{Name: "guestbook", Kind: kube.DeploymentKind, Status: argoappv1.SyncStatusCodeOutOfSync}})
cond := ctrl.autoSync(app, &syncStatus, []argoappv1.ResourceStatus{})
assert.NotNil(t, cond)
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get("my-app", metav1.GetOptions{})
assert.NoError(t, err)
@@ -416,7 +400,7 @@ func TestAutoSyncParameterOverrides(t *testing.T) {
Revision: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
}
cond := ctrl.autoSync(app, &syncStatus, []argoappv1.ResourceStatus{{Name: "guestbook", Kind: kube.DeploymentKind, Status: argoappv1.SyncStatusCodeOutOfSync}})
cond := ctrl.autoSync(app, &syncStatus, []argoappv1.ResourceStatus{})
assert.Nil(t, cond)
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get("my-app", metav1.GetOptions{})
assert.NoError(t, err)

View File

@@ -7,7 +7,6 @@ import (
log "github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
@@ -29,7 +28,7 @@ type cacheSettings struct {
type LiveStateCache interface {
// Returns k8s server version
GetVersionsInfo(serverURL string) (string, []metav1.APIGroup, error)
GetServerVersion(serverURL string) (string, error)
// Returns true of given group kind is a namespaced resource
IsNamespaced(server string, gk schema.GroupKind) (bool, error)
// Executes give callback against resource specified by the key and all its children
@@ -71,7 +70,7 @@ func NewLiveStateCache(
appInformer: appInformer,
db: db,
clusters: make(map[string]*clusterInfo),
lock: &sync.RWMutex{},
lock: &sync.Mutex{},
onObjectUpdated: onObjectUpdated,
kubectl: kubectl,
settingsMgr: settingsMgr,
@@ -83,7 +82,7 @@ func NewLiveStateCache(
type liveStateCache struct {
db db.ArgoDB
clusters map[string]*clusterInfo
lock *sync.RWMutex
lock *sync.Mutex
appInformer cache.SharedIndexInformer
onObjectUpdated ObjectUpdatedHandler
kubectl kube.Kubectl
@@ -110,47 +109,32 @@ func (c *liveStateCache) loadCacheSettings() (*cacheSettings, error) {
}
func (c *liveStateCache) getCluster(server string) (*clusterInfo, error) {
c.lock.RLock()
info, ok := c.clusters[server]
c.lock.RUnlock()
if ok {
return info, nil
}
c.lock.Lock()
defer c.lock.Unlock()
info, ok := c.clusters[server]
if !ok {
cluster, err := c.db.GetCluster(context.Background(), server)
if err != nil {
return nil, err
}
info = &clusterInfo{
apisMeta: make(map[schema.GroupKind]*apiMeta),
lock: &sync.Mutex{},
nodes: make(map[kube.ResourceKey]*node),
nsIndex: make(map[string]map[kube.ResourceKey]*node),
onObjectUpdated: c.onObjectUpdated,
kubectl: c.kubectl,
cluster: cluster,
syncTime: nil,
log: log.WithField("server", cluster.Server),
cacheSettingsSrc: c.getCacheSettings,
onEventReceived: func(event watch.EventType, un *unstructured.Unstructured) {
c.metricsServer.IncClusterEventsCount(cluster.Server)
},
}
info, ok = c.clusters[server]
if ok {
return info, nil
c.clusters[cluster.Server] = info
}
logCtx := log.WithField("server", server)
logCtx.Info("initializing cluster")
cluster, err := c.db.GetCluster(context.Background(), server)
if err != nil {
return nil, err
}
info = &clusterInfo{
apisMeta: make(map[schema.GroupKind]*apiMeta),
lock: &sync.RWMutex{},
nodes: make(map[kube.ResourceKey]*node),
nsIndex: make(map[string]map[kube.ResourceKey]*node),
onObjectUpdated: c.onObjectUpdated,
kubectl: c.kubectl,
cluster: cluster,
syncTime: nil,
log: logCtx,
cacheSettingsSrc: c.getCacheSettings,
onEventReceived: func(event watch.EventType, un *unstructured.Unstructured) {
gvk := un.GroupVersionKind()
c.metricsServer.IncClusterEventsCount(cluster.Server, gvk.Group, gvk.Kind)
},
metricsServer: c.metricsServer,
}
c.clusters[cluster.Server] = info
return info, nil
}
@@ -168,8 +152,8 @@ func (c *liveStateCache) getSyncedCluster(server string) (*clusterInfo, error) {
func (c *liveStateCache) Invalidate() {
log.Info("invalidating live state cache")
c.lock.RLock()
defer c.lock.RLock()
c.lock.Lock()
defer c.lock.Unlock()
for _, clust := range c.clusters {
clust.invalidate()
}
@@ -206,15 +190,14 @@ func (c *liveStateCache) GetManagedLiveObjs(a *appv1.Application, targetObjs []*
if err != nil {
return nil, err
}
return clusterInfo.getManagedLiveObjs(a, targetObjs)
return clusterInfo.getManagedLiveObjs(a, targetObjs, c.metricsServer)
}
func (c *liveStateCache) GetVersionsInfo(serverURL string) (string, []metav1.APIGroup, error) {
func (c *liveStateCache) GetServerVersion(serverURL string) (string, error) {
clusterInfo, err := c.getSyncedCluster(serverURL)
if err != nil {
return "", nil, err
return "", err
}
return clusterInfo.serverVersion, clusterInfo.apiGroups, nil
return clusterInfo.serverVersion, nil
}
func isClusterHasApps(apps []interface{}, cluster *appv1.Cluster) bool {
@@ -227,6 +210,8 @@ func isClusterHasApps(apps []interface{}, cluster *appv1.Cluster) bool {
}
func (c *liveStateCache) getCacheSettings() *cacheSettings {
c.cacheSettingsLock.Lock()
defer c.cacheSettingsLock.Unlock()
return c.cacheSettings
}
@@ -276,9 +261,8 @@ func (c *liveStateCache) Run(ctx context.Context) error {
util.RetryUntilSucceed(func() error {
clusterEventCallback := func(event *db.ClusterEvent) {
c.lock.Lock()
cluster, ok := c.clusters[event.Cluster.Server]
if ok {
defer c.lock.Unlock()
defer c.lock.Unlock()
if cluster, ok := c.clusters[event.Cluster.Server]; ok {
if event.Type == watch.Deleted {
cluster.invalidate()
delete(c.clusters, event.Cluster.Server)
@@ -286,14 +270,11 @@ func (c *liveStateCache) Run(ctx context.Context) error {
cluster.cluster = event.Cluster
cluster.invalidate()
}
} else {
c.lock.Unlock()
if event.Type == watch.Added && isClusterHasApps(c.appInformer.GetStore().List(), event.Cluster) {
go func() {
// warm up cache for cluster with apps
_, _ = c.getSyncedCluster(event.Cluster.Server)
}()
}
} else if event.Type == watch.Added && isClusterHasApps(c.appInformer.GetStore().List(), event.Cluster) {
go func() {
// warm up cache for cluster with apps
_, _ = c.getSyncedCluster(event.Cluster.Server)
}()
}
}
@@ -306,8 +287,8 @@ func (c *liveStateCache) Run(ctx context.Context) error {
}
func (c *liveStateCache) GetClustersInfo() []metrics.ClusterInfo {
c.lock.RLock()
defer c.lock.RUnlock()
c.lock.Lock()
defer c.lock.Unlock()
res := make([]metrics.ClusterInfo, 0)
for _, info := range c.clusters {
res = append(res, info.getClusterInfo())

View File

@@ -11,16 +11,16 @@ import (
func TestGetServerVersion(t *testing.T) {
now := time.Now()
cache := &liveStateCache{
lock: &sync.RWMutex{},
lock: &sync.Mutex{},
clusters: map[string]*clusterInfo{
"http://localhost": {
syncTime: &now,
lock: &sync.RWMutex{},
lock: &sync.Mutex{},
serverVersion: "123",
},
}}
version, _, err := cache.GetVersionsInfo("http://localhost")
version, err := cache.GetServerVersion("http://localhost")
assert.NoError(t, err)
assert.Equal(t, "123", version)
}

View File

@@ -9,22 +9,23 @@ import (
"sync"
"time"
"k8s.io/client-go/dynamic"
"k8s.io/apimachinery/pkg/types"
"github.com/argoproj/argo-cd/controller/metrics"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
"github.com/argoproj/argo-cd/controller/metrics"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/health"
"github.com/argoproj/argo-cd/util/kube"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/pager"
)
const (
@@ -44,12 +45,8 @@ type clusterInfo struct {
syncError error
apisMeta map[schema.GroupKind]*apiMeta
serverVersion string
apiGroups []metav1.APIGroup
// namespacedResources is a simple map which indicates a groupKind is namespaced
namespacedResources map[schema.GroupKind]bool
// lock is a rw lock which protects the fields of clusterInfo
lock *sync.RWMutex
lock *sync.Mutex
nodes map[kube.ResourceKey]*node
nsIndex map[string]map[kube.ResourceKey]*node
@@ -59,7 +56,6 @@ type clusterInfo struct {
cluster *appv1.Cluster
log *log.Entry
cacheSettingsSrc func() *cacheSettings
metricsServer *metrics.MetricsServer
}
func (c *clusterInfo) replaceResourceCache(gk schema.GroupKind, resourceVersion string, objs []unstructured.Unstructured, ns string) {
@@ -121,9 +117,8 @@ func isServiceAccountTokenSecret(un *unstructured.Unstructured) (bool, metav1.Ow
func (c *clusterInfo) createObjInfo(un *unstructured.Unstructured, appInstanceLabel string) *node {
ownerRefs := un.GetOwnerReferences()
gvk := un.GroupVersionKind()
// Special case for endpoint. Remove after https://github.com/kubernetes/kubernetes/issues/28483 is fixed
if gvk.Group == "" && gvk.Kind == kube.EndpointsKind && len(un.GetOwnerReferences()) == 0 {
if un.GroupVersionKind().Group == "" && un.GetKind() == kube.EndpointsKind && len(un.GetOwnerReferences()) == 0 {
ownerRefs = append(ownerRefs, metav1.OwnerReference{
Name: un.GetName(),
Kind: kube.ServiceKind,
@@ -147,15 +142,7 @@ func (c *clusterInfo) createObjInfo(un *unstructured.Unstructured, appInstanceLa
if len(ownerRefs) == 0 && appName != "" {
nodeInfo.appName = appName
nodeInfo.resource = un
} else {
// edge case. we do not label CRDs, so they miss the tracking label we inject. But we still
// want the full resource to be available in our cache (to diff), so we store all CRDs
switch gvk.Kind {
case kube.CustomResourceDefinitionKind:
nodeInfo.resource = un
}
}
nodeInfo.health, _ = health.GetResourceHealth(un, c.cacheSettingsSrc().ResourceOverrides)
return nodeInfo
}
@@ -189,19 +176,16 @@ func (c *clusterInfo) invalidate() {
c.apisMeta[i].watchCancel()
}
c.apisMeta = nil
c.namespacedResources = nil
c.log.Warnf("invalidated cluster")
}
func (c *clusterInfo) synced() bool {
syncTime := c.syncTime
if syncTime == nil {
if c.syncTime == nil {
return false
}
if c.syncError != nil {
return time.Now().Before(syncTime.Add(clusterRetryTimeout))
return time.Now().Before(c.syncTime.Add(clusterRetryTimeout))
}
return time.Now().Before(syncTime.Add(clusterSyncTimeout))
return time.Now().Before(c.syncTime.Add(clusterSyncTimeout))
}
func (c *clusterInfo) stopWatching(gk schema.GroupKind, ns string) {
@@ -211,7 +195,7 @@ func (c *clusterInfo) stopWatching(gk schema.GroupKind, ns string) {
info.watchCancel()
delete(c.apisMeta, gk)
c.replaceResourceCache(gk, "", []unstructured.Unstructured{}, ns)
c.log.Warnf("Stop watching: %s not found", gk)
log.Warnf("Stop watching %s not found on %s.", gk, c.cluster.Server)
}
}
@@ -227,10 +211,9 @@ func (c *clusterInfo) startMissingWatches() error {
if err != nil {
return err
}
namespacedResources := make(map[schema.GroupKind]bool)
for i := range apis {
api := apis[i]
namespacedResources[api.GroupKind] = api.Meta.Namespaced
if _, ok := c.apisMeta[api.GroupKind]; !ok {
ctx, cancel := context.WithCancel(context.Background())
info := &apiMeta{namespaced: api.Meta.Namespaced, watchCancel: cancel}
@@ -245,11 +228,10 @@ func (c *clusterInfo) startMissingWatches() error {
}
}
}
c.namespacedResources = namespacedResources
return nil
}
func runSynced(lock sync.Locker, action func() error) error {
func runSynced(lock *sync.Mutex, action func() error) error {
lock.Lock()
defer lock.Unlock()
return action()
@@ -265,26 +247,11 @@ func (c *clusterInfo) watchEvents(ctx context.Context, api kube.APIResourceInfo,
err = runSynced(c.lock, func() error {
if info.resourceVersion == "" {
listPager := pager.New(func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) {
res, err := resClient.List(opts)
if err == nil {
info.resourceVersion = res.GetResourceVersion()
}
return res, err
})
var items []unstructured.Unstructured
err = listPager.EachListItem(ctx, metav1.ListOptions{}, func(obj runtime.Object) error {
if un, ok := obj.(*unstructured.Unstructured); !ok {
return fmt.Errorf("object %s/%s has an unexpected type", un.GroupVersionKind().String(), un.GetName())
} else {
items = append(items, *un)
}
return nil
})
list, err := resClient.List(metav1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to load initial state of resource %s: %v", api.GroupKind.String(), err)
return err
}
c.replaceResourceCache(api.GroupKind, info.resourceVersion, items, ns)
c.replaceResourceCache(api.GroupKind, list.GetResourceVersion(), list.Items, ns)
}
return nil
})
@@ -298,10 +265,15 @@ func (c *clusterInfo) watchEvents(ctx context.Context, api kube.APIResourceInfo,
c.stopWatching(api.GroupKind, ns)
return nil
}
if errors.IsGone(err) {
info.resourceVersion = ""
c.log.Warnf("Resource version of %s is too old", api.GroupKind)
}
err = runSynced(c.lock, func() error {
if errors.IsGone(err) {
info.resourceVersion = ""
log.Warnf("Resource version of %s on %s is too old.", api.GroupKind, c.cluster.Server)
}
return err
})
if err != nil {
return err
}
@@ -332,7 +304,7 @@ func (c *clusterInfo) watchEvents(ctx context.Context, api kube.APIResourceInfo,
}
}
if err != nil {
c.log.Warnf("Failed to start missing watch: %v", err)
log.Warnf("Failed to start missing watch: %v", err)
}
} else {
return fmt.Errorf("Watch %s on %s has closed", api.GroupKind, c.cluster.Server)
@@ -371,19 +343,12 @@ func (c *clusterInfo) sync() (err error) {
}
c.apisMeta = make(map[schema.GroupKind]*apiMeta)
c.nodes = make(map[kube.ResourceKey]*node)
c.namespacedResources = make(map[schema.GroupKind]bool)
config := c.cluster.RESTConfig()
version, err := c.kubectl.GetServerVersion(config)
if err != nil {
return err
}
c.serverVersion = version
groups, err := c.kubectl.GetAPIGroups(config)
if err != nil {
return err
}
c.apiGroups = groups
apis, err := c.kubectl.GetAPIResources(config, c.cacheSettingsSrc().ResourcesFilter)
if err != nil {
return err
@@ -394,47 +359,25 @@ func (c *clusterInfo) sync() (err error) {
}
lock := sync.Mutex{}
err = util.RunAllAsync(len(apis), func(i int) error {
api := apis[i]
lock.Lock()
ctx, cancel := context.WithCancel(context.Background())
info := &apiMeta{namespaced: api.Meta.Namespaced, watchCancel: cancel}
c.apisMeta[api.GroupKind] = info
c.namespacedResources[api.GroupKind] = api.Meta.Namespaced
lock.Unlock()
return c.processApi(client, api, func(resClient dynamic.ResourceInterface, ns string) error {
listPager := pager.New(func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) {
res, err := resClient.List(opts)
if err == nil {
lock.Lock()
info.resourceVersion = res.GetResourceVersion()
lock.Unlock()
}
return res, err
})
err = listPager.EachListItem(context.Background(), metav1.ListOptions{}, func(obj runtime.Object) error {
if un, ok := obj.(*unstructured.Unstructured); !ok {
return fmt.Errorf("object %s/%s has an unexpected type", un.GroupVersionKind().String(), un.GetName())
} else {
lock.Lock()
c.setNode(c.createObjInfo(un, c.cacheSettingsSrc().AppInstanceLabelKey))
lock.Unlock()
}
return nil
})
return c.processApi(client, apis[i], func(resClient dynamic.ResourceInterface, _ string) error {
list, err := resClient.List(metav1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to load initial state of resource %s: %v", api.GroupKind.String(), err)
return err
}
go c.watchEvents(ctx, api, info, resClient, ns)
lock.Lock()
for i := range list.Items {
c.setNode(c.createObjInfo(&list.Items[i], c.cacheSettingsSrc().AppInstanceLabelKey))
}
lock.Unlock()
return nil
})
})
if err == nil {
err = c.startMissingWatches()
}
if err != nil {
log.Errorf("Failed to sync cluster %s: %v", c.cluster.Server, err)
return err
@@ -445,17 +388,12 @@ func (c *clusterInfo) sync() (err error) {
}
func (c *clusterInfo) ensureSynced() error {
// first check if cluster is synced *without lock*
if c.synced() {
return c.syncError
}
c.lock.Lock()
defer c.lock.Unlock()
// before doing any work, check once again now that we have the lock, to see if it got
// synced between the first check and now
if c.synced() {
return c.syncError
}
err := c.sync()
syncTime := time.Now()
c.syncTime = &syncTime
@@ -464,8 +402,8 @@ func (c *clusterInfo) ensureSynced() error {
}
func (c *clusterInfo) getNamespaceTopLevelResources(namespace string) map[kube.ResourceKey]appv1.ResourceNode {
c.lock.RLock()
defer c.lock.RUnlock()
c.lock.Lock()
defer c.lock.Unlock()
nodes := make(map[kube.ResourceKey]appv1.ResourceNode)
for _, node := range c.nsIndex[namespace] {
if len(node.ownerRefs) == 0 {
@@ -506,17 +444,15 @@ func (c *clusterInfo) iterateHierarchy(key kube.ResourceKey, action func(child a
}
func (c *clusterInfo) isNamespaced(gk schema.GroupKind) bool {
// this is safe to access without a lock since we always replace the entire map instead of mutating keys
if isNamespaced, ok := c.namespacedResources[gk]; ok {
return isNamespaced
if api, ok := c.apisMeta[gk]; ok && !api.namespaced {
return false
}
log.Warnf("group/kind %s scope is unknown (known objects: %d). assuming namespaced object", gk, len(c.namespacedResources))
return true
}
func (c *clusterInfo) getManagedLiveObjs(a *appv1.Application, targetObjs []*unstructured.Unstructured) (map[kube.ResourceKey]*unstructured.Unstructured, error) {
c.lock.RLock()
defer c.lock.RUnlock()
func (c *clusterInfo) getManagedLiveObjs(a *appv1.Application, targetObjs []*unstructured.Unstructured, metricsServer *metrics.MetricsServer) (map[kube.ResourceKey]*unstructured.Unstructured, error) {
c.lock.Lock()
defer c.lock.Unlock()
managedObjs := make(map[kube.ResourceKey]*unstructured.Unstructured)
// iterate all objects in live state cache to find ones associated with app
@@ -525,8 +461,8 @@ func (c *clusterInfo) getManagedLiveObjs(a *appv1.Application, targetObjs []*uns
managedObjs[key] = o.resource
}
}
config := metrics.AddMetricsTransportWrapper(c.metricsServer, a, c.cluster.RESTConfig())
// iterate target objects and identify ones that already exist in the cluster,
config := metrics.AddMetricsTransportWrapper(metricsServer, a, c.cluster.RESTConfig())
// iterate target objects and identify ones that already exist in the cluster,\
// but are simply missing our label
lock := &sync.Mutex{}
err := util.RunAllAsync(len(targetObjs), func(i int) error {
@@ -594,12 +530,9 @@ func (c *clusterInfo) processEvent(event watch.EventType, un *unstructured.Unstr
if c.onEventReceived != nil {
c.onEventReceived(event, un)
}
key := kube.GetResourceKey(un)
if event == watch.Modified && skipAppRequeing(key) {
return
}
c.lock.Lock()
defer c.lock.Unlock()
key := kube.GetResourceKey(un)
existingNode, exists := c.nodes[key]
if event == watch.Deleted {
if exists {
@@ -623,7 +556,7 @@ func (c *clusterInfo) onNodeUpdated(exists bool, existingNode *node, un *unstruc
n := nodes[i]
if ns, ok := c.nsIndex[n.ref.Namespace]; ok {
app := n.getApp(ns)
if app == "" {
if app == "" || skipAppRequeing(key) {
continue
}
toNotify[app] = n.isRootAppNode() || toNotify[app]
@@ -653,8 +586,8 @@ var (
)
func (c *clusterInfo) getClusterInfo() metrics.ClusterInfo {
c.lock.RLock()
defer c.lock.RUnlock()
c.lock.Lock()
defer c.lock.Unlock()
return metrics.ClusterInfo{
APIsCount: len(c.apisMeta),
K8SVersion: c.serverVersion,

View File

@@ -153,7 +153,7 @@ func newCluster(objs ...*unstructured.Unstructured) *clusterInfo {
func newClusterExt(kubectl kube.Kubectl) *clusterInfo {
return &clusterInfo{
lock: &sync.RWMutex{},
lock: &sync.Mutex{},
nodes: make(map[kube.ResourceKey]*node),
onObjectUpdated: func(managedByApp map[string]bool, reference corev1.ObjectReference) {},
kubectl: kubectl,
@@ -322,7 +322,7 @@ metadata:
Namespace: "default",
},
},
}, []*unstructured.Unstructured{targetDeploy})
}, []*unstructured.Unstructured{targetDeploy}, nil)
assert.Nil(t, err)
assert.Equal(t, managedObjs, map[kube.ResourceKey]*unstructured.Unstructured{
kube.NewResourceKey("apps", "Deployment", "default", "helm-guestbook"): testDeploy,

View File

@@ -14,8 +14,6 @@ import (
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
)
@@ -86,8 +84,8 @@ func (_m *LiveStateCache) GetNamespaceTopLevelResources(server string, namespace
return r0, r1
}
// GetVersionsInfo provides a mock function with given fields: serverURL
func (_m *LiveStateCache) GetVersionsInfo(serverURL string) (string, []v1.APIGroup, error) {
// GetServerVersion provides a mock function with given fields: serverURL
func (_m *LiveStateCache) GetServerVersion(serverURL string) (string, error) {
ret := _m.Called(serverURL)
var r0 string
@@ -97,23 +95,14 @@ func (_m *LiveStateCache) GetVersionsInfo(serverURL string) (string, []v1.APIGro
r0 = ret.Get(0).(string)
}
var r1 []v1.APIGroup
if rf, ok := ret.Get(1).(func(string) []v1.APIGroup); ok {
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(serverURL)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).([]v1.APIGroup)
}
r1 = ret.Error(1)
}
var r2 error
if rf, ok := ret.Get(2).(func(string) error); ok {
r2 = rf(serverURL)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
return r0, r1
}
// Invalidate provides a mock function with given fields:

View File

@@ -3,7 +3,7 @@ package metrics
import (
"context"
"net/http"
"os"
"strconv"
"time"
"github.com/prometheus/client_golang/prometheus"
@@ -31,8 +31,6 @@ type MetricsServer struct {
const (
// MetricsPath is the endpoint to collect application metrics
MetricsPath = "/metrics"
// EnvVarLegacyControllerMetrics is a env var to re-enable deprecated prometheus metrics
EnvVarLegacyControllerMetrics = "ARGOCD_LEGACY_CONTROLLER_METRICS"
)
// Follow Prometheus naming practices
@@ -43,71 +41,27 @@ var (
descAppInfo = prometheus.NewDesc(
"argocd_app_info",
"Information about application.",
append(descAppDefaultLabels, "repo", "dest_server", "dest_namespace", "sync_status", "health_status", "operation"),
append(descAppDefaultLabels, "repo", "dest_server", "dest_namespace"),
nil,
)
// DEPRECATED
descAppCreated = prometheus.NewDesc(
"argocd_app_created_time",
"Creation time in unix timestamp for an application.",
descAppDefaultLabels,
nil,
)
// DEPRECATED: superceded by sync_status label in argocd_app_info
descAppSyncStatusCode = prometheus.NewDesc(
"argocd_app_sync_status",
"The application current sync status.",
append(descAppDefaultLabels, "sync_status"),
nil,
)
// DEPRECATED: superceded by health_status label in argocd_app_info
descAppHealthStatus = prometheus.NewDesc(
"argocd_app_health_status",
"The application current health status.",
append(descAppDefaultLabels, "health_status"),
nil,
)
syncCounter = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "argocd_app_sync_total",
Help: "Number of application syncs.",
},
append(descAppDefaultLabels, "dest_server", "phase"),
)
k8sRequestCounter = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "argocd_app_k8s_request_total",
Help: "Number of kubernetes requests executed during application reconciliation.",
},
append(descAppDefaultLabels, "server", "response_code", "verb", "resource_kind", "resource_namespace"),
)
kubectlExecCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "argocd_kubectl_exec_total",
Help: "Number of kubectl executions",
}, []string{"command"})
kubectlExecPendingGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "argocd_kubectl_exec_pending",
Help: "Number of pending kubectl executions",
}, []string{"command"})
reconcileHistogram = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "argocd_app_reconcile",
Help: "Application reconciliation performance.",
// Buckets chosen after observing a ~2100ms mean reconcile time
Buckets: []float64{0.25, .5, 1, 2, 4, 8, 16},
},
[]string{"namespace", "dest_server"},
)
clusterEventsCounter = prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "argocd_cluster_events_total",
Help: "Number of processes k8s resource events.",
}, append(descClusterDefaultLabels, "group", "kind"))
)
// NewMetricsServer returns a new prometheus server which collects application metrics
@@ -122,11 +76,50 @@ func NewMetricsServer(addr string, appLister applister.ApplicationLister, health
}, promhttp.HandlerOpts{}))
healthz.ServeHealthCheck(mux, healthCheck)
syncCounter := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "argocd_app_sync_total",
Help: "Number of application syncs.",
},
append(descAppDefaultLabels, "phase"),
)
registry.MustRegister(syncCounter)
k8sRequestCounter := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "argocd_app_k8s_request_total",
Help: "Number of kubernetes requests executed during application reconciliation.",
},
append(descAppDefaultLabels, "response_code"),
)
registry.MustRegister(k8sRequestCounter)
kubectlExecCounter := prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "argocd_kubectl_exec_total",
Help: "Number of kubectl executions",
}, []string{"command"})
registry.MustRegister(kubectlExecCounter)
kubectlExecPendingGauge := prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "argocd_kubectl_exec_pending",
Help: "Number of pending kubectl executions",
}, []string{"command"})
registry.MustRegister(kubectlExecPendingGauge)
reconcileHistogram := prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "argocd_app_reconcile",
Help: "Application reconciliation performance.",
// Buckets chosen after observing a ~2100ms mean reconcile time
Buckets: []float64{0.25, .5, 1, 2, 4, 8, 16},
},
descAppDefaultLabels,
)
registry.MustRegister(reconcileHistogram)
clusterEventsCounter := prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "argocd_cluster_events_total",
Help: "Number of processes k8s resource events.",
}, descClusterDefaultLabels)
registry.MustRegister(clusterEventsCounter)
return &MetricsServer{
@@ -155,7 +148,7 @@ func (m *MetricsServer) IncSync(app *argoappv1.Application, state *argoappv1.Ope
if !state.Phase.Completed() {
return
}
m.syncCounter.WithLabelValues(app.Namespace, app.Name, app.Spec.GetProject(), app.Spec.Destination.Server, string(state.Phase)).Inc()
m.syncCounter.WithLabelValues(app.Namespace, app.Name, app.Spec.GetProject(), string(state.Phase)).Inc()
}
func (m *MetricsServer) IncKubectlExec(command string) {
@@ -171,27 +164,18 @@ func (m *MetricsServer) DecKubectlExecPending(command string) {
}
// IncClusterEventsCount increments the number of cluster events
func (m *MetricsServer) IncClusterEventsCount(server, group, kind string) {
m.clusterEventsCounter.WithLabelValues(server, group, kind).Inc()
func (m *MetricsServer) IncClusterEventsCount(server string) {
m.clusterEventsCounter.WithLabelValues(server).Inc()
}
// IncKubernetesRequest increments the kubernetes requests counter for an application
func (m *MetricsServer) IncKubernetesRequest(app *argoappv1.Application, server, statusCode, verb, resourceKind, resourceNamespace string) {
var namespace, name, project string
if app != nil {
namespace = app.Namespace
name = app.Name
project = app.Spec.GetProject()
}
m.k8sRequestCounter.WithLabelValues(
namespace, name, project, server, statusCode,
verb, resourceKind, resourceNamespace,
).Inc()
func (m *MetricsServer) IncKubernetesRequest(app *argoappv1.Application, statusCode int) {
m.k8sRequestCounter.WithLabelValues(app.Namespace, app.Name, app.Spec.GetProject(), strconv.Itoa(statusCode)).Inc()
}
// IncReconcile increments the reconcile counter for an application
func (m *MetricsServer) IncReconcile(app *argoappv1.Application, duration time.Duration) {
m.reconcileHistogram.WithLabelValues(app.Namespace, app.Spec.Destination.Server).Observe(duration.Seconds())
m.reconcileHistogram.WithLabelValues(app.Namespace, app.Name, app.Spec.GetProject()).Observe(duration.Seconds())
}
type appCollector struct {
@@ -215,6 +199,7 @@ func NewAppRegistry(appLister applister.ApplicationLister) *prometheus.Registry
// Describe implements the prometheus.Collector interface
func (c *appCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- descAppInfo
ch <- descAppCreated
ch <- descAppSyncStatusCode
ch <- descAppHealthStatus
}
@@ -248,36 +233,20 @@ func collectApps(ch chan<- prometheus.Metric, app *argoappv1.Application) {
addConstMetric(desc, prometheus.GaugeValue, v, lv...)
}
var operation string
if app.DeletionTimestamp != nil {
operation = "delete"
} else if app.Operation != nil && app.Operation.Sync != nil {
operation = "sync"
}
addGauge(descAppInfo, 1, git.NormalizeGitURL(app.Spec.Source.RepoURL), app.Spec.Destination.Server, app.Spec.Destination.Namespace)
addGauge(descAppCreated, float64(app.CreationTimestamp.Unix()))
syncStatus := app.Status.Sync.Status
if syncStatus == "" {
syncStatus = argoappv1.SyncStatusCodeUnknown
}
addGauge(descAppSyncStatusCode, boolFloat64(syncStatus == argoappv1.SyncStatusCodeSynced), string(argoappv1.SyncStatusCodeSynced))
addGauge(descAppSyncStatusCode, boolFloat64(syncStatus == argoappv1.SyncStatusCodeOutOfSync), string(argoappv1.SyncStatusCodeOutOfSync))
addGauge(descAppSyncStatusCode, boolFloat64(syncStatus == argoappv1.SyncStatusCodeUnknown || syncStatus == ""), string(argoappv1.SyncStatusCodeUnknown))
healthStatus := app.Status.Health.Status
if healthStatus == "" {
healthStatus = argoappv1.HealthStatusUnknown
}
addGauge(descAppInfo, 1, git.NormalizeGitURL(app.Spec.Source.RepoURL), app.Spec.Destination.Server, app.Spec.Destination.Namespace, string(syncStatus), healthStatus, operation)
// Deprecated controller metrics
if os.Getenv(EnvVarLegacyControllerMetrics) == "true" {
addGauge(descAppCreated, float64(app.CreationTimestamp.Unix()))
addGauge(descAppSyncStatusCode, boolFloat64(syncStatus == argoappv1.SyncStatusCodeSynced), string(argoappv1.SyncStatusCodeSynced))
addGauge(descAppSyncStatusCode, boolFloat64(syncStatus == argoappv1.SyncStatusCodeOutOfSync), string(argoappv1.SyncStatusCodeOutOfSync))
addGauge(descAppSyncStatusCode, boolFloat64(syncStatus == argoappv1.SyncStatusCodeUnknown || syncStatus == ""), string(argoappv1.SyncStatusCodeUnknown))
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusUnknown || healthStatus == ""), argoappv1.HealthStatusUnknown)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusProgressing), argoappv1.HealthStatusProgressing)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusSuspended), argoappv1.HealthStatusSuspended)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusHealthy), argoappv1.HealthStatusHealthy)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusDegraded), argoappv1.HealthStatusDegraded)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusMissing), argoappv1.HealthStatusMissing)
}
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusUnknown || healthStatus == ""), argoappv1.HealthStatusUnknown)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusProgressing), argoappv1.HealthStatusProgressing)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusSuspended), argoappv1.HealthStatusSuspended)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusHealthy), argoappv1.HealthStatusHealthy)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusDegraded), argoappv1.HealthStatusDegraded)
addGauge(descAppHealthStatus, boolFloat64(healthStatus == argoappv1.HealthStatusMissing), argoappv1.HealthStatusMissing)
}

View File

@@ -5,7 +5,6 @@ import (
"log"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
"time"
@@ -43,52 +42,25 @@ status:
status: Healthy
`
const fakeApp2 = `
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-2
namespace: argocd
spec:
destination:
namespace: dummy-namespace
server: https://localhost:6443
project: important-project
source:
path: some/path
repoURL: https://github.com/argoproj/argocd-example-apps.git
status:
sync:
status: Synced
health:
status: Healthy
operation:
sync:
revision: 041eab7439ece92c99b043f0e171788185b8fc1d
syncStrategy:
hook: {}
`
const fakeApp3 = `
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-3
namespace: argocd
deletionTimestamp: "2020-03-16T09:17:45Z"
spec:
destination:
namespace: dummy-namespace
server: https://localhost:6443
project: important-project
source:
path: some/path
repoURL: https://github.com/argoproj/argocd-example-apps.git
status:
sync:
status: OutOfSync
health:
status: Degraded
const expectedResponse = `# HELP argocd_app_created_time Creation time in unix timestamp for an application.
# TYPE argocd_app_created_time gauge
argocd_app_created_time{name="my-app",namespace="argocd",project="important-project"} -6.21355968e+10
# HELP argocd_app_health_status The application current health status.
# TYPE argocd_app_health_status gauge
argocd_app_health_status{health_status="Degraded",name="my-app",namespace="argocd",project="important-project"} 0
argocd_app_health_status{health_status="Healthy",name="my-app",namespace="argocd",project="important-project"} 1
argocd_app_health_status{health_status="Missing",name="my-app",namespace="argocd",project="important-project"} 0
argocd_app_health_status{health_status="Progressing",name="my-app",namespace="argocd",project="important-project"} 0
argocd_app_health_status{health_status="Suspended",name="my-app",namespace="argocd",project="important-project"} 0
argocd_app_health_status{health_status="Unknown",name="my-app",namespace="argocd",project="important-project"} 0
# HELP argocd_app_info Information about application.
# TYPE argocd_app_info gauge
argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:6443",name="my-app",namespace="argocd",project="important-project",repo="https://github.com/argoproj/argocd-example-apps"} 1
# HELP argocd_app_sync_status The application current sync status.
# TYPE argocd_app_sync_status gauge
argocd_app_sync_status{name="my-app",namespace="argocd",project="important-project",sync_status="OutOfSync"} 0
argocd_app_sync_status{name="my-app",namespace="argocd",project="important-project",sync_status="Synced"} 1
argocd_app_sync_status{name="my-app",namespace="argocd",project="important-project",sync_status="Unknown"} 0
`
const fakeDefaultApp = `
@@ -111,26 +83,46 @@ status:
status: Healthy
`
const expectedDefaultResponse = `# HELP argocd_app_created_time Creation time in unix timestamp for an application.
# TYPE argocd_app_created_time gauge
argocd_app_created_time{name="my-app",namespace="argocd",project="default"} -6.21355968e+10
# HELP argocd_app_health_status The application current health status.
# TYPE argocd_app_health_status gauge
argocd_app_health_status{health_status="Degraded",name="my-app",namespace="argocd",project="default"} 0
argocd_app_health_status{health_status="Healthy",name="my-app",namespace="argocd",project="default"} 1
argocd_app_health_status{health_status="Missing",name="my-app",namespace="argocd",project="default"} 0
argocd_app_health_status{health_status="Progressing",name="my-app",namespace="argocd",project="default"} 0
argocd_app_health_status{health_status="Suspended",name="my-app",namespace="argocd",project="default"} 0
argocd_app_health_status{health_status="Unknown",name="my-app",namespace="argocd",project="default"} 0
# HELP argocd_app_info Information about application.
# TYPE argocd_app_info gauge
argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:6443",name="my-app",namespace="argocd",project="default",repo="https://github.com/argoproj/argocd-example-apps"} 1
# HELP argocd_app_sync_status The application current sync status.
# TYPE argocd_app_sync_status gauge
argocd_app_sync_status{name="my-app",namespace="argocd",project="default",sync_status="OutOfSync"} 0
argocd_app_sync_status{name="my-app",namespace="argocd",project="default",sync_status="Synced"} 1
argocd_app_sync_status{name="my-app",namespace="argocd",project="default",sync_status="Unknown"} 0
`
var noOpHealthCheck = func() error {
return nil
}
func newFakeApp(fakeAppYAML string) *argoappv1.Application {
func newFakeApp(fakeApp string) *argoappv1.Application {
var app argoappv1.Application
err := yaml.Unmarshal([]byte(fakeAppYAML), &app)
err := yaml.Unmarshal([]byte(fakeApp), &app)
if err != nil {
panic(err)
}
return &app
}
func newFakeLister(fakeAppYAMLs ...string) (context.CancelFunc, applister.ApplicationLister) {
func newFakeLister(fakeApp ...string) (context.CancelFunc, applister.ApplicationLister) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
var fakeApps []runtime.Object
for _, appYAML := range fakeAppYAMLs {
a := newFakeApp(appYAML)
fakeApps = append(fakeApps, a)
for _, name := range fakeApp {
fakeApps = append(fakeApps, newFakeApp(name))
}
appClientset := appclientset.NewSimpleClientset(fakeApps...)
factory := appinformer.NewFilteredSharedInformerFactory(appClientset, 0, "argocd", func(options *metav1.ListOptions) {})
@@ -142,8 +134,8 @@ func newFakeLister(fakeAppYAMLs ...string) (context.CancelFunc, applister.Applic
return cancel, factory.Argoproj().V1alpha1().Applications().Lister()
}
func testApp(t *testing.T, fakeAppYAMLs []string, expectedResponse string) {
cancel, appLister := newFakeLister(fakeAppYAMLs...)
func testApp(t *testing.T, fakeApp string, expectedResponse string) {
cancel, appLister := newFakeLister(fakeApp)
defer cancel()
metricsServ := NewMetricsServer("localhost:8082", appLister, noOpHealthCheck)
req, err := http.NewRequest("GET", "/metrics", nil)
@@ -157,75 +149,39 @@ func testApp(t *testing.T, fakeAppYAMLs []string, expectedResponse string) {
}
type testCombination struct {
applications []string
application string
expectedResponse string
}
func TestMetrics(t *testing.T) {
combinations := []testCombination{
{
applications: []string{fakeApp, fakeApp2, fakeApp3},
expectedResponse: `
# HELP argocd_app_info Information about application.
# TYPE argocd_app_info gauge
argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:6443",health_status="Degraded",name="my-app-3",namespace="argocd",operation="delete",project="important-project",repo="https://github.com/argoproj/argocd-example-apps",sync_status="OutOfSync"} 1
argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:6443",health_status="Healthy",name="my-app",namespace="argocd",operation="",project="important-project",repo="https://github.com/argoproj/argocd-example-apps",sync_status="Synced"} 1
argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:6443",health_status="Healthy",name="my-app-2",namespace="argocd",operation="sync",project="important-project",repo="https://github.com/argoproj/argocd-example-apps",sync_status="Synced"} 1
`,
application: fakeApp,
expectedResponse: expectedResponse,
},
{
applications: []string{fakeDefaultApp},
expectedResponse: `
# HELP argocd_app_info Information about application.
# TYPE argocd_app_info gauge
argocd_app_info{dest_namespace="dummy-namespace",dest_server="https://localhost:6443",health_status="Healthy",name="my-app",namespace="argocd",operation="",project="default",repo="https://github.com/argoproj/argocd-example-apps",sync_status="Synced"} 1
`,
application: fakeDefaultApp,
expectedResponse: expectedDefaultResponse,
},
}
for _, combination := range combinations {
testApp(t, combination.applications, combination.expectedResponse)
testApp(t, combination.application, combination.expectedResponse)
}
}
func TestLegacyMetrics(t *testing.T) {
os.Setenv(EnvVarLegacyControllerMetrics, "true")
defer os.Unsetenv(EnvVarLegacyControllerMetrics)
expectedResponse := `
# HELP argocd_app_created_time Creation time in unix timestamp for an application.
# TYPE argocd_app_created_time gauge
argocd_app_created_time{name="my-app",namespace="argocd",project="important-project"} -6.21355968e+10
# HELP argocd_app_health_status The application current health status.
# TYPE argocd_app_health_status gauge
argocd_app_health_status{health_status="Degraded",name="my-app",namespace="argocd",project="important-project"} 0
argocd_app_health_status{health_status="Healthy",name="my-app",namespace="argocd",project="important-project"} 1
argocd_app_health_status{health_status="Missing",name="my-app",namespace="argocd",project="important-project"} 0
argocd_app_health_status{health_status="Progressing",name="my-app",namespace="argocd",project="important-project"} 0
argocd_app_health_status{health_status="Suspended",name="my-app",namespace="argocd",project="important-project"} 0
argocd_app_health_status{health_status="Unknown",name="my-app",namespace="argocd",project="important-project"} 0
# HELP argocd_app_sync_status The application current sync status.
# TYPE argocd_app_sync_status gauge
argocd_app_sync_status{name="my-app",namespace="argocd",project="important-project",sync_status="OutOfSync"} 0
argocd_app_sync_status{name="my-app",namespace="argocd",project="important-project",sync_status="Synced"} 1
argocd_app_sync_status{name="my-app",namespace="argocd",project="important-project",sync_status="Unknown"} 0
const appSyncTotal = `# HELP argocd_app_sync_total Number of application syncs.
# TYPE argocd_app_sync_total counter
argocd_app_sync_total{name="my-app",namespace="argocd",phase="Error",project="important-project"} 1
argocd_app_sync_total{name="my-app",namespace="argocd",phase="Failed",project="important-project"} 1
argocd_app_sync_total{name="my-app",namespace="argocd",phase="Succeeded",project="important-project"} 2
`
testApp(t, []string{fakeApp}, expectedResponse)
}
func TestMetricsSyncCounter(t *testing.T) {
cancel, appLister := newFakeLister()
defer cancel()
metricsServ := NewMetricsServer("localhost:8082", appLister, noOpHealthCheck)
appSyncTotal := `
# HELP argocd_app_sync_total Number of application syncs.
# TYPE argocd_app_sync_total counter
argocd_app_sync_total{dest_server="https://localhost:6443",name="my-app",namespace="argocd",phase="Error",project="important-project"} 1
argocd_app_sync_total{dest_server="https://localhost:6443",name="my-app",namespace="argocd",phase="Failed",project="important-project"} 1
argocd_app_sync_total{dest_server="https://localhost:6443",name="my-app",namespace="argocd",phase="Succeeded",project="important-project"} 2
`
fakeApp := newFakeApp(fakeApp)
metricsServ.IncSync(fakeApp, &argoappv1.OperationState{Phase: argoappv1.OperationRunning})
metricsServ.IncSync(fakeApp, &argoappv1.OperationState{Phase: argoappv1.OperationFailed})
@@ -246,31 +202,27 @@ argocd_app_sync_total{dest_server="https://localhost:6443",name="my-app",namespa
// assertMetricsPrinted asserts every line in the expected lines appears in the body
func assertMetricsPrinted(t *testing.T, expectedLines, body string) {
for _, line := range strings.Split(expectedLines, "\n") {
if line == "" {
continue
}
assert.Contains(t, body, line)
}
}
const appReconcileMetrics = `argocd_app_reconcile_bucket{name="my-app",namespace="argocd",project="important-project",le="0.25"} 0
argocd_app_reconcile_bucket{name="my-app",namespace="argocd",project="important-project",le="0.5"} 0
argocd_app_reconcile_bucket{name="my-app",namespace="argocd",project="important-project",le="1"} 0
argocd_app_reconcile_bucket{name="my-app",namespace="argocd",project="important-project",le="2"} 0
argocd_app_reconcile_bucket{name="my-app",namespace="argocd",project="important-project",le="4"} 0
argocd_app_reconcile_bucket{name="my-app",namespace="argocd",project="important-project",le="8"} 1
argocd_app_reconcile_bucket{name="my-app",namespace="argocd",project="important-project",le="16"} 1
argocd_app_reconcile_bucket{name="my-app",namespace="argocd",project="important-project",le="+Inf"} 1
argocd_app_reconcile_sum{name="my-app",namespace="argocd",project="important-project"} 5
argocd_app_reconcile_count{name="my-app",namespace="argocd",project="important-project"} 1
`
func TestReconcileMetrics(t *testing.T) {
cancel, appLister := newFakeLister()
defer cancel()
metricsServ := NewMetricsServer("localhost:8082", appLister, noOpHealthCheck)
appReconcileMetrics := `
# HELP argocd_app_reconcile Application reconciliation performance.
# TYPE argocd_app_reconcile histogram
argocd_app_reconcile_bucket{dest_server="https://localhost:6443",namespace="argocd",le="0.25"} 0
argocd_app_reconcile_bucket{dest_server="https://localhost:6443",namespace="argocd",le="0.5"} 0
argocd_app_reconcile_bucket{dest_server="https://localhost:6443",namespace="argocd",le="1"} 0
argocd_app_reconcile_bucket{dest_server="https://localhost:6443",namespace="argocd",le="2"} 0
argocd_app_reconcile_bucket{dest_server="https://localhost:6443",namespace="argocd",le="4"} 0
argocd_app_reconcile_bucket{dest_server="https://localhost:6443",namespace="argocd",le="8"} 1
argocd_app_reconcile_bucket{dest_server="https://localhost:6443",namespace="argocd",le="16"} 1
argocd_app_reconcile_bucket{dest_server="https://localhost:6443",namespace="argocd",le="+Inf"} 1
argocd_app_reconcile_sum{dest_server="https://localhost:6443",namespace="argocd"} 5
argocd_app_reconcile_count{dest_server="https://localhost:6443",namespace="argocd"} 1
`
fakeApp := newFakeApp(fakeApp)
metricsServ.IncReconcile(fakeApp, 5*time.Second)

View File

@@ -1,24 +1,37 @@
package metrics
import (
"strconv"
"net/http"
"github.com/argoproj/pkg/kubeclientmetrics"
"k8s.io/client-go/rest"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
)
type metricsRoundTripper struct {
roundTripper http.RoundTripper
app *v1alpha1.Application
metricsServer *MetricsServer
}
func (mrt *metricsRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
resp, err := mrt.roundTripper.RoundTrip(r)
statusCode := 0
if resp != nil {
statusCode = resp.StatusCode
}
mrt.metricsServer.IncKubernetesRequest(mrt.app, statusCode)
return resp, err
}
// AddMetricsTransportWrapper adds a transport wrapper which increments 'argocd_app_k8s_request_total' counter on each kubernetes request
func AddMetricsTransportWrapper(server *MetricsServer, app *v1alpha1.Application, config *rest.Config) *rest.Config {
inc := func(resourceInfo kubeclientmetrics.ResourceInfo) error {
namespace := resourceInfo.Namespace
kind := resourceInfo.Kind
statusCode := strconv.Itoa(resourceInfo.StatusCode)
server.IncKubernetesRequest(app, resourceInfo.Server, statusCode, string(resourceInfo.Verb), kind, namespace)
return nil
wrap := config.WrapTransport
config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
if wrap != nil {
rt = wrap(rt)
}
return &metricsRoundTripper{roundTripper: rt, metricsServer: server, app: app}
}
newConfig := kubeclientmetrics.AddMetricsTransportWrapper(config, inc)
return newConfig
return config
}

View File

@@ -7,7 +7,6 @@ import (
"time"
log "github.com/sirupsen/logrus"
"github.com/yudai/gojsondiff"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -31,7 +30,6 @@ import (
"github.com/argoproj/argo-cd/util/resource"
"github.com/argoproj/argo-cd/util/resource/ignore"
"github.com/argoproj/argo-cd/util/settings"
"github.com/argoproj/argo-cd/util/stats"
)
type managedResource struct {
@@ -72,8 +70,6 @@ type comparisonResult struct {
hooks []*unstructured.Unstructured
diffNormalizer diff.Normalizer
appSourceType v1alpha1.ApplicationSourceType
// timings maps phases of comparison to the duration it took to complete (for statistical purposes)
timings map[string]time.Duration
}
func (cr *comparisonResult) targetObjs() []*unstructured.Unstructured {
@@ -100,17 +96,14 @@ type appStateManager struct {
}
func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1.ApplicationSource, appLabelKey, revision string, noCache bool) ([]*unstructured.Unstructured, []*unstructured.Unstructured, *apiclient.ManifestResponse, error) {
ts := stats.NewTimingStats()
helmRepos, err := m.db.ListHelmRepositories(context.Background())
if err != nil {
return nil, nil, nil, err
}
ts.AddCheckpoint("helm_ms")
repo, err := m.db.GetRepository(context.Background(), source.RepoURL)
if err != nil {
return nil, nil, nil, err
}
ts.AddCheckpoint("repo_ms")
conn, repoClient, err := m.repoClientset.NewRepoServerClient()
if err != nil {
return nil, nil, nil, err
@@ -125,7 +118,7 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
if err != nil {
return nil, nil, nil, err
}
ts.AddCheckpoint("plugins_ms")
tools := make([]*appv1.ConfigManagementPlugin, len(plugins))
for i := range plugins {
tools[i] = &plugins[i]
@@ -135,12 +128,10 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
if err != nil {
return nil, nil, nil, err
}
ts.AddCheckpoint("build_options_ms")
serverVersion, apiGroups, err := m.liveStateCache.GetVersionsInfo(app.Spec.Destination.Server)
serverVersion, err := m.liveStateCache.GetServerVersion(app.Spec.Destination.Server)
if err != nil {
return nil, nil, nil, err
}
ts.AddCheckpoint("version_ms")
manifestInfo, err := repoClient.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
Repo: repo,
Repos: helmRepos,
@@ -155,23 +146,14 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
BuildOptions: buildOptions,
},
KubeVersion: serverVersion,
ApiVersions: argo.APIGroupsToVersions(apiGroups),
})
if err != nil {
return nil, nil, nil, err
}
ts.AddCheckpoint("manifests_ms")
targetObjs, hooks, err := unmarshalManifests(manifestInfo.Manifests)
if err != nil {
return nil, nil, nil, err
}
ts.AddCheckpoint("unmarshal_ms")
logCtx := log.WithField("application", app.Name)
for k, v := range ts.Timings() {
logCtx = logCtx.WithField(k, v.Milliseconds())
}
logCtx = logCtx.WithField("time_ms", time.Since(ts.StartTime).Milliseconds())
logCtx.Info("getRepoObjs stats")
return targetObjs, hooks, manifestInfo, nil
}
@@ -183,7 +165,7 @@ func unmarshalManifests(manifests []string) ([]*unstructured.Unstructured, []*un
if err != nil {
return nil, nil, err
}
if obj == nil || ignore.Ignore(obj) {
if ignore.Ignore(obj) {
continue
}
if hookutil.IsHook(obj) {
@@ -270,33 +252,27 @@ func dedupLiveResources(targetObjs []*unstructured.Unstructured, liveObjsByKey m
}
}
func (m *appStateManager) getComparisonSettings(app *appv1.Application) (string, map[string]v1alpha1.ResourceOverride, diff.Normalizer, *settings.ResourcesFilter, error) {
func (m *appStateManager) getComparisonSettings(app *appv1.Application) (string, map[string]v1alpha1.ResourceOverride, diff.Normalizer, error) {
resourceOverrides, err := m.settingsMgr.GetResourceOverrides()
if err != nil {
return "", nil, nil, nil, err
return "", nil, nil, err
}
appLabelKey, err := m.settingsMgr.GetAppInstanceLabelKey()
if err != nil {
return "", nil, nil, nil, err
return "", nil, nil, err
}
diffNormalizer, err := argo.NewDiffNormalizer(app.Spec.IgnoreDifferences, resourceOverrides)
if err != nil {
return "", nil, nil, nil, err
return "", nil, nil, err
}
resFilter, err := m.settingsMgr.GetResourcesFilter()
if err != nil {
return "", nil, nil, nil, err
}
return appLabelKey, resourceOverrides, diffNormalizer, resFilter, nil
return appLabelKey, resourceOverrides, diffNormalizer, nil
}
// CompareAppState compares application git state to the live app state, using the specified
// revision and supplied source. If revision or overrides are empty, then compares against
// revision and overrides in the app spec.
func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *appv1.AppProject, revision string, source v1alpha1.ApplicationSource, noCache bool, localManifests []string) *comparisonResult {
ts := stats.NewTimingStats()
appLabelKey, resourceOverrides, diffNormalizer, resFilter, err := m.getComparisonSettings(app)
ts.AddCheckpoint("settings_ms")
appLabelKey, resourceOverrides, diffNormalizer, err := m.getComparisonSettings(app)
// return unknown comparison result if basic comparison settings cannot be loaded
if err != nil {
@@ -337,27 +313,32 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
}
manifestInfo = nil
}
ts.AddCheckpoint("git_ms")
targetObjs, dedupConditions, err := DeduplicateTargetObjects(app.Spec.Destination.Server, app.Spec.Destination.Namespace, targetObjs, m.liveStateCache)
if err != nil {
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error(), LastTransitionTime: &now})
}
conditions = append(conditions, dedupConditions...)
for i := len(targetObjs) - 1; i >= 0; i-- {
targetObj := targetObjs[i]
gvk := targetObj.GroupVersionKind()
if resFilter.IsExcludedResource(gvk.Group, gvk.Kind, app.Spec.Destination.Server) {
targetObjs = append(targetObjs[:i], targetObjs[i+1:]...)
conditions = append(conditions, v1alpha1.ApplicationCondition{
Type: v1alpha1.ApplicationConditionExcludedResourceWarning,
Message: fmt.Sprintf("Resource %s/%s %s is excluded in the settings", gvk.Group, gvk.Kind, targetObj.GetName()),
LastTransitionTime: &now,
})
resFilter, err := m.settingsMgr.GetResourcesFilter()
if err != nil {
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error(), LastTransitionTime: &now})
} else {
for i := len(targetObjs) - 1; i >= 0; i-- {
targetObj := targetObjs[i]
gvk := targetObj.GroupVersionKind()
if resFilter.IsExcludedResource(gvk.Group, gvk.Kind, app.Spec.Destination.Server) {
targetObjs = append(targetObjs[:i], targetObjs[i+1:]...)
conditions = append(conditions, v1alpha1.ApplicationCondition{
Type: v1alpha1.ApplicationConditionExcludedResourceWarning,
Message: fmt.Sprintf("Resource %s/%s %s is excluded in the settings", gvk.Group, gvk.Kind, targetObj.GetName()),
LastTransitionTime: &now,
})
}
}
}
ts.AddCheckpoint("dedup_ms")
logCtx.Debugf("Generated config manifests")
liveObjByKey, err := m.liveStateCache.GetManagedLiveObjs(app, targetObjs)
if err != nil {
liveObjByKey = make(map[kubeutil.ResourceKey]*unstructured.Unstructured)
@@ -372,6 +353,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
}
}
logCtx.Debugf("Retrieved lived manifests")
for _, liveObj := range liveObjByKey {
if liveObj != nil {
appInstanceName := kubeutil.GetAppInstanceLabel(liveObj, appLabelKey)
@@ -400,8 +382,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
managedLiveObj[i] = nil
}
}
ts.AddCheckpoint("live_ms")
logCtx.Debugf("built managed objects list")
// Everything remaining in liveObjByKey are "extra" resources that aren't tracked in git.
// The following adds all the extras to the managedLiveObj list and backfills the targetObj
// list with nils, so that the lists are of equal lengths for comparison purposes.
@@ -417,7 +398,6 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
failedToLoadObjs = true
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error(), LastTransitionTime: &now})
}
ts.AddCheckpoint("diff_ms")
syncCode := v1alpha1.SyncStatusCodeSynced
managedResources := make([]managedResource, len(targetObjs))
@@ -443,17 +423,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
RequiresPruning: targetObj == nil && liveObj != nil,
}
var diffResult diff.DiffResult
if i < len(diffResults.Diffs) {
diffResult = diffResults.Diffs[i]
} else {
diffResult = diff.DiffResult{
Diff: gojsondiff.New().CompareObjects(map[string]interface{}{}, map[string]interface{}{}),
Modified: false,
NormalizedLive: []byte("{}"),
PredictedLive: []byte("{}"),
}
}
diffResult := diffResults.Diffs[i]
if resState.Hook || ignore.Ignore(obj) {
// For resource hooks, don't store sync status, and do not affect overall sync status
} else if diffResult.Modified || targetObj == nil || liveObj == nil {
@@ -507,7 +477,6 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
if manifestInfo != nil {
syncStatus.Revision = manifestInfo.Revision
}
ts.AddCheckpoint("sync_ms")
healthStatus, err := health.SetApplicationHealth(resourceSummaries, GetLiveObjs(managedResources), resourceOverrides, func(obj *unstructured.Unstructured) bool {
return !isSelfReferencedApp(app, kubeutil.GetObjectRef(obj))
@@ -534,8 +503,6 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
appv1.ApplicationConditionRepeatedResourceWarning: true,
appv1.ApplicationConditionExcludedResourceWarning: true,
})
ts.AddCheckpoint("health_ms")
compRes.timings = ts.Timings()
return &compRes
}

View File

@@ -47,7 +47,6 @@ type syncContext struct {
proj *v1alpha1.AppProject
compareResult *comparisonResult
config *rest.Config
rawConfig *rest.Config
dynamicIf dynamic.Interface
disco discovery.DiscoveryInterface
extensionsclientset *clientset.Clientset
@@ -174,7 +173,6 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
proj: proj,
compareResult: compareResult,
config: restConfig,
rawConfig: clst.RawRestConfig(),
dynamicIf: dynamicIf,
disco: disco,
extensionsclientset: extensionsclientset,
@@ -424,13 +422,7 @@ func (sc *syncContext) getSyncTasks() (_ syncTasks, successful bool) {
// metadata.generateName, then we will generate a formulated metadata.name before submission.
targetObj := obj.DeepCopy()
if targetObj.GetName() == "" {
var syncRevision string
if len(sc.syncRes.Revision) >= 8 {
syncRevision = sc.syncRes.Revision[0:7]
} else {
syncRevision = sc.syncRes.Revision
}
postfix := strings.ToLower(fmt.Sprintf("%s-%s-%d", syncRevision, phase, sc.opState.StartedAt.UTC().Unix()))
postfix := strings.ToLower(fmt.Sprintf("%s-%s-%d", sc.syncRes.Revision[0:7], phase, sc.opState.StartedAt.UTC().Unix()))
generateName := obj.GetGenerateName()
targetObj.SetName(fmt.Sprintf("%s%s", generateName, postfix))
}
@@ -556,8 +548,9 @@ func (sc *syncContext) ensureCRDReady(name string) {
}
// applyObject performs a `kubectl apply` of a single resource
func (sc *syncContext) applyObject(targetObj *unstructured.Unstructured, dryRun, force, validate bool) (v1alpha1.ResultCode, string) {
message, err := sc.kubectl.ApplyResource(sc.rawConfig, targetObj, targetObj.GetNamespace(), dryRun, force, validate)
func (sc *syncContext) applyObject(targetObj *unstructured.Unstructured, dryRun bool, force bool) (v1alpha1.ResultCode, string) {
validate := !resource.HasAnnotationOption(targetObj, common.AnnotationSyncOptions, "Validate=false")
message, err := sc.kubectl.ApplyResource(sc.config, targetObj, targetObj.GetNamespace(), dryRun, force, validate)
if err != nil {
return v1alpha1.ResultCodeSyncFailed, err.Error()
}
@@ -757,8 +750,7 @@ func (sc *syncContext) runTasks(tasks syncTasks, dryRun bool) runState {
defer createWg.Done()
logCtx := sc.log.WithFields(log.Fields{"dryRun": dryRun, "task": t})
logCtx.Debug("applying")
validate := !(sc.syncOp.SyncOptions.HasOption("Validate=false") || resource.HasAnnotationOption(t.targetObj, common.AnnotationSyncOptions, "Validate=false"))
result, message := sc.applyObject(t.targetObj, dryRun, sc.syncOp.SyncStrategy.Force(), validate)
result, message := sc.applyObject(t.targetObj, dryRun, sc.syncOp.SyncStrategy.Force())
if result == v1alpha1.ResultCodeSyncFailed {
logCtx.WithField("message", message).Info("apply failed")
runState = failed

View File

@@ -44,7 +44,6 @@ func newTestSyncCtx(resources ...*v1.APIResourceList) *syncContext {
})
sc := syncContext{
config: &rest.Config{},
rawConfig: &rest.Config{},
namespace: test.FakeArgoCDNamespace,
server: test.FakeClusterURL,
syncRes: &v1alpha1.SyncOperationResult{
@@ -366,20 +365,6 @@ func TestSyncOptionValidate(t *testing.T) {
}
}
// make sure Validate means we don't validate
func TestSyncValidate(t *testing.T) {
syncCtx := newTestSyncCtx()
pod := test.NewPod()
pod.SetNamespace(test.FakeArgoCDNamespace)
syncCtx.compareResult = &comparisonResult{managedResources: []managedResource{{Target: pod, Live: pod}}}
syncCtx.syncOp.SyncOptions = SyncOptions{"Validate=false"}
syncCtx.sync()
kubectl := syncCtx.kubectl.(*kubetest.MockKubectlCmd)
assert.False(t, kubectl.LastValidate)
}
func TestSelectiveSyncOnly(t *testing.T) {
syncCtx := newTestSyncCtx()
pod1 := test.NewPod()
@@ -399,40 +384,20 @@ func TestSelectiveSyncOnly(t *testing.T) {
}
func TestUnnamedHooksGetUniqueNames(t *testing.T) {
t.Run("Truncated revision", func(t *testing.T) {
syncCtx := newTestSyncCtx()
syncCtx.syncOp.SyncStrategy.Apply = nil
pod := test.NewPod()
pod.SetName("")
pod.SetAnnotations(map[string]string{common.AnnotationKeyHook: "PreSync,PostSync"})
syncCtx.compareResult = &comparisonResult{hooks: []*unstructured.Unstructured{pod}}
syncCtx := newTestSyncCtx()
syncCtx.syncOp.SyncStrategy.Apply = nil
pod := test.NewPod()
pod.SetName("")
pod.SetAnnotations(map[string]string{common.AnnotationKeyHook: "PreSync,PostSync"})
syncCtx.compareResult = &comparisonResult{hooks: []*unstructured.Unstructured{pod}}
tasks, successful := syncCtx.getSyncTasks()
assert.True(t, successful)
assert.Len(t, tasks, 2)
assert.Contains(t, tasks[0].name(), "foobarb-presync-")
assert.Contains(t, tasks[1].name(), "foobarb-postsync-")
assert.Equal(t, "", pod.GetName())
})
t.Run("Short revision", func(t *testing.T) {
syncCtx := newTestSyncCtx()
syncCtx.syncOp.SyncStrategy.Apply = nil
pod := test.NewPod()
pod.SetName("")
pod.SetAnnotations(map[string]string{common.AnnotationKeyHook: "PreSync,PostSync"})
syncCtx.compareResult = &comparisonResult{hooks: []*unstructured.Unstructured{pod}}
syncCtx.syncRes.Revision = "foobar"
tasks, successful := syncCtx.getSyncTasks()
assert.True(t, successful)
assert.Len(t, tasks, 2)
assert.Contains(t, tasks[0].name(), "foobar-presync-")
assert.Contains(t, tasks[1].name(), "foobar-postsync-")
assert.Equal(t, "", pod.GetName())
})
tasks, successful := syncCtx.getSyncTasks()
assert.True(t, successful)
assert.Len(t, tasks, 2)
assert.Contains(t, tasks[0].name(), "foobarb-presync-")
assert.Contains(t, tasks[1].name(), "foobarb-postsync-")
assert.Equal(t, "", pod.GetName())
}
func TestManagedResourceAreNotNamed(t *testing.T) {

View File

@@ -24,7 +24,7 @@ Install:
Brew users can quickly install the lot:
```bash
brew install go git-lfs kubectl kubectx dep ksonnet/tap/ks helm@2 kustomize
brew install go git-lfs kubectl kubectx dep ksonnet/tap/ks kubernetes-helm kustomize
```
Check the versions:

View File

@@ -38,12 +38,4 @@ make builder-image IMAGE_NAMESPACE=argoproj IMAGE_TAG=v1.0.0
## Public CD
Every commit to master is built and published to `docker.pkg.github.com/argoproj/argo-cd/argocd:<version>-<short-sha>`. The list of images is available at
https://github.com/argoproj/argo-cd/packages.
!!! note
Github docker registry [requires](https://github.community/t5/GitHub-Actions/docker-pull-from-public-GitHub-Package-Registry-fail-with-quot/m-p/32888#M1294) authentication to read
even publicly available packages. Follow the steps from Kubernetes [documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry)
to configure image pull secret if you want to use `docker.pkg.github.com/argoproj/argo-cd/argocd` image.
The image is automatically deployed to the dev Argo CD instance: [https://cd.apps.argoproj.io/](https://cd.apps.argoproj.io/)
[https://cd.apps.argoproj.io/](https://cd.apps.argoproj.io/)

View File

@@ -47,10 +47,6 @@ kubectl -n argocd patch secret argocd-secret \
Another option is to delete both the `admin.password` and `admin.passwordMtime` keys and restart argocd-server. This will set the password back to the pod name as per [the getting started guide](getting_started.md).
## How to disable admin user?
Add `admin.enabled: "false"` to the `argocd-cm` ConfigMap (see [user management](operator-manual/user-management/index.md)).
## Argo CD cannot deploy Helm Chart based applications without internet access, how can I solve it?
Argo CD might fail to generate Helm chart manifests if the chart has dependencies located in external repositories. To solve the problem you need to make sure that `requirements.yaml`

View File

@@ -24,8 +24,8 @@ kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
```
Follow our [getting started guide](getting_started.md). Further user oriented [documentation](user_guide/)
is provided for additional features. Developer oriented [documentation](developer-guide/) is available for people interested in building third-party integrations.
Follow our [getting started guide](getting_started.md). Further [documentation](docs/)
is provided for additional features.
## How it works

View File

@@ -27,11 +27,9 @@ spec:
# Release name override (defaults to application name)
releaseName: guestbook
# Helm values files for overriding values in the helm chart
# The path is relative to the spec.source.path directory defined above
valueFiles:
- values-prod.yaml
# Values file as block file
values: |
ingress:
@@ -92,7 +90,6 @@ spec:
automated:
prune: true # Specifies if resources should be pruned during auto-syncing ( false by default ).
selfHeal: true # Specifies if partial app sync should be executed when resources are changed only in target Kubernetes cluster and no git change detected ( false by default ).
validate: true # Validate resources before applying to k8s, defaults to true.
# Ignore differences at the specified json pointers
ignoreDifferences:

View File

@@ -100,7 +100,7 @@ data:
# List of json pointers in the object to ignore differences
ignoreDifferences: |
jsonPointers:
- /webhooks/0/clientConfig/caBundle
- webhooks/0/clientConfig/caBundle
certmanager.k8s.io/Certificate:
# Lua script for customizing the health status assessment
health.lua: |
@@ -183,16 +183,6 @@ data:
clusters:
- "*.local"
# By default all resource group/kinds are included. The resource.inclusions setting allows customizing
# list of included group/kinds.
resource.inclusions: |
- apiGroups:
- repositories.stash.appscode.com
kinds:
- Snapshot
clusters:
- "*.local"
# Configuration to add a config management plugin.
configManagementPlugins: |
- name: kasane
@@ -208,12 +198,3 @@ data:
# Tracking labels are used to determine which resources need to be deleted when pruning.
# If omitted, Argo CD injects the app name into the label: 'app.kubernetes.io/instance'
application.instanceLabelKey: mycompany.com/appname
# disables admin user. Admin is enabled by default
admin.enabled: "false"
# add an additional local user with apiKey and login capabilities
# apiKey - allows generating API keys
# login - allows to login using UI
accounts.alice: apiKey, login
# disables user. User is enabled by default
accounts.alice.enabled: "false"

View File

@@ -34,10 +34,3 @@ data:
webhook.bitbucketserver.secret: shhhh! it's a bitbucket server secret
# gogs server webhook secret
webhook.gogs.secret: shhhh! it's a gogs server secret
# an additional user password and its last modified time (see user definition in argocd-cm.yaml)
accounts.alice.password:
accounts.alice.passwordMtime:
# list of generated account tokens/api keys
accounts.alice.tokens: |
[{"id":"123","iat":1583789194,"exp":1583789194}]

View File

@@ -14,7 +14,7 @@ can be customized to use alternative toolchain required by your environment.
## Adding Tools Via Volume Mounts
The first technique is to use an `init` container and a `volumeMount` to copy a different version of
The first technique is to use an `init` container and a `volumeMount` to copy a different verison of
a tool into the repo-server container. In the following example, an init container is overwriting
the helm binary with a different version than what is bundled in Argo CD:

View File

@@ -506,7 +506,7 @@ data:
key: key
```
## Resource Exclusion/Inclusion
## Resource Exclusion
Resources can be excluded from discovery and sync so that ArgoCD is unaware of them. For example, `events.k8s.io` and `metrics.k8s.io` are always excluded. Use cases:
@@ -543,25 +543,6 @@ The `resource.exclusions` node is a list of objects. Each object can have:
If all three match, then the resource is ignored.
In addition to exclusions, you might configure the list of included resources using the `resource.inclusions` setting.
By default, all resource group/kinds are included. The `resource.inclusions` setting allows customizing the list of included group/kinds:
```yaml
apiVersion: v1
data:
resource.inclusions: |
- apiGroups:
- "*"
kinds:
- Deployment
clusters:
- https://192.168.0.20
kind: ConfigMap
```
The `resource.inclusions` and `resource.exclusions` might be used together. The final list of resources includes group/kinds specified in `resource.inclusions` minus group/kinds
specified in `resource.exclusions` setting.
Notes:
* Quote globs in your YAML to avoid parsing errors.
@@ -570,7 +551,7 @@ Notes:
## SSO & RBAC
* SSO configuration details: [SSO](./user-management/index.md)
* SSO configuration details: [SSO](./sso/index.md)
* RBAC configuration details: [RBAC](./rbac.md)
## Manage Argo CD Using Argo CD

View File

@@ -1,6 +1,6 @@
# Disaster Recovery
You can use `argocd-util` to import and export all Argo CD data.
You can use `argocd-util` can be used to import and export all Argo CD data.
Make sure you have `~/.kube/config` pointing to your Argo CD cluster.

View File

@@ -241,8 +241,6 @@ http {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
# buffering should be disabled for api/v1/stream/applications to support chunked response
proxy_buffering off;
}
}
}

View File

@@ -2,7 +2,7 @@
The RBAC feature enables restriction of access to Argo CD resources. Argo CD does not have its own
user management system and has only one built-in user `admin`. The `admin` user is a superuser and
it has unrestricted access to the system. RBAC requires [SSO configuration](user-management/index.md). Once SSO is
it has unrestricted access to the system. RBAC requires [SSO configuration](sso/index.md). Once SSO is
configured, additional RBAC roles can be defined, and SSO groups can man be mapped to roles.
## Basic Built-in Roles

View File

@@ -5,7 +5,6 @@ Argo CD is un-opinionated about how secrets are managed. There's many ways to do
* [Bitnami Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets)
* [Godaddy Kubernetes External Secrets](https://github.com/godaddy/kubernetes-external-secrets)
* [Hashicorp Vault](https://www.vaultproject.io)
* [Banzai Cloud Bank-Vaults](https://github.com/banzaicloud/bank-vaults)
* [Helm Secrets](https://github.com/futuresimple/helm-secrets)
* [Kustomize secret generator plugins](https://github.com/kubernetes-sigs/kustomize/blob/fd7a353df6cece4629b8e8ad56b71e30636f38fc/examples/kvSourceGoPlugin.md#secret-values-from-anywhere)
* [aws-secret-operator](https://github.com/mumoshu/aws-secret-operator)

View File

@@ -0,0 +1,8 @@
# Auth0
!!! note "Are you using this? Please contribute!"
If you're using this IdP please consider [contributing](../../developer-guide/site.md) to this document.
<!-- markdownlint-disable MD033 -->
<div style="text-align:center"><img src="../../../assets/argo.png" /></div>
<!-- markdownlint-enable MD033 -->

View File

@@ -1,91 +1,7 @@
# Overview
# SSO Overview
Once installed Argo CD has one built-in `admin` user that has full access to the system. It is recommended to use `admin` user only
for initial configuration and then switch to local users or configure SSO integration.
## Local users/accounts (v1.5)
The local users/accounts feature serving to main use-cases:
* Auth tokens for Argo CD management automation. It is possible to configure an API account with limited permissions and generate an authentication token.
Such token can be used to automatically create applications, projects etc.
* Additional users for a very small team when SSO integration is overkill. The local users don't provide advanced features such as groups,
login history etc. So if you need such features it is strongly recommended to use SSO.
### Create new user
New users should be defined in `argocd-cm` ConfigMap:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
# add an additional local user with apiKey and login capabilities
# apiKey - allows generating API keys
# login - allows to login using UI
accounts.alice: apiKey, login
# disables user. User is enabled by default
accounts.alice.enabled: "false"
```
Each user might have two capabilities:
* apiKey - allows generating authentication tokens for API access
* login - allows to login using UI
### Disable admin user
As soon as additional users are created it is recommended to disable `admin` user:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
admin.enabled: "false"
```
### Manage users
The Argo CD CLI provides set of commands to set user password and generate tokens.
* Get full users list
```bash
argocd account list
```
* Get specific user details
```bash
argocd account get <username>
```
* Set user password
```bash
argocd account update-password \
--account <name> \
--current-password <current-admin> \
--new-password <new-user-password>
```
* Generate auth token
```bash
# if flag --account is omitted then Argo CD generates token for current user
argocd account generate-token --account <username>
```
## SSO
There are two ways that SSO can be configured:
Argo CD does not have any local users other than the built-in `admin` user. All other users are
expected to login via SSO. There are two ways that SSO can be configured:
* [Bundled Dex OIDC provider](#dex) - use this option if your current provider does not support OIDC (e.g. SAML,
LDAP) or if you wish to leverage any of Dex's connector features (e.g. the ability to map GitHub

View File

@@ -54,11 +54,6 @@
p, role:org-admin, repositories, delete, *, allow
g, "Grp Argo CD", role:org-admin
5. Mapping role from jwt token to argo
If you want to map the roles from the jwt token to match the default roles (readonly and admin) then you must change the scope variable in the rbac-configmap.
scopes: '[roles, email]'
## With Dex

View File

@@ -74,7 +74,7 @@ oidc.config: |
issuer: https://yourorganization.oktapreview.com
clientID: 0oaltaqg3oAIf2NOa0h3
clientSecret: ZXF_CfUc-rtwNfzFecGquzdeJ_MxM4sGc8pDT2Tg6t
requestedScopes: ["openid", "profile", "email", "groups"]
requestedScopes: ["openid", "profile", "email", "groups"].
requestedIDTokenClaims: {"groups": {"essential": true}}
```
<!-- markdownlint-enable MD046 -->

View File

@@ -1,66 +0,0 @@
# Auth0
## User-definitions
User-definitions in Auth0 is out of scope for this guide. Add them directly in Auth0 database, use an enterprise registry, or "social login".
*Note*: all users have access to all Auth0 defined apps unless you restrict access via configuration - keep this in mind if argo is exposed on the internet or else anyone can login.
## Registering the app with Auth0
Follow the [register app](https://auth0.com/docs/dashboard/guides/applications/register-app-spa) instructions to create the argocd app in Auth0. In the app definition:
* Take note of the _clientId_ and _clientSecret_ values.
* Register login url as https://your.argoingress.address/login
* Set allowed callback url to https://your.argoingress.address/auth/callback
* Under connections, select the user-registries you want to use with argo
Any other settings are non-essential for the authentication to work.
## Adding authorization rules to Auth0
Follow Auth0 [authorization guide](https://auth0.com/docs/authorization) to setup authorization.
The important part to note here is that group-membership is a non-standard claim, and hence is required to be put under a FQDN claim name, for instance `http://your.domain/groups`.
## Configuring argo
### Configure OIDC for ArgoCD
`kubectl edit configmap argocd-cm`
```
...
data:
application.instanceLabelKey: argocd.argoproj.io/instance
oidc.config: |
name: Auth0
issuer: https://<yourtenant>.<eu|us>.auth0.com/
clientID: <theClientId>
clientSecret: <theClientSecret>
requestedScopes:
- openid
- profile
- email
# not strictly nesscessary - but good practice:
- 'http://your.domain/groups'
...
```
### Configure RBAC for ArgoCD
`kubectl edit configmap argocd-rbac-cm` (or use helm values).
```
...
data:
policy.csv: |
# let members with group someProjectGroup handle apps in someProject
# this can also be defined in the UI in the group-definition to avoid doing it there in the configmap
p, someProjectGroup, applications, *, someProject/*, allow
# let the group membership argocd-admins from OIDC become role:admin - needs to go into the configmap
g, argocd-global-admins, role:admin
policy.default: role:readonly
# essential to get argo to use groups for RBAC:
scopes: '[http://your.domain/groups, email]'
...
```

View File

@@ -16,7 +16,7 @@ arbitrary value in the secret. This value will be used when configuring the webh
![Add Webhook](../assets/webhook-config.png "Add Webhook")
### 2. Configure Argo CD With The WebHook Secret (Optional)
### 2. Configure Argo CD With The WebHook Secret Optional)
Configuring a webhook shared secret is optional, since Argo CD will still refresh applications
related to the Git repository, even with unauthenticated webhook events. This is safe to do since

View File

@@ -7,7 +7,7 @@ Apps can be deleted with or without a cascade option. A **cascade delete**, dele
To perform a non-cascade delete:
```bash
argocd app delete APPNAME --cascade=false
argocd app delete APPNAME
```
To perform a cascade delete:
@@ -16,12 +16,6 @@ To perform a cascade delete:
argocd app delete APPNAME --cascade
```
or
```bash
argocd app delete APPNAME
```
# Deletion Using `kubectl`
To perform a non-cascade delete:

View File

@@ -37,22 +37,6 @@ spec:
syncPolicy:
automated:
prune: true
```
## Automatic Self-Healing
By default, changes that are made to the live cluster will not trigger automated sync. To enable automatic sync
when the live cluster's state deviates from the state defined in Git, run:
```bash
argocd app set <APPNAME> --self-heal
```
Or by setting the self heal option to true in the automated sync policy:
```yaml
spec:
syncPolicy:
automated:
selfHeal: true
```
@@ -64,7 +48,7 @@ spec:
application parameters. If the most recent successful sync in the history was already performed
against the same commit-SHA and parameters, a second sync will not be attempted, unless `selfHeal` flag is set to true.
* If `selfHeal` flag is set to true then sync will be attempted again after self heal timeout (5 seconds by default)
which is controlled by `--self-heal-timeout-seconds` flag of `argocd-application-controller` deployment.
which is controller by `--self-heal-timeout-seconds` flag of `argocd-application-controller` deployment.
* Automatic sync will not reattempt a sync if the previous sync attempt against the same commit-SHA
and parameters had failed.

View File

@@ -11,7 +11,7 @@ submitted to Kubernetes in a manner which contradicts Git.
which generates different data every time `helm template` is invoked.
* For Horizontal Pod Autoscaling (HPA) objects, the HPA controller is known to reorder `spec.metrics`
in a specific order. See [kubernetes issue #74099](https://github.com/kubernetes/kubernetes/issues/74099).
To work around this, you can order `spec.metrics` in Git in the same order that the controller
To work around this, you can order `spec.replicas` in Git in the same order that the controller
prefers.
In case it is impossible to fix the upstream issue, Argo CD allows you to optionally ignore differences of problematic resources.
@@ -19,7 +19,7 @@ The diffing customization can be configured for single or multiple application r
## Application Level Configuration
Argo CD allows ignoring differences at a specific JSON path, using [RFC6902 JSON patches](http://tools.ietf.org/html/rfc6902). The following sample application is configured to ignore differences in `spec.replicas` for all deployments:
Argo CD allows ignoring differences at a specific JSON path. The following sample application is configured to ignore differences in `spec.replicas` for all deployments:
```yaml
spec:

View File

@@ -15,7 +15,7 @@ To use Kustomize with an overlay, point your path to the overlay.
If you have remote bases that are either (a) HTTPS and need username/password (b) SSH and need SSH private key, then they'll inherit that from the app's repo.
This will work if the remote bases uses the same credentials/private key. It will not work if they use different ones. For security reasons your app only ever knows about its own repo (not other team's or users repos), and so you won't be able to access other private repo, even if Argo CD knows about them.
This will work if the remote bases uses the same credentials/private key. It will not work if they use different ones. For security reasons your app only ever knows about it's own repo (not other team's or users repos), and so you won't be able to access other private repo, even if Argo CD knows about them.
Read more about [private repos](private-repositories.md).
@@ -38,4 +38,4 @@ data:
## Build Environment
Kustomize does not support parameters and therefore cannot support the standard [build environment](build-environment.md).
Kustomize does not support parameters and therefore cannot support the standard [build environment](build-environment.md).

View File

@@ -99,9 +99,6 @@ Using the UI:
!!!note
When pasting SSH private key in the UI, make sure there are no unintended line breaks or additional characters in the text area
!!!note
When your SSH repository is served from a non-standard port, you have to use `ssh://`-style URLs to specify your repository. The scp-style `git@yourgit.com:yourrepo` URLs do **not** support port specification, and will treat any port number as part of the repository's path.
> earlier than v1.2
The Argo CD UI don't support configuring SSH credentials. The SSH credentials can only be configured using the Argo CD CLI:

View File

@@ -170,7 +170,7 @@ argocd app get $PROJ-$ROLE --auth-token $JWT
# Removing the policy we added and adding one with a wildcard.
argocd proj role remove-policy $PROJ $TOKEN -a get -o $PROJ-$TOKEN
argocd proj role add-policy $PROJ $ROLE -a get --permission allow -o '*'
argocd proj role remove-policy $PROJ $TOKEN -a get -o '*'
# The wildcard allows us to access the application due to the wildcard.
argocd app get $PROJ-$TOKEN --auth-token $JWT
argocd proj role get $PROJ

View File

@@ -12,7 +12,7 @@ Kubernetes rolling update strategy.
## Usage
Hooks are simply Kubernetes manifests inside your Argo CD Application annotated with `argocd.argoproj.io/hook`, e.g.:
Hooks are simply Kubernetes manifests annotated with `argocd.argoproj.io/hook`, e.g.:
```yaml
apiVersion: batch/v1

View File

@@ -1072,7 +1072,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 5,
"w": 24,
@@ -1164,7 +1164,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 5,
"w": 24,
@@ -1253,7 +1253,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 8,
"w": 24,
@@ -1288,7 +1288,7 @@
"expr": "sum(increase(argocd_app_reconcile_count{namespace=~\"$namespace\", project=~\"$project\"}[10m])) by (namespace, project)",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{namespace}},{{project}}",
"legendFormat": "{{namespace}}",
"refId": "A"
}
],
@@ -1339,7 +1339,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 8,
"w": 24,
@@ -1374,7 +1374,7 @@
"expr": "sum(increase(argocd_app_k8s_request_total{namespace=~\"$namespace\",project=~\"$project\"}[5m])) by (namespace, project)",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{namespace}},{{project}}",
"legendFormat": "{{namespace}}",
"refId": "A"
}
],
@@ -1489,7 +1489,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 8,
"w": 24,
@@ -1575,7 +1575,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 8,
"w": 24,
@@ -1673,7 +1673,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 8,
"w": 24,
@@ -1759,7 +1759,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 24,
@@ -1845,7 +1845,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 24,
@@ -1946,7 +1946,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 12,
@@ -1978,10 +1978,10 @@
"steppedLine": false,
"targets": [
{
"expr": "increase(grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"application.ApplicationService\",namespace=~\"$namespace\"}[10m]) > 0 or on() vector (0)",
"expr": "grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"application.ApplicationService\",namespace=~\"$namespace\"} > 0",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{grpc_code}},{{grpc_method}},{{pod}}",
"legendFormat": "{{grpc_code}},{{grpc_method}}",
"refId": "A"
}
],
@@ -2040,7 +2040,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 12,
@@ -2072,10 +2072,10 @@
"steppedLine": false,
"targets": [
{
"expr": "increase(grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"cluster.ClusterService\",namespace=~\"$namespace\"}[10m]) > 0 or on() vector (0)",
"expr": "grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"cluster.ClusterService\",namespace=~\"$namespace\"} > 0",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{grpc_code}},{{grpc_method}},{{pod}}",
"legendFormat": "{{grpc_code}},{{grpc_method}}",
"refId": "A"
}
],
@@ -2134,7 +2134,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 12,
@@ -2166,10 +2166,10 @@
"steppedLine": false,
"targets": [
{
"expr": "increase(grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"project.ProjectService\",namespace=~\"$namespace\"}[10m]) > 0 or on() vector (0)",
"expr": "grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"project.ProjectService\",namespace=~\"$namespace\"} > 0",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{grpc_code}},{{grpc_method}},{{pod}}",
"legendFormat": "{{grpc_code}},{{grpc_method}}",
"refId": "A"
}
],
@@ -2228,7 +2228,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 12,
@@ -2260,10 +2260,10 @@
"steppedLine": false,
"targets": [
{
"expr": "increase(grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"repository.RepositoryService\",namespace=~\"$namespace\"}[10m]) > 0 or on() vector (0)",
"expr": "grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"repository.RepositoryService\",namespace=~\"$namespace\"} > 0",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{grpc_code}},{{grpc_method}},{{pod}}",
"legendFormat": "{{grpc_code}},{{grpc_method}}",
"refId": "A"
}
],
@@ -2322,7 +2322,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 12,
@@ -2354,10 +2354,10 @@
"steppedLine": false,
"targets": [
{
"expr": "increase(grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"session.SessionService\",namespace=~\"$namespace\"}[10m]) > 0 or on() vector (0)",
"expr": "grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"session.SessionService\",namespace=~\"$namespace\"} > 0",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{grpc_code}},{{grpc_method}},{{pod}}",
"legendFormat": "{{grpc_code}},{{grpc_method}}",
"refId": "A"
}
],
@@ -2416,7 +2416,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 12,
@@ -2448,10 +2448,10 @@
"steppedLine": false,
"targets": [
{
"expr": "increase(grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"version.VersionService\",namespace=~\"$namespace\"}[10m]) > 0 or on() vector (0)",
"expr": "grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"version.VersionService\",namespace=~\"$namespace\"} > 0",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{grpc_code}},{{grpc_method}},{{pod}}",
"legendFormat": "{{grpc_code}},{{grpc_method}}",
"refId": "A"
}
],
@@ -2510,7 +2510,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 12,
@@ -2542,10 +2542,10 @@
"steppedLine": false,
"targets": [
{
"expr": "increase(grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"account.AccountService\",namespace=~\"$namespace\"}[10m]) > 1 or on() vector (0)",
"expr": "grpc_server_handled_total{job=\"argocd-server-metrics\",grpc_service=\"account.AccountService\",namespace=~\"$namespace\"} >1",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{grpc_code}},{{grpc_method}},{{pod}}",
"legendFormat": "{{grpc_code}},{{grpc_method}}",
"refId": "A"
}
],
@@ -2621,7 +2621,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 8,
"w": 24,
@@ -2707,7 +2707,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 9,
"w": 24,
@@ -2793,7 +2793,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 8,
"w": 12,
@@ -2827,7 +2827,6 @@
"expr": "sum(increase(argocd_git_request_total{request_type=\"ls-remote\", namespace=~\"$namespace\"}[10m])) by (namespace)",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{namespace}}",
"refId": "A"
}
],
@@ -2878,7 +2877,7 @@
"dashLength": 10,
"dashes": false,
"datasource": "$Source",
"fill": 0,
"fill": 1,
"gridPos": {
"h": 8,
"w": 12,
@@ -2912,7 +2911,6 @@
"expr": "sum(increase(argocd_git_request_total{request_type=\"fetch\", namespace=~\"$namespace\"}[10m])) by (namespace)",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{namespace}}",
"refId": "A"
}
],
@@ -3062,5 +3060,5 @@
"timezone": "",
"title": "ArgoCD",
"uid": "BjWwX3jik",
"version": 7
}
"version": 5
}

View File

@@ -1,4 +1,4 @@
FROM golang:1.14.0 as builder
FROM golang:1.12.6 as builder
RUN apt-get update && apt-get install -y zip
@@ -9,7 +9,7 @@ RUN ./install.sh codegen-tools
RUN ./install.sh codegen-go-tools
RUN mkdir -p /home/user && chmod 777 /home/user
RUN HELM_HOME=/home/user/.helm helm2 init --client-only
RUN HELM_HOME=/home/user/.helm helm init --client-only
RUN mkdir -p /go/pkg && chmod 777 /go/pkg

View File

@@ -114,9 +114,7 @@ clean_swagger() {
find "${SWAGGER_ROOT}" -name '*.swagger.json' -delete
}
echo "If additional types are added, the number of expected collisions may need to be increased"
EXPECTED_COLLISION_COUNT=32
collect_swagger server ${EXPECTED_COLLISION_COUNT}
collect_swagger server 31
clean_swagger server
clean_swagger reposerver
clean_swagger controller

View File

@@ -0,0 +1,8 @@
#!/bin/bash
set -eux -o pipefail
AWS_IAM_AUTHENTICATOR_VERSION=0.4.0-alpha.1
[ -e $DOWNLOADS/aws-iam-authenticator ] || curl -sLf --retry 3 -o $DOWNLOADS/aws-iam-authenticator https://github.com/kubernetes-sigs/aws-iam-authenticator/releases/download/${AWS_IAM_AUTHENTICATOR_VERSION}/aws-iam-authenticator_${AWS_IAM_AUTHENTICATOR_VERSION}_linux_amd64
cp $DOWNLOADS/aws-iam-authenticator $BIN/
chmod +x $BIN/aws-iam-authenticator
aws-iam-authenticator version

View File

@@ -1,4 +1,4 @@
#!/bin/bash
set -eux -o pipefail
KUSTOMIZE_VERSION=2.0.3 "$(dirname $0)/../install.sh" helm2-linux jq-linux kustomize-linux protoc-linux swagger-linux
KUSTOMIZE_VERSION=2.0.3 "$(dirname $0)/../install.sh" helm-linux jq-linux kustomize-linux protoc-linux swagger-linux

View File

@@ -1,7 +1,7 @@
#!/bin/bash
set -eux -o pipefail
[ -e $DOWNLOADS/helm.tar.gz ] || curl -sLf --retry 3 -o $DOWNLOADS/helm.tar.gz https://get.helm.sh/helm-v3.1.1-linux-amd64.tar.gz
mkdir -p /tmp/helm && tar -C /tmp/helm -xf $DOWNLOADS/helm.tar.gz
cp /tmp/helm/linux-amd64/helm $BIN/helm
[ -e $DOWNLOADS/helm.tar.gz ] || curl -sLf --retry 3 -o $DOWNLOADS/helm.tar.gz https://storage.googleapis.com/kubernetes-helm/helm-v2.15.2-linux-amd64.tar.gz
tar -C /tmp/ -xf $DOWNLOADS/helm.tar.gz
cp /tmp/linux-amd64/helm $BIN/helm
helm version --client

View File

@@ -1,7 +0,0 @@
#!/bin/bash
set -eux -o pipefail
[ -e $DOWNLOADS/helm2.tar.gz ] || curl -sLf --retry 3 -o $DOWNLOADS/helm2.tar.gz https://storage.googleapis.com/kubernetes-helm/helm-v2.15.2-linux-amd64.tar.gz
mkdir -p /tmp/helm2 && tar -C /tmp/helm2 -xf $DOWNLOADS/helm2.tar.gz
cp /tmp/helm2/linux-amd64/helm $BIN/helm2
helm2 version --client

View File

@@ -20,4 +20,4 @@ report() {
trap 'report' EXIT
go test -failfast $* 2>&1 | tee $TEST_RESULTS/test.out
go test -v $* 2>&1 | tee $TEST_RESULTS/test.out

View File

@@ -14,8 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
export GO111MODULE=off
set -o errexit
set -o nounset
set -o pipefail

View File

@@ -20,7 +20,7 @@ spec:
- name: copyutil
image: argoproj/argocd:latest
imagePullPolicy: Always
command: [cp, -n, /usr/local/bin/argocd-util, /shared]
command: [cp, /usr/local/bin/argocd-util, /shared]
volumeMounts:
- mountPath: /shared
name: static-files

View File

@@ -12,4 +12,4 @@ bases:
images:
- name: argoproj/argocd
newName: argoproj/argocd
newTag: v1.5.2
newTag: v1.4.3

View File

@@ -35,18 +35,6 @@ spec:
operation:
description: Operation contains requested operation parameters.
properties:
initiatedBy:
description: OperationInitiator holds information about the operation
initiator
properties:
automated:
description: Automated is set to true if operation was initiated
automatically by the application controller.
type: boolean
username:
description: Name of a user who started operation.
type: string
type: object
sync:
description: SyncOperation contains sync operation details.
properties:
@@ -138,21 +126,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the helm
template
items:
description: HelmFileParameter is a file parameter to
a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -268,11 +241,6 @@ spec:
required:
- repoURL
type: object
syncOptions:
description: SyncOptions provide per-sync sync-options, e.g. Validate=false
items:
type: string
type: array
syncStrategy:
description: SyncStrategy describes how to perform the sync
properties:
@@ -423,21 +391,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the helm
template
items:
description: HelmFileParameter is a file parameter to a helm
template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -565,11 +518,6 @@ spec:
description: 'SelfHeal enables auto-syncing if (default: false)'
type: boolean
type: object
syncOptions:
description: Options allow youe to specify whole app sync-options
items:
type: string
type: array
type: object
required:
- destination
@@ -678,22 +626,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the
helm template
items:
description: HelmFileParameter is a file parameter to
a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm
parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -837,18 +769,6 @@ spec:
operation:
description: Operation is the original requested operation
properties:
initiatedBy:
description: OperationInitiator holds information about the
operation initiator
properties:
automated:
description: Automated is set to true if operation was initiated
automatically by the application controller.
type: boolean
username:
description: Name of a user who started operation.
type: string
type: object
sync:
description: SyncOperation contains sync operation details.
properties:
@@ -945,23 +865,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters
to the helm template
items:
description: HelmFileParameter is a file parameter
to a helm template
properties:
name:
description: Name is the name of the helm
parameter
type: string
path:
description: Path is the path value for the
helm parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm
template
@@ -1085,12 +988,6 @@ spec:
required:
- repoURL
type: object
syncOptions:
description: SyncOptions provide per-sync sync-options,
e.g. Validate=false
items:
type: string
type: array
syncStrategy:
description: SyncStrategy describes how to perform the sync
properties:
@@ -1235,22 +1132,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the
helm template
items:
description: HelmFileParameter is a file parameter
to a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm
parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -1508,22 +1389,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the
helm template
items:
description: HelmFileParameter is a file parameter
to a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm
parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:

View File

@@ -18,4 +18,4 @@ bases:
images:
- name: argoproj/argocd
newName: argoproj/argocd
newTag: v1.5.2
newTag: v1.4.3

View File

@@ -13,5 +13,11 @@ spec:
- "20"
- --operation-processors
- "10"
- --redis
- "argocd-redis-ha-haproxy:6379"
- --sentinel
- $(ARGOCD_REDIS_HA_ANNOUNCE_0_SERVICE):26379
- --sentinel
- $(ARGOCD_REDIS_HA_ANNOUNCE_1_SERVICE):26379
- --sentinel
- $(ARGOCD_REDIS_HA_ANNOUNCE_2_SERVICE):26379
- --sentinelmaster
- argocd

View File

@@ -25,5 +25,11 @@ spec:
command:
- uid_entrypoint.sh
- argocd-repo-server
- --redis
- "argocd-redis-ha-haproxy:6379"
- --sentinel
- $(ARGOCD_REDIS_HA_ANNOUNCE_0_SERVICE):26379
- --sentinel
- $(ARGOCD_REDIS_HA_ANNOUNCE_1_SERVICE):26379
- --sentinel
- $(ARGOCD_REDIS_HA_ANNOUNCE_2_SERVICE):26379
- --sentinelmaster
- argocd

View File

@@ -26,5 +26,11 @@ spec:
- argocd-server
- --staticassets
- /shared/app
- --redis
- "argocd-redis-ha-haproxy:6379"
- --sentinel
- $(ARGOCD_REDIS_HA_ANNOUNCE_0_SERVICE):26379
- --sentinel
- $(ARGOCD_REDIS_HA_ANNOUNCE_1_SERVICE):26379
- --sentinel
- $(ARGOCD_REDIS_HA_ANNOUNCE_2_SERVICE):26379
- --sentinelmaster
- argocd

View File

@@ -1,6 +1,6 @@
dependencies:
- name: redis-ha
repository: https://kubernetes-charts.storage.googleapis.com
version: 4.3.4
digest: sha256:d130faa98f99a99e503bce560bcec26e1dc0a988775a6609e39a8d855ec687d5
generated: "2020-02-20T10:42:01.98332-08:00"
version: 3.3.1
digest: sha256:3e273208c389589d3d8935ddc39bf245f72c3ea0b6d3e61c4dc0862b7c3839eb
generated: 2019-03-19T21:34:14.183861-07:00

View File

@@ -1,4 +1,4 @@
dependencies:
- name: redis-ha
version: 4.3.4
version: 3.3.1
repository: https://kubernetes-charts.storage.googleapis.com

View File

@@ -5,20 +5,18 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-redis-ha-configmap
namespace: default
labels:
heritage: Tiller
release: argocd
chart: redis-ha-4.3.4
chart: redis-ha-3.3.1
app: argocd-redis-ha
data:
redis.conf: |
dir "/data"
port 6379
maxmemory 0
maxmemory-policy volatile-lru
min-replicas-max-lag 5
min-replicas-to-write 1
min-slaves-max-lag 5
min-slaves-to-write 1
rdbchecksum yes
rdbcompression yes
repl-diskless-sync yes
@@ -26,10 +24,9 @@ data:
sentinel.conf: |
dir "/data"
sentinel down-after-milliseconds argocd 10000
sentinel failover-timeout argocd 180000
maxclients 10000
sentinel parallel-syncs argocd 5
sentinel down-after-milliseconds argocd 10000
sentinel failover-timeout argocd 180000
sentinel parallel-syncs argocd 5
init.sh: |
HOSTNAME="$(hostname)"
@@ -45,7 +42,7 @@ data:
set -eu
sentinel_update() {
echo "Updating sentinel config with master $MASTER"
echo "Updating sentinel config"
eval MY_SENTINEL_ID="\${SENTINEL_ID_$INDEX}"
sed -i "1s/^/sentinel myid $MY_SENTINEL_ID\\n/" "$SENTINEL_CONF"
sed -i "2s/^/sentinel monitor $MASTER_GROUP $1 $REDIS_PORT $QUORUM \\n/" "$SENTINEL_CONF"
@@ -88,7 +85,7 @@ data:
echo "Attempting to find master"
if [ "$(redis-cli -h "$MASTER" ping)" != "PONG" ]; then
echo "Can't ping master, attempting to force failover"
if redis-cli -h "$SERVICE" -p "$SENTINEL_PORT" sentinel failover "$MASTER_GROUP" | grep -q 'NOGOODSLAVE' ; then
if redis-cli -h "$SERVICE" -p "$SENTINEL_PORT" sentinel failover "$MASTER_GROUP" | grep -q 'NOGOODSLAVE' ; then
setup_defaults
return 0
fi
@@ -125,140 +122,53 @@ data:
if [ "${AUTH:-}" ]; then
echo "Setting auth values"
ESCAPED_AUTH=$(echo "$AUTH" | sed -e 's/[\/&]/\\&/g');
sed -i "s/replace-default-auth/${ESCAPED_AUTH}/" "$REDIS_CONF" "$SENTINEL_CONF"
sed -i "s/replace-default-auth/$AUTH/" "$REDIS_CONF" "$SENTINEL_CONF"
fi
echo "Ready..."
haproxy.cfg: |-
defaults REDIS
mode tcp
timeout connect 4s
timeout server 30s
timeout client 30s
timeout check 2s
---
# Source: redis-ha/charts/redis-ha/templates/redis-ha-healthchecks.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-redis-ha-probes
labels:
heritage: Tiller
release: argocd
chart: redis-ha-3.3.1
app: argocd-redis-ha
data:
check-quorum.sh: |
#!/bin/sh
set -eu
MASTER_GROUP="argocd"
SENTINEL_PORT=26379
REDIS_PORT=6379
NUM_SLAVES=$(redis-cli -p "$SENTINEL_PORT" sentinel master argocd | awk '/num-slaves/{getline; print}')
MIN_SLAVES=1
listen health_check_http_url
bind :8888
mode http
monitor-uri /healthz
option dontlognull
# Check Sentinel and whether they are nominated master
backend check_if_redis_is_master_0
mode tcp
option tcp-check
tcp-check connect
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check send SENTINEL\ get-master-addr-by-name\ argocd\r\n
tcp-check expect string REPLACE_ANNOUNCE0
tcp-check send QUIT\r\n
tcp-check expect string +OK
server R0 argocd-redis-ha-announce-0:26379 check inter 3s
server R1 argocd-redis-ha-announce-1:26379 check inter 3s
server R2 argocd-redis-ha-announce-2:26379 check inter 3s
# Check Sentinel and whether they are nominated master
backend check_if_redis_is_master_1
mode tcp
option tcp-check
tcp-check connect
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check send SENTINEL\ get-master-addr-by-name\ argocd\r\n
tcp-check expect string REPLACE_ANNOUNCE1
tcp-check send QUIT\r\n
tcp-check expect string +OK
server R0 argocd-redis-ha-announce-0:26379 check inter 3s
server R1 argocd-redis-ha-announce-1:26379 check inter 3s
server R2 argocd-redis-ha-announce-2:26379 check inter 3s
# Check Sentinel and whether they are nominated master
backend check_if_redis_is_master_2
mode tcp
option tcp-check
tcp-check connect
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check send SENTINEL\ get-master-addr-by-name\ argocd\r\n
tcp-check expect string REPLACE_ANNOUNCE2
tcp-check send QUIT\r\n
tcp-check expect string +OK
server R0 argocd-redis-ha-announce-0:26379 check inter 3s
server R1 argocd-redis-ha-announce-1:26379 check inter 3s
server R2 argocd-redis-ha-announce-2:26379 check inter 3s
if [ "$1" = "$SENTINEL_PORT" ]; then
if redis-cli -p "$SENTINEL_PORT" sentinel ckquorum "$MASTER_GROUP" | grep -q NOQUORUM ; then
echo "ERROR: NOQUORUM. Sentinel quorum check failed, not enough sentinels found"
exit 1
fi
elif [ "$1" = "$REDIS_PORT" ]; then
if [ "$MIN_SLAVES" -gt "$NUM_SLAVES" ]; then
echo "Could not find enough replicating slaves. Needed $MIN_SLAVES but found $NUM_SLAVES"
exit 1
fi
fi
sh /probes/readiness.sh "$1"
# decide redis backend to use
#master
frontend ft_redis_master
bind *:6379
use_backend bk_redis_master
# Check all redis servers to see if they think they are master
backend bk_redis_master
mode tcp
option tcp-check
tcp-check connect
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check send info\ replication\r\n
tcp-check expect string role:master
tcp-check send QUIT\r\n
tcp-check expect string +OK
use-server R0 if { srv_is_up(R0) } { nbsrv(check_if_redis_is_master_0) ge 2 }
server R0 argocd-redis-ha-announce-0:6379 check inter 3s fall 1 rise 1
use-server R1 if { srv_is_up(R1) } { nbsrv(check_if_redis_is_master_1) ge 2 }
server R1 argocd-redis-ha-announce-1:6379 check inter 3s fall 1 rise 1
use-server R2 if { srv_is_up(R2) } { nbsrv(check_if_redis_is_master_2) ge 2 }
server R2 argocd-redis-ha-announce-2:6379 check inter 3s fall 1 rise 1
haproxy_init.sh: |
HAPROXY_CONF=/data/haproxy.cfg
cp /readonly/haproxy.cfg "$HAPROXY_CONF"
for loop in $(seq 1 10); do
getent hosts argocd-redis-ha-announce-0 && break
echo "Waiting for service argocd-redis-ha-announce-0 to be ready ($loop) ..." && sleep 1
done
ANNOUNCE_IP0=$(getent hosts "argocd-redis-ha-announce-0" | awk '{ print $1 }')
if [ -z "$ANNOUNCE_IP0" ]; then
echo "Could not resolve the announce ip for argocd-redis-ha-announce-0"
exit 1
fi
sed -i "s/REPLACE_ANNOUNCE0/$ANNOUNCE_IP0/" "$HAPROXY_CONF"
readiness.sh: |
#!/bin/sh
set -eu
CHECK_SERVER="$(redis-cli -p "$1" ping)"
if [ "${AUTH:-}" ]; then
echo "Setting auth values"
ESCAPED_AUTH=$(echo "$AUTH" | sed -e 's/[\/&]/\\&/g');
sed -i "s/REPLACE_AUTH_SECRET/${ESCAPED_AUTH}/" "$HAPROXY_CONF"
fi
for loop in $(seq 1 10); do
getent hosts argocd-redis-ha-announce-1 && break
echo "Waiting for service argocd-redis-ha-announce-1 to be ready ($loop) ..." && sleep 1
done
ANNOUNCE_IP1=$(getent hosts "argocd-redis-ha-announce-1" | awk '{ print $1 }')
if [ -z "$ANNOUNCE_IP1" ]; then
echo "Could not resolve the announce ip for argocd-redis-ha-announce-1"
exit 1
fi
sed -i "s/REPLACE_ANNOUNCE1/$ANNOUNCE_IP1/" "$HAPROXY_CONF"
if [ "${AUTH:-}" ]; then
echo "Setting auth values"
ESCAPED_AUTH=$(echo "$AUTH" | sed -e 's/[\/&]/\\&/g');
sed -i "s/REPLACE_AUTH_SECRET/${ESCAPED_AUTH}/" "$HAPROXY_CONF"
fi
for loop in $(seq 1 10); do
getent hosts argocd-redis-ha-announce-2 && break
echo "Waiting for service argocd-redis-ha-announce-2 to be ready ($loop) ..." && sleep 1
done
ANNOUNCE_IP2=$(getent hosts "argocd-redis-ha-announce-2" | awk '{ print $1 }')
if [ -z "$ANNOUNCE_IP2" ]; then
echo "Could not resolve the announce ip for argocd-redis-ha-announce-2"
exit 1
fi
sed -i "s/REPLACE_ANNOUNCE2/$ANNOUNCE_IP2/" "$HAPROXY_CONF"
if [ "${AUTH:-}" ]; then
echo "Setting auth values"
ESCAPED_AUTH=$(echo "$AUTH" | sed -e 's/[\/&]/\\&/g');
sed -i "s/REPLACE_AUTH_SECRET/${ESCAPED_AUTH}/" "$HAPROXY_CONF"
if [ "$CHECK_SERVER" != "PONG" ]; then
echo "Server check failed with: $CHECK_SERVER"
exit 1
fi
---
@@ -268,25 +178,10 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: argocd-redis-ha
namespace: default
labels:
heritage: Tiller
release: argocd
chart: redis-ha-4.3.4
app: argocd-redis-ha
---
# Source: redis-ha/charts/redis-ha/templates/redis-haproxy-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: argocd-redis-ha-haproxy
namespace: default
labels:
heritage: Tiller
release: argocd
chart: redis-ha-4.3.4
chart: redis-ha-3.3.1
app: argocd-redis-ha
---
@@ -296,11 +191,10 @@ apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: argocd-redis-ha
namespace: default
labels:
heritage: Tiller
release: argocd
chart: redis-ha-4.3.4
chart: redis-ha-3.3.1
app: argocd-redis-ha
rules:
- apiGroups:
@@ -317,11 +211,10 @@ kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: argocd-redis-ha
namespace: default
labels:
heritage: Tiller
release: argocd
chart: redis-ha-4.3.4
chart: redis-ha-3.3.1
app: argocd-redis-ha
subjects:
- kind: ServiceAccount
@@ -339,12 +232,11 @@ apiVersion: v1
kind: Service
metadata:
name: argocd-redis-ha-announce-0
namespace: default
labels:
app: redis-ha
heritage: "Tiller"
release: "argocd"
chart: redis-ha-4.3.4
chart: redis-ha-3.3.1
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
@@ -368,12 +260,11 @@ apiVersion: v1
kind: Service
metadata:
name: argocd-redis-ha-announce-1
namespace: default
labels:
app: redis-ha
heritage: "Tiller"
release: "argocd"
chart: redis-ha-4.3.4
chart: redis-ha-3.3.1
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
@@ -397,12 +288,11 @@ apiVersion: v1
kind: Service
metadata:
name: argocd-redis-ha-announce-2
namespace: default
labels:
app: redis-ha
heritage: "Tiller"
release: "argocd"
chart: redis-ha-4.3.4
chart: redis-ha-3.3.1
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
@@ -428,12 +318,11 @@ apiVersion: v1
kind: Service
metadata:
name: argocd-redis-ha
namespace: default
labels:
app: redis-ha
heritage: "Tiller"
release: "argocd"
chart: redis-ha-4.3.4
chart: redis-ha-3.3.1
annotations:
spec:
type: ClusterIP
@@ -450,140 +339,6 @@ spec:
selector:
release: argocd
app: redis-ha
---
# Source: redis-ha/charts/redis-ha/templates/redis-haproxy-service.yaml
apiVersion: v1
kind: Service
metadata:
name: argocd-redis-ha-haproxy
namespace: default
labels:
app: redis-ha
heritage: "Tiller"
release: "argocd"
chart: redis-ha-4.3.4
component: argocd-redis-ha-haproxy
annotations:
spec:
type: ClusterIP
ports:
- name: haproxy
port: 6379
protocol: TCP
targetPort: redis
selector:
release: argocd
app: redis-ha-haproxy
---
# Source: redis-ha/charts/redis-ha/templates/redis-haproxy-deployment.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: argocd-redis-ha-haproxy
namespace: default
labels:
app: redis-ha
heritage: "Tiller"
release: "argocd"
chart: redis-ha-4.3.4
spec:
strategy:
type: RollingUpdate
revisionHistoryLimit: 1
replicas: 3
selector:
matchLabels:
app: redis-ha-haproxy
release: argocd
template:
metadata:
name: argocd-redis-ha-haproxy
labels:
app: redis-ha-haproxy
release: argocd
annotations:
checksum/config: 790be9eae7c7e468c497c0256949ab96cb3f14b935c6702424647c3c60fba91c
spec:
# Needed when using unmodified rbac-setup.yml
serviceAccountName: argocd-redis-ha-haproxy
nodeSelector:
{}
tolerations:
null
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: redis-ha-haproxy
release: argocd
topologyKey: kubernetes.io/hostname
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: redis-ha-haproxy
release: argocd
topologyKey: failure-domain.beta.kubernetes.io/zone
initContainers:
- name: config-init
image: haproxy:2.0.4
imagePullPolicy: IfNotPresent
resources:
{}
command:
- sh
args:
- /readonly/haproxy_init.sh
volumeMounts:
- name: config-volume
mountPath: /readonly
readOnly: true
- name: data
mountPath: /data
securityContext:
fsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
containers:
- name: haproxy
image: haproxy:2.0.4
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /healthz
port: 8888
initialDelaySeconds: 5
periodSeconds: 3
ports:
- name: redis
containerPort: 6379
resources:
{}
volumeMounts:
- name: data
mountPath: /usr/local/etc/haproxy
- name: shared-socket
mountPath: /run/haproxy
volumes:
- name: config-volume
configMap:
name: argocd-redis-ha-configmap
- name: shared-socket
emptyDir: {}
- name: data
emptyDir: {}
---
# Source: redis-ha/charts/redis-ha/templates/redis-ha-statefulset.yaml
@@ -591,13 +346,11 @@ apiVersion: apps/v1
kind: StatefulSet
metadata:
name: argocd-redis-ha-server
namespace: default
labels:
argocd-redis-ha: replica
app: redis-ha
heritage: "Tiller"
release: "argocd"
chart: redis-ha-4.3.4
chart: redis-ha-3.3.1
spec:
selector:
matchLabels:
@@ -611,11 +364,11 @@ spec:
template:
metadata:
annotations:
checksum/init-config: 552ee3bec8fe5d9d865e371f7b615c6d472253649eb65d53ed4ae874f782647c
checksum/init-config: 06440ee4a409be2aa01dfa08c14dd964fe3bad2ada57da1a538ad5cd771a045f
checksum/probe-config: 4b9888f173366e436f167856ee3469e8c1fd5221e29caa2129373db23578ec10
labels:
release: argocd
app: redis-ha
argocd-redis-ha: replica
spec:
affinity:
podAntiAffinity:
@@ -624,7 +377,6 @@ spec:
matchLabels:
app: redis-ha
release: argocd
argocd-redis-ha: replica
topologyKey: kubernetes.io/hostname
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
@@ -633,8 +385,8 @@ spec:
matchLabels:
app: redis-ha
release: argocd
argocd-redis-ha: replica
topologyKey: failure-domain.beta.kubernetes.io/zone
securityContext:
fsGroup: 1000
runAsNonRoot: true
@@ -643,7 +395,7 @@ spec:
serviceAccountName: argocd-redis-ha
initContainers:
- name: config-init
image: redis:5.0.6-alpine
image: redis:5.0.3-alpine
imagePullPolicy: IfNotPresent
resources:
{}
@@ -654,13 +406,13 @@ spec:
- /readonly-config/init.sh
env:
- name: SENTINEL_ID_0
value: 25b71bd9d0e4a51945d8422cab53f27027397c12
value: e791a161cb06f0d3eb0cc392117d34cf0eae9d71
- name: SENTINEL_ID_1
value: 896627000a81c7bdad8dbdcffd39728c9c17b309
value: d9b3204a90597a7500530efd881942d8145996ac
- name: SENTINEL_ID_2
value: 3acbca861108bc47379b71b1d87d1c137dce591f
value: d9deb539c0402841c2492e9959c8086602fa4284
volumeMounts:
- name: config
@@ -670,17 +422,22 @@ spec:
mountPath: /data
containers:
- name: redis
image: redis:5.0.6-alpine
image: redis:5.0.3-alpine
imagePullPolicy: IfNotPresent
command:
- redis-server
args:
- /data/conf/redis.conf
env:
livenessProbe:
tcpSocket:
port: 6379
exec:
command: [ "sh", "/probes/readiness.sh", "6379"]
initialDelaySeconds: 15
periodSeconds: 5
readinessProbe:
exec:
command: ["sh", "/probes/readiness.sh", "6379"]
initialDelaySeconds: 15
periodSeconds: 5
resources:
{}
@@ -690,17 +447,25 @@ spec:
volumeMounts:
- mountPath: /data
name: data
- mountPath: /probes
name: probes
- name: sentinel
image: redis:5.0.6-alpine
image: redis:5.0.3-alpine
imagePullPolicy: IfNotPresent
command:
- redis-sentinel
args:
- /data/conf/sentinel.conf
livenessProbe:
tcpSocket:
port: 26379
exec:
command: [ "sh", "/probes/readiness.sh", "26379"]
initialDelaySeconds: 15
periodSeconds: 5
readinessProbe:
exec:
command: ["sh", "/probes/readiness.sh", "26379"]
initialDelaySeconds: 15
periodSeconds: 5
resources:
{}
@@ -710,27 +475,21 @@ spec:
volumeMounts:
- mountPath: /data
name: data
- mountPath: /probes
name: probes
volumes:
- name: config
configMap:
name: argocd-redis-ha-configmap
- name: probes
configMap:
name: argocd-redis-ha-probes
- name: data
emptyDir: {}
---
# Source: redis-ha/charts/redis-ha/templates/redis-auth-secret.yaml
---
# Source: redis-ha/charts/redis-ha/templates/redis-ha-exporter-script-configmap.yaml
---
# Source: redis-ha/charts/redis-ha/templates/redis-ha-pdb.yaml
---
# Source: redis-ha/charts/redis-ha/templates/redis-ha-servicemonitor.yaml
---
# Source: redis-ha/charts/redis-ha/templates/redis-haproxy-servicemonitor.yaml

View File

@@ -5,5 +5,3 @@ redis-ha:
masterGroupName: argocd
config:
save: "\"\""
haproxy:
enabled: true

View File

@@ -1,6 +1,6 @@
#!/bin/sh -xe
helm2 dependency update ./chart --skip-refresh
helm dependency update ./chart --skip-refresh
# This step is necessary because we do not want the helm tests to be included
templates=$(tar -tf ./chart/charts/redis-ha-*.tgz | grep 'redis-ha/templates/redis-.*.yaml')
@@ -12,10 +12,8 @@ done
AUTOGENMSG="# This is an auto-generated file. DO NOT EDIT"
echo "${AUTOGENMSG}" > ./chart/upstream.yaml
helm2 template ./chart \
helm template ./chart \
--name argocd \
--values ./chart/values.yaml \
${helm_execute} \
>> ./chart/upstream_orig.yaml
sed -e 's/check inter 1s/check inter 3s/' ./chart/upstream_orig.yaml >> ./chart/upstream.yaml && rm ./chart/upstream_orig.yaml
>> ./chart/upstream.yaml

View File

@@ -11,6 +11,11 @@ patchesJson6902:
kind: ConfigMap
name: argocd-redis-ha-configmap
path: overlays/modify-labels.yaml
- target:
version: v1
kind: ConfigMap
name: argocd-redis-ha-probes
path: overlays/modify-labels.yaml
- target:
version: v1
kind: Service
@@ -54,22 +59,6 @@ patchesJson6902:
kind: RoleBinding
name: argocd-redis-ha
path: overlays/modify-labels.yaml
- target:
version: v1
kind: ServiceAccount
name: argocd-redis-ha-haproxy
path: overlays/haproxy-modify-labels.yaml
- target:
version: v1
kind: Service
name: argocd-redis-ha-haproxy
path: overlays/haproxy-modify-labels.yaml
- target:
group: apps
version: v1
kind: Deployment
name: argocd-redis-ha-haproxy
path: overlays/haproxy-modify-labels.yaml
# add pod template labels
- target:
@@ -78,12 +67,6 @@ patchesJson6902:
kind: StatefulSet
name: argocd-redis-ha-server
path: overlays/statefulset-labels.yaml
- target:
group: apps
version: v1
kind: Deployment
name: argocd-redis-ha-haproxy
path: overlays/deployment-labels.yaml
# update service selectors to match
- target:
@@ -106,73 +89,27 @@ patchesJson6902:
kind: Service
name: argocd-redis-ha
path: overlays/service-selector.yaml
- target:
version: v1
kind: Service
name: argocd-redis-ha-haproxy
path: overlays/haproxy-service-selector.yaml
- target:
version: v1
kind: ConfigMap
name: argocd-redis-ha-configmap
path: overlays/remove-namespace.yaml
- target:
version: v1
kind: ServiceAccount
name: argocd-redis-ha
path: overlays/remove-namespace.yaml
- target:
version: v1
kind: ServiceAccount
name: argocd-redis-ha-haproxy
path: overlays/remove-namespace.yaml
- target:
group: rbac.authorization.k8s.io
version: v1
kind: Role
name: argocd-redis-ha
path: overlays/remove-namespace.yaml
- target:
group: rbac.authorization.k8s.io
version: v1
kind: RoleBinding
name: argocd-redis-ha
path: overlays/remove-namespace.yaml
- target:
version: v1
vars:
- name: ARGOCD_REDIS_HA_ANNOUNCE_0_SERVICE
objref:
kind: Service
name: argocd-redis-ha-announce-0
path: overlays/remove-namespace.yaml
- target:
version: v1
apiVersion: v1
fieldref:
fieldpath: metadata.name
- name: ARGOCD_REDIS_HA_ANNOUNCE_1_SERVICE
objref:
kind: Service
name: argocd-redis-ha-announce-1
path: overlays/remove-namespace.yaml
- target:
version: v1
apiVersion: v1
fieldref:
fieldpath: metadata.name
- name: ARGOCD_REDIS_HA_ANNOUNCE_2_SERVICE
objref:
kind: Service
name: argocd-redis-ha-announce-2
path: overlays/remove-namespace.yaml
- target:
version: v1
kind: Service
name: argocd-redis-ha
path: overlays/remove-namespace.yaml
- target:
version: v1
kind: Service
name: argocd-redis-ha-haproxy
path: overlays/remove-namespace.yaml
- target:
group: apps
version: v1
kind: Deployment
name: argocd-redis-ha-haproxy
path: overlays/remove-namespace.yaml
- target:
group: apps
version: v1
kind: StatefulSet
name: argocd-redis-ha-server
path: overlays/remove-namespace.yaml
apiVersion: v1
fieldref:
fieldpath: metadata.name

View File

@@ -1,16 +0,0 @@
- op: replace
path: /spec/selector/matchLabels
value:
app.kubernetes.io/name: argocd-redis-ha-haproxy
- op: replace
path: /spec/template/metadata/labels
value:
app.kubernetes.io/name: argocd-redis-ha-haproxy
- op: replace
path: /spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/0/podAffinityTerm/labelSelector/matchLabels
value:
app.kubernetes.io/name: argocd-redis-ha-haproxy
- op: replace
path: /spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution/0/labelSelector/matchLabels
value:
app.kubernetes.io/name: argocd-redis-ha-haproxy

View File

@@ -1,6 +0,0 @@
- op: replace
path: /metadata/labels
value:
app.kubernetes.io/name: argocd-redis-ha-haproxy
app.kubernetes.io/component: redis
app.kubernetes.io/part-of: argocd

View File

@@ -1,3 +0,0 @@
- {op: remove, path: /spec/selector/app}
- {op: remove, path: /spec/selector/release}
- {op: add, path: /spec/selector/app.kubernetes.io~1name, value: argocd-redis-ha-haproxy}

View File

@@ -1 +0,0 @@
- {op: remove, path: /metadata/namespace}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -36,18 +36,6 @@ spec:
operation:
description: Operation contains requested operation parameters.
properties:
initiatedBy:
description: OperationInitiator holds information about the operation
initiator
properties:
automated:
description: Automated is set to true if operation was initiated
automatically by the application controller.
type: boolean
username:
description: Name of a user who started operation.
type: string
type: object
sync:
description: SyncOperation contains sync operation details.
properties:
@@ -139,21 +127,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the helm
template
items:
description: HelmFileParameter is a file parameter to
a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -269,11 +242,6 @@ spec:
required:
- repoURL
type: object
syncOptions:
description: SyncOptions provide per-sync sync-options, e.g. Validate=false
items:
type: string
type: array
syncStrategy:
description: SyncStrategy describes how to perform the sync
properties:
@@ -424,21 +392,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the helm
template
items:
description: HelmFileParameter is a file parameter to a helm
template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -566,11 +519,6 @@ spec:
description: 'SelfHeal enables auto-syncing if (default: false)'
type: boolean
type: object
syncOptions:
description: Options allow youe to specify whole app sync-options
items:
type: string
type: array
type: object
required:
- destination
@@ -679,22 +627,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the
helm template
items:
description: HelmFileParameter is a file parameter to
a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm
parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -838,18 +770,6 @@ spec:
operation:
description: Operation is the original requested operation
properties:
initiatedBy:
description: OperationInitiator holds information about the
operation initiator
properties:
automated:
description: Automated is set to true if operation was initiated
automatically by the application controller.
type: boolean
username:
description: Name of a user who started operation.
type: string
type: object
sync:
description: SyncOperation contains sync operation details.
properties:
@@ -946,23 +866,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters
to the helm template
items:
description: HelmFileParameter is a file parameter
to a helm template
properties:
name:
description: Name is the name of the helm
parameter
type: string
path:
description: Path is the path value for the
helm parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm
template
@@ -1086,12 +989,6 @@ spec:
required:
- repoURL
type: object
syncOptions:
description: SyncOptions provide per-sync sync-options,
e.g. Validate=false
items:
type: string
type: array
syncStrategy:
description: SyncStrategy describes how to perform the sync
properties:
@@ -1236,22 +1133,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the
helm template
items:
description: HelmFileParameter is a file parameter
to a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm
parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -1509,22 +1390,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the
helm template
items:
description: HelmFileParameter is a file parameter
to a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm
parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -2327,7 +2192,7 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:v1.5.2
image: argoproj/argocd:v1.4.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2379,10 +2244,9 @@ spec:
initContainers:
- command:
- cp
- -n
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:v1.5.2
image: argoproj/argocd:v1.4.3
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2446,7 +2310,7 @@ spec:
- argocd-repo-server
- --redis
- argocd-redis:6379
image: argoproj/argocd:v1.5.2
image: argoproj/argocd:v1.4.3
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -2497,7 +2361,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:v1.5.2
image: argoproj/argocd:v1.4.3
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -36,18 +36,6 @@ spec:
operation:
description: Operation contains requested operation parameters.
properties:
initiatedBy:
description: OperationInitiator holds information about the operation
initiator
properties:
automated:
description: Automated is set to true if operation was initiated
automatically by the application controller.
type: boolean
username:
description: Name of a user who started operation.
type: string
type: object
sync:
description: SyncOperation contains sync operation details.
properties:
@@ -139,21 +127,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the helm
template
items:
description: HelmFileParameter is a file parameter to
a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -269,11 +242,6 @@ spec:
required:
- repoURL
type: object
syncOptions:
description: SyncOptions provide per-sync sync-options, e.g. Validate=false
items:
type: string
type: array
syncStrategy:
description: SyncStrategy describes how to perform the sync
properties:
@@ -424,21 +392,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the helm
template
items:
description: HelmFileParameter is a file parameter to a helm
template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -566,11 +519,6 @@ spec:
description: 'SelfHeal enables auto-syncing if (default: false)'
type: boolean
type: object
syncOptions:
description: Options allow youe to specify whole app sync-options
items:
type: string
type: array
type: object
required:
- destination
@@ -679,22 +627,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the
helm template
items:
description: HelmFileParameter is a file parameter to
a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm
parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -838,18 +770,6 @@ spec:
operation:
description: Operation is the original requested operation
properties:
initiatedBy:
description: OperationInitiator holds information about the
operation initiator
properties:
automated:
description: Automated is set to true if operation was initiated
automatically by the application controller.
type: boolean
username:
description: Name of a user who started operation.
type: string
type: object
sync:
description: SyncOperation contains sync operation details.
properties:
@@ -946,23 +866,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters
to the helm template
items:
description: HelmFileParameter is a file parameter
to a helm template
properties:
name:
description: Name is the name of the helm
parameter
type: string
path:
description: Path is the path value for the
helm parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm
template
@@ -1086,12 +989,6 @@ spec:
required:
- repoURL
type: object
syncOptions:
description: SyncOptions provide per-sync sync-options,
e.g. Validate=false
items:
type: string
type: array
syncStrategy:
description: SyncStrategy describes how to perform the sync
properties:
@@ -1236,22 +1133,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the
helm template
items:
description: HelmFileParameter is a file parameter
to a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm
parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -1509,22 +1390,6 @@ spec:
helm:
description: Helm holds helm specific options
properties:
fileParameters:
description: FileParameters are file parameters to the
helm template
items:
description: HelmFileParameter is a file parameter
to a helm template
properties:
name:
description: Name is the name of the helm parameter
type: string
path:
description: Path is the path value for the helm
parameter
type: string
type: object
type: array
parameters:
description: Parameters are parameters to the helm template
items:
@@ -2242,7 +2107,7 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:v1.5.2
image: argoproj/argocd:v1.4.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2294,10 +2159,9 @@ spec:
initContainers:
- command:
- cp
- -n
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:v1.5.2
image: argoproj/argocd:v1.4.3
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2361,7 +2225,7 @@ spec:
- argocd-repo-server
- --redis
- argocd-redis:6379
image: argoproj/argocd:v1.5.2
image: argoproj/argocd:v1.4.3
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -2412,7 +2276,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:v1.5.2
image: argoproj/argocd:v1.4.3
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -26,12 +26,12 @@ nav:
- operator-manual/architecture.md
- operator-manual/declarative-setup.md
- operator-manual/ingress.md
- User Management:
- operator-manual/user-management/index.md
- operator-manual/user-management/auth0.md
- operator-manual/user-management/microsoft.md
- operator-manual/user-management/okta.md
- operator-manual/user-management/onelogin.md
- Single Sign On (SSO) & Role-Based Access Control (RBAC):
- operator-manual/sso/index.md
- operator-manual/sso/auth0.md
- operator-manual/sso/microsoft.md
- operator-manual/sso/okta.md
- operator-manual/sso/onelogin.md
- operator-manual/rbac.md
- operator-manual/security.md
- operator-manual/cluster-bootstrapping.md

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