mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-02-20 17:48:47 +01:00
Compare commits
108 Commits
commit-ser
...
v2.4.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0232073ccf | ||
|
|
860d8fd7e1 | ||
|
|
147ff80543 | ||
|
|
3800a1e49d | ||
|
|
fe80bdcfdc | ||
|
|
94c09dff59 | ||
|
|
3d9e4d439e | ||
|
|
4a955e25a0 | ||
|
|
4f99f251bf | ||
|
|
fd418cec0d | ||
|
|
dc291a629f | ||
|
|
e23a1c6026 | ||
|
|
aee88c6452 | ||
|
|
3f111cc640 | ||
|
|
596038fc0f | ||
|
|
471685feae | ||
|
|
42e1f29117 | ||
|
|
c089f9a5e5 | ||
|
|
1dc5e6aaf9 | ||
|
|
82726fcbcf | ||
|
|
e715e085aa | ||
|
|
7db5ab71b0 | ||
|
|
c6d0c8baaa | ||
|
|
2115bf7746 | ||
|
|
0a2520f511 | ||
|
|
211e9f6127 | ||
|
|
792e278080 | ||
|
|
93bf321002 | ||
|
|
48c2e0bf21 | ||
|
|
b4b893ca1c | ||
|
|
52e6025f8b | ||
|
|
b121b89c81 | ||
|
|
12149c0710 | ||
|
|
9d67469428 | ||
|
|
04c3053964 | ||
|
|
17f7f4f462 | ||
|
|
8bc3ef690d | ||
|
|
8fe9a58c21 | ||
|
|
269c61a9c8 | ||
|
|
9a08c123f9 | ||
|
|
971f0f1ff1 | ||
|
|
1ae2f97b05 | ||
|
|
bb26cc207b | ||
|
|
77d3dcdc62 | ||
|
|
f414a8e985 | ||
|
|
91aefabc5b | ||
|
|
56b8e2f356 | ||
|
|
101477a638 | ||
|
|
9bf7d1b95b | ||
|
|
da8e7b9697 | ||
|
|
eb183dcde1 | ||
|
|
ccecc693c2 | ||
|
|
dc1d4b060d | ||
|
|
512233806c | ||
|
|
b84dd8bbfa | ||
|
|
e6f37d7245 | ||
|
|
57bac9ac75 | ||
|
|
3034183791 | ||
|
|
26c87b3f16 | ||
|
|
bd8d26d444 | ||
|
|
a6c58748cd | ||
|
|
46af59e258 | ||
|
|
867660a709 | ||
|
|
b1addf5bf1 | ||
|
|
0a9d1607e2 | ||
|
|
09fc32e6cb | ||
|
|
1be9296e6c | ||
|
|
76fad02f4a | ||
|
|
2f8eb04b84 | ||
|
|
66aa0e6e01 | ||
|
|
955270eb0d | ||
|
|
225a0af9f7 | ||
|
|
5191cd077c | ||
|
|
c6b928c830 | ||
|
|
4e73b3c7ee | ||
|
|
708c9e79b9 | ||
|
|
da2c249814 | ||
|
|
c27cf3f95e | ||
|
|
dbd3ce3133 | ||
|
|
58062c45de | ||
|
|
3c61070411 | ||
|
|
697fc77379 | ||
|
|
6655a22b0a | ||
|
|
0d109279a8 | ||
|
|
4c1e1e0ad6 | ||
|
|
078cfe130b | ||
|
|
cd098638f8 | ||
|
|
2826a9215d | ||
|
|
13bef3a831 | ||
|
|
c6f80377a8 | ||
|
|
a8a451a84b | ||
|
|
cd5b2af358 | ||
|
|
f6f9fa2cd6 | ||
|
|
c7749ca67e | ||
|
|
3399a81bed | ||
|
|
80e5c55ca0 | ||
|
|
c4182aedc7 | ||
|
|
e4404372af | ||
|
|
12140f8152 | ||
|
|
6cfd394445 | ||
|
|
1998b016c0 | ||
|
|
74bc1731f9 | ||
|
|
bb28b3c697 | ||
|
|
0ee9993369 | ||
|
|
d8f845a126 | ||
|
|
5901b46785 | ||
|
|
88542a616f | ||
|
|
cbe4f1b92e |
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
@@ -202,7 +202,7 @@ jobs:
|
||||
set -ue
|
||||
git clean -fd
|
||||
mkdir -p dist/
|
||||
docker buildx build --platform linux/amd64,linux/arm64 --push -t ${IMAGE_NAMESPACE}/argocd:v${TARGET_VERSION} -t argoproj/argocd:v${TARGET_VERSION} .
|
||||
docker buildx build --platform linux/amd64,linux/arm64,linux/s390x,linux/ppc64le --push -t ${IMAGE_NAMESPACE}/argocd:v${TARGET_VERSION} -t argoproj/argocd:v${TARGET_VERSION} .
|
||||
make release-cli
|
||||
make checksums
|
||||
chmod +x ./dist/argocd-linux-amd64
|
||||
|
||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -2,28 +2,32 @@
|
||||
|
||||
## v2.4.0 (Unreleased)
|
||||
|
||||
### Web Terminal In Argo CD UI
|
||||
### Web Terminal In Argo CD UI
|
||||
|
||||
Feature enables engineers to start a shell in the running application container without leaving the web interface. Just find the required Kubernetes
|
||||
Pod using the Application Details page, click on it and select the Terminal tab. The shell starts automatically and enables you to execute the required
|
||||
commands, and helps to troubleshoot the application state.
|
||||
|
||||
### Access Control For Pod Logs & Web Terminal
|
||||
### Access Control For Pod Logs & Web Terminal
|
||||
|
||||
Argo CD is used to manage the critical infrastructure of multiple organizations, which makes security the top priority of the project. We've listened to
|
||||
your feedback and introduced additional access control settings that control access to Kubernetes Pod logs and the new Web Terminal feature.
|
||||
|
||||
#### Known UI Issue for Pod Logs Access
|
||||
|
||||
Currently, upon pressing the "LOGS" tab in pod view by users who don't have an explicit allow get logs policy, the red "unable to load data: Internal error" is received in the bottom of the screen, and "Failed to load data, please try again" is displayed.
|
||||
|
||||
### OpenTelemetry Tracing Integration
|
||||
|
||||
The new feature allows emitting richer telemetry data that might make identifying performance bottlenecks easier. The new feature is available for argocd-server
|
||||
and argocd-repo-server components and can be enabled using the --otlp-address flag.
|
||||
|
||||
### Power PC and IBM Z Support
|
||||
### Power PC and IBM Z Support
|
||||
|
||||
The list of supported architectures has been expanded, and now includes IBM Z (s390x) and PowerPC (ppc64le). Starting with the v2.4 release the official quay.io
|
||||
repository is going to have images for amd64, arm64, ppc64le, and s390x architectures.
|
||||
|
||||
### Other Notable Changes
|
||||
### Other Notable Changes
|
||||
|
||||
Overall v2.4 release includes more than 300 hundred commits from nearly 90 contributors. Here is a short sample of the contributions:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ARG BASE_IMAGE=docker.io/library/ubuntu:21.10
|
||||
ARG BASE_IMAGE=docker.io/library/ubuntu:22.04
|
||||
####################################################################################################
|
||||
# Builder image
|
||||
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
|
||||
@@ -63,7 +63,7 @@ RUN ln -s /usr/local/bin/entrypoint.sh /usr/local/bin/uid_entrypoint.sh
|
||||
# support for mounting configuration from a configmap
|
||||
WORKDIR /app/config/ssh
|
||||
RUN touch ssh_known_hosts && \
|
||||
ln -s ssh_known_hosts /etc/ssh/ssh_known_hosts
|
||||
ln -s /app/config/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts
|
||||
|
||||
WORKDIR /app/config
|
||||
RUN mkdir -p tls && \
|
||||
@@ -127,4 +127,4 @@ RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \
|
||||
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller && \
|
||||
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-k8s-auth
|
||||
|
||||
USER 999
|
||||
USER 999
|
||||
|
||||
4
Makefile
4
Makefile
@@ -234,6 +234,8 @@ release-cli: clean-debug build-ui
|
||||
make BIN_NAME=argocd-darwin-arm64 GOOS=darwin GOARCH=arm64 argocd-all
|
||||
make BIN_NAME=argocd-linux-amd64 GOOS=linux argocd-all
|
||||
make BIN_NAME=argocd-linux-arm64 GOOS=linux GOARCH=arm64 argocd-all
|
||||
make BIN_NAME=argocd-linux-ppc64le GOOS=linux GOARCH=ppc64le argocd-all
|
||||
make BIN_NAME=argocd-linux-s390x GOOS=linux GOARCH=s390x argocd-all
|
||||
make BIN_NAME=argocd-windows-amd64.exe GOOS=windows argocd-all
|
||||
|
||||
.PHONY: test-tools-image
|
||||
@@ -566,4 +568,4 @@ applicationset-controller:
|
||||
|
||||
.PHONY: checksums
|
||||
checksums:
|
||||
for f in ./dist/$(BIN_NAME)-*; do openssl dgst -sha256 "$$f" | awk ' { print $$2 }' > "$$f".sha256 ; done
|
||||
for f in ./dist/$(BIN_NAME)-*; do openssl dgst -sha256 "$$f" | awk ' { print $$2 }' > "$$f".sha256 ; done
|
||||
|
||||
10
Procfile
10
Procfile
@@ -1,12 +1,12 @@
|
||||
controller: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-application-controller $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081}"
|
||||
api-server: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-server $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} "
|
||||
controller: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-application-controller $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --otlp-address=${ARGOCD_OTLP_ADDRESS}"
|
||||
api-server: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-server $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} --otlp-address=${ARGOCD_OTLP_ADDRESS}"
|
||||
dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v2/cmd gendexcfg -o `pwd`/dist/dex.yaml && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml ghcr.io/dexidp/dex:v2.30.2 dex serve /dex.yaml"
|
||||
redis: bash -c "if [ \"$ARGOCD_REDIS_LOCAL\" == 'true' ]; then redis-server --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; else docker run --rm --name argocd-redis -i -p ${ARGOCD_E2E_REDIS_PORT:-6379}:${ARGOCD_E2E_REDIS_PORT:-6379} redis:7.0.0-alpine --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; fi"
|
||||
repo-server: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_GNUPGHOME=${ARGOCD_GNUPGHOME:-/tmp/argocd-local/gpg/keys} ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-repo-server ARGOCD_GPG_ENABLED=${ARGOCD_GPG_ENABLED:-false} $COMMAND --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379}"
|
||||
cmp-server: [ "$ARGOCD_E2E_TEST" == 'true' ] && exit 0 || [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_BINARY_NAME=argocd-cmp-server ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} $COMMAND --config-dir-path ./test/cmp --loglevel debug"
|
||||
repo-server: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_GNUPGHOME=${ARGOCD_GNUPGHOME:-/tmp/argocd-local/gpg/keys} ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} ARGOCD_GPG_DATA_PATH=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source} ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-repo-server ARGOCD_GPG_ENABLED=${ARGOCD_GPG_ENABLED:-false} $COMMAND --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --otlp-address=${ARGOCD_OTLP_ADDRESS}"
|
||||
cmp-server: [ "$ARGOCD_E2E_TEST" == 'true' ] && exit 0 || [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_BINARY_NAME=argocd-cmp-server ARGOCD_PLUGINSOCKFILEPATH=${ARGOCD_PLUGINSOCKFILEPATH:-./test/cmp} $COMMAND --config-dir-path ./test/cmp --loglevel debug --otlp-address=${ARGOCD_OTLP_ADDRESS}"
|
||||
ui: sh -c 'cd ui && ${ARGOCD_E2E_YARN_CMD:-yarn} start'
|
||||
git-server: test/fixture/testrepos/start-git.sh
|
||||
helm-registry: test/fixture/testrepos/start-helm-registry.sh
|
||||
dev-mounter: [[ "$ARGOCD_E2E_TEST" != "true" ]] && go run hack/dev-mounter/main.go --configmap argocd-ssh-known-hosts-cm=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} --configmap argocd-tls-certs-cm=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} --configmap argocd-gpg-keys-cm=${ARGOCD_GPG_DATA_PATH:-/tmp/argocd-local/gpg/source}
|
||||
applicationset-controller: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_ASK_PASS_SOCK=/tmp/applicationset-ask-pass.sock ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-applicationset-controller $COMMAND --loglevel debug --metrics-addr localhost:12345 --probe-addr localhost:12346 --argocd-repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081}"
|
||||
notification: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_BINARY_NAME=argocd-notifications $COMMAND --loglevel debug"
|
||||
notification: [ "$BIN_MODE" == 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=4 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_BINARY_NAME=argocd-notifications $COMMAND --loglevel debug"
|
||||
|
||||
1
USERS.md
1
USERS.md
@@ -37,6 +37,7 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [Chargetrip](https://chargetrip.com)
|
||||
1. [Chime](https://www.chime.com)
|
||||
1. [Cisco ET&I](https://eti.cisco.com/)
|
||||
1. [Cobalt](https://www.cobalt.io/)
|
||||
1. [Codefresh](https://www.codefresh.io/)
|
||||
1. [Codility](https://www.codility.com/)
|
||||
1. [Commonbond](https://commonbond.co/)
|
||||
|
||||
@@ -166,7 +166,7 @@ func (g *ClusterGenerator) getSecretsByClusterName(appSetGenerator *argoappsetv1
|
||||
|
||||
}
|
||||
|
||||
// santize the name in accordance with the below rules
|
||||
// sanitize the name in accordance with the below rules
|
||||
// 1. contain no more than 253 characters
|
||||
// 2. contain only lowercase alphanumeric characters, '-' or '.'
|
||||
// 3. start and end with an alphanumeric character
|
||||
|
||||
@@ -162,8 +162,10 @@ func (g *GitGenerator) generateParamsFromGitFile(filePath string, fileContent []
|
||||
}
|
||||
params["path"] = path.Dir(filePath)
|
||||
params["path.basename"] = path.Base(params["path"])
|
||||
params["path.filename"] = path.Base(filePath)
|
||||
params["path.basenameNormalized"] = sanitizeName(path.Base(params["path"]))
|
||||
for k, v := range strings.Split(strings.TrimSuffix(params["path"], params["path.basename"]), "/") {
|
||||
params["path.filenameNormalized"] = sanitizeName(path.Base(params["path.filename"]))
|
||||
for k, v := range strings.Split(params["path"], "/") {
|
||||
if len(v) > 0 {
|
||||
params["path["+strconv.Itoa(k)+"]"] = v
|
||||
}
|
||||
@@ -213,7 +215,7 @@ func (g *GitGenerator) generateParamsFromApps(requestedApps []string, _ *argopro
|
||||
params["path"] = a
|
||||
params["path.basename"] = path.Base(a)
|
||||
params["path.basenameNormalized"] = sanitizeName(path.Base(a))
|
||||
for k, v := range strings.Split(strings.TrimSuffix(params["path"], params["path.basename"]), "/") {
|
||||
for k, v := range strings.Split(params["path"], "/") {
|
||||
if len(v) > 0 {
|
||||
params["path["+strconv.Itoa(k)+"]"] = v
|
||||
}
|
||||
|
||||
@@ -47,6 +47,28 @@ func (a argoCDServiceMock) GetDirectories(ctx context.Context, repoURL string, r
|
||||
return args.Get(0).([]string), args.Error(1)
|
||||
}
|
||||
|
||||
func Test_generateParamsFromGitFile(t *testing.T) {
|
||||
params, err := (*GitGenerator)(nil).generateParamsFromGitFile("path/dir/file_name.yaml", []byte(`
|
||||
foo:
|
||||
bar: baz
|
||||
`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, []map[string]string{
|
||||
{
|
||||
"foo.bar": "baz",
|
||||
"path": "path/dir",
|
||||
"path.basename": "dir",
|
||||
"path.filename": "file_name.yaml",
|
||||
"path.basenameNormalized": "dir",
|
||||
"path.filenameNormalized": "file-name.yaml",
|
||||
"path[0]": "path",
|
||||
"path[1]": "dir",
|
||||
},
|
||||
}, params)
|
||||
}
|
||||
|
||||
func TestGitGenerateParamsFromDirectories(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
@@ -68,9 +90,9 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
|
||||
},
|
||||
repoError: nil,
|
||||
expected: []map[string]string{
|
||||
{"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1"},
|
||||
{"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2"},
|
||||
{"path": "app_3", "path.basename": "app_3", "path.basenameNormalized": "app-3"},
|
||||
{"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1", "path[0]": "app1"},
|
||||
{"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2", "path[0]": "app2"},
|
||||
{"path": "app_3", "path.basename": "app_3", "path.basenameNormalized": "app-3", "path[0]": "app_3"},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
@@ -85,8 +107,8 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
|
||||
},
|
||||
repoError: nil,
|
||||
expected: []map[string]string{
|
||||
{"path": "p1/app2", "path.basename": "app2", "path[0]": "p1", "path.basenameNormalized": "app2"},
|
||||
{"path": "p1/p2/app3", "path.basename": "app3", "path[0]": "p1", "path[1]": "p2", "path.basenameNormalized": "app3"},
|
||||
{"path": "p1/app2", "path.basename": "app2", "path[0]": "p1", "path[1]": "app2", "path.basenameNormalized": "app2"},
|
||||
{"path": "p1/p2/app3", "path.basename": "app3", "path[0]": "p1", "path[1]": "p2", "path[2]": "app3", "path.basenameNormalized": "app3"},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
@@ -102,9 +124,9 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
|
||||
},
|
||||
repoError: nil,
|
||||
expected: []map[string]string{
|
||||
{"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1"},
|
||||
{"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2"},
|
||||
{"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path.basenameNormalized": "app3"},
|
||||
{"path": "app1", "path.basename": "app1", "path[0]": "app1", "path.basenameNormalized": "app1"},
|
||||
{"path": "app2", "path.basename": "app2", "path[0]": "app2", "path.basenameNormalized": "app2"},
|
||||
{"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path[1]": "app3", "path.basenameNormalized": "app3"},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
@@ -120,9 +142,9 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) {
|
||||
},
|
||||
repoError: nil,
|
||||
expected: []map[string]string{
|
||||
{"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1"},
|
||||
{"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2"},
|
||||
{"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path.basenameNormalized": "app3"},
|
||||
{"path": "app1", "path.basename": "app1", "path[0]": "app1", "path.basenameNormalized": "app1"},
|
||||
{"path": "app2", "path.basename": "app2", "path[0]": "app2", "path.basenameNormalized": "app2"},
|
||||
{"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path[1]": "app3", "path.basenameNormalized": "app3"},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
@@ -238,7 +260,10 @@ func TestGitGenerateParamsFromFiles(t *testing.T) {
|
||||
"path": "cluster-config/production",
|
||||
"path.basename": "production",
|
||||
"path[0]": "cluster-config",
|
||||
"path[1]": "production",
|
||||
"path.basenameNormalized": "production",
|
||||
"path.filename": "config.json",
|
||||
"path.filenameNormalized": "config.json",
|
||||
},
|
||||
{
|
||||
"cluster.owner": "foo.bar@example.com",
|
||||
@@ -247,7 +272,10 @@ func TestGitGenerateParamsFromFiles(t *testing.T) {
|
||||
"path": "cluster-config/staging",
|
||||
"path.basename": "staging",
|
||||
"path[0]": "cluster-config",
|
||||
"path[1]": "staging",
|
||||
"path.basenameNormalized": "staging",
|
||||
"path.filename": "config.json",
|
||||
"path.filenameNormalized": "config.json",
|
||||
},
|
||||
},
|
||||
expectedError: nil,
|
||||
@@ -305,7 +333,10 @@ func TestGitGenerateParamsFromFiles(t *testing.T) {
|
||||
"path": "cluster-config/production",
|
||||
"path.basename": "production",
|
||||
"path[0]": "cluster-config",
|
||||
"path[1]": "production",
|
||||
"path.basenameNormalized": "production",
|
||||
"path.filename": "config.json",
|
||||
"path.filenameNormalized": "config.json",
|
||||
},
|
||||
{
|
||||
"cluster.owner": "john.doe@example.com",
|
||||
@@ -314,7 +345,10 @@ func TestGitGenerateParamsFromFiles(t *testing.T) {
|
||||
"path": "cluster-config/production",
|
||||
"path.basename": "production",
|
||||
"path[0]": "cluster-config",
|
||||
"path[1]": "production",
|
||||
"path.basenameNormalized": "production",
|
||||
"path.filename": "config.json",
|
||||
"path.filenameNormalized": "config.json",
|
||||
},
|
||||
},
|
||||
expectedError: nil,
|
||||
@@ -353,7 +387,10 @@ cluster:
|
||||
"path": "cluster-config/production",
|
||||
"path.basename": "production",
|
||||
"path[0]": "cluster-config",
|
||||
"path[1]": "production",
|
||||
"path.basenameNormalized": "production",
|
||||
"path.filename": "config.yaml",
|
||||
"path.filenameNormalized": "config.yaml",
|
||||
},
|
||||
{
|
||||
"cluster.owner": "foo.bar@example.com",
|
||||
@@ -362,7 +399,10 @@ cluster:
|
||||
"path": "cluster-config/staging",
|
||||
"path.basename": "staging",
|
||||
"path[0]": "cluster-config",
|
||||
"path[1]": "staging",
|
||||
"path.basenameNormalized": "staging",
|
||||
"path.filename": "config.yaml",
|
||||
"path.filenameNormalized": "config.yaml",
|
||||
},
|
||||
},
|
||||
expectedError: nil,
|
||||
@@ -393,7 +433,10 @@ cluster:
|
||||
"path": "cluster-config/production",
|
||||
"path.basename": "production",
|
||||
"path[0]": "cluster-config",
|
||||
"path[1]": "production",
|
||||
"path.basenameNormalized": "production",
|
||||
"path.filename": "config.yaml",
|
||||
"path.filenameNormalized": "config.yaml",
|
||||
},
|
||||
{
|
||||
"cluster.owner": "john.doe@example.com",
|
||||
@@ -402,7 +445,10 @@ cluster:
|
||||
"path": "cluster-config/production",
|
||||
"path.basename": "production",
|
||||
"path[0]": "cluster-config",
|
||||
"path[1]": "production",
|
||||
"path.basenameNormalized": "production",
|
||||
"path.filename": "config.yaml",
|
||||
"path.filenameNormalized": "config.yaml",
|
||||
},
|
||||
},
|
||||
expectedError: nil,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Built-in policy which defines two roles: role:readonly and role:admin,
|
||||
# and additionally assigns the admin user to the role:admin role.
|
||||
# There are two policy formats:
|
||||
# 1. Applications (which belong to a project):
|
||||
# 1. Applications, logs, and exec (which belong to a project):
|
||||
# p, <user/group>, <resource>, <action>, <project>/<object>
|
||||
# 2. All other resources:
|
||||
# p, <user/group>, <resource>, <action>, <object>
|
||||
|
||||
|
@@ -28,6 +28,7 @@ import (
|
||||
kubeutil "github.com/argoproj/argo-cd/v2/util/kube"
|
||||
"github.com/argoproj/argo-cd/v2/util/settings"
|
||||
"github.com/argoproj/argo-cd/v2/util/tls"
|
||||
"github.com/argoproj/argo-cd/v2/util/trace"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -58,6 +59,7 @@ func NewCommand() *cobra.Command {
|
||||
redisClient *redis.Client
|
||||
repoServerPlaintext bool
|
||||
repoServerStrictTLS bool
|
||||
otlpAddress string
|
||||
)
|
||||
var command = cobra.Command{
|
||||
Use: cliName,
|
||||
@@ -149,6 +151,14 @@ func NewCommand() *cobra.Command {
|
||||
stats.StartStatsTicker(10 * time.Minute)
|
||||
stats.RegisterHeapDumper("memprofile")
|
||||
|
||||
if otlpAddress != "" {
|
||||
closeTracer, err := trace.InitTracer(ctx, "argocd-controller", otlpAddress)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to initialize tracing: %v", err)
|
||||
}
|
||||
defer closeTracer()
|
||||
}
|
||||
|
||||
go appController.Run(ctx, statusProcessors, operationProcessors)
|
||||
|
||||
// Wait forever
|
||||
@@ -173,6 +183,7 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().BoolVar(&repoServerPlaintext, "repo-server-plaintext", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_PLAINTEXT", false), "Disable TLS on connections to repo server")
|
||||
command.Flags().BoolVar(&repoServerStrictTLS, "repo-server-strict-tls", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_STRICT_TLS", false), "Whether to use strict validation of the TLS cert presented by the repo server")
|
||||
command.Flags().StringSliceVar(&metricsAplicationLabels, "metrics-application-labels", []string{}, "List of Application labels that will be added to the argocd_application_labels metric")
|
||||
command.Flags().StringVar(&otlpAddress, "otlp-address", env.StringFromEnv("ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS", ""), "OpenTelemetry collector address to send traces to")
|
||||
cacheSrc = appstatecache.AddCacheFlagsToCmd(&command, func(client *redis.Client) {
|
||||
redisClient = client
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -40,16 +41,7 @@ func newAWSCommand() *cobra.Command {
|
||||
var command = &cobra.Command{
|
||||
Use: "aws",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
sess, err := session.NewSession()
|
||||
errors.CheckError(err)
|
||||
stsAPI := sts.New(sess)
|
||||
if roleARN != "" {
|
||||
creds := stscreds.NewCredentials(sess, roleARN)
|
||||
stsAPI = sts.New(sess, &aws.Config{Credentials: creds})
|
||||
}
|
||||
request, _ := stsAPI.GetCallerIdentityRequest(&sts.GetCallerIdentityInput{})
|
||||
request.HTTPRequest.Header.Add(clusterIDHeader, clusterName)
|
||||
presignedURLString, err := request.Presign(requestPresignParam)
|
||||
presignedURLString, err := getSignedRequestWithRetry(time.Minute, 5*time.Second, clusterName, roleARN, getSignedRequest)
|
||||
errors.CheckError(err)
|
||||
token := v1Prefix + base64.RawURLEncoding.EncodeToString([]byte(presignedURLString))
|
||||
// Set token expiration to 1 minute before the presigned URL expires for some cushion
|
||||
@@ -62,6 +54,43 @@ func newAWSCommand() *cobra.Command {
|
||||
return command
|
||||
}
|
||||
|
||||
type getSignedRequestFunc func(clusterName, roleARN string) (string, error)
|
||||
|
||||
func getSignedRequestWithRetry(timeout, interval time.Duration, clusterName, roleARN string, fn getSignedRequestFunc) (string, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
for {
|
||||
signed, err := fn(clusterName, roleARN)
|
||||
if err == nil {
|
||||
return signed, nil
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return "", fmt.Errorf("timeout while trying to get signed aws request: last error: %s", err)
|
||||
case <-time.After(interval):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getSignedRequest(clusterName, roleARN string) (string, error) {
|
||||
sess, err := session.NewSession()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error creating new AWS session: %s", err)
|
||||
}
|
||||
stsAPI := sts.New(sess)
|
||||
if roleARN != "" {
|
||||
creds := stscreds.NewCredentials(sess, roleARN)
|
||||
stsAPI = sts.New(sess, &aws.Config{Credentials: creds})
|
||||
}
|
||||
request, _ := stsAPI.GetCallerIdentityRequest(&sts.GetCallerIdentityInput{})
|
||||
request.HTTPRequest.Header.Add(clusterIDHeader, clusterName)
|
||||
signed, err := request.Presign(requestPresignParam)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error presigning AWS request: %s", err)
|
||||
}
|
||||
return signed, nil
|
||||
}
|
||||
|
||||
func formatJSON(token string, expiration time.Time) string {
|
||||
expirationTimestamp := metav1.NewTime(expiration)
|
||||
execInput := &clientauthv1beta1.ExecCredential{
|
||||
|
||||
73
cmd/argocd-k8s-auth/commands/aws_test.go
Normal file
73
cmd/argocd-k8s-auth/commands/aws_test.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetSignedRequestWithRetry(t *testing.T) {
|
||||
t.Run("will return signed request on first attempt", func(t *testing.T) {
|
||||
// given
|
||||
t.Parallel()
|
||||
mock := &signedRequestMock{
|
||||
returnFunc: func(m *signedRequestMock) (string, error) {
|
||||
return "token", nil
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
signed, err := getSignedRequestWithRetry(time.Second, time.Millisecond, "cluster-name", "", mock.getSignedRequestMock)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "token", signed)
|
||||
})
|
||||
t.Run("will return signed request on third attempt", func(t *testing.T) {
|
||||
// given
|
||||
t.Parallel()
|
||||
mock := &signedRequestMock{
|
||||
returnFunc: func(m *signedRequestMock) (string, error) {
|
||||
if m.getSignedRequestCalls < 3 {
|
||||
return "", fmt.Errorf("some error")
|
||||
}
|
||||
return "token", nil
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
signed, err := getSignedRequestWithRetry(time.Second, time.Millisecond, "cluster-name", "", mock.getSignedRequestMock)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "token", signed)
|
||||
})
|
||||
t.Run("will return error on timeout", func(t *testing.T) {
|
||||
// given
|
||||
t.Parallel()
|
||||
mock := &signedRequestMock{
|
||||
returnFunc: func(m *signedRequestMock) (string, error) {
|
||||
return "", fmt.Errorf("some error")
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
signed, err := getSignedRequestWithRetry(time.Second, time.Millisecond, "cluster-name", "", mock.getSignedRequestMock)
|
||||
|
||||
// then
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "", signed)
|
||||
})
|
||||
}
|
||||
|
||||
type signedRequestMock struct {
|
||||
getSignedRequestCalls int
|
||||
returnFunc func(m *signedRequestMock) (string, error)
|
||||
}
|
||||
|
||||
func (m *signedRequestMock) getSignedRequestMock(clusterName, roleARN string) (string, error) {
|
||||
m.getSignedRequestCalls++
|
||||
return m.returnFunc(m)
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc/health/grpc_health_v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
@@ -70,15 +71,17 @@ func getSubmoduleEnabled() bool {
|
||||
|
||||
func NewCommand() *cobra.Command {
|
||||
var (
|
||||
parallelismLimit int64
|
||||
listenPort int
|
||||
metricsPort int
|
||||
otlpAddress string
|
||||
cacheSrc func() (*reposervercache.Cache, error)
|
||||
tlsConfigCustomizer tls.ConfigCustomizer
|
||||
tlsConfigCustomizerSrc func() (tls.ConfigCustomizer, error)
|
||||
redisClient *redis.Client
|
||||
disableTLS bool
|
||||
parallelismLimit int64
|
||||
listenPort int
|
||||
metricsPort int
|
||||
otlpAddress string
|
||||
cacheSrc func() (*reposervercache.Cache, error)
|
||||
tlsConfigCustomizer tls.ConfigCustomizer
|
||||
tlsConfigCustomizerSrc func() (tls.ConfigCustomizer, error)
|
||||
redisClient *redis.Client
|
||||
disableTLS bool
|
||||
maxCombinedDirectoryManifestsSize string
|
||||
cmpTarExcludedGlobs []string
|
||||
)
|
||||
var command = cobra.Command{
|
||||
Use: cliName,
|
||||
@@ -98,15 +101,20 @@ func NewCommand() *cobra.Command {
|
||||
cache, err := cacheSrc()
|
||||
errors.CheckError(err)
|
||||
|
||||
maxCombinedDirectoryManifestsQuantity, err := resource.ParseQuantity(maxCombinedDirectoryManifestsSize)
|
||||
errors.CheckError(err)
|
||||
|
||||
askPassServer := askpass.NewServer()
|
||||
metricsServer := metrics.NewMetricsServer()
|
||||
cacheutil.CollectMetrics(redisClient, metricsServer)
|
||||
server, err := reposerver.NewServer(metricsServer, cache, tlsConfigCustomizer, repository.RepoServerInitConstants{
|
||||
ParallelismLimit: parallelismLimit,
|
||||
ParallelismLimit: parallelismLimit,
|
||||
PauseGenerationAfterFailedGenerationAttempts: getPauseGenerationAfterFailedGenerationAttempts(),
|
||||
PauseGenerationOnFailureForMinutes: getPauseGenerationOnFailureForMinutes(),
|
||||
PauseGenerationOnFailureForRequests: getPauseGenerationOnFailureForRequests(),
|
||||
SubmoduleEnabled: getSubmoduleEnabled(),
|
||||
MaxCombinedDirectoryManifestsSize: maxCombinedDirectoryManifestsQuantity,
|
||||
CMPTarExcludedGlobs: cmpTarExcludedGlobs,
|
||||
}, askPassServer)
|
||||
errors.CheckError(err)
|
||||
|
||||
@@ -182,6 +190,8 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().IntVar(&metricsPort, "metrics-port", common.DefaultPortRepoServerMetrics, "Start metrics server on given port")
|
||||
command.Flags().StringVar(&otlpAddress, "otlp-address", env.StringFromEnv("ARGOCD_REPO_SERVER_OTLP_ADDRESS", ""), "OpenTelemetry collector address to send traces to")
|
||||
command.Flags().BoolVar(&disableTLS, "disable-tls", env.ParseBoolFromEnv("ARGOCD_REPO_SERVER_DISABLE_TLS", false), "Disable TLS on the gRPC endpoint")
|
||||
command.Flags().StringVar(&maxCombinedDirectoryManifestsSize, "max-combined-directory-manifests-size", env.StringFromEnv("ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE", "10M"), "Max combined size of manifest files in a directory-type Application")
|
||||
command.Flags().StringArrayVar(&cmpTarExcludedGlobs, "plugin-tar-exclude", env.StringsFromEnv("ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS", []string{}, ";"), "Globs to filter when sending tarballs to plugins.")
|
||||
|
||||
tlsConfigCustomizerSrc = tls.AddTLSFlagsToCmd(&command)
|
||||
cacheSrc = reposervercache.AddCacheFlagsToCmd(&command, func(client *redis.Client) {
|
||||
|
||||
@@ -152,7 +152,10 @@ func NewCommand() *cobra.Command {
|
||||
stats.RegisterStackDumper()
|
||||
stats.StartStatsTicker(10 * time.Minute)
|
||||
stats.RegisterHeapDumper("memprofile")
|
||||
|
||||
argocd := server.NewServer(context.Background(), argoCDOpts)
|
||||
argocd.Init(context.Background())
|
||||
lns, err := argocd.Listen()
|
||||
errors.CheckError(err)
|
||||
for {
|
||||
var closer func()
|
||||
ctx := context.Background()
|
||||
@@ -163,8 +166,7 @@ func NewCommand() *cobra.Command {
|
||||
log.Fatalf("failed to initialize tracing: %v", err)
|
||||
}
|
||||
}
|
||||
argocd := server.NewServer(ctx, argoCDOpts)
|
||||
argocd.Run(ctx, listenPort, metricsPort)
|
||||
argocd.Run(ctx, lns)
|
||||
cancel()
|
||||
if closer != nil {
|
||||
closer()
|
||||
|
||||
@@ -88,6 +88,7 @@ func TestGetReconcileResults_Refresh(t *testing.T) {
|
||||
kubeClientset := kubefake.NewSimpleClientset(deployment, &cm)
|
||||
clusterCache := clustermocks.ClusterCache{}
|
||||
clusterCache.On("IsNamespaced", mock.Anything).Return(true, nil)
|
||||
clusterCache.On("GetGVKParser", mock.Anything).Return(nil)
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClient.On("GenerateManifest", mock.Anything, mock.Anything).Return(&argocdclient.ManifestResponse{
|
||||
Manifests: []string{test.DeploymentManifest},
|
||||
|
||||
@@ -609,7 +609,7 @@ func GenerateToken(clusterOpts cmdutil.ClusterOptions, conf *rest.Config) (strin
|
||||
clientset, err := kubernetes.NewForConfig(conf)
|
||||
errors.CheckError(err)
|
||||
|
||||
bearerToken, err := clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount)
|
||||
bearerToken, err := clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount, common.BearerTokenTimeout)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
@@ -778,7 +779,7 @@ func getLocalObjectsString(app *argoappv1.Application, local, localRepoRoot, app
|
||||
ApiVersions: apiVersions,
|
||||
Plugins: configManagementPlugins,
|
||||
TrackingMethod: trackingMethod,
|
||||
}, true, &git.NoopCredsStore{})
|
||||
}, true, &git.NoopCredsStore{}, resource.MustParse("0"))
|
||||
errors.CheckError(err)
|
||||
|
||||
return res.Manifests
|
||||
|
||||
@@ -101,7 +101,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
|
||||
clientset, err := kubernetes.NewForConfig(conf)
|
||||
errors.CheckError(err)
|
||||
if clusterOpts.ServiceAccount != "" {
|
||||
managerBearerToken, err = clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount)
|
||||
managerBearerToken, err = clusterauth.GetServiceAccountBearerToken(clientset, clusterOpts.SystemNamespace, clusterOpts.ServiceAccount, common.BearerTokenTimeout)
|
||||
} else {
|
||||
isTerminal := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
|
||||
|
||||
@@ -115,7 +115,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, clusterOpts.SystemNamespace, clusterOpts.Namespaces)
|
||||
managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, clusterOpts.SystemNamespace, clusterOpts.Namespaces, common.BearerTokenTimeout)
|
||||
}
|
||||
errors.CheckError(err)
|
||||
}
|
||||
|
||||
@@ -36,13 +36,13 @@ users:
|
||||
- auth-token: vErrYS3c3tReFRe$hToken
|
||||
name: localhost:8080`
|
||||
|
||||
const testConfigFilePath = "./testdata/config"
|
||||
const testConfigFilePath = "./testdata/local.config"
|
||||
|
||||
func TestContextDelete(t *testing.T) {
|
||||
|
||||
// Write the test config file
|
||||
err := ioutil.WriteFile(testConfigFilePath, []byte(testConfig), os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
defer os.Remove(testConfigFilePath)
|
||||
|
||||
err = os.Chmod(testConfigFilePath, 0600)
|
||||
require.NoError(t, err, "Could not change the file permission to 0600 %v", err)
|
||||
@@ -75,9 +75,4 @@ func TestContextDelete(t *testing.T) {
|
||||
assert.NotContains(t, localConfig.Servers, localconfig.Server{PlainText: true, Server: "localhost:8080"})
|
||||
assert.NotContains(t, localConfig.Users, localconfig.User{AuthToken: "vErrYS3c3tReFRe$hToken", Name: "localhost:8080"})
|
||||
assert.Contains(t, localConfig.Contexts, localconfig.ContextRef{Name: "argocd2.example.com:443", Server: "argocd2.example.com:443", User: "argocd2.example.com:443"})
|
||||
|
||||
// Write the file again so that no conflicts are made in git
|
||||
err = ioutil.WriteFile(testConfigFilePath, []byte(testConfig), os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
|
||||
}
|
||||
|
||||
@@ -215,8 +215,13 @@ func StartLocalServer(clientOpts *apiclient.ClientOptions, ctxStr string, port *
|
||||
ListenHost: *address,
|
||||
RepoClientset: &forwardRepoClientset{namespace: namespace, context: ctxStr},
|
||||
})
|
||||
srv.Init(ctx)
|
||||
|
||||
go srv.Run(ctx, *port, 0)
|
||||
lns, err := srv.Listen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go srv.Run(ctx, lns)
|
||||
clientOpts.ServerAddr = fmt.Sprintf("%s:%d", *address, *port)
|
||||
clientOpts.PlainText = true
|
||||
if !cache2.WaitForCacheSync(ctx.Done(), srv.Initialized) {
|
||||
|
||||
@@ -202,7 +202,10 @@ func oauth2Login(ctx context.Context, port int, oidcSettings *settingspkg.OIDCCo
|
||||
// completionChan is to signal flow completed. Non-empty string indicates error
|
||||
completionChan := make(chan string)
|
||||
// stateNonce is an OAuth2 state nonce
|
||||
stateNonce := rand.RandString(10)
|
||||
// According to the spec (https://www.rfc-editor.org/rfc/rfc6749#section-10.10), this must be guessable with
|
||||
// probability <= 2^(-128). The following call generates one of 52^24 random strings, ~= 2^136 possibilities.
|
||||
stateNonce, err := rand.String(24)
|
||||
errors.CheckError(err)
|
||||
var tokenString string
|
||||
var refreshToken string
|
||||
|
||||
@@ -212,7 +215,8 @@ func oauth2Login(ctx context.Context, port int, oidcSettings *settingspkg.OIDCCo
|
||||
}
|
||||
|
||||
// PKCE implementation of https://tools.ietf.org/html/rfc7636
|
||||
codeVerifier := rand.RandStringCharset(43, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~")
|
||||
codeVerifier, err := rand.StringFromCharset(43, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~")
|
||||
errors.CheckError(err)
|
||||
codeChallengeHash := sha256.Sum256([]byte(codeVerifier))
|
||||
codeChallenge := base64.RawURLEncoding.EncodeToString(codeChallengeHash[:])
|
||||
|
||||
@@ -296,7 +300,8 @@ func oauth2Login(ctx context.Context, port int, oidcSettings *settingspkg.OIDCCo
|
||||
opts = append(opts, oauth2.SetAuthURLParam("code_challenge_method", "S256"))
|
||||
url = oauth2conf.AuthCodeURL(stateNonce, opts...)
|
||||
case oidcutil.GrantTypeImplicit:
|
||||
url = oidcutil.ImplicitFlowURL(oauth2conf, stateNonce, opts...)
|
||||
url, err = oidcutil.ImplicitFlowURL(oauth2conf, stateNonce, opts...)
|
||||
errors.CheckError(err)
|
||||
default:
|
||||
log.Fatalf("Unsupported grant type: %v", grantType)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
argocdclient "github.com/argoproj/argo-cd/v2/pkg/apiclient"
|
||||
"github.com/argoproj/argo-cd/v2/util/localconfig"
|
||||
@@ -16,6 +17,10 @@ func TestLogout(t *testing.T) {
|
||||
// Write the test config file
|
||||
err := ioutil.WriteFile(testConfigFilePath, []byte(testConfig), os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
defer os.Remove(testConfigFilePath)
|
||||
|
||||
err = os.Chmod(testConfigFilePath, 0600)
|
||||
require.NoError(t, err)
|
||||
|
||||
localConfig, err := localconfig.ReadLocalConfig(testConfigFilePath)
|
||||
assert.NoError(t, err)
|
||||
@@ -32,9 +37,4 @@ func TestLogout(t *testing.T) {
|
||||
assert.Contains(t, localConfig.Contexts, localconfig.ContextRef{Name: "argocd1.example.com:443", Server: "argocd1.example.com:443", User: "argocd1.example.com:443"})
|
||||
assert.Contains(t, localConfig.Contexts, localconfig.ContextRef{Name: "argocd2.example.com:443", Server: "argocd2.example.com:443", User: "argocd2.example.com:443"})
|
||||
assert.Contains(t, localConfig.Contexts, localconfig.ContextRef{Name: "localhost:8080", Server: "localhost:8080", User: "localhost:8080"})
|
||||
|
||||
// Write the file again so that no conflicts are made in git
|
||||
err = ioutil.WriteFile(testConfigFilePath, []byte(testConfig), os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
@@ -46,6 +47,8 @@ func NewConnection(address string) (*grpc.ClientConn, error) {
|
||||
grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor(retryOpts...)),
|
||||
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(unaryInterceptors...)),
|
||||
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(MaxGRPCMessageSize), grpc.MaxCallSendMsgSize(MaxGRPCMessageSize)),
|
||||
grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()),
|
||||
grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor()),
|
||||
}
|
||||
|
||||
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
|
||||
@@ -233,12 +233,12 @@ func (s *Service) MatchRepository(stream apiclient.ConfigManagementPluginService
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = cmp.ReceiveRepoStream(bufferedCtx, stream, workDir)
|
||||
metadata, err := cmp.ReceiveRepoStream(bufferedCtx, stream, workDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("match repository error receiving stream: %s", err)
|
||||
}
|
||||
|
||||
isSupported, err := s.matchRepository(bufferedCtx, workDir)
|
||||
isSupported, err := s.matchRepository(bufferedCtx, workDir, metadata.GetEnv())
|
||||
if err != nil {
|
||||
return fmt.Errorf("match repository error: %s", err)
|
||||
}
|
||||
@@ -251,7 +251,7 @@ func (s *Service) MatchRepository(stream apiclient.ConfigManagementPluginService
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) matchRepository(ctx context.Context, workdir string) (bool, error) {
|
||||
func (s *Service) matchRepository(ctx context.Context, workdir string, envEntries []*apiclient.EnvEntry) (bool, error) {
|
||||
config := s.initConstants.PluginConfig
|
||||
if config.Spec.Discover.FileName != "" {
|
||||
log.Debugf("config.Spec.Discover.FileName is provided")
|
||||
@@ -284,7 +284,9 @@ func (s *Service) matchRepository(ctx context.Context, workdir string) (bool, er
|
||||
}
|
||||
|
||||
log.Debugf("Going to try runCommand.")
|
||||
find, err := runCommand(ctx, config.Spec.Discover.Find.Command, workdir, os.Environ())
|
||||
env := append(os.Environ(), environ(envEntries)...)
|
||||
|
||||
find, err := runCommand(ctx, config.Spec.Discover.Find.Command, workdir, env)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error running find command: %s", err)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/cmpserver/apiclient"
|
||||
"github.com/argoproj/argo-cd/v2/test"
|
||||
)
|
||||
|
||||
@@ -62,6 +63,7 @@ func TestMatchRepository(t *testing.T) {
|
||||
type fixture struct {
|
||||
service *Service
|
||||
path string
|
||||
env []*apiclient.EnvEntry
|
||||
}
|
||||
setup := func(t *testing.T, opts ...pluginOpt) *fixture {
|
||||
t.Helper()
|
||||
@@ -71,6 +73,7 @@ func TestMatchRepository(t *testing.T) {
|
||||
return &fixture{
|
||||
service: s,
|
||||
path: path,
|
||||
env: []*apiclient.EnvEntry{{Name: "ENV_VAR", Value: "1"}},
|
||||
}
|
||||
}
|
||||
t.Run("will match plugin by filename", func(t *testing.T) {
|
||||
@@ -81,7 +84,7 @@ func TestMatchRepository(t *testing.T) {
|
||||
f := setup(t, withDiscover(d))
|
||||
|
||||
// when
|
||||
match, err := f.service.matchRepository(context.Background(), f.path)
|
||||
match, err := f.service.matchRepository(context.Background(), f.path, f.env)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
@@ -95,7 +98,7 @@ func TestMatchRepository(t *testing.T) {
|
||||
f := setup(t, withDiscover(d))
|
||||
|
||||
// when
|
||||
match, err := f.service.matchRepository(context.Background(), f.path)
|
||||
match, err := f.service.matchRepository(context.Background(), f.path, f.env)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
@@ -111,7 +114,7 @@ func TestMatchRepository(t *testing.T) {
|
||||
f := setup(t, withDiscover(d))
|
||||
|
||||
// when
|
||||
match, err := f.service.matchRepository(context.Background(), f.path)
|
||||
match, err := f.service.matchRepository(context.Background(), f.path, f.env)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
@@ -127,7 +130,7 @@ func TestMatchRepository(t *testing.T) {
|
||||
f := setup(t, withDiscover(d))
|
||||
|
||||
// when
|
||||
match, err := f.service.matchRepository(context.Background(), f.path)
|
||||
match, err := f.service.matchRepository(context.Background(), f.path, f.env)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
@@ -145,7 +148,7 @@ func TestMatchRepository(t *testing.T) {
|
||||
f := setup(t, withDiscover(d))
|
||||
|
||||
// when
|
||||
match, err := f.service.matchRepository(context.Background(), f.path)
|
||||
match, err := f.service.matchRepository(context.Background(), f.path, f.env)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
@@ -163,7 +166,44 @@ func TestMatchRepository(t *testing.T) {
|
||||
f := setup(t, withDiscover(d))
|
||||
|
||||
// when
|
||||
match, err := f.service.matchRepository(context.Background(), f.path)
|
||||
match, err := f.service.matchRepository(context.Background(), f.path, f.env)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, match)
|
||||
})
|
||||
t.Run("will match plugin because env var defined", func(t *testing.T) {
|
||||
// given
|
||||
d := Discover{
|
||||
Find: Find{
|
||||
Command: Command{
|
||||
Command: []string{"sh", "-c", "echo -n $ENV_VAR"},
|
||||
},
|
||||
},
|
||||
}
|
||||
f := setup(t, withDiscover(d))
|
||||
|
||||
// when
|
||||
match, err := f.service.matchRepository(context.Background(), f.path, f.env)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, match)
|
||||
})
|
||||
t.Run("will not match plugin because no env var defined", func(t *testing.T) {
|
||||
// given
|
||||
d := Discover{
|
||||
Find: Find{
|
||||
Command: Command{
|
||||
// Use printf instead of echo since OSX prints the "-n" when there's no additional arg.
|
||||
Command: []string{"sh", "-c", `printf "%s" "$ENV_NO_VAR"`},
|
||||
},
|
||||
},
|
||||
}
|
||||
f := setup(t, withDiscover(d))
|
||||
|
||||
// when
|
||||
match, err := f.service.matchRepository(context.Background(), f.path, f.env)
|
||||
|
||||
// then
|
||||
assert.NoError(t, err)
|
||||
@@ -181,7 +221,7 @@ func TestMatchRepository(t *testing.T) {
|
||||
f := setup(t, withDiscover(d))
|
||||
|
||||
// when
|
||||
match, err := f.service.matchRepository(context.Background(), f.path)
|
||||
match, err := f.service.matchRepository(context.Background(), f.path, f.env)
|
||||
|
||||
// then
|
||||
assert.Error(t, err)
|
||||
|
||||
@@ -229,6 +229,12 @@ const (
|
||||
CacheVersion = "1.8.3"
|
||||
)
|
||||
|
||||
// Constants used by util/clusterauth package
|
||||
const (
|
||||
ClusterAuthRequestTimeout = 10 * time.Second
|
||||
BearerTokenTimeout = 30 * time.Second
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultGitRetryMaxDuration time.Duration = time.Second * 5 // 5s
|
||||
DefaultGitRetryDuration time.Duration = time.Millisecond * 250 // 0.25s
|
||||
|
||||
@@ -605,11 +605,16 @@ func (ctrl *ApplicationController) hideSecretData(app *appv1.Application, compar
|
||||
return nil, fmt.Errorf("error getting tracking method: %s", err)
|
||||
}
|
||||
|
||||
clusterCache, err := ctrl.stateCache.GetClusterCache(app.Spec.Destination.Server)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting cluster cache: %s", err)
|
||||
}
|
||||
diffConfig, err := argodiff.NewDiffConfigBuilder().
|
||||
WithDiffSettings(app.Spec.IgnoreDifferences, resourceOverrides, compareOptions.IgnoreAggregatedRoles).
|
||||
WithTracking(appLabelKey, trackingMethod).
|
||||
WithNoCache().
|
||||
WithLogger(logutils.NewLogrusLogger(logutils.NewWithCurrentConfig())).
|
||||
WithGVKParser(clusterCache.GetGVKParser()).
|
||||
Build()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("appcontroller error building diff config: %s", err)
|
||||
|
||||
@@ -121,6 +121,7 @@ func newFakeController(data *fakeData) *ApplicationController {
|
||||
clusterCacheMock := mocks.ClusterCache{}
|
||||
clusterCacheMock.On("IsNamespaced", mock.Anything).Return(true, nil)
|
||||
clusterCacheMock.On("GetOpenAPISchema").Return(nil, nil)
|
||||
clusterCacheMock.On("GetGVKParser").Return(nil)
|
||||
|
||||
mockStateCache := mockstatecache.LiveStateCache{}
|
||||
ctrl.appStateManager.(*appStateManager).liveStateCache = &mockStateCache
|
||||
|
||||
@@ -461,7 +461,14 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *ap
|
||||
} else {
|
||||
diffConfigBuilder.WithCache(m.cache, app.GetName())
|
||||
}
|
||||
// it necessary to ignore the error at this point to avoid creating duplicated
|
||||
|
||||
gvkParser, err := m.getGVKParser(app.Spec.Destination.Server)
|
||||
if err != nil {
|
||||
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionUnknownError, Message: err.Error(), LastTransitionTime: &now})
|
||||
}
|
||||
diffConfigBuilder.WithGVKParser(gvkParser)
|
||||
|
||||
// it is necessary to ignore the error at this point to avoid creating duplicated
|
||||
// application conditions as argo.StateDiffs will validate this diffConfig again.
|
||||
diffConfig, _ := diffConfigBuilder.Build()
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
v1 "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/util/managedfields"
|
||||
"k8s.io/kubectl/pkg/util/openapi"
|
||||
|
||||
cdcommon "github.com/argoproj/argo-cd/v2/common"
|
||||
@@ -46,6 +47,14 @@ func (m *appStateManager) getOpenAPISchema(server string) (openapi.Resources, er
|
||||
return cluster.GetOpenAPISchema(), nil
|
||||
}
|
||||
|
||||
func (m *appStateManager) getGVKParser(server string) (*managedfields.GvkParser, error) {
|
||||
cluster, err := m.liveStateCache.GetClusterCache(server)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cluster.GetGVKParser(), nil
|
||||
}
|
||||
|
||||
func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha1.OperationState) {
|
||||
// Sync requests might be requested with ambiguous revisions (e.g. master, HEAD, v1.2.3).
|
||||
// This can change meaning when resuming operations (e.g a hook sync). After calculating a
|
||||
@@ -140,7 +149,13 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
|
||||
}
|
||||
|
||||
atomic.AddUint64(&syncIdPrefix, 1)
|
||||
syncId := fmt.Sprintf("%05d-%s", syncIdPrefix, rand.RandString(5))
|
||||
randSuffix, err := rand.String(5)
|
||||
if err != nil {
|
||||
state.Phase = common.OperationError
|
||||
state.Message = fmt.Sprintf("Failed generate random sync ID: %v", err)
|
||||
return
|
||||
}
|
||||
syncId := fmt.Sprintf("%05d-%s", syncIdPrefix, randSuffix)
|
||||
|
||||
logEntry := log.WithFields(log.Fields{"application": app.Name, "syncId": syncId})
|
||||
initialResourcesRes := make([]common.ResourceSyncResult, 0)
|
||||
|
||||
@@ -4,10 +4,10 @@ You can download the latest Argo CD version from [the latest release page of thi
|
||||
|
||||
## Linux and WSL
|
||||
|
||||
### ArchLinux User Repository ([AUR](https://aur.archlinux.org/packages/))
|
||||
### ArchLinux
|
||||
|
||||
```bash
|
||||
yay -Sy argocd-bin
|
||||
pacman -S argocd
|
||||
```
|
||||
|
||||
### Homebrew
|
||||
|
||||
@@ -27,6 +27,8 @@ kubectl -n argocd scale deployment/argocd-dex-server --replicas 0
|
||||
kubectl -n argocd scale deployment/argocd-repo-server --replicas 0
|
||||
kubectl -n argocd scale deployment/argocd-server --replicas 0
|
||||
kubectl -n argocd scale deployment/argocd-redis --replicas 0
|
||||
kubectl -n argocd scale deployment/argocd-applicationset-controller --replicas 0
|
||||
kubectl -n argocd scale deployment/argocd-notifications-controller --replicas 0
|
||||
```
|
||||
|
||||
### Start local services
|
||||
|
||||
@@ -45,7 +45,7 @@ spec:
|
||||
metadata:
|
||||
name: '{{name}}-guestbook' # 'name' field of the Secret
|
||||
spec:
|
||||
project: "default"
|
||||
project: "my-project"
|
||||
source:
|
||||
repoURL: https://github.com/argoproj/argocd-example-apps/
|
||||
targetRevision: HEAD
|
||||
@@ -144,7 +144,7 @@ spec:
|
||||
metadata:
|
||||
name: '{{name}}-guestbook'
|
||||
spec:
|
||||
project: "default"
|
||||
project: "my-project"
|
||||
source:
|
||||
repoURL: https://github.com/argoproj/argocd-example-apps/
|
||||
# The cluster values field for each generator will be substituted here:
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
The Git generator contains two subtypes: the Git directory generator, and Git file generator.
|
||||
|
||||
!!! warning
|
||||
Git generators are often used to make it easier for (non-admin) developers to create Applications.
|
||||
If the `project` field in your ApplicationSet is templated, developers may be able to create Applications under Projects with excessive permissions.
|
||||
For ApplicationSets with a templated `project` field, [the source of truth _must_ be controlled by admins](./Security.md#templated-project-field)
|
||||
- in the case of git generators, PRs must require admin approval.
|
||||
|
||||
## Git Generator: Directories
|
||||
|
||||
The Git directory generator, one of two subtypes of the Git generator, generates parameters using the directory structure of a specified Git repository.
|
||||
@@ -41,7 +47,7 @@ spec:
|
||||
metadata:
|
||||
name: '{{path[0]}}'
|
||||
spec:
|
||||
project: default
|
||||
project: "my-project"
|
||||
source:
|
||||
repoURL: https://github.com/argoproj/argo-cd.git
|
||||
targetRevision: HEAD
|
||||
@@ -59,13 +65,15 @@ The generator parameters are:
|
||||
- `{{path.basename}}`: For any directory path within the Git repository that matches the `path` wildcard, the right-most path name is extracted (e.g. `/directory/directory2` would produce `directory2`).
|
||||
- `{{path.basenameNormalized}}`: This field is the same as `path.basename` with unsupported characters replaced with `-` (e.g. a `path` of `/directory/directory_2`, and `path.basename` of `directory_2` would produce `directory-2` here).
|
||||
|
||||
Whenever a new Helm chart/Kustomize YAML/Application/plain subfolder is added to the Git repository, the ApplicationSet controller will detect this change and automatically deploy the resulting manifests within new `Application` resources.
|
||||
**Note**: The right-most path name always becomes `{{path.basename}}`. For example, for `- path: /one/two/three/four`, `{{path.basename}}` is `four`.
|
||||
|
||||
Whenever a new Helm chart/Kustomize YAML/Application/plain subdirectory is added to the Git repository, the ApplicationSet controller will detect this change and automatically deploy the resulting manifests within new `Application` resources.
|
||||
|
||||
As with other generators, clusters *must* already be defined within Argo CD, in order to generate Applications for them.
|
||||
|
||||
### Exclude directories
|
||||
|
||||
The Git directory generator will automatically exclude folders that begin with `.` (such as `.git`).
|
||||
The Git directory generator will automatically exclude directories that begin with `.` (such as `.git`).
|
||||
|
||||
The Git directory generator also supports an `exclude` option in order to exclude directories in the repository from being scanned by the ApplicationSet controller:
|
||||
|
||||
@@ -88,7 +96,7 @@ spec:
|
||||
metadata:
|
||||
name: '{{path.basename}}'
|
||||
spec:
|
||||
project: default
|
||||
project: "my-project"
|
||||
source:
|
||||
repoURL: https://github.com/argoproj/argo-cd.git
|
||||
targetRevision: HEAD
|
||||
@@ -144,6 +152,41 @@ Or, a shorter way (using [path.Match](https://golang.org/pkg/path/#Match) syntax
|
||||
exclude: true
|
||||
```
|
||||
|
||||
### Root Of Git Repo
|
||||
|
||||
The Git directory generator can be configured to deploy from the root of the git repository by providing `'*'` as the `path`.
|
||||
|
||||
To exclude directories, you only need to put the name/[path.Match](https://golang.org/pkg/path/#Match) of the directory you do not want to deploy.
|
||||
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: ApplicationSet
|
||||
metadata:
|
||||
name: cluster-addons
|
||||
namespace: argocd
|
||||
spec:
|
||||
generators:
|
||||
- git:
|
||||
repoURL: https://github.com/example/example-repo.git
|
||||
revision: HEAD
|
||||
directories:
|
||||
- path: '*'
|
||||
- path: donotdeploy
|
||||
exclude: true
|
||||
template:
|
||||
metadata:
|
||||
name: '{{path.basename}}'
|
||||
spec:
|
||||
project: "my-project"
|
||||
source:
|
||||
repoURL: https://github.com/example/example-repo.git
|
||||
targetRevision: HEAD
|
||||
path: '{{path}}'
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: '{{path.basename}}'
|
||||
```
|
||||
|
||||
## Git Generator: Files
|
||||
|
||||
The Git file generator is the second subtype of the Git generator. The Git file generator generates parameters using the contents of JSON/YAML files found within a specified repository.
|
||||
@@ -164,7 +207,7 @@ Suppose you have a Git repository with the following directory structure:
|
||||
└── git-generator-files.yaml
|
||||
```
|
||||
|
||||
The folders are:
|
||||
The directories are:
|
||||
|
||||
- `guestbook` contains the Kubernetes resources for a simple guestbook application
|
||||
- `cluster-config` contains JSON/YAML files describing the individual engineering clusters: one for `dev` and one for `prod`.
|
||||
@@ -228,10 +271,16 @@ As with other generators, clusters *must* already be defined within Argo CD, in
|
||||
|
||||
In addition to the flattened key/value pairs from the configuration file, the following generator parameters are provided:
|
||||
|
||||
- `{{path}}`: The path to the folder containing matching configuration file within the Git repository. Example: `/clusters/clusterA`, if the config file was `/clusters/clusterA/config.json`
|
||||
- `{{path}}`: The path to the directory containing matching configuration file within the Git repository. Example: `/clusters/clusterA`, if the config file was `/clusters/clusterA/config.json`
|
||||
- `{{path[n]}}`: The path to the matching configuration file within the Git repository, split into array elements (`n` - array index). Example: `path[0]: clusters`, `path[1]: clusterA`
|
||||
- `{{path.basename}}`: Basename of the path to the folder containing the configuration file (e.g. `clusterA`, with the above example.)
|
||||
- `{{path.basename}}`: Basename of the path to the directory containing the configuration file (e.g. `clusterA`, with the above example.)
|
||||
- `{{path.basenameNormalized}}`: This field is the same as `path.basename` with unsupported characters replaced with `-` (e.g. a `path` of `/directory/directory_2`, and `path.basename` of `directory_2` would produce `directory-2` here).
|
||||
- `{{path.filename}}`: The matched filename. e.g., `config.json` in the above example.
|
||||
- `{{path.filenameNormalized}}`: The matched filename with unsupported characters replaced with `-`.
|
||||
|
||||
**Note**: The right-most *directory* name always becomes `{{path.basename}}`. For example, from `- path: /one/two/three/four/config.json`, `{{path.basename}}` will be `four`.
|
||||
The filename can always be accessed using `{{path.filename}}`.
|
||||
|
||||
|
||||
## Webhook Configuration
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ spec:
|
||||
metadata:
|
||||
name: '{{cluster}}-guestbook'
|
||||
spec:
|
||||
project: default
|
||||
project: "my-project"
|
||||
source:
|
||||
repoURL: https://github.com/argoproj/argo-cd.git
|
||||
targetRevision: HEAD
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Pull Request Generator
|
||||
|
||||
The Pull Request generator uses the API of an SCMaaS provider (eg GitHub/GitLab) to automatically discover open pull requests within an repository. This fits well with the style of building a test environment when you create a pull request.
|
||||
|
||||
The Pull Request generator uses the API of an SCMaaS provider (GitHub, Gitea, or Bitbucket Server) to automatically discover open pull requests within a repository. This fits well with the style of building a test environment when you create a pull request.
|
||||
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
@@ -16,9 +15,15 @@ spec:
|
||||
# ...
|
||||
```
|
||||
|
||||
!!! note
|
||||
Know the security implications of PR generators in ApplicationSets.
|
||||
[Only admins may create ApplicationSets](./Security.md#only-admins-may-createupdatedelete-applicationsets) to avoid
|
||||
leaking Secrets, and [only admins may create PRs](./Security.md#templated-project-field) if the `project` field of
|
||||
an ApplicationSet with a PR generator is templated, to avoid granting management of out-of-bounds resources.
|
||||
|
||||
## GitHub
|
||||
|
||||
Specify the repository from which to fetch the Github Pull requests.
|
||||
Specify the repository from which to fetch the GitHub Pull requests.
|
||||
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
@@ -48,7 +53,7 @@ spec:
|
||||
```
|
||||
|
||||
* `owner`: Required name of the GitHub organization or user.
|
||||
* `repo`: Required name of the Github repository.
|
||||
* `repo`: Required name of the GitHub repository.
|
||||
* `api`: If using GitHub Enterprise, the URL to access it. (Optional)
|
||||
* `tokenRef`: A `Secret` name and key containing the GitHub access token to use for requests. If not specified, will make anonymous requests which have a lower rate limit and can only see public repositories. (Optional)
|
||||
* `labels`: Labels is used to filter the PRs that you want to target. (Optional)
|
||||
@@ -182,7 +187,7 @@ spec:
|
||||
parameters:
|
||||
- name: "image.tag"
|
||||
value: "pull-{{head_sha}}"
|
||||
project: default
|
||||
project: "my-project"
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: default
|
||||
@@ -213,7 +218,7 @@ spec:
|
||||
app.kubernetes.io/instance: {{branch}}-{{number}}
|
||||
images:
|
||||
- ghcr.io/myorg/myrepo:{{head_sha}}
|
||||
project: default
|
||||
project: "my-project"
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: default
|
||||
@@ -230,6 +235,7 @@ When using a Pull Request generator, the ApplicationSet controller polls every `
|
||||
The configuration is almost the same as the one described [in the Git generator](Generators-Git.md), but there is one difference: if you want to use the Pull Request Generator as well, additionally configure the following settings.
|
||||
|
||||
In section 1, _"Create the webhook in the Git provider"_, add an event so that a webhook request will be sent when a pull request is created, closed, or label changed.
|
||||
|
||||
Select `Let me select individual events` and enable the checkbox for `Pull requests`.
|
||||
|
||||

|
||||
|
||||
@@ -19,6 +19,12 @@ spec:
|
||||
|
||||
* `cloneProtocol`: Which protocol to use for the SCM URL. Default is provider-specific but ssh if possible. Not all providers necessarily support all protocols, see provider documentation below for available options.
|
||||
|
||||
!!! note
|
||||
Know the security implications of using SCM generators. [Only admins may create ApplicationSets](./Security.md#only-admins-may-createupdatedelete-applicationsets)
|
||||
to avoid leaking Secrets, and [only admins may create repos/branches](./Security.md#templated-project-field) if the
|
||||
`project` field of an ApplicationSet with an SCM generator is templated, to avoid granting management of
|
||||
out-of-bounds resources.
|
||||
|
||||
## GitHub
|
||||
|
||||
The GitHub mode uses the GitHub API to scan and organization in either github.com or GitHub Enterprise.
|
||||
|
||||
@@ -22,9 +22,9 @@ Follow the [Argo CD Getting Started](../../getting_started.md) instructions for
|
||||
|
||||
### B) Install ApplicationSet into an existing Argo CD install (pre-Argo CD v2.3)
|
||||
|
||||
**Note**: These instruction only apply to versions of Argo CD before v2.3.0.
|
||||
**Note**: These instructions only apply to versions of Argo CD before v2.3.0.
|
||||
|
||||
The ApplicationSet controller *must* be installed into the same namespace as the Argo CD it is targetting.
|
||||
The ApplicationSet controller *must* be installed into the same namespace as the Argo CD it is targeting.
|
||||
|
||||
Presuming that Argo CD is installed into the `argocd` namespace, run the following command:
|
||||
|
||||
|
||||
38
docs/operator-manual/applicationset/Security.md
Normal file
38
docs/operator-manual/applicationset/Security.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# ApplicationSet Security
|
||||
|
||||
ApplicationSet is a powerful tool, and it is crucial to understand its security implications before using it.
|
||||
|
||||
## Only admins may create/update/delete ApplicationSets
|
||||
|
||||
ApplicationSets can create Applications under arbitrary [Projects](../../user-guide/projects.md). Argo CD setups often
|
||||
include Projects (such as the `default`) with high levels of permissions, often including the ability to manage the
|
||||
resources of Argo CD itself (like the RBAC ConfigMap).
|
||||
|
||||
ApplicationSets can also quickly create an arbitrary number of Applications and just as quickly delete them.
|
||||
|
||||
Finally, ApplicationSets can reveal privileged information. For example, the [git generator](./Generators-Git.md) can
|
||||
read Secrets in the Argo CD namespace and send them to arbitrary URLs as auth headers. (This functionality is intended
|
||||
for authorizing requests to SCM providers like GitHub, but it could be abused by a malicious user.)
|
||||
|
||||
For these reasons, **only admins** may be given permission (via Kubernetes RBAC or any other mechanism) to create,
|
||||
update, or delete ApplicationSets.
|
||||
|
||||
## Admins must apply appropriate controls for ApplicationSets' sources of truth
|
||||
|
||||
Even if non-admins can't create ApplicationSet resources, they may be able to affect the behavior of ApplicationSets.
|
||||
|
||||
For example, if an ApplicationSet uses a [git generator](./Generators-Git.md), a malicious user with push access to the
|
||||
source git repository could generate an excessively high number of Applications, putting strain on the ApplicationSet
|
||||
and Application controllers. They could also cause the SCM provider's rate limiting to kick in, degrading ApplicationSet
|
||||
service.
|
||||
|
||||
### Templated `project` field
|
||||
|
||||
It's important to pay special attention to ApplicationSets where the `project` field is templated. A malicious user with
|
||||
write access to the generator's source of truth (for example, someone with push access to the git repo for a git
|
||||
generator) could create Applications under Projects with insufficient restrictions. A malicious user with the ability to
|
||||
create an Application under an unrestricted Project (like the `default` Project) could take control of Argo CD itself
|
||||
by, for example, modifying its RBAC ConfigMap.
|
||||
|
||||
If the `project` field is not hard-coded in an ApplicationSet's template, then admins _must_ control all sources of
|
||||
truth for the ApplicationSet's generators.
|
||||
@@ -15,6 +15,9 @@ The ApplicationSet controller, supplements Argo CD by adding additional features
|
||||
- Improved support for monorepos: in the context of Argo CD, a monorepo is multiple Argo CD Application resources defined within a single Git repository
|
||||
- Within multitenant clusters, improves the ability of individual cluster tenants to deploy applications using Argo CD (without needing to involve privileged cluster administrators in enabling the destination clusters/namespaces)
|
||||
|
||||
!!! note
|
||||
Be aware of the [security implications](./Security.md) of ApplicationSets before using them.
|
||||
|
||||
## The ApplicationSet resource
|
||||
|
||||
This example defines a new `guestbook` resource of kind `ApplicationSet`:
|
||||
@@ -37,6 +40,7 @@ spec:
|
||||
metadata:
|
||||
name: '{{cluster}}-guestbook'
|
||||
spec:
|
||||
project: my-project
|
||||
source:
|
||||
repoURL: https://github.com/infra-team/cluster-deployments.git
|
||||
targetRevision: HEAD
|
||||
|
||||
@@ -288,3 +288,9 @@ data:
|
||||
|
||||
# exec.enabled indicates whether the UI exec feature is enabled. It is disabled by default.
|
||||
exec.enabled: "false"
|
||||
|
||||
# oidc.tls.insecure.skip.verify determines whether certificate verification is skipped when verifying tokens with the
|
||||
# configured OIDC provider (either external or the bundled Dex instance). Setting this to "true" will cause JWT
|
||||
# token verification to pass despite the OIDC provider having an invalid certificate. Only set to "true" if you
|
||||
# understand the risks.
|
||||
oidc.tls.insecure.skip.verify: "false"
|
||||
|
||||
@@ -17,6 +17,9 @@ data:
|
||||
# Redis database
|
||||
redis.db:
|
||||
|
||||
# Open-Telemetry collector address: (e.g. "otel-collector:4317")
|
||||
otlp.address:
|
||||
|
||||
## Controller Properties
|
||||
# Repo server RPC call timeout seconds.
|
||||
controller.repo.server.timeout.seconds: "60"
|
||||
@@ -103,4 +106,10 @@ data:
|
||||
reposerver.repo.cache.expiration: "24h0m0s"
|
||||
# Cache expiration default (default 24h0m0s)
|
||||
reposerver.default.cache.expiration: "24h0m0s"
|
||||
|
||||
# Max combined manifest file size for a single directory-type Application. In-memory manifest representation may be as
|
||||
# much as 300x the manifest file size. Limit this to stay within the memory limits of the repo-server while allowing
|
||||
# for 300x memory expansion and N Applications running at the same time.
|
||||
# (example 10M max * 300 expansion * 10 Apps = 30G max theoretical memory usage).
|
||||
reposerver.max.combined.directory.manifests.size: '10M'
|
||||
# Paths to be excluded from the tarball streamed to plugins. Separate with ;
|
||||
reposerver.plugin.tar.exclusions: ""
|
||||
|
||||
66
docs/operator-manual/notifications/services/pagerduty.md
Executable file
66
docs/operator-manual/notifications/services/pagerduty.md
Executable file
@@ -0,0 +1,66 @@
|
||||
# Pagerduty
|
||||
|
||||
## Parameters
|
||||
|
||||
The Pagerduty notification service is used to create pagerduty incidents and requires specifying the following settings:
|
||||
|
||||
* `pagerdutyToken` - the pagerduty auth token
|
||||
* `from` - email address of a valid user associated with the account making the request.
|
||||
* `serviceID` - The ID of the resource.
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
The following snippet contains sample Pagerduty service configuration:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: <secret-name>
|
||||
stringData:
|
||||
pagerdutyToken: <pd-api-token>
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: <config-map-name>
|
||||
data:
|
||||
service.pagerduty: |
|
||||
token: $pagerdutyToken
|
||||
from: <emailid>
|
||||
```
|
||||
|
||||
## Template
|
||||
|
||||
Notification templates support specifying subject for pagerduty notifications:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: <config-map-name>
|
||||
data:
|
||||
template.rollout-aborted: |
|
||||
message: Rollout {{.rollout.metadata.name}} is aborted.
|
||||
pagerduty:
|
||||
title: "Rollout {{.rollout.metadata.name}}"
|
||||
urgency: "high"
|
||||
body: "Rollout {{.rollout.metadata.name}} aborted "
|
||||
priorityID: "<priorityID of incident>"
|
||||
```
|
||||
|
||||
NOTE: A Priority is a label representing the importance and impact of an incident. This is only available on Standard and Enterprise plans of pagerduty.
|
||||
|
||||
## Annotation
|
||||
|
||||
Annotation sample for pagerduty notifications:
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
annotations:
|
||||
notifications.argoproj.io/subscribe.on-rollout-aborted.pagerduty: "<serviceID for Pagerduty>"
|
||||
```
|
||||
@@ -54,6 +54,26 @@ The Slack notification service configuration includes following settings:
|
||||
annotations:
|
||||
notifications.argoproj.io/subscribe.on-sync-succeeded.slack: my_channel
|
||||
|
||||
1. Annotation with more than one trigger multiple of destinations and recipients
|
||||
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
annotations:
|
||||
notifications.argoproj.io/subscriptions: |
|
||||
- trigger: [on-scaling-replica-set, on-rollout-updated, on-rollout-step-completed]
|
||||
destinations:
|
||||
- service: slack
|
||||
recipients: [my-channel-1, my-channel-2]
|
||||
- service: email
|
||||
recipients: [recipient-1, recipient-2, recipient-3 ]
|
||||
- trigger: [on-rollout-aborted, on-analysis-run-failed, on-analysis-run-error]
|
||||
destinations:
|
||||
- service: slack
|
||||
recipients: [my-channel-21, my-channel-22]
|
||||
```
|
||||
|
||||
## Templates
|
||||
|
||||
Notification templates can be customized to leverage slack message blocks and attachments
|
||||
|
||||
@@ -18,11 +18,11 @@ These default built-in role definitions can be seen in [builtin-policy.csv](http
|
||||
|
||||
Breaking down the permissions definition differs slightly between applications and every other resource type in Argo CD.
|
||||
|
||||
* All resources *except* applications permissions (see next bullet):
|
||||
* All resources *except* application-specific permissions (see next bullet):
|
||||
|
||||
`p, <role/user/group>, <resource>, <action>, <object>`
|
||||
|
||||
* Applications (which belong to an AppProject):
|
||||
* Applications, logs, and exec (which belong to an AppProject):
|
||||
|
||||
`p, <role/user/group>, <resource>, <action>, <appproject>/<object>`
|
||||
|
||||
@@ -30,7 +30,29 @@ Breaking down the permissions definition differs slightly between applications a
|
||||
|
||||
Resources: `clusters`, `projects`, `applications`, `repositories`, `certificates`, `accounts`, `gpgkeys`, `logs`, `exec`
|
||||
|
||||
Actions: `get`, `create`, `update`, `delete`, `sync`, `override`, `action`
|
||||
Actions: `get`, `create`, `update`, `delete`, `sync`, `override`,
|
||||
`action/<group/kind/action-name>`
|
||||
|
||||
#### Application resources
|
||||
|
||||
The resource path for application objects is of the form
|
||||
`<project-name>/<application-name>`.
|
||||
|
||||
Delete access to sub-resources of a project, such as a rollout or a pod, cannot
|
||||
be managed granularly. `<project-name>/<application-name>` grants access to all
|
||||
subresources of an application.
|
||||
|
||||
#### The `action` action
|
||||
|
||||
The `action` action corresponds to either built-in resource customizations defined
|
||||
[in the Argo CD repository](https://github.com/argoproj/argo-cd/search?q=filename%3Aaction.lua+path%3Aresource_customizations),
|
||||
or to [custom resource actions](resource_actions.md#custom-resource-actions) defined by you.
|
||||
The `action` path is of the form `action/<api-group>/<Kind>/<action-name>`. For
|
||||
example, a resource customization path
|
||||
`resource_customizations/extensions/DaemonSet/actions/restart/action.lua`
|
||||
corresponds to the `action` path `action/extensions/DaemonSet/restart`. You can
|
||||
also use glob patterns in the action path: `action/*` (or regex patterns if you have
|
||||
[enabled the `regex` match mode](https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/argocd-rbac-cm.yaml)).
|
||||
|
||||
#### `exec` resource
|
||||
|
||||
@@ -42,7 +64,8 @@ they have `create` privileges. If the Pod mounts a ServiceAccount token (which i
|
||||
then the user effectively has the same privileges as that ServiceAccount.
|
||||
|
||||
The exec feature is disabled entirely by default. To enable it, set the `exec.enabled` key to "true" on the argocd-cm
|
||||
ConfigMap. You will also need to add the following to the argocd-api-server Role or ClusterRole.
|
||||
ConfigMap. You will also need to add the following to the argocd-api-server Role (if you're using Argo CD in namespaced
|
||||
mode) or ClusterRole (if you're using Argo CD in cluster mode).
|
||||
|
||||
```yaml
|
||||
- apiGroups:
|
||||
@@ -78,7 +101,7 @@ data:
|
||||
p, role:org-admin, repositories, update, *, allow
|
||||
p, role:org-admin, repositories, delete, *, allow
|
||||
p, role:org-admin, logs, get, *, allow
|
||||
p, role:org-admin, exec, get, *, allow
|
||||
p, role:org-admin, exec, create, */*, allow
|
||||
|
||||
g, your-github-org:your-team, role:org-admin
|
||||
```
|
||||
@@ -94,12 +117,12 @@ p, role:staging-db-admins, applications, override, staging-db-admins/*, allow
|
||||
p, role:staging-db-admins, applications, sync, staging-db-admins/*, allow
|
||||
p, role:staging-db-admins, applications, update, staging-db-admins/*, allow
|
||||
p, role:staging-db-admins, logs, get, staging-db-admins/*, allow
|
||||
p, role:staging-db-admins, exec, get, staging-db-admins/*, allow
|
||||
p, role:staging-db-admins, exec, create, staging-db-admins/*, allow
|
||||
p, role:staging-db-admins, projects, get, staging-db-admins, allow
|
||||
g, db-admins, role:staging-db-admins
|
||||
```
|
||||
|
||||
This example defines a *role* called `staging-db-admins` with *eight permissions* that allow that role to perform the *actions* (`create`/`delete`/`get`/`override`/`sync`/`update` applications, `get` logs, `get` exec and `get` appprojects) against `*` (all) objects in the `staging-db-admins` Argo CD AppProject.
|
||||
This example defines a *role* called `staging-db-admins` with *eight permissions* that allow that role to perform the *actions* (`create`/`delete`/`get`/`override`/`sync`/`update` applications, `get` logs, `create` exec and `get` appprojects) against `*` (all) objects in the `staging-db-admins` Argo CD AppProject.
|
||||
|
||||
## Anonymous Access
|
||||
|
||||
|
||||
@@ -119,6 +119,13 @@ kubectl delete secret argocd-manager-token-XXXXXX -n kube-system
|
||||
argocd cluster add CONTEXTNAME
|
||||
```
|
||||
|
||||
!!! note
|
||||
Kubernetes 1.24 [stopped automatically creating tokens for Service Accounts](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.24.md#no-really-you-must-read-this-before-you-upgrade).
|
||||
[Starting in Argo CD 2.4](https://github.com/argoproj/argo-cd/pull/9546), `argocd cluster add` creates a
|
||||
ServiceAccount _and_ a non-expiring Service Account token Secret when adding 1.24 clusters. In the future, Argo CD
|
||||
will [add support for the Kubernetes TokenRequest API](https://github.com/argoproj/argo-cd/issues/9610) to avoid
|
||||
using long-lived tokens.
|
||||
|
||||
To revoke Argo CD's access to a managed cluster, delete the RBAC artifacts against the *_managed_*
|
||||
cluster, and remove the cluster entry from Argo CD:
|
||||
|
||||
@@ -210,4 +217,50 @@ Argo CD logs payloads of most API requests except request that are considered se
|
||||
can be found in [server/server.go](https://github.com/argoproj/argo-cd/blob/abba8dddce8cd897ba23320e3715690f465b4a95/server/server.go#L516).
|
||||
|
||||
Argo CD does not log IP addresses of clients requesting API endpoints, since the API server is typically behind a proxy. Instead, it is recommended
|
||||
to configure IP addresses logging in the proxy server that sits in front of the API server.
|
||||
to configure IP addresses logging in the proxy server that sits in front of the API server.
|
||||
|
||||
## ApplicationSets
|
||||
|
||||
Argo CD's ApplicationSets feature has its own [security considerations](./applicationset/Security.md). Be aware of those
|
||||
issues before using ApplicationSets.
|
||||
|
||||
## Limiting Directory App Memory Usage
|
||||
|
||||
> >2.2.10, 2.1.16, >2.3.5
|
||||
|
||||
Directory-type Applications (those whose source is raw JSON or YAML files) can consume significant
|
||||
[repo-server](architecture.md#repository-server) memory, depending on the size and structure of the YAML files.
|
||||
|
||||
To avoid over-using memory in the repo-server (potentially causing a crash and denial of service), set the
|
||||
`reposerver.max.combined.directory.manifests.size` config option in [argocd-cmd-params-cm](argocd-cmd-params-cm.yaml).
|
||||
|
||||
This option limits the combined size of all JSON or YAML files in an individual app. Note that the in-memory
|
||||
representation of a manifest may be as much as 300x the size of the manifest on disk. Also note that the limit is per
|
||||
Application. If manifests are generated for multiple applications at once, memory usage will be higher.
|
||||
|
||||
**Example:**
|
||||
|
||||
Suppose your repo-server has a 10G memory limit, and you have ten Applications which use raw JSON or YAML files. To
|
||||
calculate the max safe combined file size per Application, divide 10G by 300 * 10 Apps (300 being the worst-case memory
|
||||
growth factor for the manifests).
|
||||
|
||||
```
|
||||
10G / 300 * 10 = 3M
|
||||
```
|
||||
|
||||
So a reasonably safe configuration for this setup would be a 3M limit per app.
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: argocd-cmd-params-cm
|
||||
data:
|
||||
reposerver.max.combined.directory.manifests.size: '3M'
|
||||
```
|
||||
|
||||
The 300x ratio assumes a maliciously-crafted manifest file. If you only want to protect against accidental excessive
|
||||
memory use, it is probably safe to use a smaller ratio.
|
||||
|
||||
Keep in mind that if a malicious user can create additional Applications, they can increase the total memory usage.
|
||||
Grant [App creation privileges](rbac.md) carefully.
|
||||
|
||||
@@ -37,6 +37,7 @@ argocd-application-controller [flags]
|
||||
--metrics-port int Start metrics server on given port (default 8082)
|
||||
-n, --namespace string If present, the namespace scope for this CLI request
|
||||
--operation-processors int Number of application operation processors (default 10)
|
||||
--otlp-address string OpenTelemetry collector address to send traces to
|
||||
--password string Password for basic authentication to the API server
|
||||
--redis string Redis server hostname and port (e.g. argocd-redis:6379).
|
||||
--redis-ca-certificate string Path to Redis server CA certificate (e.g. /etc/certs/redis/ca.crt). If not specified, system trusted CAs will be used for server certificate validation.
|
||||
|
||||
@@ -13,28 +13,30 @@ argocd-repo-server [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
--default-cache-expiration duration Cache expiration default (default 24h0m0s)
|
||||
--disable-tls Disable TLS on the gRPC endpoint
|
||||
-h, --help help for argocd-repo-server
|
||||
--logformat string Set the logging format. One of: text|json (default "text")
|
||||
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
|
||||
--metrics-port int Start metrics server on given port (default 8084)
|
||||
--otlp-address string OpenTelemetry collector address to send traces to
|
||||
--parallelismlimit int Limit on number of concurrent manifests generate requests. Any value less the 1 means no limit.
|
||||
--port int Listen on given port for incoming connections (default 8081)
|
||||
--redis string Redis server hostname and port (e.g. argocd-redis:6379).
|
||||
--redis-ca-certificate string Path to Redis server CA certificate (e.g. /etc/certs/redis/ca.crt). If not specified, system trusted CAs will be used for server certificate validation.
|
||||
--redis-client-certificate string Path to Redis client certificate (e.g. /etc/certs/redis/client.crt).
|
||||
--redis-client-key string Path to Redis client key (e.g. /etc/certs/redis/client.crt).
|
||||
--redis-insecure-skip-tls-verify Skip Redis server certificate validation.
|
||||
--redis-use-tls Use TLS when connecting to Redis.
|
||||
--redisdb int Redis database.
|
||||
--repo-cache-expiration duration Cache expiration for repo state, incl. app lists, app details, manifest generation, revision meta-data (default 24h0m0s)
|
||||
--revision-cache-expiration duration Cache expiration for cached revision (default 3m0s)
|
||||
--sentinel stringArray Redis sentinel hostname and port (e.g. argocd-redis-ha-announce-0:6379).
|
||||
--sentinelmaster string Redis sentinel master group name. (default "master")
|
||||
--tlsciphers string The list of acceptable ciphers to be used when establishing TLS connections. Use 'list' to list available ciphers. (default "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_GCM_SHA384")
|
||||
--tlsmaxversion string The maximum SSL/TLS version that is acceptable (one of: 1.0|1.1|1.2|1.3) (default "1.3")
|
||||
--tlsminversion string The minimum SSL/TLS version that is acceptable (one of: 1.0|1.1|1.2|1.3) (default "1.2")
|
||||
--default-cache-expiration duration Cache expiration default (default 24h0m0s)
|
||||
--disable-tls Disable TLS on the gRPC endpoint
|
||||
-h, --help help for argocd-repo-server
|
||||
--logformat string Set the logging format. One of: text|json (default "text")
|
||||
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
|
||||
--max-combined-directory-manifests-size string Max combined size of manifest files in a directory-type Application (default "10M")
|
||||
--metrics-port int Start metrics server on given port (default 8084)
|
||||
--otlp-address string OpenTelemetry collector address to send traces to
|
||||
--parallelismlimit int Limit on number of concurrent manifests generate requests. Any value less the 1 means no limit.
|
||||
--plugin-tar-exclude stringArray Globs to filter when sending tarballs to plugins.
|
||||
--port int Listen on given port for incoming connections (default 8081)
|
||||
--redis string Redis server hostname and port (e.g. argocd-redis:6379).
|
||||
--redis-ca-certificate string Path to Redis server CA certificate (e.g. /etc/certs/redis/ca.crt). If not specified, system trusted CAs will be used for server certificate validation.
|
||||
--redis-client-certificate string Path to Redis client certificate (e.g. /etc/certs/redis/client.crt).
|
||||
--redis-client-key string Path to Redis client key (e.g. /etc/certs/redis/client.crt).
|
||||
--redis-insecure-skip-tls-verify Skip Redis server certificate validation.
|
||||
--redis-use-tls Use TLS when connecting to Redis.
|
||||
--redisdb int Redis database.
|
||||
--repo-cache-expiration duration Cache expiration for repo state, incl. app lists, app details, manifest generation, revision meta-data (default 24h0m0s)
|
||||
--revision-cache-expiration duration Cache expiration for cached revision (default 3m0s)
|
||||
--sentinel stringArray Redis sentinel hostname and port (e.g. argocd-redis-ha-announce-0:6379).
|
||||
--sentinelmaster string Redis sentinel master group name. (default "master")
|
||||
--tlsciphers string The list of acceptable ciphers to be used when establishing TLS connections. Use 'list' to list available ciphers. (default "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_GCM_SHA384")
|
||||
--tlsmaxversion string The maximum SSL/TLS version that is acceptable (one of: 1.0|1.1|1.2|1.3) (default "1.3")
|
||||
--tlsminversion string The minimum SSL/TLS version that is acceptable (one of: 1.0|1.1|1.2|1.3) (default "1.2")
|
||||
```
|
||||
|
||||
|
||||
@@ -6,8 +6,11 @@ The Argo CD Notifications and ApplicationSet are part of Argo CD now. You no lon
|
||||
The Notifications and ApplicationSet components are bundled into default Argo CD installation manifests.
|
||||
|
||||
The bundled manifests are drop-in replacements for the previous versions. If you are using Kustomize to bundle the manifests together then just
|
||||
remove references to https://github.com/argoproj-labs/argocd-notifications and https://github.com/argoproj-labs/applicationset. No action is required
|
||||
if you are using `kubectl apply`.
|
||||
remove references to https://github.com/argoproj-labs/argocd-notifications and https://github.com/argoproj-labs/applicationset.
|
||||
|
||||
If you are using [the argocd-notifications helm chart](https://github.com/argoproj/argo-helm/tree/argocd-notifications-1.8.1/charts/argocd-notifications), you can move the chart [values](https://github.com/argoproj/argo-helm/blob/argocd-notifications-1.8.1/charts/argocd-notifications/values.yaml) to the `notifications` section of the argo-cd chart [values](https://github.com/argoproj/argo-helm/blob/main/charts/argo-cd/values.yaml#L2152). Although most values remain as is, for details please look up the values that are relevant to you.
|
||||
|
||||
No action is required if you are using `kubectl apply`.
|
||||
|
||||
## Configure Additional Argo CD Binaries
|
||||
|
||||
@@ -42,4 +45,4 @@ Note that bundled Kustomize version has been upgraded from 4.2.0 to 4.4.1.
|
||||
|
||||
## Upgraded Helm Version
|
||||
|
||||
Note that bundled Helm version has been upgraded from 3.7.1 to 3.8.0.
|
||||
Note that bundled Helm version has been upgraded from 3.7.1 to 3.8.0.
|
||||
|
||||
@@ -2,20 +2,92 @@
|
||||
|
||||
## KSonnet support is removed
|
||||
|
||||
The [https://ksonnet.io/] had been deprecated in [2019](https://github.com/ksonnet/ksonnet/pull/914/files) and no longer maintained.
|
||||
The time has come to remove it from the ArgoCD.
|
||||
Ksonnet was deprecated in [2019](https://github.com/ksonnet/ksonnet/pull/914/files) and is no longer maintained.
|
||||
The time has come to remove it from the Argo CD.
|
||||
|
||||
## Helm 2 support is removed
|
||||
|
||||
Helm 2 is not been officially supported since [Nov 2020](https://helm.sh/blog/helm-2-becomes-unsupported/). In order to ensure a smooth transition
|
||||
Helm 2 support was preserved in the Argo CD. We feel that Helm 3 is stable and it is time to drop Helm 2 support.
|
||||
Helm 2 has not been officially supported since [Nov 2020](https://helm.sh/blog/helm-2-becomes-unsupported/). In order to ensure a smooth transition,
|
||||
Helm 2 support was preserved in the Argo CD. We feel that Helm 3 is stable, and it is time to drop Helm 2 support.
|
||||
|
||||
## Support for private repo SSH keys using the SHA-1 signature hash algorithm is removed
|
||||
|
||||
Argo CD 2.4 upgraded its base image from Ubuntu 20.04 to Ubuntu 22.04, which upgraded OpenSSH to 8.9. OpenSSH starting
|
||||
with 8.8 [dropped support for the `ssh-rsa` SHA-1 key signature algorithm](https://www.openssh.com/txt/release-8.8).
|
||||
|
||||
The signature algorithm is _not_ the same as the algorithm used when generating the key. There is no need to update
|
||||
keys.
|
||||
|
||||
The signature algorithm is negotiated with the SSH server when the connection is being set up. The client offers its
|
||||
list of accepted signature algorithms, and if the server has a match, the connection proceeds. For most SSH servers on
|
||||
up-to-date git providers, acceptable algorithms other than `ssh-rsa` should be available.
|
||||
|
||||
Before upgrading to Argo CD 2.4, check whether your git provider(s) using SSH authentication support algorithms newer
|
||||
than `rsa-ssh`.
|
||||
|
||||
1. Make sure your version of SSH >= 8.9 (the version used by Argo CD). If not, upgrade it before proceeding.
|
||||
|
||||
```shell
|
||||
ssh -V
|
||||
```
|
||||
|
||||
Example output: `OpenSSH_8.9p1 Ubuntu-3, OpenSSL 3.0.2 15 Mar 2022`
|
||||
|
||||
2. Once you have a recent version of OpenSSH, follow the directions from the [OpenSSH 8.8 release notes](https://www.openssh.com/txt/release-8.7):
|
||||
|
||||
> To check whether a server is using the weak ssh-rsa public key
|
||||
> algorithm, for host authentication, try to connect to it after
|
||||
> removing the ssh-rsa algorithm from ssh(1)'s allowed list:
|
||||
>
|
||||
> ```shell
|
||||
> ssh -oHostKeyAlgorithms=-ssh-rsa user@host
|
||||
> ```
|
||||
>
|
||||
> If the host key verification fails and no other supported host key
|
||||
> types are available, the server software on that host should be
|
||||
> upgraded.
|
||||
|
||||
If the server does not support an acceptable version, you will get an error similar to this;
|
||||
|
||||
```
|
||||
$ ssh -oHostKeyAlgorithms=-ssh-rsa vs-ssh.visualstudio.com
|
||||
Unable to negotiate with 20.42.134.1 port 22: no matching host key type found. Their offer: ssh-rsa
|
||||
```
|
||||
|
||||
This indicates that the server needs to update its supported key signature algorithms, and Argo CD will not connect
|
||||
to it.
|
||||
|
||||
### Workaround
|
||||
|
||||
The [OpenSSH 8.8 release notes](https://www.openssh.com/txt/release-8.8) describe a workaround if you cannot change the
|
||||
server's key signature algorithms configuration.
|
||||
|
||||
> Incompatibility is more likely when connecting to older SSH
|
||||
> implementations that have not been upgraded or have not closely tracked
|
||||
> improvements in the SSH protocol. For these cases, it may be necessary
|
||||
> to selectively re-enable RSA/SHA1 to allow connection and/or user
|
||||
> authentication via the HostkeyAlgorithms and PubkeyAcceptedAlgorithms
|
||||
> options. For example, the following stanza in ~/.ssh/config will enable
|
||||
> RSA/SHA1 for host and user authentication for a single destination host:
|
||||
>
|
||||
> ```
|
||||
> Host old-host
|
||||
> HostkeyAlgorithms +ssh-rsa
|
||||
> PubkeyAcceptedAlgorithms +ssh-rsa
|
||||
> ```
|
||||
>
|
||||
> We recommend enabling RSA/SHA1 only as a stopgap measure until legacy
|
||||
> implementations can be upgraded or reconfigured with another key type
|
||||
> (such as ECDSA or Ed25519).
|
||||
|
||||
To apply this to Argo CD, you could create a ConfigMap with the desired ssh config file and then mount it at
|
||||
`/home/argocd/.ssh/config`.
|
||||
|
||||
## Configure RBAC to account for new `exec` resource
|
||||
|
||||
2.4 introduces a new `exec` [RBAC resource](https://argo-cd.readthedocs.io/en/stable/operator-manual/rbac/#rbac-resources-and-actions).
|
||||
|
||||
When you upgrade to 2.4, RBAC policies with `*` in the resource field and `create` or `*` in the verb field will automatically grant the `exec` privilege.
|
||||
When you upgrade to 2.4, RBAC policies with `*` in the resource field and `create` or `*` in the action field will automatically grant the `exec` privilege.
|
||||
|
||||
To avoid granting the new privilege, replace the existing policy with a list of new policies explicitly listing the old resources.
|
||||
|
||||
@@ -42,12 +114,61 @@ p, role: org-admin, accounts, create, my-proj/*, allow
|
||||
p, role: org-admin, gpgkeys, create, my-proj/*, allow
|
||||
```
|
||||
|
||||
## Remove the shared volume from any sidecar plugins
|
||||
## Enable logs RBAC enforcement
|
||||
|
||||
2.4 introduced `logs` as a new RBAC resource. In 2.3, users with `applications, get` access automatically get logs
|
||||
access. In 2.5, you will have to explicitly grant `logs, get` access. Logs RBAC enforcement can be enabled with a flag
|
||||
in 2.4. We recommend enabling the flag now for an easier upgrade experience in 2.5.
|
||||
|
||||
To enabled logs RBAC enforcement, add this to your argocd-cm ConfigMap:
|
||||
|
||||
```yaml
|
||||
server.rbac.log.enforce.enable: "true"
|
||||
```
|
||||
|
||||
If you want to allow the same users to continue to have logs access, just find every line that grants
|
||||
`applications, get` access and also grant `logs, get`.
|
||||
|
||||
### Example
|
||||
|
||||
Old:
|
||||
|
||||
```csv
|
||||
p, role:staging-db-admins, applications, get, staging-db-admins/*, allow
|
||||
|
||||
p, role:test-db-admins, applications, *, staging-db-admins/*, allow
|
||||
```
|
||||
|
||||
New:
|
||||
|
||||
```csv
|
||||
p, role:staging-db-admins, applications, get, staging-db-admins/*, allow
|
||||
p, role:staging-db-admins, logs, get, staging-db-admins/*, allow
|
||||
|
||||
p, role:test-db-admins, applications, *, staging-db-admins/*, allow
|
||||
p, role:test-db-admins, logs, get, staging-db-admins/*, allow
|
||||
```
|
||||
|
||||
## Known UI issue
|
||||
|
||||
Currently, upon pressing the "LOGS" tab in pod view by users who don't have an explicit allow get logs policy, the red "unable to load data: Internal error" is received in the bottom of the screen, and "Failed to load data, please try again" is displayed.
|
||||
|
||||
## Test repo-server with its new dedicated Service Account
|
||||
|
||||
As a security enhancement, the argocd-repo-server Deployment uses its own Service Account instead of `default`.
|
||||
|
||||
If you have a custom environment that might depend on repo-server using the `default` Service Account (such as a plugin
|
||||
that uses the Service Account for auth), be sure to test before deploying the 2.4 upgrade to production.
|
||||
|
||||
## Plugins
|
||||
|
||||
### Remove the shared volume from any sidecar plugins
|
||||
|
||||
As a security enhancement, [sidecar plugins](../../user-guide/config-management-plugins.md#option-2-configure-plugin-via-sidecar)
|
||||
no longer share the /tmp directory with the repo-server.
|
||||
|
||||
If you have one or more sidecar plugins enabled, remove the /tmp volume mount from the plugin container definition.
|
||||
If you have one or more sidecar plugins enabled, replace the /tmp volume mount for each sidecar to use a volume specific
|
||||
to each plugin.
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
@@ -60,7 +181,47 @@ spec:
|
||||
containers:
|
||||
- name: your-plugin-name
|
||||
volumeMounts:
|
||||
# Remove the next two lines:
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
name: your-plugin-name-tmp
|
||||
volumes:
|
||||
# Add this volume.
|
||||
- name: your-plugin-name-tmp
|
||||
emptyDir: {}
|
||||
```
|
||||
|
||||
### Update plugins to use newly-prefixed environment variables
|
||||
|
||||
If you use plugins that depend on user-supplied environment variables, then they must be updated to be compatible with
|
||||
Argo CD 2.4. Here is an example of user-supplied environment variables in the `plugin` section of an Application spec:
|
||||
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
spec:
|
||||
source:
|
||||
plugin:
|
||||
env:
|
||||
- name: FOO
|
||||
value: bar
|
||||
```
|
||||
|
||||
Going forward, all user-supplied environment variables will be prefixed with `ARGOCD_ENV_` before being sent to the
|
||||
plugin's `init`, `generate`, or `discover` commands. This prevents users from setting potentially-sensitive environment
|
||||
variables.
|
||||
|
||||
If you have written a custom plugin which handles user-provided environment variables, update it to handle the new
|
||||
prefix.
|
||||
|
||||
If you use a third-party plugin which does not explicitly advertise Argo CD 2.4 support, it might not handle the
|
||||
prefixed environment variables. Open an issue with the plugin's authors and confirm support before upgrading to Argo CD
|
||||
2.4.
|
||||
|
||||
### Confirm sidecar plugins have all necessary environment variables
|
||||
|
||||
A bug in < 2.4 caused `init` and `generate` commands to receive environment variables from the main repo-server
|
||||
container, taking precedence over environment variables from the plugin's sidecar.
|
||||
|
||||
Starting in 2.4, sidecar plugins will not receive environment variables from the main repo-server container. Make sure
|
||||
that any environment variables necessary for the sidecar plugin to function are set on the sidecar plugin.
|
||||
|
||||
argocd-cm plugins will continue to receive environment variables from the main repo-server container.
|
||||
|
||||
@@ -50,7 +50,7 @@ If you've never configured this, you'll be redirected straight to this if you tr
|
||||
|
||||
### Configure Argo to use OpenID Connect
|
||||
|
||||
Edit `argo-cm` and add the following `dex.config` to the data section, replacing `clientID` and `clientSecret` with the values you saved before:
|
||||
Edit `argocd-cm` and add the following `dex.config` to the data section, replacing `clientID` and `clientSecret` with the values you saved before:
|
||||
|
||||
```yaml
|
||||
data:
|
||||
@@ -113,7 +113,7 @@ data:
|
||||
|
||||
### Configure Argo to use the new Google SAML App
|
||||
|
||||
Edit `argo-cm` and add the following `dex.config` to the data section, replacing the `caData`, `argocd.example.com`, `sso-url`, and optionally `google-entity-id` with your values from the Google SAML App:
|
||||
Edit `argocd-cm` and add the following `dex.config` to the data section, replacing the `caData`, `argocd.example.com`, `sso-url`, and optionally `google-entity-id` with your values from the Google SAML App:
|
||||
|
||||
```yaml
|
||||
data:
|
||||
@@ -211,7 +211,7 @@ Go through the same steps as in [OpenID Connect using Dex](#openid-connect-using
|
||||
defaultMode: 420
|
||||
secretName: argocd-google-groups-json
|
||||
|
||||
3. Edit `argo-cm` and add the following `dex.config` to the data section, replacing `clientID` and `clientSecret` with the values you saved before, `adminEmail` with the address for the admin user you're going to impersonate, and editing `redirectURI` with your Argo CD domain:
|
||||
3. Edit `argocd-cm` and add the following `dex.config` to the data section, replacing `clientID` and `clientSecret` with the values you saved before, `adminEmail` with the address for the admin user you're going to impersonate, and editing `redirectURI` with your Argo CD domain:
|
||||
|
||||
dex.config: |
|
||||
connectors:
|
||||
|
||||
@@ -197,6 +197,7 @@ NOTES:
|
||||
* There is no need to set `redirectURI` in the `connectors.config` as shown in the dex documentation.
|
||||
Argo CD will automatically use the correct `redirectURI` for any OAuth2 connectors, to match the
|
||||
correct external callback URL (e.g. `https://argocd.example.com/api/dex/callback`)
|
||||
* When using a custom secret (e.g., `some_K8S_secret` above,) it *must* have the label `app.kubernetes.io/part-of: argocd`.
|
||||
|
||||
## OIDC Configuration with DEX
|
||||
|
||||
@@ -495,3 +496,20 @@ data:
|
||||
clientSecret: $another-secret:oidc.auth0.clientSecret # Mind the ':'
|
||||
...
|
||||
```
|
||||
|
||||
### Skipping certificate verification on OIDC provider connections
|
||||
|
||||
By default, all connections made by the API server to OIDC providers (either external providers or the bundled Dex
|
||||
instance) must pass certificate validation. These connections occur when getting the OIDC provider's well-known
|
||||
configuration, when getting the OIDC provider's keys, and when exchanging an authorization code or verifying an ID
|
||||
token as part of an OIDC login flow.
|
||||
|
||||
Disabling certificate verification might make sense if:
|
||||
* You are using the bundled Dex instance **and** your Argo CD instance has TLS configured with a self-signed certificate
|
||||
**and** you understand and accept the risks of skipping OIDC provider cert verification.
|
||||
* You are using an external OIDC provider **and** that provider uses an invalid certificate **and** you cannot solve
|
||||
the problem by setting `oidcConfig.rootCA` **and** you understand and accept the risks of skipping OIDC provider cert
|
||||
verification.
|
||||
|
||||
If either of those two applies, then you can disable OIDC provider certificate verification by setting
|
||||
`oidc.tls.insecure.skip.verify` to `"true"` in the `argocd-cm` ConfigMap.
|
||||
|
||||
@@ -4,6 +4,10 @@ The [ApplicationSet controller](../operator-manual/applicationset/index.md) is a
|
||||
|
||||
The set of tools provided by the ApplicationSet controller may also be used to allow developers (without access to the Argo CD namespace) to independently create Applications without cluster-administrator intervention.
|
||||
|
||||
!!! warning
|
||||
Be aware of the [security implications](../operator-manual/applicationset/Security.md) before allowing developers to
|
||||
create Applications via ApplicationSets.
|
||||
|
||||
The ApplicationSet controller is installed alongside Argo CD (within the same namespace), and the controller automatically generates Argo CD Applications based on the contents of a new `ApplicationSet` Custom Resource (CR).
|
||||
|
||||
Here is an example of an `ApplicationSet` resource that can be used to target an Argo CD Application to multiple clusters:
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
Argo CD allows integrating more config management tools using config management plugins.
|
||||
|
||||
!!! warning
|
||||
Plugins are granted a level of trust in the Argo CD system, so it is important to implement plugins securely. Argo
|
||||
CD administrators should only install plugins from trusted sources, and they should audit plugins to weigh their
|
||||
particular risks and benefits.
|
||||
|
||||
## Installing a CMP
|
||||
|
||||
There are two ways to install a Config Management Plugin (CMP):
|
||||
@@ -62,8 +67,6 @@ spec:
|
||||
command: [sh, -c, 'echo "{\"kind\": \"ConfigMap\", \"apiVersion\": \"v1\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"Foo\": \"$FOO\", \"KubeVersion\": \"$KUBE_VERSION\", \"KubeApiVersion\": \"$KUBE_API_VERSIONS\",\"Bar\": \"baz\"}}}"']
|
||||
discover:
|
||||
fileName: "./subdir/s*.yaml"
|
||||
allowConcurrency: true
|
||||
lockRepo: false
|
||||
```
|
||||
|
||||
!!! note
|
||||
@@ -85,9 +88,6 @@ If `discover.fileName` is not provided, the `discover.find.command` is executed
|
||||
application repository is supported by the plugin or not. The `find` command should return a non-error exit code
|
||||
and produce output to stdout when the application source type is supported.
|
||||
|
||||
If your plugin makes use of `git` (e.g. `git crypt`), it is advised to set `lockRepo` to `true` so that your plugin will have exclusive access to the
|
||||
repository at the time it is executed. Otherwise, two applications synced at the same time may result in a race condition and sync failure.
|
||||
|
||||
#### 2. Place the plugin configuration file in the sidecar
|
||||
|
||||
Argo CD expects the plugin configuration file to be located at `/home/argocd/cmp-server/config/plugin.yaml` in the sidecar.
|
||||
@@ -114,8 +114,6 @@ data:
|
||||
command: [sh, -c, 'echo "{\"kind\": \"ConfigMap\", \"apiVersion\": \"v1\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"Foo\": \"$FOO\", \"KubeVersion\": \"$KUBE_VERSION\", \"KubeApiVersion\": \"$KUBE_API_VERSIONS\",\"Bar\": \"baz\"}}}"']
|
||||
discover:
|
||||
fileName: "./subdir/s*.yaml"
|
||||
allowConcurrency: true
|
||||
lockRepo: false
|
||||
```
|
||||
|
||||
#### 3. Register the plugin sidecar
|
||||
@@ -140,10 +138,16 @@ containers:
|
||||
- mountPath: /home/argocd/cmp-server/config/plugin.yaml
|
||||
subPath: plugin.yaml
|
||||
name: cmp-plugin
|
||||
volumes:
|
||||
- configMap:
|
||||
name: cmp-plugin
|
||||
# Starting with v2.4, do NOT mount the same tmp volume as the repo-server container. The filesystem separation helps
|
||||
# mitigate path traversal attacks.
|
||||
- mountPath: /tmp
|
||||
name: cmp-tmp
|
||||
volumes:
|
||||
- configMap:
|
||||
name: cmp-plugin
|
||||
name: cmp-plugin
|
||||
- emptyDir: {}
|
||||
name: cmp-tmp
|
||||
```
|
||||
|
||||
!!! important "Double-check these items"
|
||||
@@ -155,7 +159,7 @@ containers:
|
||||
|
||||
CMP commands have access to
|
||||
|
||||
1. The system environment variables
|
||||
1. The system environment variables (of the repo-server container for argocd-cm plugins or of the sidecar for sidecar plugins)
|
||||
2. [Standard build environment](build-environment.md)
|
||||
3. Variables in the application spec (References to system and build variables will get interpolated in the variables' values):
|
||||
|
||||
@@ -172,6 +176,19 @@ spec:
|
||||
value: test-$ARGOCD_APP_REVISION
|
||||
```
|
||||
|
||||
!!! note
|
||||
The `discover.command` command only has access to the above environment starting with v2.4.
|
||||
|
||||
> v2.4
|
||||
|
||||
Before reaching the `init.command`, `generate.command`, and `discover.command` commands, Argo CD prefixes all
|
||||
user-supplied environment variables (#3 above) with `ARGOCD_ENV_`. This prevents users from directly setting
|
||||
potentially-sensitive environment variables.
|
||||
|
||||
If your plugin was written before 2.4 and depends on user-supplied environment variables, then you will need to update
|
||||
your plugin's behavior to work with 2.4. If you use a third-party plugin, make sure they explicitly advertise support
|
||||
for 2.4.
|
||||
|
||||
## Using a CMP
|
||||
|
||||
If your CMP is defined in the `argocd-cm` ConfigMap, you can create a new Application using the CLI. Replace
|
||||
@@ -217,3 +234,17 @@ If you don't need to set any environment variables, you can set an empty plugin
|
||||
Each CMP command will also independently timeout on the `ARGOCD_EXEC_TIMEOUT` set for the CMP sidecar. The default
|
||||
is 90s. So if you increase the repo server timeout greater than 90s, be sure to set `ARGOCD_EXEC_TIMEOUT` on the
|
||||
sidecar.
|
||||
|
||||
## Tarball stream filtering
|
||||
|
||||
In order to increase the speed of manifest generation, certain files and folders can be excluded from being sent to your
|
||||
plugin. We recommend excluding your `.git` folder if it isn't necessary. Use Go's
|
||||
[filepatch.Match](https://pkg.go.dev/path/filepath#Match) syntax.
|
||||
|
||||
You can set it one of three ways:
|
||||
1. The `--plugin-tar-exclude` argument on the repo server.
|
||||
2. The `reposerver.plugin.tar.exclusions` key if you are using `argocd-cmd-params-cm`
|
||||
3. Directly setting 'ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS' environment variable on the repo server.
|
||||
|
||||
For option 1, the flag can be repeated multiple times. For option 2 and 3, you can specify multiple globs by separating
|
||||
them with semicolons.
|
||||
9
docs/user-guide/environment-variables.md
Normal file
9
docs/user-guide/environment-variables.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Environment Variables
|
||||
|
||||
The following environment variables can be used with `argocd` CLI:
|
||||
|
||||
| Environment Variable | Description |
|
||||
| --- | --- |
|
||||
| `ARGOCD_SERVER` | the address of the ArgoCD server without `https://` prefix <br> (instead of specifying `--server` for every command) <br> eg. `ARGOCD_SERVER=argocd.mycompany.com` if served through an ingress with DNS |
|
||||
| `ARGOCD_AUTH_TOKEN` | the ArgoCD `apiKey` for your ArgoCD user to be able to authenticate |
|
||||
| `ARGOCD_OPTS` | command-line options to pass to `argocd` CLI <br> eg. `ARGOCD_OPTS="--grpc-web"` |
|
||||
@@ -83,7 +83,13 @@ Private repositories that require an SSH private key have a URL that typically s
|
||||
|
||||
> v1.2 or later
|
||||
|
||||
You can configure your Git repository using HTTPS either using the CLI or the UI.
|
||||
You can configure your Git repository using SSH either using the CLI or the UI.
|
||||
|
||||
!!! note
|
||||
Argo CD 2.4 upgraded to OpenSSH 8.9. OpenSSH 8.8
|
||||
[dropped support for the `ssh-rsa` SHA-1 key signature algorithm](https://www.openssh.com/txt/release-8.8).
|
||||
See the [2.3 to 2.4 upgrade guide](../operator-manual/upgrading/2.3-2.4.md) for details about testing SSH servers
|
||||
for compatibility with Argo CD and for working around servers that do not support newer algorithms.
|
||||
|
||||
Using the CLI:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
ArgoCD allows users to customize some aspects of how it syncs the desired state in the target cluster. Some Sync Options can defined as annotations in a specific resource. Most of the Sync Options are configured in the Application resource `spec.syncPolicy.syncOptions` attribute.
|
||||
|
||||
Bellow you can find details about each available Sync Option:
|
||||
Below you can find details about each available Sync Option:
|
||||
|
||||
## No Prune Resources
|
||||
|
||||
|
||||
23
go.mod
23
go.mod
@@ -9,15 +9,15 @@ require (
|
||||
github.com/TomOnTime/utfutil v0.0.0-20180511104225-09c41003ee1d
|
||||
github.com/alicebob/miniredis v2.5.0+incompatible
|
||||
github.com/alicebob/miniredis/v2 v2.14.2
|
||||
github.com/argoproj/gitops-engine v0.6.1-0.20220328190556-73bcea9c8c8f
|
||||
github.com/argoproj/notifications-engine v0.3.1-0.20220322174744-ac18ca10234c
|
||||
github.com/argoproj/gitops-engine v0.7.0
|
||||
github.com/argoproj/notifications-engine v0.3.1-0.20220430155844-567361917320
|
||||
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0
|
||||
github.com/aws/aws-sdk-go v1.38.49
|
||||
github.com/bombsimon/logrusr/v2 v2.0.1
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.0.4
|
||||
github.com/casbin/casbin/v2 v2.39.1
|
||||
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible
|
||||
github.com/fsnotify/fsnotify v1.5.1
|
||||
@@ -60,7 +60,7 @@ require (
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180306154005-525d0eb5f91d // indirect
|
||||
github.com/pquerna/cachecontrol v0.1.0 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/r3labs/diff v1.1.0
|
||||
github.com/robfig/cron v1.2.0
|
||||
@@ -75,11 +75,11 @@ require (
|
||||
github.com/whilp/git-urls v0.0.0-20191001220047-6db9661140c0
|
||||
github.com/xanzy/go-gitlab v0.60.0
|
||||
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
|
||||
golang.org/x/net v0.0.0-20220621193019-9d032be2e588
|
||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa
|
||||
google.golang.org/grpc v1.45.0
|
||||
google.golang.org/protobuf v1.28.0
|
||||
@@ -202,7 +202,7 @@ require (
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
golang.org/x/exp v0.0.0-20210901193431-a062eea981d2 // indirect
|
||||
golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4 // indirect
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff // indirect
|
||||
@@ -214,10 +214,10 @@ require (
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.2.2 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
k8s.io/apiserver v0.23.1 // indirect
|
||||
k8s.io/apiserver v0.23.1
|
||||
k8s.io/cli-runtime v0.23.1 // indirect
|
||||
k8s.io/component-base v0.23.1 // indirect
|
||||
k8s.io/component-helpers v0.23.1 // indirect
|
||||
@@ -237,6 +237,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/PagerDuty/go-pagerduty v1.5.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
|
||||
|
||||
37
go.sum
37
go.sum
@@ -104,6 +104,8 @@ github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PagerDuty/go-pagerduty v1.5.0 h1:/p8FGD32G8HGm7MQIjlTPTGXRJ62Qkm8Lmt5BcUVJOo=
|
||||
github.com/PagerDuty/go-pagerduty v1.5.0/go.mod h1:txr8VbObXdk2RkqF+C2an4qWssdGY99fK26XYUDjh+4=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
@@ -144,10 +146,10 @@ github.com/antonmedv/expr v1.8.9/go.mod h1:5qsM3oLGDND7sDmQGDXHkYfkjYMUX14qsgqmH
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/appscode/go v0.0.0-20190808133642-1d4ef1f1c1e0/go.mod h1:iy07dV61Z7QQdCKJCIvUoDL21u6AIceRhZzyleh2ymc=
|
||||
github.com/argoproj/gitops-engine v0.6.1-0.20220328190556-73bcea9c8c8f h1:3x8pG690gbZtGK2G/dlL7b243t/WyyeDT7OUs2n76Nk=
|
||||
github.com/argoproj/gitops-engine v0.6.1-0.20220328190556-73bcea9c8c8f/go.mod h1:pRgVpLW7pZqf7n3COJ7UcDepk4cI61LAcJd64Q3Jq/c=
|
||||
github.com/argoproj/notifications-engine v0.3.1-0.20220322174744-ac18ca10234c h1:n/5BIocdWYtp1qC8/GFgUUV62I+gln54KFZZLgczwDc=
|
||||
github.com/argoproj/notifications-engine v0.3.1-0.20220322174744-ac18ca10234c/go.mod h1:QF4tr3wfWOnhkKSaRpx7k/KEErQAh8iwKQ2pYFu/SfA=
|
||||
github.com/argoproj/gitops-engine v0.7.0 h1:X6W8VP9bWTe74wWxAV3i8KZ0yBmre5DU8g+GWH09FCo=
|
||||
github.com/argoproj/gitops-engine v0.7.0/go.mod h1:pRgVpLW7pZqf7n3COJ7UcDepk4cI61LAcJd64Q3Jq/c=
|
||||
github.com/argoproj/notifications-engine v0.3.1-0.20220430155844-567361917320 h1:XDjtTfccs4rSOT1n+i1zV9RpxQdKky1b4YBic16E0qY=
|
||||
github.com/argoproj/notifications-engine v0.3.1-0.20220430155844-567361917320/go.mod h1:R3zlopt+/juYlebQc9Jarn9vBQ2xZruWOWjUNkfGY9M=
|
||||
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0 h1:Cfp7rO/HpVxnwlRqJe0jHiBbZ77ZgXhB6HWlYD02Xdc=
|
||||
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0/go.mod h1:ra+bQPmbVAoEL+gYSKesuigt4m49i3Qa3mE/xQcjCiA=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
@@ -252,8 +254,9 @@ github.com/coredns/corefile-migration v1.0.14/go.mod h1:XnhgULOEouimnzgn0t4WPuFD
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
@@ -942,8 +945,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180306154005-525d0eb5f91d h1:7gXyC293Lsm2YWgQ+0uaAFFFDO82ruiQSwc3ua+Vtlc=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180306154005-525d0eb5f91d/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc=
|
||||
github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
@@ -1228,8 +1231,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -1340,8 +1344,10 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY=
|
||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220621193019-9d032be2e588 h1:9ubFuySsnAJYGyJrZ3koiEv8FyqofCBdz3G9Mbf2YFc=
|
||||
golang.org/x/net v0.0.0-20220621193019-9d032be2e588/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1361,8 +1367,9 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb h1:8tDJ3aechhddbdPAxpycgXHJRMLpk/Ab+aa4OgdN5/g=
|
||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1482,11 +1489,14 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1786,8 +1796,9 @@ gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
|
||||
@@ -119,6 +119,12 @@ spec:
|
||||
name: argocd-cmd-params-cm
|
||||
key: controller.default.cache.expiration
|
||||
optional: true
|
||||
- name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: argocd-cmd-params-cm
|
||||
key: otlp.address
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
@@ -178,4 +184,4 @@ spec:
|
||||
- key: tls.key
|
||||
path: tls.key
|
||||
- key: ca.crt
|
||||
path: ca.crt
|
||||
path: ca.crt
|
||||
|
||||
@@ -5,7 +5,7 @@ kind: Kustomization
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: latest
|
||||
newTag: v2.4.5
|
||||
resources:
|
||||
- ./application-controller
|
||||
- ./dex
|
||||
|
||||
@@ -15,16 +15,13 @@ spec:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-repo-server
|
||||
spec:
|
||||
serviceAccountName: argocd-repo-server
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- name: argocd-repo-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
imagePullPolicy: Always
|
||||
command:
|
||||
- entrypoint.sh
|
||||
- argocd-repo-server
|
||||
- --redis
|
||||
- $(ARGOCD_REDIS_SERVICE):6379
|
||||
command: [ "sh", "-c", "entrypoint.sh argocd-repo-server --redis $(ARGOCD_REDIS_SERVICE):6379"]
|
||||
env:
|
||||
- name: ARGOCD_RECONCILIATION_TIMEOUT
|
||||
valueFrom:
|
||||
@@ -98,6 +95,24 @@ spec:
|
||||
name: argocd-cmd-params-cm
|
||||
key: reposerver.default.cache.expiration
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: argocd-cmd-params-cm
|
||||
key: otlp.address
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: argocd-cmd-params-cm
|
||||
key: reposerver.max.combined.directory.manifests.size
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: argocd-cmd-params-cm
|
||||
key: reposerver.plugin.tar.exclusions
|
||||
optional: true
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
|
||||
8
manifests/base/repo-server/argocd-repo-server-sa.yaml
Normal file
8
manifests/base/repo-server/argocd-repo-server-sa.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-repo-server
|
||||
app.kubernetes.io/part-of: argocd
|
||||
app.kubernetes.io/component: repo-server
|
||||
name: argocd-repo-server
|
||||
@@ -2,6 +2,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- argocd-repo-server-sa.yaml
|
||||
- argocd-repo-server-deployment.yaml
|
||||
- argocd-repo-server-service.yaml
|
||||
- argocd-repo-server-network-policy.yaml
|
||||
- argocd-repo-server-network-policy.yaml
|
||||
|
||||
@@ -178,6 +178,12 @@ spec:
|
||||
name: argocd-cmd-params-cm
|
||||
key: server.http.cookie.maxnumber
|
||||
optional: true
|
||||
- name: ARGOCD_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: argocd-cmd-params-cm
|
||||
key: otlp.address
|
||||
optional: true
|
||||
volumeMounts:
|
||||
- name: ssh-known-hosts
|
||||
mountPath: /app/config/ssh
|
||||
|
||||
@@ -9017,6 +9017,15 @@ metadata:
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-redis
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: repo-server
|
||||
app.kubernetes.io/name: argocd-repo-server
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-repo-server
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
@@ -9376,7 +9385,7 @@ spec:
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -9506,10 +9515,9 @@ spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- command:
|
||||
- entrypoint.sh
|
||||
- argocd-repo-server
|
||||
- --redis
|
||||
- argocd-redis:6379
|
||||
- sh
|
||||
- -c
|
||||
- entrypoint.sh argocd-repo-server --redis argocd-redis:6379
|
||||
env:
|
||||
- name: ARGOCD_RECONCILIATION_TIMEOUT
|
||||
valueFrom:
|
||||
@@ -9583,13 +9591,31 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.max.combined.directory.manifests.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.plugin.tar.exclusions
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -9638,7 +9664,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -9650,6 +9676,7 @@ spec:
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
name: var-files
|
||||
serviceAccountName: argocd-repo-server
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -9818,7 +9845,13 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -12,4 +12,4 @@ resources:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: latest
|
||||
newTag: v2.4.5
|
||||
|
||||
@@ -11,7 +11,7 @@ patchesStrategicMerge:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: latest
|
||||
newTag: v2.4.5
|
||||
resources:
|
||||
- ../../base/application-controller
|
||||
- ../../base/applicationset-controller
|
||||
|
||||
@@ -9042,6 +9042,15 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: repo-server
|
||||
app.kubernetes.io/name: argocd-repo-server
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-repo-server
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: server
|
||||
@@ -10311,7 +10320,7 @@ spec:
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -10408,7 +10417,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -10448,7 +10457,7 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- argocd-notifications
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -10681,13 +10690,31 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.max.combined.directory.manifests.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.plugin.tar.exclusions
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -10736,7 +10763,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -10748,6 +10775,7 @@ spec:
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
name: var-files
|
||||
serviceAccountName: argocd-repo-server
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -10976,7 +11004,13 @@ spec:
|
||||
key: server.http.cookie.maxnumber
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: ARGOCD_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -11178,7 +11212,13 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -51,6 +51,15 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: repo-server
|
||||
app.kubernetes.io/name: argocd-repo-server
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-repo-server
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: server
|
||||
@@ -1235,7 +1244,7 @@ spec:
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -1332,7 +1341,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -1372,7 +1381,7 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- argocd-notifications
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -1605,13 +1614,31 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.max.combined.directory.manifests.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.plugin.tar.exclusions
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1660,7 +1687,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -1672,6 +1699,7 @@ spec:
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
name: var-files
|
||||
serviceAccountName: argocd-repo-server
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -1900,7 +1928,13 @@ spec:
|
||||
key: server.http.cookie.maxnumber
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: ARGOCD_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -2102,7 +2136,13 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -9033,6 +9033,15 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: repo-server
|
||||
app.kubernetes.io/name: argocd-repo-server
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-repo-server
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: server
|
||||
@@ -9683,7 +9692,7 @@ spec:
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -9780,7 +9789,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -9820,7 +9829,7 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- argocd-notifications
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -9945,10 +9954,9 @@ spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- command:
|
||||
- entrypoint.sh
|
||||
- argocd-repo-server
|
||||
- --redis
|
||||
- argocd-redis:6379
|
||||
- sh
|
||||
- -c
|
||||
- entrypoint.sh argocd-repo-server --redis argocd-redis:6379
|
||||
env:
|
||||
- name: ARGOCD_RECONCILIATION_TIMEOUT
|
||||
valueFrom:
|
||||
@@ -10022,13 +10030,31 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.max.combined.directory.manifests.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.plugin.tar.exclusions
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -10077,7 +10103,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -10089,6 +10115,7 @@ spec:
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
name: var-files
|
||||
serviceAccountName: argocd-repo-server
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -10313,7 +10340,13 @@ spec:
|
||||
key: server.http.cookie.maxnumber
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: ARGOCD_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -10509,7 +10542,13 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -42,6 +42,15 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: repo-server
|
||||
app.kubernetes.io/name: argocd-repo-server
|
||||
app.kubernetes.io/part-of: argocd
|
||||
name: argocd-repo-server
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: server
|
||||
@@ -607,7 +616,7 @@ spec:
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -704,7 +713,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -744,7 +753,7 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- argocd-notifications
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -869,10 +878,9 @@ spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- command:
|
||||
- entrypoint.sh
|
||||
- argocd-repo-server
|
||||
- --redis
|
||||
- argocd-redis:6379
|
||||
- sh
|
||||
- -c
|
||||
- entrypoint.sh argocd-repo-server --redis argocd-redis:6379
|
||||
env:
|
||||
- name: ARGOCD_RECONCILIATION_TIMEOUT
|
||||
valueFrom:
|
||||
@@ -946,13 +954,31 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_MAX_COMBINED_DIRECTORY_MANIFESTS_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.max.combined.directory.manifests.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_PLUGIN_TAR_EXCLUSIONS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.plugin.tar.exclusions
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1001,7 +1027,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -1013,6 +1039,7 @@ spec:
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
name: var-files
|
||||
serviceAccountName: argocd-repo-server
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -1237,7 +1264,13 @@ spec:
|
||||
key: server.http.cookie.maxnumber
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: ARGOCD_SERVER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -1433,7 +1466,13 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: ARGOCD_APPLICATION_CONTROLLER_OTLP_ADDRESS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: otlp.address
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.4.5
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -64,6 +64,7 @@ nav:
|
||||
- operator-manual/notifications/services/mattermost.md
|
||||
- operator-manual/notifications/services/opsgenie.md
|
||||
- operator-manual/notifications/services/overview.md
|
||||
- operator-manual/notifications/services/pagerduty.md
|
||||
- operator-manual/notifications/services/pushover.md
|
||||
- operator-manual/notifications/services/rocketchat.md
|
||||
- operator-manual/notifications/services/slack.md
|
||||
@@ -75,6 +76,7 @@ nav:
|
||||
- Introduction: operator-manual/applicationset/index.md
|
||||
- Installations: operator-manual/applicationset/Getting-Started.md
|
||||
- Use Cases: operator-manual/applicationset/Use-Cases.md
|
||||
- Security: operator-manual/applicationset/Security.md
|
||||
- How ApplicationSet controller interacts with Argo CD: operator-manual/applicationset/Argo-CD-Integration.md
|
||||
- Generators:
|
||||
- operator-manual/applicationset/Generators.md
|
||||
@@ -127,6 +129,7 @@ nav:
|
||||
- user-guide/compare-options.md
|
||||
- user-guide/sync-options.md
|
||||
- user-guide/parameters.md
|
||||
- user-guide/environment-variables.md
|
||||
- user-guide/build-environment.md
|
||||
- user-guide/tracking_strategies.md
|
||||
- user-guide/resource_tracking.md
|
||||
|
||||
@@ -238,9 +238,9 @@ func (m *RevisionMetadataQuery) GetRevision() string {
|
||||
// ApplicationEventsQuery is a query for application resource events
|
||||
type ApplicationResourceEventsQuery struct {
|
||||
Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
|
||||
ResourceNamespace *string `protobuf:"bytes,2,req,name=resourceNamespace" json:"resourceNamespace,omitempty"`
|
||||
ResourceName *string `protobuf:"bytes,3,req,name=resourceName" json:"resourceName,omitempty"`
|
||||
ResourceUID *string `protobuf:"bytes,4,req,name=resourceUID" json:"resourceUID,omitempty"`
|
||||
ResourceNamespace *string `protobuf:"bytes,2,opt,name=resourceNamespace" json:"resourceNamespace,omitempty"`
|
||||
ResourceName *string `protobuf:"bytes,3,opt,name=resourceName" json:"resourceName,omitempty"`
|
||||
ResourceUID *string `protobuf:"bytes,4,opt,name=resourceUID" json:"resourceUID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@@ -951,7 +951,7 @@ func (m *ApplicationRollbackRequest) GetPrune() bool {
|
||||
|
||||
type ApplicationResourceRequest struct {
|
||||
Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,req,name=namespace" json:"namespace,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,opt,name=namespace" json:"namespace,omitempty"`
|
||||
ResourceName *string `protobuf:"bytes,3,req,name=resourceName" json:"resourceName,omitempty"`
|
||||
Version *string `protobuf:"bytes,4,req,name=version" json:"version,omitempty"`
|
||||
Group *string `protobuf:"bytes,5,opt,name=group" json:"group,omitempty"`
|
||||
@@ -1038,7 +1038,7 @@ func (m *ApplicationResourceRequest) GetKind() string {
|
||||
|
||||
type ApplicationResourcePatchRequest struct {
|
||||
Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,req,name=namespace" json:"namespace,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,opt,name=namespace" json:"namespace,omitempty"`
|
||||
ResourceName *string `protobuf:"bytes,3,req,name=resourceName" json:"resourceName,omitempty"`
|
||||
Version *string `protobuf:"bytes,4,req,name=version" json:"version,omitempty"`
|
||||
Group *string `protobuf:"bytes,5,opt,name=group" json:"group,omitempty"`
|
||||
@@ -1141,7 +1141,7 @@ func (m *ApplicationResourcePatchRequest) GetPatchType() string {
|
||||
|
||||
type ApplicationResourceDeleteRequest struct {
|
||||
Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,req,name=namespace" json:"namespace,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,opt,name=namespace" json:"namespace,omitempty"`
|
||||
ResourceName *string `protobuf:"bytes,3,req,name=resourceName" json:"resourceName,omitempty"`
|
||||
Version *string `protobuf:"bytes,4,req,name=version" json:"version,omitempty"`
|
||||
Group *string `protobuf:"bytes,5,opt,name=group" json:"group,omitempty"`
|
||||
@@ -1244,7 +1244,7 @@ func (m *ApplicationResourceDeleteRequest) GetOrphan() bool {
|
||||
|
||||
type ResourceActionRunRequest struct {
|
||||
Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,req,name=namespace" json:"namespace,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,opt,name=namespace" json:"namespace,omitempty"`
|
||||
ResourceName *string `protobuf:"bytes,3,req,name=resourceName" json:"resourceName,omitempty"`
|
||||
Version *string `protobuf:"bytes,4,req,name=version" json:"version,omitempty"`
|
||||
Group *string `protobuf:"bytes,5,opt,name=group" json:"group,omitempty"`
|
||||
@@ -1433,7 +1433,7 @@ func (m *ApplicationResourceResponse) GetManifest() string {
|
||||
|
||||
type ApplicationPodLogsQuery struct {
|
||||
Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,req,name=namespace" json:"namespace,omitempty"`
|
||||
Namespace *string `protobuf:"bytes,2,opt,name=namespace" json:"namespace,omitempty"`
|
||||
PodName *string `protobuf:"bytes,3,opt,name=podName" json:"podName,omitempty"`
|
||||
Container *string `protobuf:"bytes,4,opt,name=container" json:"container,omitempty"`
|
||||
SinceSeconds *int64 `protobuf:"varint,5,opt,name=sinceSeconds" json:"sinceSeconds,omitempty"`
|
||||
@@ -2100,147 +2100,147 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_df6e82b174b5eaec = []byte{
|
||||
// 2237 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x5a, 0xcd, 0x8f, 0x1c, 0x47,
|
||||
0x15, 0x57, 0xed, 0xe7, 0xcc, 0x1b, 0x7f, 0x56, 0x62, 0xd3, 0x69, 0xaf, 0x37, 0xab, 0xf2, 0xd7,
|
||||
0x7a, 0xed, 0x9d, 0xb1, 0x07, 0x0b, 0x39, 0x1b, 0x10, 0x38, 0x89, 0xd9, 0x38, 0xec, 0x6e, 0x4c,
|
||||
0xaf, 0x8d, 0x51, 0x38, 0x40, 0xa5, 0xbb, 0x66, 0xb6, 0xd9, 0x9e, 0xae, 0x76, 0x77, 0xcf, 0x58,
|
||||
0x23, 0xe3, 0x4b, 0x10, 0x37, 0x04, 0x12, 0xe4, 0x80, 0x10, 0x42, 0x88, 0x28, 0x12, 0x37, 0xe0,
|
||||
0x12, 0x21, 0x71, 0x81, 0x0b, 0x1f, 0x12, 0x07, 0x04, 0xff, 0x00, 0x58, 0x9c, 0xb8, 0x70, 0xe5,
|
||||
0x88, 0xaa, 0xba, 0xba, 0xbb, 0x7a, 0x76, 0xa6, 0x67, 0xcc, 0x4e, 0x14, 0xdf, 0xfa, 0xd5, 0x54,
|
||||
0xbd, 0xf7, 0xab, 0xf7, 0x59, 0xef, 0x69, 0xe0, 0x7c, 0xc4, 0xc2, 0x1e, 0x0b, 0x1b, 0x34, 0x08,
|
||||
0x3c, 0xd7, 0xa6, 0xb1, 0xcb, 0x7d, 0xfd, 0xbb, 0x1e, 0x84, 0x3c, 0xe6, 0xb8, 0xa6, 0x2d, 0x99,
|
||||
0x4b, 0x6d, 0xce, 0xdb, 0x1e, 0x6b, 0xd0, 0xc0, 0x6d, 0x50, 0xdf, 0xe7, 0xb1, 0x5c, 0x8e, 0x92,
|
||||
0xad, 0x26, 0xd9, 0xbf, 0x19, 0xd5, 0x5d, 0x2e, 0x7f, 0xb5, 0x79, 0xc8, 0x1a, 0xbd, 0xeb, 0x8d,
|
||||
0x36, 0xf3, 0x59, 0x48, 0x63, 0xe6, 0xa8, 0x3d, 0x37, 0xf2, 0x3d, 0x1d, 0x6a, 0xef, 0xb9, 0x3e,
|
||||
0x0b, 0xfb, 0x8d, 0x60, 0xbf, 0x2d, 0x16, 0xa2, 0x46, 0x87, 0xc5, 0x74, 0xd8, 0xa9, 0xad, 0xb6,
|
||||
0x1b, 0xef, 0x75, 0xdf, 0xad, 0xdb, 0xbc, 0xd3, 0xa0, 0x61, 0x9b, 0x07, 0x21, 0xff, 0xa6, 0xfc,
|
||||
0x58, 0xb7, 0x9d, 0x46, 0xaf, 0x99, 0x33, 0xd0, 0xef, 0xd2, 0xbb, 0x4e, 0xbd, 0x60, 0x8f, 0x1e,
|
||||
0xe4, 0x76, 0x7b, 0x0c, 0xb7, 0x90, 0x05, 0x5c, 0xe9, 0x46, 0x7e, 0xba, 0x31, 0x0f, 0xfb, 0xda,
|
||||
0x67, 0xc2, 0x86, 0x7c, 0x84, 0xe0, 0xc4, 0xad, 0x5c, 0xde, 0x97, 0xbb, 0x2c, 0xec, 0x63, 0x0c,
|
||||
0x73, 0x3e, 0xed, 0x30, 0x03, 0xad, 0xa0, 0xd5, 0xaa, 0x25, 0xbf, 0xb1, 0x01, 0x8b, 0x21, 0x6b,
|
||||
0x85, 0x2c, 0xda, 0x33, 0x66, 0xe4, 0x72, 0x4a, 0x62, 0x13, 0x2a, 0x42, 0x38, 0xb3, 0xe3, 0xc8,
|
||||
0x98, 0x5d, 0x99, 0x5d, 0xad, 0x5a, 0x19, 0x8d, 0x57, 0xe1, 0x78, 0xc8, 0x22, 0xde, 0x0d, 0x6d,
|
||||
0xf6, 0x15, 0x16, 0x46, 0x2e, 0xf7, 0x8d, 0x39, 0x79, 0x7a, 0x70, 0x59, 0x70, 0x89, 0x98, 0xc7,
|
||||
0xec, 0x98, 0x87, 0xc6, 0xbc, 0xdc, 0x92, 0xd1, 0x02, 0x8f, 0x00, 0x6e, 0x2c, 0x24, 0x78, 0xc4,
|
||||
0x37, 0x79, 0x19, 0xaa, 0x3b, 0xdc, 0x61, 0x23, 0x01, 0x93, 0x4d, 0x38, 0x65, 0xb1, 0x9e, 0x2b,
|
||||
0x98, 0x6f, 0xb3, 0x98, 0x3a, 0x34, 0xa6, 0x83, 0x9b, 0x67, 0xb2, 0xdb, 0x99, 0x50, 0x09, 0xd5,
|
||||
0x66, 0x63, 0x46, 0xae, 0x67, 0x34, 0xf9, 0x05, 0x82, 0x65, 0x4d, 0x45, 0x96, 0x02, 0x7e, 0xbb,
|
||||
0xc7, 0xfc, 0x38, 0x1a, 0xcd, 0xf2, 0x2a, 0x9c, 0x4c, 0xef, 0xb8, 0x43, 0x3b, 0x2c, 0x0a, 0xa8,
|
||||
0xcd, 0x14, 0xef, 0x83, 0x3f, 0x60, 0x02, 0x47, 0xf4, 0x45, 0x63, 0x56, 0x6e, 0x2c, 0xac, 0xe1,
|
||||
0x15, 0xa8, 0xa5, 0xf4, 0xfd, 0x3b, 0x6f, 0x18, 0x73, 0x72, 0x8b, 0xbe, 0x44, 0xde, 0x02, 0x43,
|
||||
0x43, 0xba, 0x4d, 0x7d, 0xb7, 0xc5, 0xa2, 0x78, 0xd2, 0x6b, 0xa3, 0xc2, 0xb5, 0x4f, 0xc1, 0x0b,
|
||||
0xc5, 0x5b, 0x07, 0xdc, 0x8f, 0x18, 0xf9, 0x2d, 0x2a, 0xc8, 0x78, 0x3d, 0x64, 0x34, 0x66, 0x16,
|
||||
0x7b, 0xd8, 0x65, 0x51, 0x8c, 0xf7, 0x41, 0x8f, 0x34, 0x29, 0xaa, 0xd6, 0xbc, 0x53, 0xcf, 0x5d,
|
||||
0xb5, 0x9e, 0xba, 0xaa, 0xfc, 0xf8, 0xba, 0xed, 0xd4, 0x7b, 0xcd, 0x7a, 0xb0, 0xdf, 0xae, 0x0b,
|
||||
0xc7, 0xaf, 0xeb, 0x81, 0x9b, 0x3a, 0x7e, 0x5d, 0x07, 0xa1, 0x73, 0xc7, 0xa7, 0x61, 0xa1, 0x1b,
|
||||
0x44, 0x2c, 0x8c, 0x25, 0xf4, 0x8a, 0xa5, 0x28, 0x71, 0xa9, 0x1e, 0xf5, 0x5c, 0x87, 0xc6, 0x42,
|
||||
0x8d, 0xe2, 0x97, 0x8c, 0x26, 0x1f, 0x14, 0xd1, 0xdf, 0x0f, 0x9c, 0x4f, 0x0a, 0xbd, 0x8e, 0x72,
|
||||
0x66, 0x00, 0x65, 0xaf, 0x00, 0xf2, 0x0d, 0xe6, 0xb1, 0x1c, 0xe4, 0x30, 0x33, 0x1a, 0xb0, 0x68,
|
||||
0xd3, 0xc8, 0xa6, 0x4e, 0xca, 0x2a, 0x25, 0x85, 0x13, 0x06, 0x21, 0x0f, 0x68, 0x5b, 0x72, 0xba,
|
||||
0xcb, 0x3d, 0xd7, 0xee, 0x4b, 0xa5, 0x54, 0xad, 0x83, 0x3f, 0x90, 0x73, 0x50, 0xdb, 0xed, 0xfb,
|
||||
0xf6, 0xdb, 0x81, 0x4c, 0x88, 0xf8, 0x45, 0x98, 0x77, 0x63, 0xd6, 0x89, 0x0c, 0x24, 0xa3, 0x3a,
|
||||
0x21, 0xc8, 0x7f, 0xe7, 0xe0, 0xb4, 0x86, 0x4e, 0x1c, 0x28, 0xc3, 0x56, 0xe2, 0x62, 0xc2, 0x82,
|
||||
0x4e, 0xd8, 0xb7, 0xba, 0xbe, 0xb2, 0x93, 0xa2, 0x84, 0xe0, 0x20, 0xec, 0xfa, 0x4c, 0xe6, 0x8a,
|
||||
0x8a, 0x95, 0x10, 0xb8, 0x05, 0x95, 0x28, 0x16, 0x29, 0xb0, 0xdd, 0x97, 0x19, 0xa2, 0xd6, 0x7c,
|
||||
0xeb, 0x70, 0xb6, 0x11, 0xd0, 0x77, 0x15, 0x47, 0x2b, 0xe3, 0x8d, 0x1f, 0x42, 0x35, 0x8d, 0xa9,
|
||||
0xc8, 0x58, 0x5c, 0x99, 0x5d, 0xad, 0x35, 0x77, 0x0f, 0x2f, 0xe8, 0xed, 0x40, 0xa4, 0x6f, 0x2d,
|
||||
0x7f, 0x58, 0xb9, 0x14, 0xbc, 0x04, 0xd5, 0x8e, 0x0a, 0xd6, 0xc8, 0xa8, 0x48, 0x6d, 0xe7, 0x0b,
|
||||
0xf8, 0xab, 0x30, 0xef, 0xfa, 0x2d, 0x1e, 0x19, 0x55, 0x09, 0xe6, 0xb5, 0xc3, 0x81, 0xb9, 0xe3,
|
||||
0xb7, 0xb8, 0x95, 0x30, 0xc4, 0x0f, 0xe1, 0x68, 0xc8, 0xe2, 0xb0, 0x9f, 0x6a, 0xc1, 0x00, 0xa9,
|
||||
0xd7, 0x2f, 0x1d, 0x4e, 0x82, 0xa5, 0xb3, 0xb4, 0x8a, 0x12, 0xf0, 0x06, 0xd4, 0xa2, 0xdc, 0xc7,
|
||||
0x8c, 0x9a, 0x14, 0x68, 0x14, 0x18, 0x69, 0x3e, 0x68, 0xe9, 0x9b, 0xc9, 0xaf, 0x11, 0x2c, 0x1d,
|
||||
0x88, 0xde, 0xdd, 0x80, 0x95, 0x3a, 0x20, 0x85, 0xb9, 0x28, 0x60, 0xb6, 0x4c, 0xbd, 0xb5, 0xe6,
|
||||
0xf6, 0xd4, 0xc2, 0x59, 0xca, 0x95, 0xac, 0x4b, 0x33, 0x0e, 0x85, 0x4f, 0x69, 0x87, 0xee, 0xd2,
|
||||
0xd8, 0xde, 0x2b, 0x43, 0x2b, 0x5c, 0x5f, 0xec, 0x51, 0x95, 0x22, 0x21, 0x84, 0x7f, 0xc8, 0x8f,
|
||||
0x7b, 0xfd, 0x20, 0x2d, 0x0d, 0xf9, 0x02, 0xf1, 0xc1, 0xd4, 0xd3, 0x0c, 0xf7, 0xbc, 0x77, 0xa9,
|
||||
0xbd, 0x5f, 0x26, 0xe5, 0x18, 0xcc, 0xb8, 0x8e, 0x14, 0x31, 0x6b, 0xcd, 0xb8, 0xce, 0xb3, 0x05,
|
||||
0xa2, 0x78, 0x33, 0x98, 0x43, 0x0a, 0x62, 0x99, 0xc0, 0x25, 0xa8, 0xfa, 0x03, 0x45, 0x30, 0x5f,
|
||||
0x98, 0xa8, 0xf8, 0x19, 0xb0, 0xd8, 0xcb, 0x5e, 0x10, 0xe2, 0xe7, 0x94, 0x14, 0x20, 0xdb, 0x21,
|
||||
0xef, 0x06, 0xea, 0xd9, 0x90, 0x10, 0x02, 0xc5, 0xbe, 0xeb, 0x3b, 0xc6, 0x42, 0x82, 0x42, 0x7c,
|
||||
0x93, 0xff, 0x20, 0x78, 0x79, 0x08, 0xf0, 0xb1, 0x46, 0x79, 0x2e, 0xd0, 0xe7, 0xae, 0xb1, 0x38,
|
||||
0xd2, 0x35, 0x2a, 0x83, 0xae, 0xf1, 0x6f, 0x04, 0x2b, 0x43, 0x6e, 0x3c, 0xbe, 0xa4, 0x3c, 0x37,
|
||||
0x57, 0x6e, 0xf1, 0xd0, 0x66, 0xc6, 0x62, 0xe2, 0x7f, 0x92, 0x10, 0xde, 0xca, 0xc3, 0x60, 0x8f,
|
||||
0xfa, 0x46, 0x25, 0xf1, 0xd6, 0x84, 0x22, 0x7f, 0x41, 0x60, 0xa4, 0x37, 0xbc, 0x65, 0xcb, 0xfb,
|
||||
0x76, 0xfd, 0xe7, 0xff, 0x92, 0xa7, 0x61, 0x81, 0x4a, 0xb4, 0xca, 0xb0, 0x8a, 0x22, 0xdf, 0x41,
|
||||
0x70, 0xa6, 0x78, 0x9d, 0x68, 0xcb, 0x8d, 0xe2, 0xf4, 0x25, 0x86, 0x5b, 0xb0, 0x98, 0xec, 0x4c,
|
||||
0x0a, 0x74, 0xad, 0xb9, 0x75, 0xd8, 0xb4, 0x5d, 0x50, 0x5d, 0xca, 0x9c, 0xbc, 0x02, 0x67, 0x86,
|
||||
0x46, 0xbb, 0x82, 0x61, 0x42, 0x25, 0x2d, 0x55, 0x4a, 0xb9, 0x19, 0x4d, 0xfe, 0x38, 0x5b, 0xcc,
|
||||
0x7e, 0xdc, 0xd9, 0xe2, 0xed, 0x92, 0x37, 0x73, 0xb9, 0x41, 0x0c, 0x58, 0x0c, 0xb8, 0xa3, 0x6c,
|
||||
0x21, 0x5b, 0x10, 0x45, 0x8a, 0x73, 0x36, 0xf7, 0x63, 0x2a, 0x3a, 0x31, 0xd5, 0x60, 0xe4, 0x0b,
|
||||
0xc2, 0x90, 0x91, 0xeb, 0xdb, 0x6c, 0x97, 0xd9, 0xdc, 0x77, 0x22, 0x69, 0x91, 0x59, 0xab, 0xb0,
|
||||
0x86, 0xdf, 0x84, 0xaa, 0xa4, 0xef, 0xb9, 0x1d, 0x26, 0xfb, 0x8c, 0x5a, 0x73, 0xad, 0x9e, 0xb4,
|
||||
0x79, 0x75, 0xbd, 0xcd, 0xcb, 0x75, 0x28, 0xda, 0xbc, 0x7a, 0xef, 0x7a, 0x5d, 0x9c, 0xb0, 0xf2,
|
||||
0xc3, 0x02, 0x4b, 0x4c, 0x5d, 0x6f, 0xcb, 0xf5, 0xe5, 0xf3, 0x41, 0x88, 0xca, 0x17, 0x84, 0xb1,
|
||||
0x5b, 0xdc, 0xf3, 0xf8, 0xa3, 0xd4, 0x77, 0x13, 0x4a, 0x9c, 0xea, 0xfa, 0xb1, 0xeb, 0x49, 0xf9,
|
||||
0xd5, 0xe4, 0x06, 0xd9, 0x82, 0x3c, 0xe5, 0x7a, 0x31, 0x0b, 0x65, 0x81, 0xae, 0x5a, 0x8a, 0xca,
|
||||
0xdc, 0xa9, 0x96, 0xf4, 0x3d, 0x69, 0xcc, 0x24, 0x8e, 0x77, 0x44, 0x77, 0xbc, 0x41, 0x67, 0x3e,
|
||||
0x2a, 0x7f, 0x2c, 0x3a, 0xb3, 0x6c, 0xe4, 0x58, 0xcf, 0xe5, 0xdd, 0xc8, 0x38, 0x96, 0x94, 0xb1,
|
||||
0x94, 0x26, 0xbf, 0x43, 0x50, 0xd9, 0xe2, 0xed, 0xdb, 0x7e, 0x1c, 0xf6, 0xe5, 0x7b, 0x93, 0xfb,
|
||||
0x31, 0xf3, 0x53, 0x8b, 0xa7, 0xa4, 0x50, 0x63, 0xec, 0x76, 0xd8, 0x6e, 0x4c, 0x3b, 0x81, 0xaa,
|
||||
0xb8, 0xcf, 0xa4, 0xc6, 0xec, 0xb0, 0xb8, 0x9a, 0x47, 0xa3, 0x58, 0x46, 0x5d, 0xc5, 0x92, 0xdf,
|
||||
0xe2, 0x12, 0xd9, 0x86, 0xdd, 0x38, 0x54, 0x21, 0x57, 0x58, 0xd3, 0x9d, 0x64, 0x3e, 0xc1, 0xa6,
|
||||
0x48, 0xd2, 0x80, 0x97, 0xb2, 0x47, 0xd8, 0x3d, 0x16, 0x76, 0x5c, 0x9f, 0x96, 0xe6, 0x40, 0x72,
|
||||
0xbd, 0xe0, 0xf8, 0xe2, 0x55, 0xf2, 0xc0, 0xf5, 0x1d, 0xfe, 0x68, 0xb4, 0x03, 0x93, 0xbf, 0x15,
|
||||
0x7b, 0x45, 0xed, 0x4c, 0x16, 0x2f, 0x6f, 0xc2, 0x51, 0x11, 0x59, 0x3d, 0xa6, 0x7e, 0x50, 0xc1,
|
||||
0x4b, 0x0a, 0x41, 0x39, 0x94, 0x87, 0x55, 0x3c, 0x88, 0xb7, 0xe0, 0x38, 0x8d, 0x22, 0xb7, 0xed,
|
||||
0x33, 0x27, 0xe5, 0x35, 0x33, 0x31, 0xaf, 0xc1, 0xa3, 0x49, 0x13, 0x21, 0x77, 0x28, 0x9d, 0xa7,
|
||||
0x24, 0xf9, 0x36, 0x82, 0x53, 0x43, 0x99, 0x64, 0xfe, 0x87, 0xb4, 0x74, 0x26, 0x1a, 0x79, 0x7b,
|
||||
0x8f, 0x39, 0x5d, 0x2f, 0x0d, 0xe1, 0x8c, 0x16, 0xbf, 0x39, 0xdd, 0xc4, 0x02, 0x2a, 0x9d, 0x66,
|
||||
0x34, 0x5e, 0x06, 0xe8, 0x50, 0xbf, 0x4b, 0x3d, 0x09, 0x61, 0x4e, 0x42, 0xd0, 0x56, 0xc8, 0x12,
|
||||
0x98, 0xc3, 0xcc, 0xa7, 0xda, 0xd2, 0x5f, 0x21, 0x38, 0x96, 0xa6, 0x26, 0x65, 0x9f, 0x55, 0x38,
|
||||
0xae, 0xa9, 0x61, 0x27, 0x37, 0xd5, 0xe0, 0xf2, 0x60, 0xda, 0x41, 0xc5, 0xb4, 0x93, 0xda, 0x79,
|
||||
0xb6, 0x38, 0x0d, 0xe9, 0x15, 0xe6, 0x19, 0x13, 0xe7, 0xfd, 0x2c, 0x50, 0xc9, 0xb7, 0xc0, 0xd8,
|
||||
0xa6, 0x3e, 0x6d, 0x33, 0x27, 0x03, 0x9e, 0x39, 0xc9, 0x37, 0xf4, 0xd6, 0xeb, 0xd0, 0x8d, 0x4e,
|
||||
0x56, 0xf6, 0xdd, 0x56, 0x4b, 0xb5, 0x71, 0xcd, 0x7f, 0x2e, 0x03, 0xd6, 0x8d, 0xca, 0xc2, 0x9e,
|
||||
0x6b, 0x33, 0xfc, 0x03, 0x04, 0x73, 0xa2, 0xca, 0xe0, 0xb3, 0xa3, 0x7c, 0x48, 0x2a, 0xd7, 0x9c,
|
||||
0xde, 0x3b, 0x5a, 0x48, 0x23, 0x4b, 0xef, 0xfd, 0xfd, 0x5f, 0x3f, 0x9c, 0x39, 0x8d, 0x5f, 0x94,
|
||||
0x73, 0xb7, 0xde, 0x75, 0x7d, 0x06, 0x16, 0xe1, 0xef, 0x22, 0xc0, 0xaa, 0xf4, 0x69, 0xa3, 0x17,
|
||||
0x7c, 0x65, 0x14, 0xc4, 0x21, 0x23, 0x1a, 0xf3, 0xac, 0x96, 0x86, 0xea, 0x36, 0x0f, 0x99, 0x48,
|
||||
0x3a, 0x72, 0x83, 0x04, 0xb0, 0x26, 0x01, 0x9c, 0xc7, 0x64, 0x18, 0x80, 0xc6, 0x63, 0x61, 0xf4,
|
||||
0x27, 0x0d, 0x96, 0xc8, 0xfd, 0x39, 0x82, 0xf9, 0x07, 0xf2, 0xf1, 0x35, 0x46, 0x49, 0xbb, 0x53,
|
||||
0x53, 0x92, 0x14, 0x27, 0xd1, 0x92, 0x73, 0x12, 0xe9, 0x59, 0x7c, 0x26, 0x45, 0x1a, 0xc5, 0x21,
|
||||
0xa3, 0x9d, 0x02, 0xe0, 0x6b, 0x08, 0x7f, 0x88, 0x60, 0x21, 0x19, 0xce, 0xe0, 0x0b, 0xa3, 0x50,
|
||||
0x16, 0x86, 0x37, 0xe6, 0xf4, 0x26, 0x1d, 0xe4, 0xb2, 0xc4, 0x78, 0x8e, 0x0c, 0x35, 0xe7, 0x46,
|
||||
0x61, 0x0e, 0xf2, 0x3e, 0x82, 0xd9, 0x4d, 0x36, 0xd6, 0xdf, 0xa6, 0x08, 0xee, 0x80, 0x02, 0x87,
|
||||
0x98, 0x1a, 0x7f, 0x80, 0xe0, 0xa5, 0x4d, 0x16, 0x0f, 0xcf, 0xe5, 0x78, 0x75, 0x7c, 0x82, 0x55,
|
||||
0x6e, 0x77, 0x65, 0x82, 0x9d, 0x59, 0x12, 0x6b, 0x48, 0x64, 0x97, 0xf1, 0xa5, 0x32, 0x27, 0x14,
|
||||
0x0d, 0xf1, 0x23, 0x85, 0xe3, 0xcf, 0x08, 0x4e, 0x0c, 0x0e, 0x39, 0x71, 0x31, 0xfb, 0x0f, 0x9d,
|
||||
0x81, 0x9a, 0x3b, 0x87, 0x4d, 0x28, 0x45, 0xa6, 0xe4, 0x96, 0x44, 0xfe, 0x2a, 0x7e, 0xa5, 0x0c,
|
||||
0x79, 0x3a, 0xf7, 0x89, 0x1a, 0x8f, 0xd3, 0xcf, 0x27, 0x72, 0x5a, 0x2e, 0x61, 0xbf, 0x87, 0xe0,
|
||||
0xc8, 0x26, 0x8b, 0xb7, 0xb3, 0xb1, 0xc7, 0x48, 0xb7, 0x2d, 0xcc, 0x35, 0xcd, 0xa5, 0xba, 0x36,
|
||||
0xd4, 0x4e, 0x7f, 0xca, 0x54, 0xba, 0x2e, 0x81, 0x5d, 0xc2, 0x17, 0xca, 0x80, 0xe5, 0xa3, 0x96,
|
||||
0xdf, 0x23, 0x58, 0x48, 0xc6, 0x0a, 0xa3, 0xc5, 0x17, 0x86, 0x86, 0xd3, 0x74, 0xcc, 0xdb, 0x12,
|
||||
0xeb, 0xe7, 0xcd, 0x6b, 0xc3, 0xb1, 0xea, 0xe7, 0x53, 0xad, 0xd5, 0xe5, 0x05, 0x8a, 0x11, 0xf5,
|
||||
0x11, 0x02, 0xc8, 0x47, 0x23, 0xf8, 0x72, 0xf9, 0x3d, 0xb4, 0xf1, 0x89, 0x39, 0xdd, 0xe1, 0x08,
|
||||
0xa9, 0xcb, 0xfb, 0xac, 0x9a, 0x2b, 0xa5, 0xee, 0x1c, 0x30, 0x7b, 0x23, 0x19, 0xa3, 0xfc, 0x0c,
|
||||
0xc1, 0xbc, 0xec, 0xc5, 0xf1, 0xf9, 0x51, 0x98, 0xf5, 0x56, 0x7d, 0x9a, 0xaa, 0xbf, 0x28, 0xa1,
|
||||
0xae, 0x34, 0xcb, 0x72, 0xc2, 0x06, 0x5a, 0xc3, 0x3d, 0x58, 0x48, 0x7a, 0xe7, 0xd1, 0xee, 0x51,
|
||||
0xe8, 0xad, 0xcd, 0x95, 0x92, 0x1a, 0x95, 0x78, 0xa8, 0x4a, 0x47, 0x6b, 0xe3, 0xd2, 0xd1, 0x9c,
|
||||
0xc8, 0x18, 0xf8, 0x5c, 0x59, 0x3e, 0xf9, 0x18, 0x14, 0x73, 0x45, 0xa2, 0xbb, 0x40, 0x56, 0xc6,
|
||||
0xa5, 0x24, 0xa1, 0x9d, 0x1f, 0x21, 0x38, 0x31, 0xf8, 0xa4, 0xc1, 0x67, 0x06, 0xd2, 0x91, 0xfe,
|
||||
0x46, 0x33, 0x8b, 0x5a, 0x1c, 0xf5, 0x1c, 0x22, 0x5f, 0x90, 0x28, 0x36, 0xf0, 0xcd, 0xb1, 0x91,
|
||||
0xb1, 0x93, 0x06, 0xb4, 0x60, 0xb4, 0x9e, 0x4f, 0x58, 0x7f, 0x83, 0xe0, 0x48, 0xca, 0xf7, 0x5e,
|
||||
0xc8, 0x58, 0x39, 0xac, 0xe9, 0x05, 0x82, 0x90, 0x45, 0x3e, 0x2b, 0xe1, 0x7f, 0x06, 0xdf, 0x98,
|
||||
0x10, 0x7e, 0x0a, 0x7b, 0x3d, 0x16, 0x48, 0xff, 0x80, 0xe0, 0xe4, 0x83, 0xc4, 0xef, 0x3f, 0x21,
|
||||
0xfc, 0xaf, 0x4b, 0xfc, 0x9f, 0xc3, 0xaf, 0x96, 0x3c, 0x39, 0xc6, 0x5d, 0xe3, 0x1a, 0xc2, 0xbf,
|
||||
0x44, 0x50, 0x49, 0xa7, 0x93, 0xf8, 0xd2, 0xc8, 0xc0, 0x28, 0xce, 0x2f, 0xa7, 0xe9, 0xcc, 0xaa,
|
||||
0xbe, 0x92, 0xf3, 0xa5, 0x55, 0x4a, 0xc9, 0x17, 0x0e, 0xfd, 0x3e, 0x02, 0x9c, 0xf5, 0x1a, 0x59,
|
||||
0xf7, 0x81, 0x2f, 0x16, 0x44, 0x8d, 0x6c, 0x2a, 0xcd, 0x4b, 0x63, 0xf7, 0x15, 0xab, 0xd4, 0x5a,
|
||||
0x69, 0x95, 0xe2, 0x99, 0xfc, 0xef, 0x21, 0xa8, 0x6d, 0xb2, 0xec, 0x39, 0x5c, 0xa2, 0xcb, 0xe2,
|
||||
0x68, 0xd6, 0x5c, 0x1d, 0xbf, 0x51, 0x21, 0xba, 0x2a, 0x11, 0x5d, 0xc4, 0xe5, 0xaa, 0x4a, 0x01,
|
||||
0xfc, 0x04, 0xc1, 0xd1, 0xbb, 0xba, 0x8b, 0xe2, 0xab, 0xe3, 0x24, 0x15, 0x32, 0xf9, 0xe4, 0xb8,
|
||||
0x3e, 0x2d, 0x71, 0xad, 0x93, 0x89, 0x70, 0x6d, 0xa8, 0x19, 0xe9, 0x4f, 0x11, 0xbc, 0xa0, 0xf7,
|
||||
0x0f, 0x6a, 0x9a, 0xf6, 0xff, 0xea, 0xad, 0x64, 0x28, 0x47, 0x6e, 0x48, 0x7c, 0x75, 0x7c, 0x75,
|
||||
0x12, 0x7c, 0x0d, 0x35, 0x62, 0xc3, 0x3f, 0x46, 0x70, 0x52, 0xce, 0x2a, 0x75, 0xc6, 0x03, 0x25,
|
||||
0x66, 0xd4, 0x64, 0x73, 0x82, 0x12, 0xa3, 0xf2, 0x0f, 0x79, 0x26, 0x50, 0x1b, 0x6a, 0x0e, 0x89,
|
||||
0xbf, 0x8f, 0xe0, 0x58, 0x5a, 0xd4, 0x94, 0x75, 0xd7, 0xc7, 0x29, 0xee, 0x59, 0x8b, 0xa0, 0x72,
|
||||
0xb7, 0xb5, 0xc9, 0xdc, 0xed, 0x43, 0x04, 0x8b, 0x6a, 0x96, 0x58, 0xf2, 0x54, 0xd0, 0x86, 0x8d,
|
||||
0xe6, 0xa9, 0xc2, 0xae, 0x74, 0x90, 0x45, 0xbe, 0x26, 0xc5, 0xde, 0xc7, 0x8d, 0x32, 0xb1, 0x01,
|
||||
0x77, 0xa2, 0xc6, 0x63, 0x35, 0x45, 0x7a, 0xd2, 0xf0, 0x78, 0x3b, 0x7a, 0x87, 0xe0, 0xd2, 0x82,
|
||||
0x28, 0xf6, 0x5c, 0x43, 0xaf, 0x7d, 0xf1, 0x4f, 0x4f, 0x97, 0xd1, 0x5f, 0x9f, 0x2e, 0xa3, 0x7f,
|
||||
0x3c, 0x5d, 0x46, 0xef, 0xdc, 0x9c, 0xec, 0xff, 0x1f, 0xb6, 0xe7, 0x32, 0x3f, 0xd6, 0xd9, 0xfe,
|
||||
0x2f, 0x00, 0x00, 0xff, 0xff, 0xef, 0x54, 0xd5, 0x40, 0xe5, 0x22, 0x00, 0x00,
|
||||
// 2236 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x5a, 0xcd, 0x8f, 0x1b, 0x49,
|
||||
0x15, 0x57, 0xcd, 0xa7, 0xfd, 0x9c, 0xcf, 0xda, 0x4d, 0xe8, 0xed, 0x4c, 0x66, 0x47, 0x95, 0xaf,
|
||||
0xc9, 0x24, 0x63, 0x27, 0x26, 0x42, 0xd9, 0x59, 0x10, 0x64, 0x77, 0xc3, 0x6c, 0x96, 0x99, 0xd9,
|
||||
0xd0, 0x93, 0x10, 0xb4, 0x1c, 0xa0, 0xb6, 0xbb, 0xec, 0x69, 0xc6, 0xee, 0xea, 0x74, 0xb7, 0x1d,
|
||||
0x59, 0x21, 0x97, 0x45, 0xdc, 0x10, 0x48, 0xb0, 0x07, 0x84, 0x10, 0x42, 0xac, 0x56, 0xe2, 0x06,
|
||||
0x5c, 0x56, 0x48, 0x5c, 0xe0, 0xc2, 0x87, 0xc4, 0x01, 0xc1, 0x3f, 0x00, 0x11, 0x27, 0x2e, 0x5c,
|
||||
0x39, 0xa2, 0xaa, 0xae, 0x6a, 0x57, 0x7b, 0xec, 0xb6, 0xc3, 0x78, 0xb5, 0xb9, 0xf5, 0x2b, 0x57,
|
||||
0xbd, 0xf7, 0xab, 0x57, 0xbf, 0x7a, 0xaf, 0xde, 0x93, 0xe1, 0x7c, 0xcc, 0xa2, 0x2e, 0x8b, 0x6a,
|
||||
0x34, 0x0c, 0x5b, 0xbe, 0x4b, 0x13, 0x9f, 0x07, 0xe6, 0x77, 0x35, 0x8c, 0x78, 0xc2, 0x71, 0xc5,
|
||||
0x18, 0xb2, 0x97, 0x9a, 0x9c, 0x37, 0x5b, 0xac, 0x46, 0x43, 0xbf, 0x46, 0x83, 0x80, 0x27, 0x72,
|
||||
0x38, 0x4e, 0xa7, 0xda, 0x64, 0xff, 0x66, 0x5c, 0xf5, 0xb9, 0xfc, 0xd5, 0xe5, 0x11, 0xab, 0x75,
|
||||
0xaf, 0xd7, 0x9a, 0x2c, 0x60, 0x11, 0x4d, 0x98, 0xa7, 0xe6, 0xdc, 0xe8, 0xcf, 0x69, 0x53, 0x77,
|
||||
0xcf, 0x0f, 0x58, 0xd4, 0xab, 0x85, 0xfb, 0x4d, 0x31, 0x10, 0xd7, 0xda, 0x2c, 0xa1, 0xc3, 0x56,
|
||||
0x6d, 0x35, 0xfd, 0x64, 0xaf, 0xf3, 0x6e, 0xd5, 0xe5, 0xed, 0x1a, 0x8d, 0x9a, 0x3c, 0x8c, 0xf8,
|
||||
0x37, 0xe5, 0xc7, 0xba, 0xeb, 0xd5, 0xba, 0xf5, 0xbe, 0x02, 0x73, 0x2f, 0xdd, 0xeb, 0xb4, 0x15,
|
||||
0xee, 0xd1, 0x83, 0xda, 0x6e, 0x8f, 0xd1, 0x16, 0xb1, 0x90, 0x2b, 0xdf, 0xc8, 0x4f, 0x3f, 0xe1,
|
||||
0x51, 0xcf, 0xf8, 0x4c, 0xd5, 0x90, 0x8f, 0x10, 0x9c, 0xb8, 0xd5, 0xb7, 0xf7, 0xe5, 0x0e, 0x8b,
|
||||
0x7a, 0x18, 0xc3, 0x5c, 0x40, 0xdb, 0xcc, 0x42, 0x2b, 0x68, 0xb5, 0xec, 0xc8, 0x6f, 0x6c, 0xc1,
|
||||
0x62, 0xc4, 0x1a, 0x11, 0x8b, 0xf7, 0xac, 0x19, 0x39, 0xac, 0x45, 0x6c, 0x43, 0x49, 0x18, 0x67,
|
||||
0x6e, 0x12, 0x5b, 0xb3, 0x2b, 0xb3, 0xab, 0x65, 0x27, 0x93, 0xf1, 0x2a, 0x1c, 0x8f, 0x58, 0xcc,
|
||||
0x3b, 0x91, 0xcb, 0xbe, 0xc2, 0xa2, 0xd8, 0xe7, 0x81, 0x35, 0x27, 0x57, 0x0f, 0x0e, 0x0b, 0x2d,
|
||||
0x31, 0x6b, 0x31, 0x37, 0xe1, 0x91, 0x35, 0x2f, 0xa7, 0x64, 0xb2, 0xc0, 0x23, 0x80, 0x5b, 0x0b,
|
||||
0x29, 0x1e, 0xf1, 0x4d, 0x5e, 0x86, 0xf2, 0x0e, 0xf7, 0xd8, 0x48, 0xc0, 0x64, 0x13, 0x4e, 0x39,
|
||||
0xac, 0xeb, 0x0b, 0xe5, 0xdb, 0x2c, 0xa1, 0x1e, 0x4d, 0xe8, 0xe0, 0xe4, 0x99, 0x6c, 0x77, 0x36,
|
||||
0x94, 0x22, 0x35, 0xd9, 0x9a, 0x91, 0xe3, 0x99, 0x4c, 0x7e, 0x81, 0x60, 0xd9, 0x70, 0x91, 0xa3,
|
||||
0x80, 0xdf, 0xee, 0xb2, 0x20, 0x89, 0x47, 0xab, 0xbc, 0x0a, 0x27, 0xf5, 0x1e, 0x77, 0x68, 0x9b,
|
||||
0xc5, 0x21, 0x75, 0x99, 0x72, 0xdd, 0xc1, 0x1f, 0x30, 0x81, 0x23, 0xe6, 0xa0, 0x35, 0x2b, 0x27,
|
||||
0xe6, 0xc6, 0xf0, 0x0a, 0x54, 0xb4, 0x7c, 0xff, 0xce, 0x1b, 0xca, 0x91, 0xe6, 0x10, 0x79, 0x0b,
|
||||
0x2c, 0x03, 0xe9, 0x36, 0x0d, 0xfc, 0x06, 0x8b, 0x93, 0x49, 0xb7, 0x8d, 0x72, 0xdb, 0x3e, 0x05,
|
||||
0x2f, 0xe4, 0x77, 0x1d, 0xf2, 0x20, 0x66, 0xe4, 0xb7, 0x28, 0x67, 0xe3, 0xf5, 0x88, 0xd1, 0x84,
|
||||
0x39, 0xec, 0x61, 0x87, 0xc5, 0x09, 0xde, 0x07, 0xf3, 0xa6, 0x49, 0x53, 0x95, 0xfa, 0x9d, 0x6a,
|
||||
0x9f, 0xaa, 0x55, 0x4d, 0x55, 0xf9, 0xf1, 0x75, 0xd7, 0xab, 0x76, 0xeb, 0xd5, 0x70, 0xbf, 0x59,
|
||||
0x15, 0xc4, 0xaf, 0x9a, 0x17, 0x57, 0x13, 0xbf, 0x6a, 0x82, 0x30, 0xb5, 0xe3, 0xd3, 0xb0, 0xd0,
|
||||
0x09, 0x63, 0x16, 0x25, 0x12, 0x7a, 0xc9, 0x51, 0x92, 0xd8, 0x54, 0x97, 0xb6, 0x7c, 0x8f, 0x26,
|
||||
0xa9, 0x1b, 0x4b, 0x4e, 0x26, 0x93, 0x0f, 0xf2, 0xe8, 0xef, 0x87, 0xde, 0x27, 0x85, 0xde, 0x44,
|
||||
0x39, 0x33, 0x80, 0xb2, 0x9b, 0x03, 0xf9, 0x06, 0x6b, 0xb1, 0x3e, 0xc8, 0x61, 0xc7, 0x68, 0xc1,
|
||||
0xa2, 0x4b, 0x63, 0x97, 0x7a, 0x5a, 0x95, 0x16, 0x05, 0x09, 0xc3, 0x88, 0x87, 0xb4, 0x29, 0x35,
|
||||
0xdd, 0xe5, 0x2d, 0xdf, 0xed, 0x29, 0x6e, 0x1d, 0xfc, 0x81, 0x9c, 0x83, 0xca, 0x6e, 0x2f, 0x70,
|
||||
0xdf, 0x0e, 0x65, 0x40, 0xc4, 0x2f, 0xc2, 0xbc, 0x9f, 0xb0, 0x76, 0x6c, 0x21, 0x79, 0xab, 0x53,
|
||||
0x81, 0xfc, 0x77, 0x0e, 0x4e, 0x1b, 0xe8, 0xc4, 0x82, 0x22, 0x6c, 0x05, 0x14, 0x13, 0x27, 0xe8,
|
||||
0x45, 0x3d, 0xa7, 0x13, 0xa8, 0x73, 0x52, 0x92, 0x30, 0x1c, 0x46, 0x9d, 0x80, 0x49, 0x8a, 0x97,
|
||||
0x9c, 0x54, 0xc0, 0x0d, 0x28, 0xc5, 0x89, 0x08, 0x81, 0xcd, 0x9e, 0x8c, 0x10, 0x95, 0xfa, 0x5b,
|
||||
0x87, 0x3b, 0x1b, 0x01, 0x7d, 0x57, 0x69, 0x74, 0x32, 0xdd, 0xf8, 0x21, 0x94, 0xf5, 0x9d, 0x8a,
|
||||
0xad, 0xc5, 0x95, 0xd9, 0xd5, 0x4a, 0x7d, 0xf7, 0xf0, 0x86, 0xde, 0x0e, 0x45, 0xf8, 0x36, 0xe2,
|
||||
0x87, 0xd3, 0xb7, 0x82, 0x97, 0xa0, 0xdc, 0x56, 0x97, 0x35, 0xb6, 0x4a, 0xd2, 0xdb, 0xfd, 0x01,
|
||||
0xfc, 0x55, 0x98, 0xf7, 0x83, 0x06, 0x8f, 0xad, 0xb2, 0x04, 0xf3, 0xda, 0xe1, 0xc0, 0xdc, 0x09,
|
||||
0x1a, 0xdc, 0x49, 0x15, 0xe2, 0x87, 0x70, 0x34, 0x62, 0x49, 0xd4, 0xd3, 0x5e, 0xb0, 0x40, 0xfa,
|
||||
0xf5, 0x4b, 0x87, 0xb3, 0xe0, 0x98, 0x2a, 0x9d, 0xbc, 0x05, 0xbc, 0x01, 0x95, 0xb8, 0xcf, 0x31,
|
||||
0xab, 0x22, 0x0d, 0x5a, 0x39, 0x45, 0x06, 0x07, 0x1d, 0x73, 0x32, 0xf9, 0x35, 0x82, 0xa5, 0x03,
|
||||
0xb7, 0x77, 0x37, 0x64, 0x85, 0x04, 0xa4, 0x30, 0x17, 0x87, 0xcc, 0x95, 0x61, 0xbd, 0x52, 0xdf,
|
||||
0x9e, 0xda, 0x75, 0x96, 0x76, 0xa5, 0xea, 0xc2, 0x88, 0x43, 0xe1, 0x53, 0xc6, 0xa2, 0xbb, 0x34,
|
||||
0x71, 0xf7, 0x8a, 0xd0, 0x0a, 0xea, 0x8b, 0x39, 0x2a, 0x0b, 0xa5, 0x82, 0xe0, 0x87, 0xfc, 0xb8,
|
||||
0xd7, 0x0b, 0x85, 0x05, 0xf1, 0x4b, 0x7f, 0x80, 0x04, 0x60, 0x9b, 0x61, 0x86, 0xb7, 0x5a, 0xef,
|
||||
0x52, 0x77, 0xbf, 0xc8, 0xca, 0x31, 0x98, 0xf1, 0x3d, 0x69, 0x62, 0xd6, 0x99, 0xf1, 0xbd, 0x67,
|
||||
0xbb, 0x88, 0xe2, 0xcd, 0x60, 0x0f, 0x49, 0x88, 0x45, 0x06, 0x97, 0xa0, 0x1c, 0x0c, 0x24, 0xc1,
|
||||
0xfe, 0xc0, 0x90, 0xe4, 0x37, 0x73, 0x20, 0xf9, 0x59, 0xb0, 0xd8, 0xcd, 0x5e, 0x10, 0xe2, 0x67,
|
||||
0x2d, 0x0a, 0x90, 0xcd, 0x88, 0x77, 0x42, 0xf5, 0x6c, 0x48, 0x05, 0x81, 0x62, 0xdf, 0x0f, 0x3c,
|
||||
0x6b, 0x21, 0x45, 0x21, 0xbe, 0xc9, 0x7f, 0x10, 0xbc, 0x3c, 0x04, 0xf8, 0xd8, 0x43, 0x79, 0x2e,
|
||||
0xd0, 0xf7, 0xa9, 0xb1, 0x38, 0x92, 0x1a, 0xa5, 0x41, 0x6a, 0xfc, 0x1b, 0xc1, 0xca, 0x90, 0x1d,
|
||||
0x8f, 0x4f, 0x29, 0xcf, 0xcd, 0x96, 0x1b, 0x3c, 0x72, 0x99, 0xb5, 0x98, 0xf2, 0x4f, 0x0a, 0x82,
|
||||
0xad, 0x3c, 0x0a, 0xf7, 0x68, 0x60, 0x95, 0x52, 0xb6, 0xa6, 0x12, 0xf9, 0x0b, 0x02, 0x4b, 0xef,
|
||||
0xf0, 0x96, 0x2b, 0xf7, 0xdb, 0x09, 0x9e, 0xff, 0x4d, 0x9e, 0x86, 0x05, 0x2a, 0xd1, 0xaa, 0x83,
|
||||
0x55, 0x12, 0xf9, 0x0e, 0x82, 0x33, 0xf9, 0xed, 0xc4, 0x5b, 0x7e, 0x9c, 0xe8, 0x97, 0x18, 0x6e,
|
||||
0xc0, 0x62, 0x3a, 0x33, 0x4d, 0xd0, 0x95, 0xfa, 0xd6, 0x61, 0xc3, 0x76, 0xce, 0x75, 0x5a, 0x39,
|
||||
0x79, 0x05, 0xce, 0x0c, 0xbd, 0xed, 0x0a, 0x86, 0x0d, 0x25, 0x9d, 0xaa, 0x94, 0x73, 0x33, 0x99,
|
||||
0xfc, 0x71, 0x36, 0x1f, 0xfd, 0xb8, 0xb7, 0xc5, 0x9b, 0x05, 0x6f, 0xe6, 0xe2, 0x03, 0xb1, 0x60,
|
||||
0x31, 0xe4, 0x9e, 0xf1, 0x3c, 0xd6, 0xa2, 0x58, 0xe7, 0xf2, 0x20, 0xa1, 0xa2, 0x12, 0x53, 0xef,
|
||||
0xe2, 0xfe, 0x80, 0x38, 0xc8, 0xd8, 0x0f, 0x5c, 0xb6, 0xcb, 0x5c, 0x1e, 0x78, 0xb1, 0x3c, 0x91,
|
||||
0x59, 0x27, 0x37, 0x86, 0xdf, 0x84, 0xb2, 0x94, 0xef, 0xf9, 0x6d, 0x26, 0xeb, 0x8c, 0x4a, 0x7d,
|
||||
0xad, 0x9a, 0x96, 0x79, 0x55, 0xb3, 0xcc, 0xeb, 0xfb, 0x50, 0x94, 0x79, 0xd5, 0xee, 0xf5, 0xaa,
|
||||
0x58, 0xe1, 0xf4, 0x17, 0x0b, 0x2c, 0x09, 0xf5, 0x5b, 0x5b, 0x7e, 0x20, 0x9f, 0x0f, 0xc2, 0x54,
|
||||
0x7f, 0x40, 0x1c, 0x76, 0x83, 0xb7, 0x5a, 0xfc, 0x91, 0xe6, 0x6e, 0x2a, 0x89, 0x55, 0x9d, 0x20,
|
||||
0xf1, 0x5b, 0xd2, 0x7e, 0x39, 0xdd, 0x41, 0x36, 0x20, 0x57, 0xf9, 0xad, 0x84, 0x45, 0x32, 0x41,
|
||||
0x97, 0x1d, 0x25, 0x65, 0x74, 0xaa, 0xa4, 0x75, 0x8f, 0xbe, 0x33, 0x29, 0xf1, 0x8e, 0x98, 0xc4,
|
||||
0x1b, 0x24, 0xf3, 0xd1, 0x21, 0xf5, 0x85, 0x2c, 0xe4, 0x58, 0xd7, 0xe7, 0x9d, 0xd8, 0x3a, 0x96,
|
||||
0xa6, 0x31, 0x2d, 0x93, 0xdf, 0x21, 0x28, 0x6d, 0xf1, 0xe6, 0xed, 0x20, 0x89, 0x7a, 0xf2, 0xbd,
|
||||
0xc9, 0x83, 0x84, 0x05, 0xfa, 0xc4, 0xb5, 0x28, 0xdc, 0x98, 0xf8, 0x6d, 0xb6, 0x9b, 0xd0, 0x76,
|
||||
0xa8, 0x32, 0xee, 0x33, 0xb9, 0x31, 0x5b, 0x2c, 0xb6, 0xd6, 0xa2, 0x71, 0x22, 0x6f, 0x5d, 0xc9,
|
||||
0x91, 0xdf, 0x62, 0x13, 0xd9, 0x84, 0xdd, 0x24, 0x52, 0x57, 0x2e, 0x37, 0x66, 0x92, 0x64, 0x3e,
|
||||
0xc5, 0xa6, 0x44, 0x52, 0x83, 0x97, 0xb2, 0x47, 0xd8, 0x3d, 0x16, 0xb5, 0xfd, 0x80, 0x16, 0xc6,
|
||||
0x40, 0x72, 0x3d, 0x47, 0x7c, 0xf1, 0x2a, 0x79, 0xe0, 0x07, 0x1e, 0x7f, 0x34, 0x9a, 0xc0, 0xe4,
|
||||
0x6f, 0xf9, 0x5a, 0xd1, 0x58, 0x93, 0xdd, 0x97, 0x37, 0xe1, 0xa8, 0xb8, 0x59, 0x5d, 0xa6, 0x7e,
|
||||
0x50, 0x97, 0x97, 0xe4, 0x2e, 0xe5, 0x50, 0x1d, 0x4e, 0x7e, 0x21, 0xde, 0x82, 0xe3, 0x34, 0x8e,
|
||||
0xfd, 0x66, 0xc0, 0x3c, 0xad, 0x6b, 0x66, 0x62, 0x5d, 0x83, 0x4b, 0xd3, 0x22, 0x42, 0xce, 0x50,
|
||||
0x3e, 0xd7, 0x22, 0xf9, 0x36, 0x82, 0x53, 0x43, 0x95, 0x64, 0xfc, 0x43, 0x46, 0x38, 0x13, 0x85,
|
||||
0xbc, 0xbb, 0xc7, 0xbc, 0x4e, 0x8b, 0xe9, 0x52, 0x5a, 0xcb, 0xe2, 0x37, 0xaf, 0x93, 0x9e, 0x80,
|
||||
0x0a, 0xa7, 0x99, 0x8c, 0x97, 0x01, 0xda, 0x34, 0xe8, 0xd0, 0x96, 0x84, 0x30, 0x27, 0x21, 0x18,
|
||||
0x23, 0x64, 0x09, 0xec, 0x61, 0xc7, 0xa7, 0xca, 0xd2, 0x5f, 0x21, 0x38, 0xa6, 0x43, 0x93, 0x3a,
|
||||
0x9f, 0x55, 0x38, 0x6e, 0xb8, 0x61, 0xa7, 0x7f, 0x54, 0x83, 0xc3, 0x63, 0xc2, 0x8e, 0x3e, 0xe7,
|
||||
0xd9, 0x7c, 0x37, 0xa4, 0x9b, 0xeb, 0x67, 0x4c, 0x1c, 0xf7, 0xb3, 0x8b, 0x4a, 0xbe, 0x05, 0xd6,
|
||||
0x36, 0x0d, 0x68, 0x93, 0x79, 0x19, 0xf0, 0x8c, 0x24, 0xdf, 0x30, 0x4b, 0xaf, 0x43, 0x17, 0x3a,
|
||||
0x59, 0xda, 0xf7, 0x1b, 0x0d, 0x55, 0xc6, 0xd5, 0xff, 0xb9, 0x0c, 0xd8, 0x3c, 0x54, 0x16, 0x75,
|
||||
0x7d, 0x97, 0xe1, 0x1f, 0x20, 0x98, 0x13, 0x59, 0x06, 0x9f, 0x1d, 0xc5, 0x21, 0xe9, 0x5c, 0x7b,
|
||||
0x7a, 0xef, 0x68, 0x61, 0x8d, 0x2c, 0xbd, 0xf7, 0xf7, 0x7f, 0xfd, 0x70, 0xe6, 0x34, 0x7e, 0x51,
|
||||
0xf6, 0xdd, 0xba, 0xd7, 0xcd, 0x1e, 0x58, 0x8c, 0xbf, 0x8b, 0x00, 0xab, 0xd4, 0x67, 0xb4, 0x5e,
|
||||
0xf0, 0x95, 0x51, 0x10, 0x87, 0xb4, 0x68, 0xec, 0xb3, 0x46, 0x18, 0xaa, 0xba, 0x3c, 0x62, 0x22,
|
||||
0xe8, 0xc8, 0x09, 0x12, 0xc0, 0x9a, 0x04, 0x70, 0x1e, 0x93, 0x61, 0x00, 0x6a, 0x8f, 0xc5, 0xa1,
|
||||
0x3f, 0xa9, 0xb1, 0xd4, 0xee, 0xcf, 0x11, 0xcc, 0x3f, 0x90, 0x8f, 0xaf, 0x31, 0x4e, 0xda, 0x9d,
|
||||
0x9a, 0x93, 0xa4, 0x39, 0x89, 0x96, 0x9c, 0x93, 0x48, 0xcf, 0xe2, 0x33, 0x1a, 0x69, 0x9c, 0x44,
|
||||
0x8c, 0xb6, 0x73, 0x80, 0xaf, 0x21, 0xfc, 0x21, 0x82, 0x85, 0xb4, 0x39, 0x83, 0x2f, 0x8c, 0x42,
|
||||
0x99, 0x6b, 0xde, 0xd8, 0xd3, 0xeb, 0x74, 0x90, 0xcb, 0x12, 0xe3, 0x39, 0x32, 0xf4, 0x38, 0x37,
|
||||
0x72, 0x7d, 0x90, 0xf7, 0x11, 0xcc, 0x6e, 0xb2, 0xb1, 0x7c, 0x9b, 0x22, 0xb8, 0x03, 0x0e, 0x1c,
|
||||
0x72, 0xd4, 0xf8, 0x03, 0x04, 0x2f, 0x6d, 0xb2, 0x64, 0x78, 0x2c, 0xc7, 0xab, 0xe3, 0x03, 0xac,
|
||||
0xa2, 0xdd, 0x95, 0x09, 0x66, 0x66, 0x41, 0xac, 0x26, 0x91, 0x5d, 0xc6, 0x97, 0x8a, 0x48, 0x28,
|
||||
0x0a, 0xe2, 0x47, 0x0a, 0xc7, 0x9f, 0x11, 0x9c, 0x18, 0x6c, 0x72, 0xe2, 0x7c, 0xf4, 0x1f, 0xda,
|
||||
0x03, 0xb5, 0x77, 0x0e, 0x1b, 0x50, 0xf2, 0x4a, 0xc9, 0x2d, 0x89, 0xfc, 0x55, 0xfc, 0x4a, 0x11,
|
||||
0x72, 0xdd, 0xf7, 0x89, 0x6b, 0x8f, 0xf5, 0xe7, 0x13, 0xd9, 0x2d, 0x97, 0xb0, 0xdf, 0x43, 0x70,
|
||||
0x64, 0x93, 0x25, 0xdb, 0x59, 0xdb, 0x63, 0x24, 0x6d, 0x73, 0x7d, 0x4d, 0x7b, 0xa9, 0x6a, 0x34,
|
||||
0xb5, 0xf5, 0x4f, 0x99, 0x4b, 0xd7, 0x25, 0xb0, 0x4b, 0xf8, 0x42, 0x11, 0xb0, 0x7e, 0xab, 0xe5,
|
||||
0xf7, 0x08, 0x16, 0xd2, 0xb6, 0xc2, 0x68, 0xf3, 0xb9, 0xa6, 0xe1, 0x34, 0x89, 0x79, 0x5b, 0x62,
|
||||
0xfd, 0xbc, 0x7d, 0x6d, 0x38, 0x56, 0x73, 0xbd, 0xf6, 0x5a, 0x55, 0x6e, 0x20, 0x7f, 0xa3, 0x3e,
|
||||
0x42, 0x00, 0xfd, 0xd6, 0x08, 0xbe, 0x5c, 0xbc, 0x0f, 0xa3, 0x7d, 0x62, 0x4f, 0xb7, 0x39, 0x42,
|
||||
0xaa, 0x72, 0x3f, 0xab, 0xf6, 0x4a, 0x21, 0x9d, 0x43, 0xe6, 0x6e, 0xa4, 0x6d, 0x94, 0x9f, 0x21,
|
||||
0x98, 0x97, 0xb5, 0x38, 0x3e, 0x3f, 0x0a, 0xb3, 0x59, 0xaa, 0x4f, 0xd3, 0xf5, 0x17, 0x25, 0xd4,
|
||||
0x95, 0x7a, 0x51, 0x4c, 0xd8, 0x40, 0x6b, 0xb8, 0x0b, 0x0b, 0x69, 0xed, 0x3c, 0x9a, 0x1e, 0xb9,
|
||||
0xda, 0xda, 0x5e, 0x29, 0xc8, 0x51, 0x29, 0x43, 0x55, 0x38, 0x5a, 0x1b, 0x17, 0x8e, 0xe6, 0x44,
|
||||
0xc4, 0xc0, 0xe7, 0x8a, 0xe2, 0xc9, 0xc7, 0xe0, 0x98, 0x2b, 0x12, 0xdd, 0x05, 0xb2, 0x32, 0x2e,
|
||||
0x24, 0x09, 0xef, 0xfc, 0x08, 0xc1, 0x89, 0xc1, 0x27, 0x0d, 0x3e, 0x33, 0x10, 0x8e, 0xcc, 0x37,
|
||||
0x9a, 0x9d, 0xf7, 0xe2, 0xa8, 0xe7, 0x10, 0xf9, 0x82, 0x44, 0xb1, 0x81, 0x6f, 0x8e, 0xbd, 0x19,
|
||||
0x3b, 0xfa, 0x42, 0x0b, 0x45, 0xeb, 0xfd, 0x0e, 0xeb, 0x6f, 0x10, 0x1c, 0xd1, 0x7a, 0xef, 0x45,
|
||||
0x8c, 0x15, 0xc3, 0x9a, 0xde, 0x45, 0x10, 0xb6, 0xc8, 0x67, 0x25, 0xfc, 0xcf, 0xe0, 0x1b, 0x13,
|
||||
0xc2, 0xd7, 0xb0, 0xd7, 0x13, 0x81, 0xf4, 0x0f, 0x08, 0x4e, 0x3e, 0x48, 0x79, 0xff, 0x09, 0xe1,
|
||||
0x7f, 0x5d, 0xe2, 0xff, 0x1c, 0x7e, 0xb5, 0xe0, 0xc9, 0x31, 0x6e, 0x1b, 0xd7, 0x10, 0xfe, 0x25,
|
||||
0x82, 0x92, 0xee, 0x4e, 0xe2, 0x4b, 0x23, 0x2f, 0x46, 0xbe, 0x7f, 0x39, 0x4d, 0x32, 0xab, 0xfc,
|
||||
0x4a, 0xce, 0x17, 0x66, 0x29, 0x65, 0x5f, 0x10, 0xfa, 0x7d, 0x04, 0x38, 0xab, 0x35, 0xb2, 0xea,
|
||||
0x03, 0x5f, 0xcc, 0x99, 0x1a, 0x59, 0x54, 0xda, 0x97, 0xc6, 0xce, 0xcb, 0x67, 0xa9, 0xb5, 0xc2,
|
||||
0x2c, 0xc5, 0x33, 0xfb, 0xdf, 0x43, 0x50, 0xd9, 0x64, 0xd9, 0x73, 0xb8, 0xc0, 0x97, 0xf9, 0xd6,
|
||||
0xac, 0xbd, 0x3a, 0x7e, 0xa2, 0x42, 0x74, 0x55, 0x22, 0xba, 0x88, 0x8b, 0x5d, 0xa5, 0x01, 0xfc,
|
||||
0x04, 0xc1, 0xd1, 0xbb, 0x26, 0x45, 0xf1, 0xd5, 0x71, 0x96, 0x72, 0x91, 0x7c, 0x72, 0x5c, 0x9f,
|
||||
0x96, 0xb8, 0xd6, 0xc9, 0x44, 0xb8, 0x36, 0x54, 0x8f, 0xf4, 0xa7, 0x08, 0x5e, 0x30, 0xeb, 0x07,
|
||||
0xd5, 0x4d, 0xfb, 0x7f, 0xfd, 0x56, 0xd0, 0x94, 0x23, 0x37, 0x24, 0xbe, 0x2a, 0xbe, 0x3a, 0x09,
|
||||
0xbe, 0x9a, 0x6a, 0xb1, 0xe1, 0x1f, 0x23, 0x38, 0x29, 0x7b, 0x95, 0xa6, 0xe2, 0x81, 0x14, 0x33,
|
||||
0xaa, 0xb3, 0x39, 0x41, 0x8a, 0x51, 0xf1, 0x87, 0x3c, 0x13, 0xa8, 0x0d, 0xd5, 0x87, 0xc4, 0xdf,
|
||||
0x47, 0x70, 0x4c, 0x27, 0x35, 0x75, 0xba, 0xeb, 0xe3, 0x1c, 0xf7, 0xac, 0x49, 0x50, 0xd1, 0x6d,
|
||||
0x6d, 0x32, 0xba, 0x7d, 0x88, 0x60, 0x51, 0xf5, 0x12, 0x0b, 0x9e, 0x0a, 0x46, 0xb3, 0xd1, 0x3e,
|
||||
0x95, 0x9b, 0xa5, 0x1b, 0x59, 0xe4, 0x6b, 0xd2, 0xec, 0x7d, 0x5c, 0x2b, 0x32, 0x1b, 0x72, 0x2f,
|
||||
0xae, 0x3d, 0x56, 0x5d, 0xa4, 0x27, 0xb5, 0x16, 0x6f, 0xc6, 0xef, 0x10, 0x5c, 0x98, 0x10, 0xc5,
|
||||
0x9c, 0x6b, 0xe8, 0xb5, 0x2f, 0xfe, 0xe9, 0xe9, 0x32, 0xfa, 0xeb, 0xd3, 0x65, 0xf4, 0x8f, 0xa7,
|
||||
0xcb, 0xe8, 0x9d, 0x9b, 0x93, 0xfd, 0xff, 0xc3, 0x6d, 0xf9, 0x2c, 0x48, 0x4c, 0xb5, 0xff, 0x0b,
|
||||
0x00, 0x00, 0xff, 0xff, 0xa3, 0x87, 0x84, 0x43, 0xe5, 0x22, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@@ -3455,27 +3455,21 @@ func (m *ApplicationResourceEventsQuery) MarshalToSizedBuffer(dAtA []byte) (int,
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if m.ResourceUID == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceUID")
|
||||
} else {
|
||||
if m.ResourceUID != nil {
|
||||
i -= len(*m.ResourceUID)
|
||||
copy(dAtA[i:], *m.ResourceUID)
|
||||
i = encodeVarintApplication(dAtA, i, uint64(len(*m.ResourceUID)))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
if m.ResourceName == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceName")
|
||||
} else {
|
||||
if m.ResourceName != nil {
|
||||
i -= len(*m.ResourceName)
|
||||
copy(dAtA[i:], *m.ResourceName)
|
||||
i = encodeVarintApplication(dAtA, i, uint64(len(*m.ResourceName)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if m.ResourceNamespace == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceNamespace")
|
||||
} else {
|
||||
if m.ResourceNamespace != nil {
|
||||
i -= len(*m.ResourceNamespace)
|
||||
copy(dAtA[i:], *m.ResourceNamespace)
|
||||
i = encodeVarintApplication(dAtA, i, uint64(len(*m.ResourceNamespace)))
|
||||
@@ -4136,9 +4130,7 @@ func (m *ApplicationResourceRequest) MarshalToSizedBuffer(dAtA []byte) (int, err
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if m.Namespace == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
} else {
|
||||
if m.Namespace != nil {
|
||||
i -= len(*m.Namespace)
|
||||
copy(dAtA[i:], *m.Namespace)
|
||||
i = encodeVarintApplication(dAtA, i, uint64(len(*m.Namespace)))
|
||||
@@ -4233,9 +4225,7 @@ func (m *ApplicationResourcePatchRequest) MarshalToSizedBuffer(dAtA []byte) (int
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if m.Namespace == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
} else {
|
||||
if m.Namespace != nil {
|
||||
i -= len(*m.Namespace)
|
||||
copy(dAtA[i:], *m.Namespace)
|
||||
i = encodeVarintApplication(dAtA, i, uint64(len(*m.Namespace)))
|
||||
@@ -4332,9 +4322,7 @@ func (m *ApplicationResourceDeleteRequest) MarshalToSizedBuffer(dAtA []byte) (in
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if m.Namespace == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
} else {
|
||||
if m.Namespace != nil {
|
||||
i -= len(*m.Namespace)
|
||||
copy(dAtA[i:], *m.Namespace)
|
||||
i = encodeVarintApplication(dAtA, i, uint64(len(*m.Namespace)))
|
||||
@@ -4420,9 +4408,7 @@ func (m *ResourceActionRunRequest) MarshalToSizedBuffer(dAtA []byte) (int, error
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if m.Namespace == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
} else {
|
||||
if m.Namespace != nil {
|
||||
i -= len(*m.Namespace)
|
||||
copy(dAtA[i:], *m.Namespace)
|
||||
i = encodeVarintApplication(dAtA, i, uint64(len(*m.Namespace)))
|
||||
@@ -4633,9 +4619,7 @@ func (m *ApplicationPodLogsQuery) MarshalToSizedBuffer(dAtA []byte) (int, error)
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if m.Namespace == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
} else {
|
||||
if m.Namespace != nil {
|
||||
i -= len(*m.Namespace)
|
||||
copy(dAtA[i:], *m.Namespace)
|
||||
i = encodeVarintApplication(dAtA, i, uint64(len(*m.Namespace)))
|
||||
@@ -6437,7 +6421,6 @@ func (m *ApplicationResourceEventsQuery) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ResourceNamespace = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ResourceName", wireType)
|
||||
@@ -6471,7 +6454,6 @@ func (m *ApplicationResourceEventsQuery) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ResourceName = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000004)
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ResourceUID", wireType)
|
||||
@@ -6505,7 +6487,6 @@ func (m *ApplicationResourceEventsQuery) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ResourceUID = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000008)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipApplication(dAtA[iNdEx:])
|
||||
@@ -6525,15 +6506,6 @@ func (m *ApplicationResourceEventsQuery) Unmarshal(dAtA []byte) error {
|
||||
if hasFields[0]&uint64(0x00000001) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("name")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000002) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceNamespace")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000004) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceName")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000008) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceUID")
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
@@ -8123,7 +8095,6 @@ func (m *ApplicationResourceRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Namespace = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ResourceName", wireType)
|
||||
@@ -8157,7 +8128,7 @@ func (m *ApplicationResourceRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ResourceName = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000004)
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
|
||||
@@ -8191,7 +8162,7 @@ func (m *ApplicationResourceRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Version = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000008)
|
||||
hasFields[0] |= uint64(0x00000004)
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType)
|
||||
@@ -8258,7 +8229,7 @@ func (m *ApplicationResourceRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Kind = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000010)
|
||||
hasFields[0] |= uint64(0x00000008)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipApplication(dAtA[iNdEx:])
|
||||
@@ -8279,15 +8250,12 @@ func (m *ApplicationResourceRequest) Unmarshal(dAtA []byte) error {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("name")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000002) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000004) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceName")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000008) == 0 {
|
||||
if hasFields[0]&uint64(0x00000004) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("version")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000010) == 0 {
|
||||
if hasFields[0]&uint64(0x00000008) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("kind")
|
||||
}
|
||||
|
||||
@@ -8393,7 +8361,6 @@ func (m *ApplicationResourcePatchRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Namespace = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ResourceName", wireType)
|
||||
@@ -8427,7 +8394,7 @@ func (m *ApplicationResourcePatchRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ResourceName = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000004)
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
|
||||
@@ -8461,7 +8428,7 @@ func (m *ApplicationResourcePatchRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Version = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000008)
|
||||
hasFields[0] |= uint64(0x00000004)
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType)
|
||||
@@ -8528,7 +8495,7 @@ func (m *ApplicationResourcePatchRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Kind = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000010)
|
||||
hasFields[0] |= uint64(0x00000008)
|
||||
case 7:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Patch", wireType)
|
||||
@@ -8562,7 +8529,7 @@ func (m *ApplicationResourcePatchRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Patch = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000020)
|
||||
hasFields[0] |= uint64(0x00000010)
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field PatchType", wireType)
|
||||
@@ -8596,7 +8563,7 @@ func (m *ApplicationResourcePatchRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.PatchType = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000040)
|
||||
hasFields[0] |= uint64(0x00000020)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipApplication(dAtA[iNdEx:])
|
||||
@@ -8617,21 +8584,18 @@ func (m *ApplicationResourcePatchRequest) Unmarshal(dAtA []byte) error {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("name")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000002) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000004) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceName")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000008) == 0 {
|
||||
if hasFields[0]&uint64(0x00000004) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("version")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000010) == 0 {
|
||||
if hasFields[0]&uint64(0x00000008) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("kind")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000020) == 0 {
|
||||
if hasFields[0]&uint64(0x00000010) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("patch")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000040) == 0 {
|
||||
if hasFields[0]&uint64(0x00000020) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("patchType")
|
||||
}
|
||||
|
||||
@@ -8737,7 +8701,6 @@ func (m *ApplicationResourceDeleteRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Namespace = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ResourceName", wireType)
|
||||
@@ -8771,7 +8734,7 @@ func (m *ApplicationResourceDeleteRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ResourceName = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000004)
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
|
||||
@@ -8805,7 +8768,7 @@ func (m *ApplicationResourceDeleteRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Version = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000008)
|
||||
hasFields[0] |= uint64(0x00000004)
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType)
|
||||
@@ -8872,7 +8835,7 @@ func (m *ApplicationResourceDeleteRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Kind = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000010)
|
||||
hasFields[0] |= uint64(0x00000008)
|
||||
case 7:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Force", wireType)
|
||||
@@ -8935,15 +8898,12 @@ func (m *ApplicationResourceDeleteRequest) Unmarshal(dAtA []byte) error {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("name")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000002) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000004) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceName")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000008) == 0 {
|
||||
if hasFields[0]&uint64(0x00000004) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("version")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000010) == 0 {
|
||||
if hasFields[0]&uint64(0x00000008) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("kind")
|
||||
}
|
||||
|
||||
@@ -9049,7 +9009,6 @@ func (m *ResourceActionRunRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Namespace = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ResourceName", wireType)
|
||||
@@ -9083,7 +9042,7 @@ func (m *ResourceActionRunRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ResourceName = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000004)
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
|
||||
@@ -9117,7 +9076,7 @@ func (m *ResourceActionRunRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Version = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000008)
|
||||
hasFields[0] |= uint64(0x00000004)
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType)
|
||||
@@ -9184,7 +9143,7 @@ func (m *ResourceActionRunRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Kind = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000010)
|
||||
hasFields[0] |= uint64(0x00000008)
|
||||
case 7:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Action", wireType)
|
||||
@@ -9218,7 +9177,7 @@ func (m *ResourceActionRunRequest) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Action = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000020)
|
||||
hasFields[0] |= uint64(0x00000010)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipApplication(dAtA[iNdEx:])
|
||||
@@ -9239,18 +9198,15 @@ func (m *ResourceActionRunRequest) Unmarshal(dAtA []byte) error {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("name")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000002) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000004) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("resourceName")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000008) == 0 {
|
||||
if hasFields[0]&uint64(0x00000004) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("version")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000010) == 0 {
|
||||
if hasFields[0]&uint64(0x00000008) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("kind")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000020) == 0 {
|
||||
if hasFields[0]&uint64(0x00000010) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("action")
|
||||
}
|
||||
|
||||
@@ -9530,7 +9486,6 @@ func (m *ApplicationPodLogsQuery) Unmarshal(dAtA []byte) error {
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Namespace = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field PodName", wireType)
|
||||
@@ -9899,9 +9854,6 @@ func (m *ApplicationPodLogsQuery) Unmarshal(dAtA []byte) error {
|
||||
if hasFields[0]&uint64(0x00000001) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("name")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000002) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("namespace")
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
|
||||
@@ -100,7 +100,11 @@ func (c *client) executeRequest(fullMethodName string, msg []byte, md metadata.M
|
||||
}
|
||||
|
||||
func (c *client) startGRPCProxy() (*grpc.Server, net.Listener, error) {
|
||||
serverAddr := fmt.Sprintf("%s/argocd-%s.sock", os.TempDir(), rand.RandString(16))
|
||||
randSuffix, err := rand.String(16)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to generate random socket filename: %w", err)
|
||||
}
|
||||
serverAddr := fmt.Sprintf("%s/argocd-%s.sock", os.TempDir(), randSuffix)
|
||||
ln, err := net.Listen("unix", serverAddr)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -1542,6 +1542,19 @@ func isValidAction(action string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: same as validActions, refacotor to use rbacpolicy.ResourceApplications etc.
|
||||
var validResources = map[string]bool{
|
||||
"applications": true,
|
||||
"repositories": true,
|
||||
"clusters": true,
|
||||
"exec": true,
|
||||
"logs": true,
|
||||
}
|
||||
|
||||
func isValidResource(resource string) bool {
|
||||
return validResources[resource]
|
||||
}
|
||||
|
||||
func validatePolicy(proj string, role string, policy string) error {
|
||||
policyComponents := strings.Split(policy, ",")
|
||||
if len(policyComponents) != 6 || strings.Trim(policyComponents[0], " ") != "p" {
|
||||
@@ -1555,7 +1568,7 @@ func validatePolicy(proj string, role string, policy string) error {
|
||||
}
|
||||
// resource
|
||||
resource := strings.Trim(policyComponents[2], " ")
|
||||
if resource != "applications" && resource != "repositories" && resource != "clusters" {
|
||||
if !isValidResource(resource) {
|
||||
return status.Errorf(codes.InvalidArgument, "invalid policy rule '%s': project resource must be: 'applications', 'repositories' or 'clusters', not '%s'", policy, resource)
|
||||
}
|
||||
// action
|
||||
|
||||
@@ -2546,10 +2546,19 @@ func Test_validatePolicy_projIsNotRegex(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_validatePolicy_ValidResource(t *testing.T) {
|
||||
err := validatePolicy("some-project", "org-admin", "p, proj:some-project:org-admin, repositories, *, some-project/*, allow")
|
||||
err := validatePolicy("some-project", "org-admin", "p, proj:some-project:org-admin, applications, *, some-project/*, allow")
|
||||
assert.NoError(t, err)
|
||||
err = validatePolicy("some-project", "org-admin", "p, proj:some-project:org-admin, repositories, *, some-project/*, allow")
|
||||
assert.NoError(t, err)
|
||||
err = validatePolicy("some-project", "org-admin", "p, proj:some-project:org-admin, clusters, *, some-project/*, allow")
|
||||
assert.NoError(t, err)
|
||||
err = validatePolicy("some-project", "org-admin", "p, proj:some-project:org-admin, exec, *, some-project/*, allow")
|
||||
assert.NoError(t, err)
|
||||
err = validatePolicy("some-project", "org-admin", "p, proj:some-project:org-admin, logs, *, some-project/*, allow")
|
||||
assert.NoError(t, err)
|
||||
err = validatePolicy("some-project", "org-admin", "p, proj:some-project:org-admin, unknown, *, some-project/*, allow")
|
||||
assert.Error(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestEnvsubst(t *testing.T) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
@@ -63,6 +64,8 @@ func NewConnection(address string, timeoutSeconds int, tlsConfig *TLSConfigurati
|
||||
grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor(retryOpts...)),
|
||||
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(unaryInterceptors...)),
|
||||
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(MaxGRPCMessageSize), grpc.MaxCallSendMsgSize(MaxGRPCMessageSize)),
|
||||
grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()),
|
||||
grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor()),
|
||||
}
|
||||
|
||||
tlsC := &tls.Config{}
|
||||
|
||||
@@ -18,6 +18,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
kubeyaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/io/files"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/TomOnTime/utfutil"
|
||||
"github.com/argoproj/gitops-engine/pkg/utils/kube"
|
||||
@@ -69,6 +75,8 @@ const (
|
||||
ociPrefix = "oci://"
|
||||
)
|
||||
|
||||
var ErrExceededMaxCombinedManifestFileSize = errors.New("exceeded max combined manifest file size")
|
||||
|
||||
// Service implements ManifestService interface
|
||||
type Service struct {
|
||||
gitCredsStore git.CredsStore
|
||||
@@ -94,6 +102,8 @@ type RepoServerInitConstants struct {
|
||||
PauseGenerationOnFailureForMinutes int
|
||||
PauseGenerationOnFailureForRequests int
|
||||
SubmoduleEnabled bool
|
||||
MaxCombinedDirectoryManifestsSize resource.Quantity
|
||||
CMPTarExcludedGlobs []string
|
||||
}
|
||||
|
||||
// NewService returns a new instance of the Manifest service
|
||||
@@ -204,7 +214,7 @@ func (s *Service) ListApps(ctx context.Context, q *apiclient.ListAppsRequest) (*
|
||||
}
|
||||
|
||||
defer io.Close(closer)
|
||||
apps, err := discovery.Discover(ctx, gitClient.Root(), q.EnabledSourceTypes)
|
||||
apps, err := discovery.Discover(ctx, gitClient.Root(), q.EnabledSourceTypes, s.initConstants.CMPTarExcludedGlobs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -448,10 +458,15 @@ func (s *Service) runManifestGenAsync(ctx context.Context, repoRoot, commitSHA,
|
||||
close(ch.errCh)
|
||||
close(ch.responseCh)
|
||||
}()
|
||||
|
||||
// GenerateManifests mutates the source (applies overrides). Those overrides shouldn't be reflected in the cache
|
||||
// key. Overrides will break the cache anyway, because changes to overrides will change the revision.
|
||||
appSourceCopy := q.ApplicationSource.DeepCopy()
|
||||
|
||||
var manifestGenResult *apiclient.ManifestResponse
|
||||
opContext, err := opContextSrc()
|
||||
if err == nil {
|
||||
manifestGenResult, err = GenerateManifests(ctx, opContext.appPath, repoRoot, commitSHA, q, false, s.gitCredsStore, WithCMPTarDoneChannel(ch.tarDoneCh))
|
||||
manifestGenResult, err = GenerateManifests(ctx, opContext.appPath, repoRoot, commitSHA, q, false, s.gitCredsStore, s.initConstants.MaxCombinedDirectoryManifestsSize, WithCMPTarDoneChannel(ch.tarDoneCh), WithCMPTarExcludedGlobs(s.initConstants.CMPTarExcludedGlobs))
|
||||
}
|
||||
if err != nil {
|
||||
// If manifest generation error caching is enabled
|
||||
@@ -460,9 +475,9 @@ func (s *Service) runManifestGenAsync(ctx context.Context, repoRoot, commitSHA,
|
||||
// Retrieve a new copy (if available) of the cached response: this ensures we are updating the latest copy of the cache,
|
||||
// rather than a copy of the cache that occurred before (a potentially lengthy) manifest generation.
|
||||
innerRes := &cache.CachedManifestResponse{}
|
||||
cacheErr := s.cache.GetManifests(cacheKey, q.ApplicationSource, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, innerRes)
|
||||
cacheErr := s.cache.GetManifests(cacheKey, appSourceCopy, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, innerRes)
|
||||
if cacheErr != nil && cacheErr != reposervercache.ErrCacheMiss {
|
||||
log.Warnf("manifest cache set error %s: %v", q.ApplicationSource.String(), cacheErr)
|
||||
log.Warnf("manifest cache set error %s: %v", appSourceCopy.String(), cacheErr)
|
||||
ch.errCh <- cacheErr
|
||||
return
|
||||
}
|
||||
@@ -476,9 +491,9 @@ func (s *Service) runManifestGenAsync(ctx context.Context, repoRoot, commitSHA,
|
||||
// Update the cache to include failure information
|
||||
innerRes.NumberOfConsecutiveFailures++
|
||||
innerRes.MostRecentError = err.Error()
|
||||
cacheErr = s.cache.SetManifests(cacheKey, q.ApplicationSource, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, innerRes)
|
||||
cacheErr = s.cache.SetManifests(cacheKey, appSourceCopy, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, innerRes)
|
||||
if cacheErr != nil {
|
||||
log.Warnf("manifest cache set error %s: %v", q.ApplicationSource.String(), cacheErr)
|
||||
log.Warnf("manifest cache set error %s: %v", appSourceCopy.String(), cacheErr)
|
||||
ch.errCh <- cacheErr
|
||||
return
|
||||
}
|
||||
@@ -497,9 +512,9 @@ func (s *Service) runManifestGenAsync(ctx context.Context, repoRoot, commitSHA,
|
||||
}
|
||||
manifestGenResult.Revision = commitSHA
|
||||
manifestGenResult.VerifyResult = opContext.verificationResult
|
||||
err = s.cache.SetManifests(cacheKey, q.ApplicationSource, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, &manifestGenCacheEntry)
|
||||
err = s.cache.SetManifests(cacheKey, appSourceCopy, q, q.Namespace, q.TrackingMethod, q.AppLabelKey, q.AppName, &manifestGenCacheEntry)
|
||||
if err != nil {
|
||||
log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.String(), cacheKey, err)
|
||||
log.Warnf("manifest cache set error %s/%s: %v", appSourceCopy.String(), cacheKey, err)
|
||||
}
|
||||
ch.responseCh <- manifestGenCacheEntry.ManifestResponse
|
||||
}
|
||||
@@ -844,7 +859,8 @@ func getRepoCredential(repoCredentials []*v1alpha1.RepoCreds, repoURL string) *v
|
||||
|
||||
type GenerateManifestOpt func(*generateManifestOpt)
|
||||
type generateManifestOpt struct {
|
||||
cmpTarDoneCh chan<- bool
|
||||
cmpTarDoneCh chan<- bool
|
||||
cmpTarExcludedGlobs []string
|
||||
}
|
||||
|
||||
func newGenerateManifestOpt(opts ...GenerateManifestOpt) *generateManifestOpt {
|
||||
@@ -864,14 +880,23 @@ func WithCMPTarDoneChannel(ch chan<- bool) GenerateManifestOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateManifests generates manifests from a path
|
||||
func GenerateManifests(ctx context.Context, appPath, repoRoot, revision string, q *apiclient.ManifestRequest, isLocal bool, gitCredsStore git.CredsStore, opts ...GenerateManifestOpt) (*apiclient.ManifestResponse, error) {
|
||||
// WithCMPTarExcludedGlobs defines globs for files to filter out when streaming the tarball
|
||||
// to a CMP sidecar.
|
||||
func WithCMPTarExcludedGlobs(excludedGlobs []string) GenerateManifestOpt {
|
||||
return func(o *generateManifestOpt) {
|
||||
o.cmpTarExcludedGlobs = excludedGlobs
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateManifests generates manifests from a path. Overrides are applied as a side effect on the given ApplicationSource.
|
||||
func GenerateManifests(ctx context.Context, appPath, repoRoot, revision string, q *apiclient.ManifestRequest, isLocal bool, gitCredsStore git.CredsStore, maxCombinedManifestQuantity resource.Quantity, opts ...GenerateManifestOpt) (*apiclient.ManifestResponse, error) {
|
||||
opt := newGenerateManifestOpt(opts...)
|
||||
var targetObjs []*unstructured.Unstructured
|
||||
var dest *v1alpha1.ApplicationDestination
|
||||
|
||||
resourceTracking := argo.NewResourceTracking()
|
||||
appSourceType, err := GetAppSourceType(ctx, q.ApplicationSource, appPath, q.AppName, q.EnabledSourceTypes)
|
||||
|
||||
appSourceType, err := GetAppSourceType(ctx, q.ApplicationSource, appPath, q.AppName, q.EnabledSourceTypes, opt.cmpTarExcludedGlobs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -895,7 +920,7 @@ func GenerateManifests(ctx context.Context, appPath, repoRoot, revision string,
|
||||
if q.ApplicationSource.Plugin != nil && q.ApplicationSource.Plugin.Name != "" {
|
||||
targetObjs, err = runConfigManagementPlugin(appPath, repoRoot, env, q, q.Repo.GetGitCreds(gitCredsStore))
|
||||
} else {
|
||||
targetObjs, err = runConfigManagementPluginSidecars(ctx, appPath, repoRoot, env, q, q.Repo.GetGitCreds(gitCredsStore), opt.cmpTarDoneCh)
|
||||
targetObjs, err = runConfigManagementPluginSidecars(ctx, appPath, repoRoot, env, q, q.Repo.GetGitCreds(gitCredsStore), opt.cmpTarDoneCh, opt.cmpTarExcludedGlobs)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("plugin sidecar failed. %s", err.Error())
|
||||
}
|
||||
@@ -905,7 +930,8 @@ func GenerateManifests(ctx context.Context, appPath, repoRoot, revision string,
|
||||
if directory = q.ApplicationSource.Directory; directory == nil {
|
||||
directory = &v1alpha1.ApplicationSourceDirectory{}
|
||||
}
|
||||
targetObjs, err = findManifests(appPath, repoRoot, env, *directory, q.EnabledSourceTypes)
|
||||
logCtx := log.WithField("application", q.AppName)
|
||||
targetObjs, err = findManifests(logCtx, appPath, repoRoot, env, *directory, q.EnabledSourceTypes, maxCombinedManifestQuantity)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -982,7 +1008,7 @@ func mergeSourceParameters(source *v1alpha1.ApplicationSource, path, appName str
|
||||
overrides = append(overrides, filepath.Join(path, fmt.Sprintf(appSourceFile, appName)))
|
||||
}
|
||||
|
||||
var merged v1alpha1.ApplicationSource = *source.DeepCopy()
|
||||
var merged = *source.DeepCopy()
|
||||
|
||||
for _, filename := range overrides {
|
||||
info, err := os.Stat(filename)
|
||||
@@ -1028,7 +1054,7 @@ func mergeSourceParameters(source *v1alpha1.ApplicationSource, path, appName str
|
||||
}
|
||||
|
||||
// GetAppSourceType returns explicit application source type or examines a directory and determines its application source type
|
||||
func GetAppSourceType(ctx context.Context, source *v1alpha1.ApplicationSource, path, appName string, enableGenerateManifests map[string]bool) (v1alpha1.ApplicationSourceType, error) {
|
||||
func GetAppSourceType(ctx context.Context, source *v1alpha1.ApplicationSource, path, appName string, enableGenerateManifests map[string]bool, tarExcludedGlobs []string) (v1alpha1.ApplicationSourceType, error) {
|
||||
err := mergeSourceParameters(source, path, appName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error while parsing source parameters: %v", err)
|
||||
@@ -1045,7 +1071,7 @@ func GetAppSourceType(ctx context.Context, source *v1alpha1.ApplicationSource, p
|
||||
}
|
||||
return *appSourceType, nil
|
||||
}
|
||||
appType, err := discovery.AppType(ctx, path, enableGenerateManifests)
|
||||
appType, err := discovery.AppType(ctx, path, enableGenerateManifests, tarExcludedGlobs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1075,47 +1101,30 @@ func isNullList(obj *unstructured.Unstructured) bool {
|
||||
var manifestFile = regexp.MustCompile(`^.*\.(yaml|yml|json|jsonnet)$`)
|
||||
|
||||
// findManifests looks at all yaml files in a directory and unmarshals them into a list of unstructured objects
|
||||
func findManifests(appPath string, repoRoot string, env *v1alpha1.Env, directory v1alpha1.ApplicationSourceDirectory, enabledManifestGeneration map[string]bool) ([]*unstructured.Unstructured, error) {
|
||||
func findManifests(logCtx *log.Entry, appPath string, repoRoot string, env *v1alpha1.Env, directory v1alpha1.ApplicationSourceDirectory, enabledManifestGeneration map[string]bool, maxCombinedManifestQuantity resource.Quantity) ([]*unstructured.Unstructured, error) {
|
||||
// Validate the directory before loading any manifests to save memory.
|
||||
potentiallyValidManifests, err := getPotentiallyValidManifests(logCtx, appPath, repoRoot, directory.Recurse, directory.Include, directory.Exclude, maxCombinedManifestQuantity)
|
||||
if err != nil {
|
||||
logCtx.Errorf("failed to get potentially valid manifests: %s", err)
|
||||
return nil, fmt.Errorf("failed to get potentially valid manifests: %w", err)
|
||||
}
|
||||
|
||||
var objs []*unstructured.Unstructured
|
||||
err := filepath.Walk(appPath, func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if f.IsDir() {
|
||||
if path != appPath && !directory.Recurse {
|
||||
return filepath.SkipDir
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
for _, potentiallyValidManifest := range potentiallyValidManifests {
|
||||
manifestPath := potentiallyValidManifest.path
|
||||
manifestFileInfo := potentiallyValidManifest.fileInfo
|
||||
|
||||
if !manifestFile.MatchString(f.Name()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
relPath, err := filepath.Rel(appPath, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if directory.Exclude != "" && glob.Match(directory.Exclude, relPath) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if directory.Include != "" && !glob.Match(directory.Include, relPath) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if strings.HasSuffix(f.Name(), ".jsonnet") {
|
||||
if strings.HasSuffix(manifestFileInfo.Name(), ".jsonnet") {
|
||||
if !discovery.IsManifestGenerationEnabled(v1alpha1.ApplicationSourceTypeDirectory, enabledManifestGeneration) {
|
||||
return nil
|
||||
continue
|
||||
}
|
||||
vm, err := makeJsonnetVm(appPath, repoRoot, directory.Jsonnet, env)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
jsonStr, err := vm.EvaluateFile(path)
|
||||
jsonStr, err := vm.EvaluateFile(manifestPath)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.FailedPrecondition, "Failed to evaluate jsonnet %q: %v", f.Name(), err)
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "Failed to evaluate jsonnet %q: %v", manifestFileInfo.Name(), err)
|
||||
}
|
||||
|
||||
// attempt to unmarshal either array or single object
|
||||
@@ -1127,49 +1136,207 @@ func findManifests(appPath string, repoRoot string, env *v1alpha1.Env, directory
|
||||
var jsonObj unstructured.Unstructured
|
||||
err = json.Unmarshal([]byte(jsonStr), &jsonObj)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.FailedPrecondition, "Failed to unmarshal generated json %q: %v", f.Name(), err)
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "Failed to unmarshal generated json %q: %v", manifestFileInfo.Name(), err)
|
||||
}
|
||||
objs = append(objs, &jsonObj)
|
||||
}
|
||||
} else {
|
||||
out, err := utfutil.ReadFile(path, utfutil.UTF8)
|
||||
err := getObjsFromYAMLOrJson(logCtx, manifestPath, manifestFileInfo.Name(), &objs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasSuffix(f.Name(), ".json") {
|
||||
var obj unstructured.Unstructured
|
||||
err = json.Unmarshal(out, &obj)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.FailedPrecondition, "Failed to unmarshal %q: %v", f.Name(), err)
|
||||
}
|
||||
objs = append(objs, &obj)
|
||||
} else {
|
||||
yamlObjs, err := kube.SplitYAML(out)
|
||||
if err != nil {
|
||||
if len(yamlObjs) > 0 {
|
||||
// If we get here, we had a multiple objects in a single YAML file which had some
|
||||
// valid k8s objects, but errors parsing others (within the same file). It's very
|
||||
// likely the user messed up a portion of the YAML, so report on that.
|
||||
return status.Errorf(codes.FailedPrecondition, "Failed to unmarshal %q: %v", f.Name(), err)
|
||||
}
|
||||
// Otherwise, let's see if it looks like a resource, if yes, we return error
|
||||
if bytes.Contains(out, []byte("apiVersion:")) &&
|
||||
bytes.Contains(out, []byte("kind:")) &&
|
||||
bytes.Contains(out, []byte("metadata:")) {
|
||||
return status.Errorf(codes.FailedPrecondition, "Failed to unmarshal %q: %v", f.Name(), err)
|
||||
}
|
||||
// Otherwise, it might be a unrelated YAML file which we will ignore
|
||||
return nil
|
||||
}
|
||||
objs = append(objs, yamlObjs...)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return objs, nil
|
||||
}
|
||||
|
||||
// getObjsFromYAMLOrJson unmarshals the given yaml or json file and appends it to the given list of objects.
|
||||
func getObjsFromYAMLOrJson(logCtx *log.Entry, manifestPath string, filename string, objs *[]*unstructured.Unstructured) error {
|
||||
reader, err := utfutil.OpenFile(manifestPath, utfutil.UTF8)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.FailedPrecondition, "Failed to open %q", manifestPath)
|
||||
}
|
||||
defer func() {
|
||||
err := reader.Close()
|
||||
if err != nil {
|
||||
logCtx.Errorf("failed to close %q - potential memory leak", manifestPath)
|
||||
}
|
||||
}()
|
||||
if strings.HasSuffix(filename, ".json") {
|
||||
var obj unstructured.Unstructured
|
||||
decoder := json.NewDecoder(reader)
|
||||
err = decoder.Decode(&obj)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.FailedPrecondition, "Failed to unmarshal %q: %v", filename, err)
|
||||
}
|
||||
if decoder.More() {
|
||||
return status.Errorf(codes.FailedPrecondition, "Found multiple objects in %q. Only single objects are allowed in JSON files.", filename)
|
||||
}
|
||||
*objs = append(*objs, &obj)
|
||||
} else {
|
||||
yamlObjs, err := splitYAMLOrJSON(reader)
|
||||
if err != nil {
|
||||
if len(yamlObjs) > 0 {
|
||||
// If we get here, we had a multiple objects in a single YAML file which had some
|
||||
// valid k8s objects, but errors parsing others (within the same file). It's very
|
||||
// likely the user messed up a portion of the YAML, so report on that.
|
||||
return status.Errorf(codes.FailedPrecondition, "Failed to unmarshal %q: %v", filename, err)
|
||||
}
|
||||
// Read the whole file to check whether it looks like a manifest.
|
||||
out, err := utfutil.ReadFile(manifestPath, utfutil.UTF8)
|
||||
// Otherwise, let's see if it looks like a resource, if yes, we return error
|
||||
if bytes.Contains(out, []byte("apiVersion:")) &&
|
||||
bytes.Contains(out, []byte("kind:")) &&
|
||||
bytes.Contains(out, []byte("metadata:")) {
|
||||
return status.Errorf(codes.FailedPrecondition, "Failed to unmarshal %q: %v", filename, err)
|
||||
}
|
||||
// Otherwise, it might be an unrelated YAML file which we will ignore
|
||||
}
|
||||
*objs = append(*objs, yamlObjs...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// splitYAMLOrJSON reads a YAML or JSON file and gets each document as an unstructured object. If the unmarshaller
|
||||
// encounters an error, objects read up until the error are returned.
|
||||
func splitYAMLOrJSON(reader goio.Reader) ([]*unstructured.Unstructured, error) {
|
||||
d := kubeyaml.NewYAMLOrJSONDecoder(reader, 4096)
|
||||
var objs []*unstructured.Unstructured
|
||||
for {
|
||||
u := &unstructured.Unstructured{}
|
||||
if err := d.Decode(&u); err != nil {
|
||||
if err == goio.EOF {
|
||||
break
|
||||
}
|
||||
return objs, fmt.Errorf("failed to unmarshal manifest: %v", err)
|
||||
}
|
||||
if u == nil {
|
||||
continue
|
||||
}
|
||||
objs = append(objs, u)
|
||||
}
|
||||
return objs, nil
|
||||
}
|
||||
|
||||
// getPotentiallyValidManifestFile checks whether the given path/FileInfo may be a valid manifest file. Returns a non-nil error if
|
||||
// there was an error that should not be handled by ignoring the file. Returns non-nil realFileInfo if the file is a
|
||||
// potential manifest. Returns a non-empty ignoreMessage if there's a message that should be logged about why the file
|
||||
// was skipped. If realFileInfo is nil and the ignoreMessage is empty, there's no need to log the ignoreMessage; the
|
||||
// file was skipped for a mundane reason.
|
||||
//
|
||||
// The file is still only a "potentially" valid manifest file because it could be invalid JSON or YAML, or it might not
|
||||
// be a valid Kubernetes resource. This function tests everything possible without actually reading the file.
|
||||
//
|
||||
// repoPath must be absolute.
|
||||
func getPotentiallyValidManifestFile(path string, f os.FileInfo, appPath, repoRoot, include, exclude string) (realFileInfo os.FileInfo, warning string, err error) {
|
||||
relPath, err := filepath.Rel(appPath, path)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("failed to get relative path of %q: %w", path, err)
|
||||
}
|
||||
|
||||
if !manifestFile.MatchString(f.Name()) {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
// If the file is a symlink, these will be overridden with the destination file's info.
|
||||
var relRealPath = relPath
|
||||
realFileInfo = f
|
||||
|
||||
if files.IsSymlink(f) {
|
||||
realPath, err := filepath.EvalSymlinks(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, fmt.Sprintf("destination of symlink %q is missing", relPath), nil
|
||||
}
|
||||
return nil, "", fmt.Errorf("failed to evaluate symlink at %q: %w", relPath, err)
|
||||
}
|
||||
if !files.Inbound(realPath, repoRoot) {
|
||||
return nil, "", fmt.Errorf("illegal filepath in symlink at %q", relPath)
|
||||
}
|
||||
realFileInfo, err = os.Stat(realPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// This should have been caught by filepath.EvalSymlinks, but check again since that function's docs
|
||||
// don't promise to return this error.
|
||||
return nil, fmt.Sprintf("destination of symlink %q is missing at %q", relPath, realPath), nil
|
||||
}
|
||||
return nil, "", fmt.Errorf("failed to get file info for symlink at %q to %q: %w", relPath, realPath, err)
|
||||
}
|
||||
relRealPath, err = filepath.Rel(repoRoot, realPath)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("failed to get relative path of %q: %w", realPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
// FileInfo.Size() behavior is platform-specific for non-regular files. Allow only regular files, so we guarantee
|
||||
// accurate file sizes.
|
||||
if !realFileInfo.Mode().IsRegular() {
|
||||
return nil, fmt.Sprintf("ignoring symlink at %q to non-regular file %q", relPath, relRealPath), nil
|
||||
}
|
||||
|
||||
if exclude != "" && glob.Match(exclude, relPath) {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
if include != "" && !glob.Match(include, relPath) {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
return realFileInfo, "", nil
|
||||
}
|
||||
|
||||
type potentiallyValidManifest struct {
|
||||
path string
|
||||
fileInfo os.FileInfo
|
||||
}
|
||||
|
||||
// getPotentiallyValidManifests ensures that 1) there are no errors while checking for potential manifest files in the given dir
|
||||
// and 2) the combined file size of the potentially-valid manifest files does not exceed the limit.
|
||||
func getPotentiallyValidManifests(logCtx *log.Entry, appPath string, repoRoot string, recurse bool, include string, exclude string, maxCombinedManifestQuantity resource.Quantity) ([]potentiallyValidManifest, error) {
|
||||
maxCombinedManifestFileSize := maxCombinedManifestQuantity.Value()
|
||||
var currentCombinedManifestFileSize = int64(0)
|
||||
|
||||
var potentiallyValidManifests []potentiallyValidManifest
|
||||
err := filepath.Walk(appPath, func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.IsDir() {
|
||||
if path != appPath && !recurse {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
realFileInfo, warning, err := getPotentiallyValidManifestFile(path, f, appPath, repoRoot, include, exclude)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid manifest file %q: %w", path, err)
|
||||
}
|
||||
if realFileInfo == nil {
|
||||
if warning != "" {
|
||||
logCtx.Warnf("skipping manifest file %q: %s", path, warning)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// Don't count jsonnet file size against max. It's jsonnet's responsibility to manage memory usage.
|
||||
if !strings.HasSuffix(f.Name(), ".jsonnet") {
|
||||
// We use the realFileInfo size (which is guaranteed to be a regular file instead of a symlink or other
|
||||
// non-regular file) because .Size() behavior is platform-specific for non-regular files.
|
||||
currentCombinedManifestFileSize += realFileInfo.Size()
|
||||
if maxCombinedManifestFileSize != 0 && currentCombinedManifestFileSize > maxCombinedManifestFileSize {
|
||||
return ErrExceededMaxCombinedManifestFileSize
|
||||
}
|
||||
}
|
||||
potentiallyValidManifests = append(potentiallyValidManifests, potentiallyValidManifest{path: path, fileInfo: f})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
// Not wrapping, because this error should be wrapped by the caller.
|
||||
return nil, err
|
||||
}
|
||||
return objs, nil
|
||||
|
||||
return potentiallyValidManifests, nil
|
||||
}
|
||||
|
||||
func makeJsonnetVm(appPath string, repoRoot string, sourceJsonnet v1alpha1.ApplicationSourceJsonnet, env *v1alpha1.Env) (*jsonnet.VM, error) {
|
||||
@@ -1252,7 +1419,7 @@ func runConfigManagementPlugin(appPath, repoRoot string, envVars *v1alpha1.Env,
|
||||
}
|
||||
}
|
||||
|
||||
env, err := getPluginEnvs(envVars, q, creds)
|
||||
env, err := getPluginEnvs(envVars, q, creds, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1270,8 +1437,14 @@ func runConfigManagementPlugin(appPath, repoRoot string, envVars *v1alpha1.Env,
|
||||
return kube.SplitYAML([]byte(out))
|
||||
}
|
||||
|
||||
func getPluginEnvs(envVars *v1alpha1.Env, q *apiclient.ManifestRequest, creds git.Creds) ([]string, error) {
|
||||
env := append(os.Environ(), envVars.Environ()...)
|
||||
func getPluginEnvs(envVars *v1alpha1.Env, q *apiclient.ManifestRequest, creds git.Creds, remote bool) ([]string, error) {
|
||||
env := envVars.Environ()
|
||||
// Local plugins need also to have access to the local environment variables.
|
||||
// Remote side car plugins will use the environment in the side car
|
||||
// container.
|
||||
if !remote {
|
||||
env = append(os.Environ(), env...)
|
||||
}
|
||||
if creds != nil {
|
||||
closer, environ, err := creds.Environ()
|
||||
if err != nil {
|
||||
@@ -1294,28 +1467,30 @@ func getPluginEnvs(envVars *v1alpha1.Env, q *apiclient.ManifestRequest, creds gi
|
||||
|
||||
if q.ApplicationSource.Plugin != nil {
|
||||
pluginEnv := q.ApplicationSource.Plugin.Env
|
||||
for i, j := range pluginEnv {
|
||||
pluginEnv[i].Value = parsedEnv.Envsubst(j.Value)
|
||||
for _, entry := range pluginEnv {
|
||||
newValue := parsedEnv.Envsubst(entry.Value)
|
||||
env = append(env, fmt.Sprintf("ARGOCD_ENV_%s=%s", entry.Name, newValue))
|
||||
}
|
||||
env = append(env, pluginEnv.Environ()...)
|
||||
}
|
||||
return env, nil
|
||||
}
|
||||
|
||||
func runConfigManagementPluginSidecars(ctx context.Context, appPath, repoPath string, envVars *v1alpha1.Env, q *apiclient.ManifestRequest, creds git.Creds, tarDoneCh chan<- bool) ([]*unstructured.Unstructured, error) {
|
||||
func runConfigManagementPluginSidecars(ctx context.Context, appPath, repoPath string, envVars *v1alpha1.Env, q *apiclient.ManifestRequest, creds git.Creds, tarDoneCh chan<- bool, tarExcludedGlobs []string) ([]*unstructured.Unstructured, error) {
|
||||
// compute variables.
|
||||
env, err := getPluginEnvs(envVars, q, creds, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// detect config management plugin server (sidecar)
|
||||
conn, cmpClient, err := discovery.DetectConfigManagementPlugin(ctx, appPath)
|
||||
conn, cmpClient, err := discovery.DetectConfigManagementPlugin(ctx, appPath, env, tarExcludedGlobs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer io.Close(conn)
|
||||
|
||||
// generate manifests using commands provided in plugin config file in detected cmp-server sidecar
|
||||
env, err := getPluginEnvs(envVars, q, creds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmpManifests, err := generateManifestsCMP(ctx, appPath, repoPath, env, cmpClient, tarDoneCh)
|
||||
cmpManifests, err := generateManifestsCMP(ctx, appPath, repoPath, env, cmpClient, tarDoneCh, tarExcludedGlobs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error generating manifests in cmp: %s", err)
|
||||
}
|
||||
@@ -1333,7 +1508,7 @@ func runConfigManagementPluginSidecars(ctx context.Context, appPath, repoPath st
|
||||
// generateManifestsCMP will send the appPath files to the cmp-server over a gRPC stream.
|
||||
// The cmp-server will generate the manifests. Returns a response object with the generated
|
||||
// manifests.
|
||||
func generateManifestsCMP(ctx context.Context, appPath, repoPath string, env []string, cmpClient pluginclient.ConfigManagementPluginServiceClient, tarDoneCh chan<- bool) (*pluginclient.ManifestResponse, error) {
|
||||
func generateManifestsCMP(ctx context.Context, appPath, repoPath string, env []string, cmpClient pluginclient.ConfigManagementPluginServiceClient, tarDoneCh chan<- bool, tarExcludedGlobs []string) (*pluginclient.ManifestResponse, error) {
|
||||
generateManifestStream, err := cmpClient.GenerateManifest(ctx, grpc_retry.Disable())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting generateManifestStream: %s", err)
|
||||
@@ -1341,7 +1516,7 @@ func generateManifestsCMP(ctx context.Context, appPath, repoPath string, env []s
|
||||
opts := []cmp.SenderOption{
|
||||
cmp.WithTarDoneChan(tarDoneCh),
|
||||
}
|
||||
err = cmp.SendRepoStream(generateManifestStream.Context(), appPath, repoPath, generateManifestStream, env, opts...)
|
||||
err = cmp.SendRepoStream(generateManifestStream.Context(), appPath, repoPath, generateManifestStream, env, tarExcludedGlobs, opts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error sending file to cmp-server: %s", err)
|
||||
}
|
||||
@@ -1359,7 +1534,7 @@ func (s *Service) GetAppDetails(ctx context.Context, q *apiclient.RepoServerAppD
|
||||
return err
|
||||
}
|
||||
|
||||
appSourceType, err := GetAppSourceType(ctx, q.Source, opContext.appPath, q.AppName, q.EnabledSourceTypes)
|
||||
appSourceType, err := GetAppSourceType(ctx, q.Source, opContext.appPath, q.AppName, q.EnabledSourceTypes, s.initConstants.CMPTarExcludedGlobs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1434,8 +1609,12 @@ func populateHelmAppDetails(res *apiclient.RepoAppDetailsResponse, appPath strin
|
||||
return err
|
||||
}
|
||||
|
||||
if err := loadFileIntoIfExists(filepath.Join(appPath, "values.yaml"), &res.Helm.Values); err != nil {
|
||||
return err
|
||||
if resolvedValuesPath, _, err := pathutil.ResolveFilePath(appPath, repoRoot, "values.yaml", []string{}); err == nil {
|
||||
if err := loadFileIntoIfExists(resolvedValuesPath, &res.Helm.Values); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Warnf("Values file %s is not allowed: %v", filepath.Join(appPath, "values.yaml"), err)
|
||||
}
|
||||
var resolvedSelectedValueFiles []pathutil.ResolvedFilePath
|
||||
// drop not allowed values files
|
||||
@@ -1443,10 +1622,10 @@ func populateHelmAppDetails(res *apiclient.RepoAppDetailsResponse, appPath strin
|
||||
if resolvedFile, _, err := pathutil.ResolveFilePath(appPath, repoRoot, file, q.GetValuesFileSchemes()); err == nil {
|
||||
resolvedSelectedValueFiles = append(resolvedSelectedValueFiles, resolvedFile)
|
||||
} else {
|
||||
log.Debugf("Values file %s is not allowed: %v", file, err)
|
||||
log.Warnf("Values file %s is not allowed: %v", file, err)
|
||||
}
|
||||
}
|
||||
params, err := h.GetParameters(resolvedSelectedValueFiles)
|
||||
params, err := h.GetParameters(resolvedSelectedValueFiles, appPath, repoRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1465,15 +1644,16 @@ func populateHelmAppDetails(res *apiclient.RepoAppDetailsResponse, appPath strin
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadFileIntoIfExists(path string, destination *string) error {
|
||||
info, err := os.Stat(path)
|
||||
func loadFileIntoIfExists(path pathutil.ResolvedFilePath, destination *string) error {
|
||||
stringPath := string(path)
|
||||
info, err := os.Stat(stringPath)
|
||||
|
||||
if err == nil && !info.IsDir() {
|
||||
if bytes, err := ioutil.ReadFile(path); err != nil {
|
||||
*destination = string(bytes)
|
||||
} else {
|
||||
bytes, err := ioutil.ReadFile(stringPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*destination = string(bytes)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
//go:build !race
|
||||
// +build !race
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
|
||||
)
|
||||
|
||||
func TestHelmDependencyWithConcurrency(t *testing.T) {
|
||||
|
||||
// !race:
|
||||
// Un-synchronized use of a random source, will be fixed when this is merged:
|
||||
// https://github.com/argoproj/argo-cd/issues/4728
|
||||
|
||||
cleanup := func() {
|
||||
_ = os.Remove(filepath.Join("../../util/helm/testdata/dependency", helmDepUpMarkerFile))
|
||||
_ = os.RemoveAll(filepath.Join("../../util/helm/testdata/dependency", "charts"))
|
||||
}
|
||||
cleanup()
|
||||
defer cleanup()
|
||||
|
||||
helmRepo := argoappv1.Repository{Name: "bitnami", Type: "helm", Repo: "https://charts.bitnami.com/bitnami"}
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(3)
|
||||
for i := 0; i < 3; i++ {
|
||||
go func() {
|
||||
res, err := helmTemplate("../../util/helm/testdata/dependency", "../..", nil, &apiclient.ManifestRequest{
|
||||
ApplicationSource: &argoappv1.ApplicationSource{},
|
||||
Repos: []*argoappv1.Repository{&helmRepo},
|
||||
}, false)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
goio "io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -16,6 +17,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
@@ -129,6 +133,31 @@ func newServiceWithCommitSHA(root, revision string) *Service {
|
||||
return service
|
||||
}
|
||||
|
||||
// createSymlink creates a symlink with name linkName to file destName in
|
||||
// workingDir
|
||||
func createSymlink(t *testing.T, workingDir, destName, linkName string) error {
|
||||
oldWorkingDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if workingDir != "" {
|
||||
err = os.Chdir(workingDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Chdir(oldWorkingDir); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
err = os.Symlink(destName, linkName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestGenerateYamlManifestInDir(t *testing.T) {
|
||||
service := newService("../..")
|
||||
|
||||
@@ -136,7 +165,7 @@ func TestGenerateYamlManifestInDir(t *testing.T) {
|
||||
q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src}
|
||||
|
||||
// update this value if we add/remove manifests
|
||||
const countOfManifests = 46
|
||||
const countOfManifests = 47
|
||||
|
||||
res1, err := service.GenerateManifest(context.Background(), &q)
|
||||
|
||||
@@ -144,11 +173,81 @@ func TestGenerateYamlManifestInDir(t *testing.T) {
|
||||
assert.Equal(t, countOfManifests, len(res1.Manifests))
|
||||
|
||||
// this will test concatenated manifests to verify we split YAMLs correctly
|
||||
res2, err := GenerateManifests(context.Background(), "./testdata/concatenated", "/", "", &q, false, &git.NoopCredsStore{})
|
||||
res2, err := GenerateManifests(context.Background(), "./testdata/concatenated", "/", "", &q, false, &git.NoopCredsStore{}, resource.MustParse("0"))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 3, len(res2.Manifests))
|
||||
}
|
||||
|
||||
func Test_GenerateManifests_NoOutOfBoundsAccess(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
outOfBoundsFilename string
|
||||
outOfBoundsFileContents string
|
||||
mustNotContain string // Optional string that must not appear in error or manifest output. If empty, use outOfBoundsFileContents.
|
||||
}{
|
||||
{
|
||||
name: "out of bounds JSON file should not appear in error output",
|
||||
outOfBoundsFilename: "test.json",
|
||||
outOfBoundsFileContents: `{"some": "json"}`,
|
||||
},
|
||||
{
|
||||
name: "malformed JSON file contents should not appear in error output",
|
||||
outOfBoundsFilename: "test.json",
|
||||
outOfBoundsFileContents: "$",
|
||||
},
|
||||
{
|
||||
name: "out of bounds JSON manifest should not appear in manifest output",
|
||||
outOfBoundsFilename: "test.json",
|
||||
// JSON marshalling is deterministic. So if there's a leak, exactly this should appear in the manifests.
|
||||
outOfBoundsFileContents: `{"apiVersion":"v1","kind":"Secret","metadata":{"name":"test","namespace":"default"},"type":"Opaque"}`,
|
||||
},
|
||||
{
|
||||
name: "out of bounds YAML manifest should not appear in manifest output",
|
||||
outOfBoundsFilename: "test.yaml",
|
||||
outOfBoundsFileContents: "apiVersion: v1\nkind: Secret\nmetadata:\n name: test\n namespace: default\ntype: Opaque",
|
||||
mustNotContain: `{"apiVersion":"v1","kind":"Secret","metadata":{"name":"test","namespace":"default"},"type":"Opaque"}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
testCaseCopy := testCase
|
||||
t.Run(testCaseCopy.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
outOfBoundsDir := t.TempDir()
|
||||
outOfBoundsFile := path.Join(outOfBoundsDir, testCaseCopy.outOfBoundsFilename)
|
||||
err := os.WriteFile(outOfBoundsFile, []byte(testCaseCopy.outOfBoundsFileContents), os.FileMode(0444))
|
||||
require.NoError(t, err)
|
||||
|
||||
repoDir := t.TempDir()
|
||||
err = os.Symlink(outOfBoundsFile, path.Join(repoDir, testCaseCopy.outOfBoundsFilename))
|
||||
require.NoError(t, err)
|
||||
|
||||
var mustNotContain = testCaseCopy.outOfBoundsFileContents
|
||||
if testCaseCopy.mustNotContain != "" {
|
||||
mustNotContain = testCaseCopy.mustNotContain
|
||||
}
|
||||
|
||||
q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &argoappv1.ApplicationSource{}}
|
||||
res, err := GenerateManifests(context.Background(), repoDir, "", "", &q, false, &git.NoopCredsStore{}, resource.MustParse("0"))
|
||||
require.Error(t, err)
|
||||
assert.NotContains(t, err.Error(), mustNotContain)
|
||||
assert.Contains(t, err.Error(), "illegal filepath")
|
||||
assert.Nil(t, res)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateManifests_MissingSymlinkDestination(t *testing.T) {
|
||||
repoDir := t.TempDir()
|
||||
err := os.Symlink("/obviously/does/not/exist", path.Join(repoDir, "test.yaml"))
|
||||
require.NoError(t, err)
|
||||
|
||||
q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &argoappv1.ApplicationSource{}}
|
||||
_, err = GenerateManifests(context.Background(), repoDir, "", "", &q, false, &git.NoopCredsStore{}, resource.MustParse("0"))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGenerateManifests_K8SAPIResetCache(t *testing.T) {
|
||||
service := newService("../..")
|
||||
|
||||
@@ -283,28 +382,6 @@ func TestGenerateJsonnetLibOutside(t *testing.T) {
|
||||
require.Contains(t, err.Error(), "value file '../../../testdata/jsonnet/vendor' resolved to outside repository root")
|
||||
}
|
||||
|
||||
func TestGenerateHelmChartWithDependencies(t *testing.T) {
|
||||
service := newService("../..")
|
||||
|
||||
cleanup := func() {
|
||||
_ = os.Remove(filepath.Join("../../util/helm/testdata/dependency", helmDepUpMarkerFile))
|
||||
_ = os.RemoveAll(filepath.Join("../../util/helm/testdata/dependency", "charts"))
|
||||
}
|
||||
cleanup()
|
||||
defer cleanup()
|
||||
|
||||
helmRepo := argoappv1.Repository{Name: "bitnami", Type: "helm", Repo: "https://charts.bitnami.com/bitnami"}
|
||||
q := apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: "./util/helm/testdata/dependency",
|
||||
},
|
||||
Repos: []*argoappv1.Repository{&helmRepo},
|
||||
}
|
||||
res1, err := service.GenerateManifest(context.Background(), &q)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, res1.Manifests, 10)
|
||||
}
|
||||
func TestManifestGenErrorCacheByNumRequests(t *testing.T) {
|
||||
|
||||
// Returns the state of the manifest generation cache, by querying the cache for the previously set result
|
||||
@@ -997,15 +1074,15 @@ func TestGenerateNullList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIdentifyAppSourceTypeByAppDirWithKustomizations(t *testing.T) {
|
||||
sourceType, err := GetAppSourceType(context.Background(), &argoappv1.ApplicationSource{}, "./testdata/kustomization_yaml", "testapp", map[string]bool{})
|
||||
sourceType, err := GetAppSourceType(context.Background(), &argoappv1.ApplicationSource{}, "./testdata/kustomization_yaml", "testapp", map[string]bool{}, []string{})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, argoappv1.ApplicationSourceTypeKustomize, sourceType)
|
||||
|
||||
sourceType, err = GetAppSourceType(context.Background(), &argoappv1.ApplicationSource{}, "./testdata/kustomization_yml", "testapp", map[string]bool{})
|
||||
sourceType, err = GetAppSourceType(context.Background(), &argoappv1.ApplicationSource{}, "./testdata/kustomization_yml", "testapp", map[string]bool{}, []string{})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, argoappv1.ApplicationSourceTypeKustomize, sourceType)
|
||||
|
||||
sourceType, err = GetAppSourceType(context.Background(), &argoappv1.ApplicationSource{}, "./testdata/Kustomization", "testapp", map[string]bool{})
|
||||
sourceType, err = GetAppSourceType(context.Background(), &argoappv1.ApplicationSource{}, "./testdata/Kustomization", "testapp", map[string]bool{}, []string{})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, argoappv1.ApplicationSourceTypeKustomize, sourceType)
|
||||
}
|
||||
@@ -1031,7 +1108,7 @@ func TestRunCustomTool(t *testing.T) {
|
||||
Name: "test",
|
||||
Generate: argoappv1.Command{
|
||||
Command: []string{"sh", "-c"},
|
||||
Args: []string{`echo "{\"kind\": \"FakeObject\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"GIT_ASKPASS\": \"$GIT_ASKPASS\", \"GIT_USERNAME\": \"$GIT_USERNAME\", \"GIT_PASSWORD\": \"$GIT_PASSWORD\"}, \"labels\": {\"revision\": \"$TEST_REVISION\"}}}"`},
|
||||
Args: []string{`echo "{\"kind\": \"FakeObject\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"GIT_ASKPASS\": \"$GIT_ASKPASS\", \"GIT_USERNAME\": \"$GIT_USERNAME\", \"GIT_PASSWORD\": \"$GIT_PASSWORD\"}, \"labels\": {\"revision\": \"$ARGOCD_ENV_TEST_REVISION\"}}}"`},
|
||||
},
|
||||
}},
|
||||
Repo: &argoappv1.Repository{
|
||||
@@ -1058,7 +1135,7 @@ func TestGenerateFromUTF16(t *testing.T) {
|
||||
Repo: &argoappv1.Repository{},
|
||||
ApplicationSource: &argoappv1.ApplicationSource{},
|
||||
}
|
||||
res1, err := GenerateManifests(context.Background(), "./testdata/utf-16", "/", "", &q, false, &git.NoopCredsStore{})
|
||||
res1, err := GenerateManifests(context.Background(), "./testdata/utf-16", "/", "", &q, false, &git.NoopCredsStore{}, resource.MustParse("0"))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 2, len(res1.Manifests))
|
||||
}
|
||||
@@ -1070,16 +1147,20 @@ func TestListApps(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
expectedApps := map[string]string{
|
||||
"Kustomization": "Kustomize",
|
||||
"app-parameters/multi": "Kustomize",
|
||||
"app-parameters/single-app-only": "Kustomize",
|
||||
"app-parameters/single-global": "Kustomize",
|
||||
"invalid-helm": "Helm",
|
||||
"invalid-kustomize": "Kustomize",
|
||||
"kustomization_yaml": "Kustomize",
|
||||
"kustomization_yml": "Kustomize",
|
||||
"my-chart": "Helm",
|
||||
"my-chart-2": "Helm",
|
||||
"Kustomization": "Kustomize",
|
||||
"app-parameters/multi": "Kustomize",
|
||||
"app-parameters/single-app-only": "Kustomize",
|
||||
"app-parameters/single-global": "Kustomize",
|
||||
"app-parameters/single-global-helm": "Helm",
|
||||
"invalid-helm": "Helm",
|
||||
"in-bounds-values-file-link": "Helm",
|
||||
"invalid-kustomize": "Kustomize",
|
||||
"kustomization_yaml": "Kustomize",
|
||||
"kustomization_yml": "Kustomize",
|
||||
"my-chart": "Helm",
|
||||
"my-chart-2": "Helm",
|
||||
"out-of-bounds-values-file-link": "Helm",
|
||||
"values-files": "Helm",
|
||||
}
|
||||
assert.Equal(t, expectedApps, res.Apps)
|
||||
}
|
||||
@@ -1398,6 +1479,7 @@ func mkTempParameters(source string) string {
|
||||
func runWithTempTestdata(t *testing.T, path string, runner func(t *testing.T, path string)) {
|
||||
tempDir := mkTempParameters("./testdata/app-parameters")
|
||||
runner(t, filepath.Join(tempDir, "app-parameters", path))
|
||||
os.RemoveAll(tempDir)
|
||||
}
|
||||
|
||||
func TestGenerateManifestsWithAppParameterFile(t *testing.T) {
|
||||
@@ -1430,6 +1512,35 @@ func TestGenerateManifestsWithAppParameterFile(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Single global override Helm", func(t *testing.T) {
|
||||
runWithTempTestdata(t, "single-global-helm", func(t *testing.T, path string) {
|
||||
service := newService(".")
|
||||
manifests, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: path,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
resourceByKindName := make(map[string]*unstructured.Unstructured)
|
||||
for _, manifest := range manifests.Manifests {
|
||||
var un unstructured.Unstructured
|
||||
err := yaml.Unmarshal([]byte(manifest), &un)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
resourceByKindName[fmt.Sprintf("%s/%s", un.GetKind(), un.GetName())] = &un
|
||||
}
|
||||
deployment, ok := resourceByKindName["Deployment/guestbook-ui"]
|
||||
require.True(t, ok)
|
||||
containers, ok, _ := unstructured.NestedSlice(deployment.Object, "spec", "template", "spec", "containers")
|
||||
require.True(t, ok)
|
||||
image, ok, _ := unstructured.NestedString(containers[0].(map[string]interface{}), "image")
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, "gcr.io/heptio-images/ks-guestbook-demo:0.2", image)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Application specific override", func(t *testing.T) {
|
||||
service := newService(".")
|
||||
runWithTempTestdata(t, "single-app-only", func(t *testing.T, path string) {
|
||||
@@ -1489,6 +1600,28 @@ func TestGenerateManifestsWithAppParameterFile(t *testing.T) {
|
||||
assert.Equal(t, "gcr.io/heptio-images/ks-guestbook-demo:0.1", image)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Override info does not appear in cache key", func(t *testing.T) {
|
||||
service := newService(".")
|
||||
runWithTempTestdata(t, "single-global", func(t *testing.T, path string) {
|
||||
source := &argoappv1.ApplicationSource{
|
||||
Path: path,
|
||||
}
|
||||
sourceCopy := source.DeepCopy() // make a copy in case GenerateManifest mutates it.
|
||||
_, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
ApplicationSource: sourceCopy,
|
||||
AppName: "test",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
res := &cache.CachedManifestResponse{}
|
||||
// Try to pull from the cache with a `source` that does not include any overrides. Overrides should not be
|
||||
// part of the cache key, because you can't get the overrides without a repo operation. And avoiding repo
|
||||
// operations is the point of the cache.
|
||||
err = service.cache.GetManifests(mock.Anything, source, &argoappv1.ClusterInfo{}, "", "", "", "test", res)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenerateManifestWithAnnotatedAndRegularGitTagHashes(t *testing.T) {
|
||||
@@ -1599,11 +1732,11 @@ func TestFindResources(t *testing.T) {
|
||||
for i := range testCases {
|
||||
tc := testCases[i]
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
objs, err := findManifests("testdata/app-include-exclude", ".", nil, argoappv1.ApplicationSourceDirectory{
|
||||
objs, err := findManifests(&log.Entry{}, "testdata/app-include-exclude", ".", nil, argoappv1.ApplicationSourceDirectory{
|
||||
Recurse: true,
|
||||
Include: tc.include,
|
||||
Exclude: tc.exclude,
|
||||
}, map[string]bool{})
|
||||
}, map[string]bool{}, resource.MustParse("0"))
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
@@ -1617,10 +1750,10 @@ func TestFindResources(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFindManifests_Exclude(t *testing.T) {
|
||||
objs, err := findManifests("testdata/app-include-exclude", ".", nil, argoappv1.ApplicationSourceDirectory{
|
||||
objs, err := findManifests(&log.Entry{}, "testdata/app-include-exclude", ".", nil, argoappv1.ApplicationSourceDirectory{
|
||||
Recurse: true,
|
||||
Exclude: "subdir/deploymentSub.yaml",
|
||||
}, map[string]bool{})
|
||||
}, map[string]bool{}, resource.MustParse("0"))
|
||||
|
||||
if !assert.NoError(t, err) || !assert.Len(t, objs, 1) {
|
||||
return
|
||||
@@ -1630,10 +1763,10 @@ func TestFindManifests_Exclude(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFindManifests_Exclude_NothingMatches(t *testing.T) {
|
||||
objs, err := findManifests("testdata/app-include-exclude", ".", nil, argoappv1.ApplicationSourceDirectory{
|
||||
objs, err := findManifests(&log.Entry{}, "testdata/app-include-exclude", ".", nil, argoappv1.ApplicationSourceDirectory{
|
||||
Recurse: true,
|
||||
Exclude: "nothing.yaml",
|
||||
}, map[string]bool{})
|
||||
}, map[string]bool{}, resource.MustParse("0"))
|
||||
|
||||
if !assert.NoError(t, err) || !assert.Len(t, objs, 2) {
|
||||
return
|
||||
@@ -1643,6 +1776,477 @@ func TestFindManifests_Exclude_NothingMatches(t *testing.T) {
|
||||
[]string{"nginx-deployment", "nginx-deployment-sub"}, []string{objs[0].GetName(), objs[1].GetName()})
|
||||
}
|
||||
|
||||
func tempDir(t *testing.T) string {
|
||||
dir, err := ioutil.TempDir(".", "")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
err = os.RemoveAll(dir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
absDir, err := filepath.Abs(dir)
|
||||
require.NoError(t, err)
|
||||
return absDir
|
||||
}
|
||||
|
||||
func walkFor(t *testing.T, root string, testPath string, run func(info fs.FileInfo)) {
|
||||
var hitExpectedPath = false
|
||||
err := filepath.Walk(root, func(path string, info fs.FileInfo, err error) error {
|
||||
if path == testPath {
|
||||
require.NoError(t, err)
|
||||
hitExpectedPath = true
|
||||
run(info)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.True(t, hitExpectedPath, "did not hit expected path when walking directory")
|
||||
}
|
||||
|
||||
func Test_getPotentiallyValidManifestFile(t *testing.T) {
|
||||
// These tests use filepath.Walk instead of os.Stat to get file info, because FileInfo from os.Stat does not return
|
||||
// true for IsSymlink like os.Walk does.
|
||||
|
||||
// These tests do not use t.TempDir() because those directories can contain symlinks which cause test to fail
|
||||
// InBound checks.
|
||||
|
||||
t.Run("non-JSON/YAML is skipped with an empty ignore message", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
filePath := filepath.Join(appDir, "not-json-or-yaml")
|
||||
file, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0644)
|
||||
require.NoError(t, err)
|
||||
err = file.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, filePath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(filePath, info, appDir, appDir, "", "")
|
||||
assert.Nil(t, realFileInfo)
|
||||
assert.Empty(t, ignoreMessage)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("circular link should throw an error", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
|
||||
aPath := filepath.Join(appDir, "a.json")
|
||||
bPath := filepath.Join(appDir, "b.json")
|
||||
err := os.Symlink(bPath, aPath)
|
||||
require.NoError(t, err)
|
||||
err = os.Symlink(aPath, bPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, aPath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(aPath, info, appDir, appDir, "", "")
|
||||
assert.Nil(t, realFileInfo)
|
||||
assert.Empty(t, ignoreMessage)
|
||||
assert.ErrorContains(t, err, "too many links")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("symlink with missing destination should throw an error", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
|
||||
aPath := filepath.Join(appDir, "a.json")
|
||||
bPath := filepath.Join(appDir, "b.json")
|
||||
err := os.Symlink(bPath, aPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, aPath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(aPath, info, appDir, appDir, "", "")
|
||||
assert.Nil(t, realFileInfo)
|
||||
assert.NotEmpty(t, ignoreMessage)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("out-of-bounds symlink should throw an error", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
|
||||
linkPath := filepath.Join(appDir, "a.json")
|
||||
err := os.Symlink("..", linkPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, linkPath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(linkPath, info, appDir, appDir, "", "")
|
||||
assert.Nil(t, realFileInfo)
|
||||
assert.Empty(t, ignoreMessage)
|
||||
assert.ErrorContains(t, err, "illegal filepath in symlink")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("symlink to a non-regular file should be skipped with warning", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
|
||||
dirPath := filepath.Join(appDir, "test.dir")
|
||||
err := os.MkdirAll(dirPath, 0644)
|
||||
require.NoError(t, err)
|
||||
linkPath := filepath.Join(appDir, "test.json")
|
||||
err = os.Symlink(dirPath, linkPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, linkPath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(linkPath, info, appDir, appDir, "", "")
|
||||
assert.Nil(t, realFileInfo)
|
||||
assert.Contains(t, ignoreMessage, "non-regular file")
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("non-included file should be skipped with no message", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
|
||||
filePath := filepath.Join(appDir, "not-included.yaml")
|
||||
file, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0644)
|
||||
require.NoError(t, err)
|
||||
err = file.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, filePath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(filePath, info, appDir, appDir, "*.json", "")
|
||||
assert.Nil(t, realFileInfo)
|
||||
assert.Empty(t, ignoreMessage)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("excluded file should be skipped with no message", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
|
||||
filePath := filepath.Join(appDir, "excluded.json")
|
||||
file, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0644)
|
||||
require.NoError(t, err)
|
||||
err = file.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, filePath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(filePath, info, appDir, appDir, "", "excluded.*")
|
||||
assert.Nil(t, realFileInfo)
|
||||
assert.Empty(t, ignoreMessage)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("symlink to a regular file is potentially valid", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
|
||||
filePath := filepath.Join(appDir, "regular-file")
|
||||
file, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0644)
|
||||
require.NoError(t, err)
|
||||
err = file.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
linkPath := filepath.Join(appDir, "link.json")
|
||||
err = os.Symlink(filePath, linkPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, linkPath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(linkPath, info, appDir, appDir, "", "")
|
||||
assert.NotNil(t, realFileInfo)
|
||||
assert.Empty(t, ignoreMessage)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("a regular file is potentially valid", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
|
||||
filePath := filepath.Join(appDir, "regular-file.json")
|
||||
file, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0644)
|
||||
require.NoError(t, err)
|
||||
err = file.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, filePath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(filePath, info, appDir, appDir, "", "")
|
||||
assert.NotNil(t, realFileInfo)
|
||||
assert.Empty(t, ignoreMessage)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("realFileInfo is for the destination rather than the symlink", func(t *testing.T) {
|
||||
appDir := tempDir(t)
|
||||
|
||||
filePath := filepath.Join(appDir, "regular-file")
|
||||
file, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0644)
|
||||
require.NoError(t, err)
|
||||
err = file.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
linkPath := filepath.Join(appDir, "link.json")
|
||||
err = os.Symlink(filePath, linkPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
walkFor(t, appDir, linkPath, func(info fs.FileInfo) {
|
||||
realFileInfo, ignoreMessage, err := getPotentiallyValidManifestFile(linkPath, info, appDir, appDir, "", "")
|
||||
assert.NotNil(t, realFileInfo)
|
||||
assert.Equal(t, filepath.Base(filePath), realFileInfo.Name())
|
||||
assert.Empty(t, ignoreMessage)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_getPotentiallyValidManifests(t *testing.T) {
|
||||
// Tests which return no manifests and an error check to make sure the directory exists before running. A missing
|
||||
// directory would produce those same results.
|
||||
|
||||
logCtx := log.WithField("test", "test")
|
||||
|
||||
t.Run("unreadable file throws error", func(t *testing.T) {
|
||||
appDir := t.TempDir()
|
||||
unreadablePath := filepath.Join(appDir, "unreadable.json")
|
||||
err := os.WriteFile(unreadablePath, []byte{}, 0666)
|
||||
require.NoError(t, err)
|
||||
err = os.Chmod(appDir, 0000)
|
||||
require.NoError(t, err)
|
||||
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, appDir, appDir, false, "", "", resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
|
||||
// allow cleanup
|
||||
err = os.Chmod(appDir, 0777)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no recursion when recursion is disabled", func(t *testing.T) {
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, "./testdata/recurse", "./testdata/recurse", false, "", "", resource.MustParse("0"))
|
||||
assert.Len(t, manifests, 1)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("recursion when recursion is enabled", func(t *testing.T) {
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, "./testdata/recurse", "./testdata/recurse", true, "", "", resource.MustParse("0"))
|
||||
assert.Len(t, manifests, 2)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("non-JSON/YAML is skipped", func(t *testing.T) {
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, "./testdata/non-manifest-file", "./testdata/non-manifest-file", false, "", "", resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("circular link should throw an error", func(t *testing.T) {
|
||||
const testDir = "./testdata/circular-link"
|
||||
require.DirExists(t, testDir)
|
||||
require.NoError(t, createSymlink(t, testDir, "a.json", "b.json"))
|
||||
defer os.Remove(path.Join(testDir, "a.json"))
|
||||
require.NoError(t, createSymlink(t, testDir, "b.json", "a.json"))
|
||||
defer os.Remove(path.Join(testDir, "b.json"))
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, "./testdata/circular-link", "./testdata/circular-link", false, "", "", resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("out-of-bounds symlink should throw an error", func(t *testing.T) {
|
||||
require.DirExists(t, "./testdata/out-of-bounds-link")
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, "./testdata/out-of-bounds-link", "./testdata/out-of-bounds-link", false, "", "", resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("symlink to a regular file works", func(t *testing.T) {
|
||||
repoRoot, err := filepath.Abs("./testdata/in-bounds-link")
|
||||
require.NoError(t, err)
|
||||
appPath, err := filepath.Abs("./testdata/in-bounds-link/app")
|
||||
require.NoError(t, err)
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, appPath, repoRoot, false, "", "", resource.MustParse("0"))
|
||||
assert.Len(t, manifests, 1)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("symlink to nowhere should be ignored", func(t *testing.T) {
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, "./testdata/link-to-nowhere", "./testdata/link-to-nowhere", false, "", "", resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("link to over-sized manifest fails", func(t *testing.T) {
|
||||
repoRoot, err := filepath.Abs("./testdata/in-bounds-link")
|
||||
require.NoError(t, err)
|
||||
appPath, err := filepath.Abs("./testdata/in-bounds-link/app")
|
||||
require.NoError(t, err)
|
||||
// The file is 35 bytes.
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, appPath, repoRoot, false, "", "", resource.MustParse("34"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.ErrorIs(t, err, ErrExceededMaxCombinedManifestFileSize)
|
||||
})
|
||||
|
||||
t.Run("group of files should be limited at precisely the sum of their size", func(t *testing.T) {
|
||||
// There is a total of 10 files, ech file being 10 bytes.
|
||||
manifests, err := getPotentiallyValidManifests(logCtx, "./testdata/several-files", "./testdata/several-files", false, "", "", resource.MustParse("365"))
|
||||
assert.Len(t, manifests, 10)
|
||||
assert.NoError(t, err)
|
||||
|
||||
manifests, err = getPotentiallyValidManifests(logCtx, "./testdata/several-files", "./testdata/several-files", false, "", "", resource.MustParse("100"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.ErrorIs(t, err, ErrExceededMaxCombinedManifestFileSize)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_findManifests(t *testing.T) {
|
||||
logCtx := log.WithField("test", "test")
|
||||
noRecurse := argoappv1.ApplicationSourceDirectory{Recurse: false}
|
||||
|
||||
t.Run("unreadable file throws error", func(t *testing.T) {
|
||||
appDir := t.TempDir()
|
||||
unreadablePath := filepath.Join(appDir, "unreadable.json")
|
||||
err := os.WriteFile(unreadablePath, []byte{}, 0666)
|
||||
require.NoError(t, err)
|
||||
err = os.Chmod(appDir, 0000)
|
||||
require.NoError(t, err)
|
||||
|
||||
manifests, err := findManifests(logCtx, appDir, appDir, nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
|
||||
// allow cleanup
|
||||
err = os.Chmod(appDir, 0777)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no recursion when recursion is disabled", func(t *testing.T) {
|
||||
manifests, err := findManifests(logCtx, "./testdata/recurse", "./testdata/recurse", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Len(t, manifests, 2)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("recursion when recursion is enabled", func(t *testing.T) {
|
||||
recurse := argoappv1.ApplicationSourceDirectory{Recurse: true}
|
||||
manifests, err := findManifests(logCtx, "./testdata/recurse", "./testdata/recurse", nil, recurse, nil, resource.MustParse("0"))
|
||||
assert.Len(t, manifests, 4)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("non-JSON/YAML is skipped", func(t *testing.T) {
|
||||
manifests, err := findManifests(logCtx, "./testdata/non-manifest-file", "./testdata/non-manifest-file", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("circular link should throw an error", func(t *testing.T) {
|
||||
const testDir = "./testdata/circular-link"
|
||||
require.DirExists(t, testDir)
|
||||
require.NoError(t, createSymlink(t, testDir, "a.json", "b.json"))
|
||||
defer os.Remove(path.Join(testDir, "a.json"))
|
||||
require.NoError(t, createSymlink(t, testDir, "b.json", "a.json"))
|
||||
defer os.Remove(path.Join(testDir, "b.json"))
|
||||
manifests, err := findManifests(logCtx, "./testdata/circular-link", "./testdata/circular-link", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("out-of-bounds symlink should throw an error", func(t *testing.T) {
|
||||
require.DirExists(t, "./testdata/out-of-bounds-link")
|
||||
manifests, err := findManifests(logCtx, "./testdata/out-of-bounds-link", "./testdata/out-of-bounds-link", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("symlink to a regular file works", func(t *testing.T) {
|
||||
repoRoot, err := filepath.Abs("./testdata/in-bounds-link")
|
||||
require.NoError(t, err)
|
||||
appPath, err := filepath.Abs("./testdata/in-bounds-link/app")
|
||||
require.NoError(t, err)
|
||||
manifests, err := findManifests(logCtx, appPath, repoRoot, nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Len(t, manifests, 1)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("symlink to nowhere should be ignored", func(t *testing.T) {
|
||||
manifests, err := findManifests(logCtx, "./testdata/link-to-nowhere", "./testdata/link-to-nowhere", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("link to over-sized manifest fails", func(t *testing.T) {
|
||||
repoRoot, err := filepath.Abs("./testdata/in-bounds-link")
|
||||
require.NoError(t, err)
|
||||
appPath, err := filepath.Abs("./testdata/in-bounds-link/app")
|
||||
require.NoError(t, err)
|
||||
// The file is 35 bytes.
|
||||
manifests, err := findManifests(logCtx, appPath, repoRoot, nil, noRecurse, nil, resource.MustParse("34"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.ErrorIs(t, err, ErrExceededMaxCombinedManifestFileSize)
|
||||
})
|
||||
|
||||
t.Run("group of files should be limited at precisely the sum of their size", func(t *testing.T) {
|
||||
// There is a total of 10 files, each file being 10 bytes.
|
||||
manifests, err := findManifests(logCtx, "./testdata/several-files", "./testdata/several-files", nil, noRecurse, nil, resource.MustParse("365"))
|
||||
assert.Len(t, manifests, 10)
|
||||
assert.NoError(t, err)
|
||||
|
||||
manifests, err = findManifests(logCtx, "./testdata/several-files", "./testdata/several-files", nil, noRecurse, nil, resource.MustParse("364"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.ErrorIs(t, err, ErrExceededMaxCombinedManifestFileSize)
|
||||
})
|
||||
|
||||
t.Run("jsonnet isn't counted against size limit", func(t *testing.T) {
|
||||
// Each file is 36 bytes. Only the 36-byte json file should be counted against the limit.
|
||||
manifests, err := findManifests(logCtx, "./testdata/jsonnet-and-json", "./testdata/jsonnet-and-json", nil, noRecurse, nil, resource.MustParse("36"))
|
||||
assert.Len(t, manifests, 2)
|
||||
assert.NoError(t, err)
|
||||
|
||||
manifests, err = findManifests(logCtx, "./testdata/jsonnet-and-json", "./testdata/jsonnet-and-json", nil, noRecurse, nil, resource.MustParse("35"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.ErrorIs(t, err, ErrExceededMaxCombinedManifestFileSize)
|
||||
})
|
||||
|
||||
t.Run("partially valid YAML file throws an error", func(t *testing.T) {
|
||||
require.DirExists(t, "./testdata/partially-valid-yaml")
|
||||
manifests, err := findManifests(logCtx, "./testdata/partially-valid-yaml", "./testdata/partially-valid-yaml", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("invalid manifest throws an error", func(t *testing.T) {
|
||||
require.DirExists(t, "./testdata/invalid-manifests")
|
||||
manifests, err := findManifests(logCtx, "./testdata/invalid-manifests", "./testdata/invalid-manifests", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("irrelevant YAML gets skipped, relevant YAML gets parsed", func(t *testing.T) {
|
||||
manifests, err := findManifests(logCtx, "./testdata/irrelevant-yaml", "./testdata/irrelevant-yaml", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Len(t, manifests, 1)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("multiple JSON objects in one file throws an error", func(t *testing.T) {
|
||||
require.DirExists(t, "./testdata/json-list")
|
||||
manifests, err := findManifests(logCtx, "./testdata/json-list", "./testdata/json-list", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("invalid JSON throws an error", func(t *testing.T) {
|
||||
require.DirExists(t, "./testdata/invalid-json")
|
||||
manifests, err := findManifests(logCtx, "./testdata/invalid-json", "./testdata/invalid-json", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Empty(t, manifests)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("valid JSON returns manifest and no error", func(t *testing.T) {
|
||||
manifests, err := findManifests(logCtx, "./testdata/valid-json", "./testdata/valid-json", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Len(t, manifests, 1)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("YAML with an empty document doesn't throw an error", func(t *testing.T) {
|
||||
manifests, err := findManifests(logCtx, "./testdata/yaml-with-empty-document", "./testdata/yaml-with-empty-document", nil, noRecurse, nil, resource.MustParse("0"))
|
||||
assert.Len(t, manifests, 1)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTestRepoOCI(t *testing.T) {
|
||||
service := newService(".")
|
||||
_, err := service.TestRepository(context.Background(), &apiclient.TestRepositoryRequest{
|
||||
@@ -1825,3 +2429,52 @@ func runGit(t *testing.T, workDir string, args ...string) string {
|
||||
require.NoError(t, err, stringOut)
|
||||
return stringOut
|
||||
}
|
||||
|
||||
func Test_findHelmValueFilesInPath(t *testing.T) {
|
||||
t.Run("does not exist", func(t *testing.T) {
|
||||
files, err := findHelmValueFilesInPath("/obviously/does/not/exist")
|
||||
assert.Error(t, err)
|
||||
assert.Empty(t, files)
|
||||
})
|
||||
t.Run("values files", func(t *testing.T) {
|
||||
files, err := findHelmValueFilesInPath("./testdata/values-files")
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, files, 4)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_populateHelmAppDetails(t *testing.T) {
|
||||
res := apiclient.RepoAppDetailsResponse{}
|
||||
q := apiclient.RepoServerAppDetailsQuery{
|
||||
Repo: &argoappv1.Repository{},
|
||||
Source: &argoappv1.ApplicationSource{
|
||||
Helm: &argoappv1.ApplicationSourceHelm{ValueFiles: []string{"exclude.yaml", "has-the-word-values.yaml"}},
|
||||
},
|
||||
}
|
||||
appPath, err := filepath.Abs("./testdata/values-files/")
|
||||
require.NoError(t, err)
|
||||
err = populateHelmAppDetails(&res, appPath, appPath, &q)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res.Helm.Parameters, 3)
|
||||
assert.Len(t, res.Helm.ValueFiles, 4)
|
||||
}
|
||||
|
||||
func Test_populateHelmAppDetails_values_symlinks(t *testing.T) {
|
||||
t.Run("inbound", func(t *testing.T) {
|
||||
res := apiclient.RepoAppDetailsResponse{}
|
||||
q := apiclient.RepoServerAppDetailsQuery{Repo: &argoappv1.Repository{}, Source: &argoappv1.ApplicationSource{}}
|
||||
err := populateHelmAppDetails(&res, "./testdata/in-bounds-values-file-link/", "./testdata/in-bounds-values-file-link/", &q)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, res.Helm.Values)
|
||||
assert.NotEmpty(t, res.Helm.Parameters)
|
||||
})
|
||||
|
||||
t.Run("out of bounds", func(t *testing.T) {
|
||||
res := apiclient.RepoAppDetailsResponse{}
|
||||
q := apiclient.RepoServerAppDetailsQuery{Repo: &argoappv1.Repository{}, Source: &argoappv1.ApplicationSource{}}
|
||||
err := populateHelmAppDetails(&res, "./testdata/out-of-bounds-values-file-link/", "./testdata/out-of-bounds-values-file-link/", &q)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, res.Helm.Values)
|
||||
assert.Empty(t, res.Helm.Parameters)
|
||||
})
|
||||
}
|
||||
|
||||
4
reposerver/repository/testdata/app-parameters/single-global-helm/.argocd-source.yaml
vendored
Normal file
4
reposerver/repository/testdata/app-parameters/single-global-helm/.argocd-source.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
helm:
|
||||
parameters:
|
||||
- name: image.tag
|
||||
value: '0.2'
|
||||
2
reposerver/repository/testdata/app-parameters/single-global-helm/Chart.yaml
vendored
Normal file
2
reposerver/repository/testdata/app-parameters/single-global-helm/Chart.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
name: my-chart
|
||||
version: 1.1.0
|
||||
18
reposerver/repository/testdata/app-parameters/single-global-helm/templates/deployment.yaml
vendored
Normal file
18
reposerver/repository/testdata/app-parameters/single-global-helm/templates/deployment.yaml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: guestbook-ui
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: guestbook-ui
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: guestbook-ui
|
||||
spec:
|
||||
containers:
|
||||
- image: gcr.io/heptio-images/ks-guestbook-demo:{{.Values.image.tag}}
|
||||
name: guestbook-ui
|
||||
ports:
|
||||
- containerPort: 81
|
||||
2
reposerver/repository/testdata/app-parameters/single-global-helm/values.yaml
vendored
Normal file
2
reposerver/repository/testdata/app-parameters/single-global-helm/values.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
image:
|
||||
tag: 0.1
|
||||
0
reposerver/repository/testdata/circular-link/.keep
vendored
Normal file
0
reposerver/repository/testdata/circular-link/.keep
vendored
Normal file
1
reposerver/repository/testdata/in-bounds-link/app/cm.link.yaml
vendored
Symbolic link
1
reposerver/repository/testdata/in-bounds-link/app/cm.link.yaml
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../cm.yaml
|
||||
2
reposerver/repository/testdata/in-bounds-link/cm.yaml
vendored
Normal file
2
reposerver/repository/testdata/in-bounds-link/cm.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
2
reposerver/repository/testdata/in-bounds-values-file-link/Chart.yaml
vendored
Normal file
2
reposerver/repository/testdata/in-bounds-values-file-link/Chart.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
name: my-chart
|
||||
version: 1.1.0
|
||||
1
reposerver/repository/testdata/in-bounds-values-file-link/values-2.yaml
vendored
Normal file
1
reposerver/repository/testdata/in-bounds-values-file-link/values-2.yaml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
some: yaml
|
||||
1
reposerver/repository/testdata/in-bounds-values-file-link/values.yaml
vendored
Symbolic link
1
reposerver/repository/testdata/in-bounds-values-file-link/values.yaml
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
values-2.yaml
|
||||
1
reposerver/repository/testdata/invalid-json/invalid.json
vendored
Normal file
1
reposerver/repository/testdata/invalid-json/invalid.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[
|
||||
1
reposerver/repository/testdata/irrelevant-yaml/irrelevant.yaml
vendored
Normal file
1
reposerver/repository/testdata/irrelevant-yaml/irrelevant.yaml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
some: [irrelevant, yaml]
|
||||
2
reposerver/repository/testdata/irrelevant-yaml/relevant.yaml
vendored
Normal file
2
reposerver/repository/testdata/irrelevant-yaml/relevant.yaml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
2
reposerver/repository/testdata/json-list/list.json
vendored
Normal file
2
reposerver/repository/testdata/json-list/list.json
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
{"apiVersion": "v1", "kind": "ConfigMap"}
|
||||
{"apiVersion": "v1", "kind": "ConfigMap"}
|
||||
1
reposerver/repository/testdata/jsonnet-and-json/test.json
vendored
Normal file
1
reposerver/repository/testdata/jsonnet-and-json/test.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"apiVersion": "v1", "kind": "Pod"}
|
||||
1
reposerver/repository/testdata/jsonnet-and-json/test.jsonnet
vendored
Normal file
1
reposerver/repository/testdata/jsonnet-and-json/test.jsonnet
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"apiVersion": "v1", "kind": "Pod"}
|
||||
1
reposerver/repository/testdata/link-to-nowhere/nowhere.json
vendored
Symbolic link
1
reposerver/repository/testdata/link-to-nowhere/nowhere.json
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
nowhere
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user