mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-04-07 17:28:49 +02:00
Compare commits
16 Commits
v1.5.2
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24834112d6 | ||
|
|
48cced9d92 | ||
|
|
bc77ea70c4 | ||
|
|
f8721a7360 | ||
|
|
8ada07e0f5 | ||
|
|
de8ae9c617 | ||
|
|
2d029488ab | ||
|
|
3771486c14 | ||
|
|
97922f0439 | ||
|
|
141ef96a44 | ||
|
|
92824215f8 | ||
|
|
f74640d95c | ||
|
|
5c0ebb59d2 | ||
|
|
6d65d01757 | ||
|
|
36bbc29891 | ||
|
|
5af52f6698 |
@@ -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
|
||||
|
||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -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/)).
|
||||
|
||||
2
.github/workflows/gh-pages.yaml
vendored
2
.github/workflows/gh-pages.yaml
vendored
@@ -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
|
||||
|
||||
57
.github/workflows/image.yaml
vendored
57
.github/workflows/image.yaml
vendored
@@ -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
|
||||
162
CHANGELOG.md
162
CHANGELOG.md
@@ -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)
|
||||
|
||||
15
Dockerfile
15
Dockerfile
@@ -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
25
Gopkg.lock
generated
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
21
Makefile
21
Makefile
@@ -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
4
OWNERS
@@ -3,8 +3,10 @@ owners:
|
||||
- alexmt
|
||||
- jessesuen
|
||||
|
||||
reviewers:
|
||||
- jannfis
|
||||
|
||||
approvers:
|
||||
- alexec
|
||||
- alexmt
|
||||
- jannfis
|
||||
- jessesuen
|
||||
|
||||
56
README.md
56
README.md
@@ -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
|
||||
|
||||
|
||||
58
USERS.md
58
USERS.md
@@ -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/)
|
||||
@@ -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 |
@@ -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
|
||||
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(¤tPassword, "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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
103
controller/cache/cache.go
vendored
103
controller/cache/cache.go
vendored
@@ -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())
|
||||
|
||||
6
controller/cache/cache_test.go
vendored
6
controller/cache/cache_test.go
vendored
@@ -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)
|
||||
}
|
||||
|
||||
173
controller/cache/cluster.go
vendored
173
controller/cache/cluster.go
vendored
@@ -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,
|
||||
|
||||
4
controller/cache/cluster_test.go
vendored
4
controller/cache/cluster_test.go
vendored
@@ -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,
|
||||
|
||||
23
controller/cache/mocks/LiveStateCache.go
vendored
23
controller/cache/mocks/LiveStateCache.go
vendored
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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/)
|
||||
@@ -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`
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
@@ -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}]
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
8
docs/operator-manual/sso/auth0.md
Normal file
8
docs/operator-manual/sso/auth0.md
Normal 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 -->
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 -->
|
||||
@@ -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]'
|
||||
...
|
||||
```
|
||||
@@ -16,7 +16,7 @@ arbitrary value in the secret. This value will be used when configuring the webh
|
||||
|
||||

|
||||
|
||||
### 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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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).
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
8
hack/installers/install-aws-iam-authenticator-linux.sh
Executable file
8
hack/installers/install-aws-iam-authenticator-linux.sh
Executable 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,4 +12,4 @@ bases:
|
||||
images:
|
||||
- name: argoproj/argocd
|
||||
newName: argoproj/argocd
|
||||
newTag: v1.5.2
|
||||
newTag: v1.4.3
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -18,4 +18,4 @@ bases:
|
||||
images:
|
||||
- name: argoproj/argocd
|
||||
newName: argoproj/argocd
|
||||
newTag: v1.5.2
|
||||
newTag: v1.4.3
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
dependencies:
|
||||
- name: redis-ha
|
||||
version: 4.3.4
|
||||
version: 3.3.1
|
||||
repository: https://kubernetes-charts.storage.googleapis.com
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -5,5 +5,3 @@ redis-ha:
|
||||
masterGroupName: argocd
|
||||
config:
|
||||
save: "\"\""
|
||||
haproxy:
|
||||
enabled: true
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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}
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
12
mkdocs.yml
12
mkdocs.yml
@@ -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
Reference in New Issue
Block a user