From a041bf80fc7709b804c01925ec78a1b09e003875 Mon Sep 17 00:00:00 2001 From: Blake Pettersson Date: Mon, 27 Jun 2022 15:35:59 +0200 Subject: [PATCH 01/33] feat: allow interpolation of cluster generator values (#9254) * feat: allow interpolation of generator values Allow the interpolation of `values` found in the cluster generator. This allows interpolation of `{{name}}`, `{{server}}`, `{{metadata.labels.*}}` and `{{metadata.annotations.*}}`. See argoproj/applicationset#371. This interpolation could potentially be extended to the list and duck-type generators if desired. Signed-off-by: Blake Pettersson * docs: add values interpolation usage instructions Add a basic example of how values interpolation can be used with the cluster generator. Signed-off-by: Blake Pettersson * fix: remove billion-laughs attack vector The previous implementation was vulnerable to a billion-laughs attack, where someone could interpolate values based upon other values, something like: ```yaml values: lol1: lol lol2: '{{values.lol1}}{{values.lol1}}' # lol3: '{{values.lol2}}{{values.lol2}}{{values.lol2}}{{values.lol2}}' ``` To counteract that, instead of directly manipulating the `params` map, we create a map to keep track of the interpolated values, and only template the values which have been previously whitelisted. Once we go through all the values, we then merge the interpolated values map back to the `params` map. Signed-off-by: Blake Pettersson --- applicationset/generators/cluster.go | 54 ++++++++++++++++--- applicationset/generators/cluster_test.go | 18 +++++-- applicationset/utils/utils.go | 2 +- .../applicationset/Generators-Cluster.md | 46 ++++++++++++++++ 4 files changed, 107 insertions(+), 13 deletions(-) diff --git a/applicationset/generators/cluster.go b/applicationset/generators/cluster.go index cc291e40bed92..60109ee28ec1f 100644 --- a/applicationset/generators/cluster.go +++ b/applicationset/generators/cluster.go @@ -3,6 +3,7 @@ package generators import ( "context" "fmt" + "github.com/valyala/fasttemplate" "regexp" "strings" "time" @@ -37,6 +38,8 @@ type ClusterGenerator struct { settingsManager *settings.SettingsManager } +var render = &utils.Render{} + func NewClusterGenerator(c client.Client, ctx context.Context, clientset kubernetes.Interface, namespace string) Generator { settingsManager := settings.NewSettingsManager(ctx, clientset, namespace) @@ -106,19 +109,21 @@ func (g *ClusterGenerator) GenerateParams( params["name"] = cluster.Name params["server"] = cluster.Server - for key, value := range appSetGenerator.Clusters.Values { - params[fmt.Sprintf("values.%s", key)] = value + err = appendTemplatedValues(appSetGenerator.Clusters.Values, params) + if err != nil { + return nil, err } - log.WithField("cluster", "local cluster").Info("matched local cluster") - res = append(res, params) + + log.WithField("cluster", "local cluster").Info("matched local cluster") } } // For each matching cluster secret (non-local clusters only) for _, cluster := range secretsFound { params := map[string]string{} + params["name"] = string(cluster.Data["name"]) params["nameNormalized"] = sanitizeName(string(cluster.Data["name"])) params["server"] = string(cluster.Data["server"]) @@ -128,17 +133,52 @@ func (g *ClusterGenerator) GenerateParams( for key, value := range cluster.ObjectMeta.Labels { params[fmt.Sprintf("metadata.labels.%s", key)] = value } - for key, value := range appSetGenerator.Clusters.Values { - params[fmt.Sprintf("values.%s", key)] = value + + err = appendTemplatedValues(appSetGenerator.Clusters.Values, params) + if err != nil { + return nil, err } - log.WithField("cluster", cluster.Name).Info("matched cluster secret") res = append(res, params) + + log.WithField("cluster", cluster.Name).Info("matched cluster secret") } return res, nil } +func appendTemplatedValues(clusterValues map[string]string, params map[string]string) error { + // We create a local map to ensure that we do not fall victim to a billion-laughs attack. We iterate through the + // cluster values map and only replace values in said map if it has already been whitelisted in the params map. + // Once we iterate through all the cluster values we can then safely merge the `tmp` map into the main params map. + tmp := map[string]string{} + + for key, value := range clusterValues { + result, err := replaceTemplatedString(value, params) + + if err != nil { + return err + } + + tmp[fmt.Sprintf("values.%s", key)] = result + } + + for key, value := range tmp { + params[key] = value + } + + return nil +} + +func replaceTemplatedString(value string, params map[string]string) (string, error) { + fstTmpl := fasttemplate.New(value, "{{", "}}") + replacedTmplStr, err := render.Replace(fstTmpl, params, true) + if err != nil { + return "", err + } + return replacedTmplStr, nil +} + func (g *ClusterGenerator) getSecretsByClusterName(appSetGenerator *argoappsetv1alpha1.ApplicationSetGenerator) (map[string]corev1.Secret, error) { // List all Clusters: clusterSecretList := &corev1.SecretList{} diff --git a/applicationset/generators/cluster_test.go b/applicationset/generators/cluster_test.go index a519a4073ab13..b798150348a0d 100644 --- a/applicationset/generators/cluster_test.go +++ b/applicationset/generators/cluster_test.go @@ -94,15 +94,23 @@ func TestGenerateParams(t *testing.T) { { name: "no label selector", selector: metav1.LabelSelector{}, - values: nil, - expected: []map[string]string{ - {"name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar", + values: map[string]string{ + "lol1": "lol", + "lol2": "{{values.lol1}}{{values.lol1}}", + "lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", + "foo": "bar", + "bar": "{{ metadata.annotations.foo.argoproj.io }}", + "bat": "{{ metadata.labels.environment }}", + "aaa": "{{ server }}", + "no-op": "{{ this-does-not-exist }}", + }, expected: []map[string]string{ + {"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "production", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "production", "values.aaa": "https://production-01.example.com", "name": "production_01/west", "nameNormalized": "production-01-west", "server": "https://production-01.example.com", "metadata.labels.environment": "production", "metadata.labels.org": "bar", "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "production"}, - {"name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo", + {"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "staging", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "staging", "values.aaa": "https://staging-01.example.com", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo", "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging"}, - {"name": "in-cluster", "server": "https://kubernetes.default.svc"}, + {"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "name": "in-cluster", "server": "https://kubernetes.default.svc"}, }, clientError: false, expectedError: nil, diff --git a/applicationset/utils/utils.go b/applicationset/utils/utils.go index f3586ffdad29c..b2b1445022776 100644 --- a/applicationset/utils/utils.go +++ b/applicationset/utils/utils.go @@ -64,7 +64,7 @@ func (r *Render) RenderTemplateParams(tmpl *argoappsv1.Application, syncPolicy * } // Replace executes basic string substitution of a template with replacement values. -// 'allowUnresolved' indicates whether or not it is acceptable to have unresolved variables +// 'allowUnresolved' indicates whether it is acceptable to have unresolved variables // remaining in the substituted template. func (r *Render) Replace(fstTmpl *fasttemplate.Template, replaceMap map[string]string, allowUnresolved bool) (string, error) { var unresolvedErr error diff --git a/docs/operator-manual/applicationset/Generators-Cluster.md b/docs/operator-manual/applicationset/Generators-Cluster.md index ad2316d119d6b..04546278a7c39 100644 --- a/docs/operator-manual/applicationset/Generators-Cluster.md +++ b/docs/operator-manual/applicationset/Generators-Cluster.md @@ -159,3 +159,49 @@ In this example the `revision` value from the `generators.clusters` fields is pa !!! note The `values.` prefix is always prepended to values provided via `generators.clusters.values` field. Ensure you include this prefix in the parameter name within the `template` when using it. + +In `values` we can also interpolate the following parameter values (i.e. the same values as presented in the beginning of this page) + +- `name` +- `nameNormalized` *('name' but normalized to contain only lowercase alphanumeric characters, '-' or '.')* +- `server` +- `metadata.labels.` *(for each label in the Secret)* +- `metadata.annotations.` *(for each annotation in the Secret)* + +Extending the example above, we could do something like this: + +```yaml +spec: + generators: + - clusters: + selector: + matchLabels: + type: 'staging' + # A key-value map for arbitrary parameters + values: + # If `my-custom-annotation` is in your cluster secret, `revision` will be substituted with it. + revision: '{{metadata.annotations.my-custom-annotation}}' + clusterName: '{{name}}' + - clusters: + selector: + matchLabels: + type: 'production' + values: + # production uses a different revision value, for 'stable' branch + revision: stable + clusterName: '{{name}}' + template: + metadata: + name: '{{name}}-guestbook' + spec: + project: "my-project" + source: + repoURL: https://github.com/argoproj/argocd-example-apps/ + # The cluster values field for each generator will be substituted here: + targetRevision: '{{values.revision}}' + path: guestbook + destination: + # In this case this is equivalent to just using {{name}} + server: '{{values.clusterName}}' + namespace: guestbook +``` \ No newline at end of file From 0d0d5fc8e57143311fa35e22068a8f384d29f184 Mon Sep 17 00:00:00 2001 From: TomHellier Date: Mon, 27 Jun 2022 18:25:52 +0100 Subject: [PATCH 02/33] fix: websockets for terminal not working on subPath (#9795) Signed-off-by: Tom Hellier --- .../components/pod-terminal-viewer/pod-terminal-viewer.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/src/app/applications/components/pod-terminal-viewer/pod-terminal-viewer.tsx b/ui/src/app/applications/components/pod-terminal-viewer/pod-terminal-viewer.tsx index 5d29777b563b7..b4d4b423da99d 100644 --- a/ui/src/app/applications/components/pod-terminal-viewer/pod-terminal-viewer.tsx +++ b/ui/src/app/applications/components/pod-terminal-viewer/pod-terminal-viewer.tsx @@ -141,8 +141,9 @@ export const PodTerminalViewer: React.FC = ({selectedNod function setupConnection() { const {name = '', namespace = ''} = selectedNode || {}; + const url = `${location.host}${appContext.baseHref}`.replace(/\/$/, ''); webSocket = new WebSocket( - `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/terminal?pod=${name}&container=${AppUtils.getContainerName( + `${location.protocol === 'https:' ? 'wss' : 'ws'}://${url}/terminal?pod=${name}&container=${AppUtils.getContainerName( podState, activeContainer )}&appName=${applicationName}&projectName=${projectName}&namespace=${namespace}` From 1434e8960dca2bdb2de33eee7a54f808373e4833 Mon Sep 17 00:00:00 2001 From: Chris Reilly Date: Mon, 27 Jun 2022 14:35:36 -0700 Subject: [PATCH 03/33] docs: explain rightmost git generator path parameter behavior (#9799) --- docs/operator-manual/applicationset/Generators-Git.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/operator-manual/applicationset/Generators-Git.md b/docs/operator-manual/applicationset/Generators-Git.md index a87ab89322ca2..944cdc969c0d0 100644 --- a/docs/operator-manual/applicationset/Generators-Git.md +++ b/docs/operator-manual/applicationset/Generators-Git.md @@ -65,6 +65,8 @@ 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). +**Note**: The right-most path name always becomes `{{path.basename}}`. For example, to use `four` as a parameter from `- path: /one/two/three/four`, use `{{path.basename}}` not `{{path[3]}}`. + 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. As with other generators, clusters *must* already be defined within Argo CD, in order to generate Applications for them. @@ -274,6 +276,9 @@ In addition to the flattened key/value pairs from the configuration file, the fo - `{{path.basename}}`: Basename of the path to the folder 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). +**Note**: The right-most path name always becomes `{{path.basename}}`. For example, to use `four` as a parameter from `- path: /one/two/three/four/config.json`, use `{{path.basename}}` not `{{path[3]}}`. + + ## Webhook Configuration When using a Git generator, ApplicationSet polls Git repositories every three minutes to detect changes. To eliminate From a491eb2d40f7cf2aa9905d41df44cd8ad3f61ad3 Mon Sep 17 00:00:00 2001 From: YaytayAtWork Date: Tue, 28 Jun 2022 14:00:45 +0100 Subject: [PATCH 04/33] docs: getting started notes on self-signed cert (#9429) (#9784) * Fix #9429: A couple of notes in the docs to explain that the default certificate is insecure. Signed-off-by: Jim Talbut * Fixes #9429: More verbose, but complete, text for Getting Started. Signed-off-by: Jim Talbut --- docs/faq.md | 4 +++- docs/getting_started.md | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/faq.md b/docs/faq.md index 85612570173f4..c0176354521f1 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -174,7 +174,9 @@ argocd ... --grpc-web ## Why Am I Getting `x509: certificate signed by unknown authority` When Using The CLI? -Your not running your server with correct certs. +The certificate created by default by Argo CD is not automatically recognised by the Argo CD CLI, in order +to create a secure system you must follow the instructions to [install a certificate](/operator-manual/tls/) +and configure your client OS to trust that certificate. If you're not running in a production system (e.g. you're testing Argo CD out), try the `--insecure` flag: diff --git a/docs/getting_started.md b/docs/getting_started.md index 65d611fb994dd..0eca3cbecf8be 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -29,6 +29,12 @@ kubectl create namespace argocd kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/core-install.yaml ``` +This default installation will have a self-signed certificate and cannot be accessed without a bit of extra work. +Do one of: +* Follow the [instructions to configure a certificate](./operator-manual/tls) (and ensure that the client OS trusts it). +* Configure the client OS to trust the self signed certificate. +* Use the --insecure flag on all Argo CD CLI operations in this guide. + Use `argocd login --core` to [configure](./user-guide/commands/argocd_login.md) CLI access and skip steps 3-5. ## 2. Download Argo CD CLI From 356307e243973f90b5238cff150821fffd7668c2 Mon Sep 17 00:00:00 2001 From: Joe Bowbeer Date: Tue, 28 Jun 2022 06:19:46 -0700 Subject: [PATCH 05/33] fix: pss restricted securityContext (#9765) * fix: pss restricted securityContext Signed-off-by: Joe Bowbeer * fix: argocd-dex-server seccomp strict Signed-off-by: Joe Bowbeer * fix: remove seccomp from generated haproxy manifests Signed-off-by: Joe Bowbeer * fix: indentation in namespace-install Signed-off-by: Joe Bowbeer * fix: indentation in namespace-install Signed-off-by: Joe Bowbeer --- ...cd-application-controller-statefulset.yaml | 4 ++- ...-applicationset-controller-deployment.yaml | 14 ++++++---- .../dex/argocd-dex-server-deployment.yaml | 4 +++ ...d-notifications-controller-deployment.yaml | 6 ++-- .../base/redis/argocd-redis-deployment.yaml | 4 ++- .../argocd-repo-server-deployment.yaml | 8 ++++-- .../base/server/argocd-server-deployment.yaml | 4 ++- manifests/core-install.yaml | 18 +++++++++--- manifests/ha/install.yaml | 24 +++++++++++++--- manifests/ha/namespace-install.yaml | 24 +++++++++++++--- manifests/install.yaml | 28 +++++++++++++++---- manifests/namespace-install.yaml | 28 +++++++++++++++---- 12 files changed, 131 insertions(+), 35 deletions(-) diff --git a/manifests/base/application-controller/argocd-application-controller-statefulset.yaml b/manifests/base/application-controller/argocd-application-controller-statefulset.yaml index 47498703ede77..a133c61b85fc4 100644 --- a/manifests/base/application-controller/argocd-application-controller-statefulset.yaml +++ b/manifests/base/application-controller/argocd-application-controller-statefulset.yaml @@ -142,7 +142,9 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL + seccompProfile: + type: RuntimeDefault workingDir: /home/argocd volumeMounts: - name: argocd-repo-server-tls diff --git a/manifests/base/applicationset-controller/argocd-applicationset-controller-deployment.yaml b/manifests/base/applicationset-controller/argocd-applicationset-controller-deployment.yaml index f988199258589..c27d77b2921ff 100644 --- a/manifests/base/applicationset-controller/argocd-applicationset-controller-deployment.yaml +++ b/manifests/base/applicationset-controller/argocd-applicationset-controller-deployment.yaml @@ -44,12 +44,14 @@ spec: - mountPath: /tmp name: tmp securityContext: - capabilities: - drop: - - ALL - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsNonRoot: true + capabilities: + drop: + - ALL + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault serviceAccountName: argocd-applicationset-controller volumes: - configMap: diff --git a/manifests/base/dex/argocd-dex-server-deployment.yaml b/manifests/base/dex/argocd-dex-server-deployment.yaml index 66c70b536e4b8..ae227f172d4ce 100644 --- a/manifests/base/dex/argocd-dex-server-deployment.yaml +++ b/manifests/base/dex/argocd-dex-server-deployment.yaml @@ -33,6 +33,8 @@ spec: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault containers: - name: dex image: ghcr.io/dexidp/dex:v2.30.2 @@ -45,6 +47,8 @@ spec: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault ports: - containerPort: 5556 - containerPort: 5557 diff --git a/manifests/base/notification/argocd-notifications-controller-deployment.yaml b/manifests/base/notification/argocd-notifications-controller-deployment.yaml index f35f7c0b7b9ae..94d01e7343f8a 100644 --- a/manifests/base/notification/argocd-notifications-controller-deployment.yaml +++ b/manifests/base/notification/argocd-notifications-controller-deployment.yaml @@ -48,7 +48,9 @@ spec: drop: - ALL allowPrivilegeEscalation: false - readOnlyRootFilesystem: true + readOnlyRootFilesystem: true serviceAccountName: argocd-notifications-controller securityContext: - runAsNonRoot: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault diff --git a/manifests/base/redis/argocd-redis-deployment.yaml b/manifests/base/redis/argocd-redis-deployment.yaml index a2e4dd7455f0e..5a4d076aded71 100644 --- a/manifests/base/redis/argocd-redis-deployment.yaml +++ b/manifests/base/redis/argocd-redis-deployment.yaml @@ -18,6 +18,8 @@ spec: securityContext: runAsNonRoot: true runAsUser: 999 + seccompProfile: + type: RuntimeDefault serviceAccountName: argocd-redis containers: - name: redis @@ -34,7 +36,7 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: diff --git a/manifests/base/repo-server/argocd-repo-server-deployment.yaml b/manifests/base/repo-server/argocd-repo-server-deployment.yaml index 6db49e3c31ceb..252bc36e64c4f 100644 --- a/manifests/base/repo-server/argocd-repo-server-deployment.yaml +++ b/manifests/base/repo-server/argocd-repo-server-deployment.yaml @@ -135,7 +135,9 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL + seccompProfile: + type: RuntimeDefault volumeMounts: - name: ssh-known-hosts mountPath: /app/config/ssh @@ -167,7 +169,9 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /var/run/argocd name: var-files diff --git a/manifests/base/server/argocd-server-deployment.yaml b/manifests/base/server/argocd-server-deployment.yaml index 98a31228f6e3d..dd7512ad12521 100644 --- a/manifests/base/server/argocd-server-deployment.yaml +++ b/manifests/base/server/argocd-server-deployment.yaml @@ -216,7 +216,9 @@ spec: runAsNonRoot: true capabilities: drop: - - all + - ALL + seccompProfile: + type: RuntimeDefault volumes: - emptyDir: {} name: plugins-home diff --git a/manifests/core-install.yaml b/manifests/core-install.yaml index fbe836f63d97a..b8570a7aa9706 100644 --- a/manifests/core-install.yaml +++ b/manifests/core-install.yaml @@ -9550,6 +9550,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -9624,10 +9626,12 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL securityContext: runAsNonRoot: true runAsUser: 999 + seccompProfile: + type: RuntimeDefault serviceAccountName: argocd-redis --- apiVersion: apps/v1 @@ -9782,9 +9786,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -9814,9 +9820,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /var/run/argocd name: var-files @@ -10010,9 +10018,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/controller/tls name: argocd-repo-server-tls diff --git a/manifests/ha/install.yaml b/manifests/ha/install.yaml index 0e482f97577cc..0119c91231725 100644 --- a/manifests/ha/install.yaml +++ b/manifests/ha/install.yaml @@ -10489,6 +10489,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -10560,6 +10562,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files @@ -10581,6 +10585,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files @@ -10631,6 +10637,8 @@ spec: workingDir: /app securityContext: runAsNonRoot: true + seccompProfile: + type: RuntimeDefault serviceAccountName: argocd-notifications-controller volumes: - configMap: @@ -10885,9 +10893,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -10917,9 +10927,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /var/run/argocd name: var-files @@ -11180,9 +11192,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -11381,9 +11395,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/controller/tls name: argocd-repo-server-tls diff --git a/manifests/ha/namespace-install.yaml b/manifests/ha/namespace-install.yaml index 2c035fb26c413..6747aabcb8e89 100644 --- a/manifests/ha/namespace-install.yaml +++ b/manifests/ha/namespace-install.yaml @@ -1263,6 +1263,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -1334,6 +1336,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files @@ -1355,6 +1359,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files @@ -1405,6 +1411,8 @@ spec: workingDir: /app securityContext: runAsNonRoot: true + seccompProfile: + type: RuntimeDefault serviceAccountName: argocd-notifications-controller volumes: - configMap: @@ -1659,9 +1667,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -1691,9 +1701,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /var/run/argocd name: var-files @@ -1954,9 +1966,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -2155,9 +2169,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/controller/tls name: argocd-repo-server-tls diff --git a/manifests/install.yaml b/manifests/install.yaml index efd0c3c52a769..2a8e182e047d5 100644 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -9861,6 +9861,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -9932,6 +9934,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files @@ -9953,6 +9957,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files @@ -10003,6 +10009,8 @@ spec: workingDir: /app securityContext: runAsNonRoot: true + seccompProfile: + type: RuntimeDefault serviceAccountName: argocd-notifications-controller volumes: - configMap: @@ -10067,10 +10075,12 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL securityContext: runAsNonRoot: true runAsUser: 999 + seccompProfile: + type: RuntimeDefault serviceAccountName: argocd-redis --- apiVersion: apps/v1 @@ -10225,9 +10235,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -10257,9 +10269,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /var/run/argocd name: var-files @@ -10516,9 +10530,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -10711,9 +10727,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/controller/tls name: argocd-repo-server-tls diff --git a/manifests/namespace-install.yaml b/manifests/namespace-install.yaml index 42ec09e080099..5c39145baff2b 100644 --- a/manifests/namespace-install.yaml +++ b/manifests/namespace-install.yaml @@ -635,6 +635,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -706,6 +708,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files @@ -727,6 +731,8 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /shared name: static-files @@ -777,6 +783,8 @@ spec: workingDir: /app securityContext: runAsNonRoot: true + seccompProfile: + type: RuntimeDefault serviceAccountName: argocd-notifications-controller volumes: - configMap: @@ -841,10 +849,12 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL securityContext: runAsNonRoot: true runAsUser: 999 + seccompProfile: + type: RuntimeDefault serviceAccountName: argocd-redis --- apiVersion: apps/v1 @@ -999,9 +1009,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -1031,9 +1043,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /var/run/argocd name: var-files @@ -1290,9 +1304,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/ssh name: ssh-known-hosts @@ -1485,9 +1501,11 @@ spec: allowPrivilegeEscalation: false capabilities: drop: - - all + - ALL readOnlyRootFilesystem: true runAsNonRoot: true + seccompProfile: + type: RuntimeDefault volumeMounts: - mountPath: /app/config/controller/tls name: argocd-repo-server-tls From 8649c419bcf166816c3380574e5cd43b127ca903 Mon Sep 17 00:00:00 2001 From: Alex Collins Date: Tue, 28 Jun 2022 07:59:56 -0700 Subject: [PATCH 06/33] fix: upgrade superagent from 7.1.3 to 7.1.6 (#9748) Snyk has created this PR to upgrade superagent from 7.1.3 to 7.1.6. See this package in npm: See this project in Snyk: https://app.snyk.io/org/argoproj/project/d2931792-eef9-4d7c-b9d6-c0cbd2bd4dbe?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot --- ui/package.json | 2 +- ui/yarn.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/package.json b/ui/package.json index 8359083555f52..a2571235a3a0a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -43,7 +43,7 @@ "react-svg-piechart": "^2.4.2", "redoc": "^2.0.0-rc.64", "rxjs": "^6.6.6", - "superagent": "^7.1.3", + "superagent": "^7.1.6", "timezones-list": "3.0.1", "tsx": "^3.4.0", "unidiff": "^1.0.2", diff --git a/ui/yarn.lock b/ui/yarn.lock index 31762f4d24cbd..ab0301af3b93d 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -6409,7 +6409,7 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.5.0: +mime@2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== @@ -9214,10 +9214,10 @@ style-loader@^3.3.1: resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== -superagent@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-7.1.3.tgz#783ff8330e7c2dad6ad8f0095edc772999273b6b" - integrity sha512-WA6et4nAvgBCS73lJvv1D0ssI5uk5Gh+TGN/kNe+B608EtcVs/yzfl+OLXTzDs7tOBDIpvgh/WUs1K2OK1zTeQ== +superagent@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/superagent/-/superagent-7.1.6.tgz#64f303ed4e4aba1e9da319f134107a54cacdc9c6" + integrity sha512-gZkVCQR1gy/oUXr+kxJMLDjla434KmSOKbx5iGD30Ql+AkJQ/YlPKECJy2nhqOsHLjGHzoDTXNSjhnvWhzKk7g== dependencies: component-emitter "^1.3.0" cookiejar "^2.1.3" @@ -9226,7 +9226,7 @@ superagent@^7.1.3: form-data "^4.0.0" formidable "^2.0.1" methods "^1.1.2" - mime "^2.5.0" + mime "2.6.0" qs "^6.10.3" readable-stream "^3.6.0" semver "^7.3.7" From 2786b70ae8a1f54092b0ea514253e1be5534867d Mon Sep 17 00:00:00 2001 From: Soumya Ghosh Dastidar <44349253+gdsoumya@users.noreply.github.com> Date: Tue, 28 Jun 2022 22:17:49 +0530 Subject: [PATCH 07/33] fix: updated all a tags to Link tags in app summary (#9777) * fix: updated all a tags to Link tags Signed-off-by: Soumya Ghosh Dastidar * fix: revert external links to a tags Signed-off-by: Soumya Ghosh Dastidar * fix: linting Signed-off-by: Soumya Ghosh Dastidar --- .../components/application-summary/application-summary.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/src/app/applications/components/application-summary/application-summary.tsx b/ui/src/app/applications/components/application-summary/application-summary.tsx index da4bd94ca115d..a166d3b1b9b45 100644 --- a/ui/src/app/applications/components/application-summary/application-summary.tsx +++ b/ui/src/app/applications/components/application-summary/application-summary.tsx @@ -13,6 +13,7 @@ import {RevisionFormField} from '../revision-form-field/revision-form-field'; import {ComparisonStatusIcon, HealthStatusIcon, syncStatusMessage, urlPattern} from '../utils'; import {ApplicationRetryOptions} from '../application-retry-options/application-retry-options'; import {ApplicationRetryView} from '../application-retry-view/application-retry-view'; +import {Link} from 'react-router-dom'; require('./application-summary.scss'); @@ -31,7 +32,7 @@ export const ApplicationSummary = (props: {app: models.Application; updateApp: ( const attributes = [ { title: 'PROJECT', - view: {app.spec.project}, + view: {app.spec.project}, edit: (formApi: FormApi) => ( services.projects.list('items.metadata.name').then(projs => projs.map(item => item.metadata.name))}> {projects => } From 202001ac24f4d598a665cec46f66142e13fc52fe Mon Sep 17 00:00:00 2001 From: Lawrence Carvalho Date: Tue, 28 Jun 2022 19:49:51 +0100 Subject: [PATCH 08/33] fix(applicationset): provide nameNormalized template param for local cluster (#9728) Signed-off-by: Lawrence Carvalho --- applicationset/generators/cluster.go | 1 + applicationset/generators/cluster_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/applicationset/generators/cluster.go b/applicationset/generators/cluster.go index 60109ee28ec1f..cbcb877258629 100644 --- a/applicationset/generators/cluster.go +++ b/applicationset/generators/cluster.go @@ -107,6 +107,7 @@ func (g *ClusterGenerator) GenerateParams( // If there is no secret for the cluster, it's the local cluster, so handle it here. params := map[string]string{} params["name"] = cluster.Name + params["nameNormalized"] = cluster.Name params["server"] = cluster.Server err = appendTemplatedValues(appSetGenerator.Clusters.Values, params) diff --git a/applicationset/generators/cluster_test.go b/applicationset/generators/cluster_test.go index b798150348a0d..fe1f8b99ea858 100644 --- a/applicationset/generators/cluster_test.go +++ b/applicationset/generators/cluster_test.go @@ -110,7 +110,7 @@ func TestGenerateParams(t *testing.T) { {"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "staging", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "staging", "values.aaa": "https://staging-01.example.com", "name": "staging-01", "nameNormalized": "staging-01", "server": "https://staging-01.example.com", "metadata.labels.environment": "staging", "metadata.labels.org": "foo", "metadata.labels.argocd.argoproj.io/secret-type": "cluster", "metadata.annotations.foo.argoproj.io": "staging"}, - {"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "name": "in-cluster", "server": "https://kubernetes.default.svc"}, + {"values.lol1": "lol", "values.lol2": "{{values.lol1}}{{values.lol1}}", "values.lol3": "{{values.lol2}}{{values.lol2}}{{values.lol2}}", "values.foo": "bar", "values.bar": "{{ metadata.annotations.foo.argoproj.io }}", "values.no-op": "{{ this-does-not-exist }}", "values.bat": "{{ metadata.labels.environment }}", "values.aaa": "https://kubernetes.default.svc", "nameNormalized": "in-cluster", "name": "in-cluster", "server": "https://kubernetes.default.svc"}, }, clientError: false, expectedError: nil, From b52476971425d396cfd63306d53193a3e9f54df6 Mon Sep 17 00:00:00 2001 From: Kent Rancourt Date: Tue, 28 Jun 2022 14:55:51 -0400 Subject: [PATCH 09/33] feat: implement consistent startup messages for all components (#9800) * feat: implement consistent startup messages for all components Signed-off-by: Kent * DRY up previous commit Signed-off-by: Kent --- .../commands/argocd_application_controller.go | 15 +++++++++----- .../commands/applicationset_controller.go | 20 +++++++++++-------- .../commands/argocd_cmp_server.go | 3 +++ cmd/argocd-dex/commands/argocd_dex.go | 15 ++++++++++---- .../commands/controller.go | 12 ++++++++++- .../commands/argocd_repo_server.go | 12 +++++++++-- cmd/argocd-server/commands/argocd_server.go | 15 ++++++++++---- common/version.go | 12 +++++++++++ 8 files changed, 80 insertions(+), 24 deletions(-) diff --git a/cmd/argocd-application-controller/commands/argocd_application_controller.go b/cmd/argocd-application-controller/commands/argocd_application_controller.go index e345d078066a4..4eec3d1f5d3d7 100644 --- a/cmd/argocd-application-controller/commands/argocd_application_controller.go +++ b/cmd/argocd-application-controller/commands/argocd_application_controller.go @@ -67,6 +67,16 @@ func NewCommand() *cobra.Command { Long: "ArgoCD application controller is a Kubernetes controller that continuously monitors running applications and compares the current, live state against the desired target state (as specified in the repo). This command runs Application Controller in the foreground. It can be configured by following options.", DisableAutoGenTag: true, RunE: func(c *cobra.Command, args []string) error { + vers := common.GetVersion() + namespace, _, err := clientConfig.Namespace() + errors.CheckError(err) + vers.LogStartupInfo( + "ArgoCD Application Controller", + map[string]any{ + "namespace": namespace, + }, + ) + cli.SetLogFormat(cmdutil.LogFormat) cli.SetLogLevel(cmdutil.LogLevel) cli.SetGLogLevel(glogLevel) @@ -74,15 +84,11 @@ func NewCommand() *cobra.Command { config, err := clientConfig.ClientConfig() errors.CheckError(err) errors.CheckError(v1alpha1.SetK8SConfigDefaults(config)) - vers := common.GetVersion() config.UserAgent = fmt.Sprintf("argocd-application-controller/%s (%s)", vers.Version, vers.Platform) kubeClient := kubernetes.NewForConfigOrDie(config) appClient := appclientset.NewForConfigOrDie(config) - namespace, _, err := clientConfig.Namespace() - errors.CheckError(err) - hardResyncDuration := time.Duration(appHardResyncPeriod) * time.Second var resyncDuration time.Duration @@ -146,7 +152,6 @@ func NewCommand() *cobra.Command { errors.CheckError(err) cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer()) - log.Infof("Application Controller (version: %s, built: %s) starting (namespace: %s)", vers.Version, vers.BuildDate, namespace) stats.RegisterStackDumper() stats.StartStatsTicker(10 * time.Minute) stats.RegisterHeapDumper("memprofile") diff --git a/cmd/argocd-applicationset-controller/commands/applicationset_controller.go b/cmd/argocd-applicationset-controller/commands/applicationset_controller.go index 99ba630403395..7a18b2d4f050d 100644 --- a/cmd/argocd-applicationset-controller/commands/applicationset_controller.go +++ b/cmd/argocd-applicationset-controller/commands/applicationset_controller.go @@ -60,24 +60,28 @@ func NewCommand() *cobra.Command { Use: "controller", Short: "Starts Argo CD ApplicationSet controller", RunE: func(c *cobra.Command, args []string) error { + vers := common.GetVersion() + namespace, _, err := clientConfig.Namespace() + errors.CheckError(err) + vers.LogStartupInfo( + "ArgoCD ApplicationSet Controller", + map[string]any{ + "namespace": namespace, + }, + ) + restConfig, err := clientConfig.ClientConfig() if err != nil { return err } - vers := common.GetVersion() + restConfig.UserAgent = fmt.Sprintf("argocd-applicationset-controller/%s (%s)", vers.Version, vers.Platform) - if namespace == "" { - namespace, _, err = clientConfig.Namespace() - if err != nil { - return err - } - } + level, err := log.ParseLevel(logLevel) if err != nil { return err } log.SetLevel(level) - log.Info(fmt.Sprintf("ApplicationSet controller %s using namespace '%s' ", vers.Version, namespace), "namespace", namespace, "COMMIT_ID", vers.GitCommit) switch strings.ToLower(logFormat) { case "json": log.SetFormatter(&log.JSONFormatter{}) diff --git a/cmd/argocd-cmp-server/commands/argocd_cmp_server.go b/cmd/argocd-cmp-server/commands/argocd_cmp_server.go index f9efe9f5bdaf9..2ba46a153e1f2 100644 --- a/cmd/argocd-cmp-server/commands/argocd_cmp_server.go +++ b/cmd/argocd-cmp-server/commands/argocd_cmp_server.go @@ -34,6 +34,9 @@ func NewCommand() *cobra.Command { Long: "ArgoCD ConfigManagementPlugin Server is an internal service which runs as sidecar container in reposerver deployment. It can be configured by following options.", DisableAutoGenTag: true, RunE: func(c *cobra.Command, args []string) error { + vers := common.GetVersion() + vers.LogStartupInfo("ArgoCD ConfigManagementPlugin Server", nil) + cli.SetLogFormat(cmdutil.LogFormat) cli.SetLogLevel(cmdutil.LogLevel) diff --git a/cmd/argocd-dex/commands/argocd_dex.go b/cmd/argocd-dex/commands/argocd_dex.go index b8777fc483236..a706388fc02cf 100644 --- a/cmd/argocd-dex/commands/argocd_dex.go +++ b/cmd/argocd-dex/commands/argocd_dex.go @@ -51,16 +51,23 @@ func NewRunDexCommand() *cobra.Command { Use: "rundex", Short: "Runs dex generating a config using settings from the Argo CD configmap and secret", RunE: func(c *cobra.Command, args []string) error { + vers := common.GetVersion() + namespace, _, err := clientConfig.Namespace() + errors.CheckError(err) + vers.LogStartupInfo( + "ArgoCD Dex Server", + map[string]any{ + "namespace": namespace, + }, + ) + cli.SetLogFormat(cmdutil.LogFormat) cli.SetLogLevel(cmdutil.LogLevel) - _, err := exec.LookPath("dex") + _, err = exec.LookPath("dex") errors.CheckError(err) config, err := clientConfig.ClientConfig() errors.CheckError(err) - vers := common.GetVersion() config.UserAgent = fmt.Sprintf("argocd-dex/%s (%s)", vers.Version, vers.Platform) - namespace, _, err := clientConfig.Namespace() - errors.CheckError(err) kubeClientset := kubernetes.NewForConfigOrDie(config) settingsMgr := settings.NewSettingsManager(context.Background(), kubeClientset, namespace) diff --git a/cmd/argocd-notification/commands/controller.go b/cmd/argocd-notification/commands/controller.go index d5bd041cef6a7..4c4330d540410 100644 --- a/cmd/argocd-notification/commands/controller.go +++ b/cmd/argocd-notification/commands/controller.go @@ -9,6 +9,7 @@ import ( "github.com/argoproj/argo-cd/v2/common" + "github.com/argoproj/argo-cd/v2/util/errors" service "github.com/argoproj/argo-cd/v2/util/notification/argocd" notificationscontroller "github.com/argoproj/argo-cd/v2/notification_controller/controller" @@ -57,11 +58,20 @@ func NewCommand() *cobra.Command { Use: "controller", Short: "Starts Argo CD Notifications controller", RunE: func(c *cobra.Command, args []string) error { + vers := common.GetVersion() + namespace, _, err := clientConfig.Namespace() + errors.CheckError(err) + vers.LogStartupInfo( + "ArgoCD Notifications Controller", + map[string]any{ + "namespace": namespace, + }, + ) + restConfig, err := clientConfig.ClientConfig() if err != nil { return err } - vers := common.GetVersion() restConfig.UserAgent = fmt.Sprintf("argocd-notifications-controller/%s (%s)", vers.Version, vers.Platform) dynamicClient, err := dynamic.NewForConfig(restConfig) if err != nil { diff --git a/cmd/argocd-repo-server/commands/argocd_repo_server.go b/cmd/argocd-repo-server/commands/argocd_repo_server.go index 733db6764bbd2..3644151dc1dfa 100644 --- a/cmd/argocd-repo-server/commands/argocd_repo_server.go +++ b/cmd/argocd-repo-server/commands/argocd_repo_server.go @@ -88,6 +88,14 @@ func NewCommand() *cobra.Command { Long: "ArgoCD Repository Server is an internal service which maintains a local cache of the Git repository holding the application manifests, and is responsible for generating and returning the Kubernetes manifests. This command runs Repository Server in the foreground. It can be configured by following options.", DisableAutoGenTag: true, RunE: func(c *cobra.Command, args []string) error { + vers := common.GetVersion() + vers.LogStartupInfo( + "ArgoCD Repository Server", + map[string]any{ + "port": listenPort, + }, + ) + cli.SetLogFormat(cmdutil.LogFormat) cli.SetLogLevel(cmdutil.LogLevel) @@ -107,7 +115,7 @@ func NewCommand() *cobra.Command { 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(), @@ -169,7 +177,7 @@ func NewCommand() *cobra.Command { go func() { errors.CheckError(reposerver.StartGPGWatcher(getGnuPGSourcePath())) }() } - log.Infof("argocd-repo-server %s serving on %s", common.GetVersion(), listener.Addr()) + log.Infof("argocd-repo-server is listening on %s", listener.Addr()) stats.RegisterStackDumper() stats.StartStatsTicker(10 * time.Minute) stats.RegisterHeapDumper("memprofile") diff --git a/cmd/argocd-server/commands/argocd_server.go b/cmd/argocd-server/commands/argocd_server.go index a5d2f8c2efdbe..2c7b20a366880 100644 --- a/cmd/argocd-server/commands/argocd_server.go +++ b/cmd/argocd-server/commands/argocd_server.go @@ -74,6 +74,17 @@ func NewCommand() *cobra.Command { Long: "The API server is a gRPC/REST server which exposes the API consumed by the Web UI, CLI, and CI/CD systems. This command runs API server in the foreground. It can be configured by following options.", DisableAutoGenTag: true, Run: func(c *cobra.Command, args []string) { + vers := common.GetVersion() + namespace, _, err := clientConfig.Namespace() + errors.CheckError(err) + vers.LogStartupInfo( + "ArgoCD API Server", + map[string]any{ + "namespace": namespace, + "port": listenPort, + }, + ) + cli.SetLogFormat(cmdutil.LogFormat) cli.SetLogLevel(cmdutil.LogLevel) cli.SetGLogLevel(glogLevel) @@ -82,9 +93,6 @@ func NewCommand() *cobra.Command { errors.CheckError(err) errors.CheckError(v1alpha1.SetK8SConfigDefaults(config)) - namespace, _, err := clientConfig.Namespace() - errors.CheckError(err) - tlsConfigCustomizer, err := tlsConfigCustomizerSrc() errors.CheckError(err) cache, err := cacheSrc() @@ -95,7 +103,6 @@ func NewCommand() *cobra.Command { appclientsetConfig, err := clientConfig.ClientConfig() errors.CheckError(err) errors.CheckError(v1alpha1.SetK8SConfigDefaults(appclientsetConfig)) - vers := common.GetVersion() config.UserAgent = fmt.Sprintf("argocd-server/%s (%s)", vers.Version, vers.Platform) if failureRetryCount > 0 { diff --git a/common/version.go b/common/version.go index b06976877f9b2..8598f98c3171d 100644 --- a/common/version.go +++ b/common/version.go @@ -3,6 +3,8 @@ package common import ( "fmt" "runtime" + + log "github.com/sirupsen/logrus" ) // Version information set by link flags during build. We fall back to these sane @@ -33,6 +35,16 @@ func (v Version) String() string { return v.Version } +func (v Version) LogStartupInfo(componentName string, fields map[string]any) { + if fields == nil { + fields = map[string]any{} + } + fields["version"] = v.Version + fields["commit"] = v.GitCommit + fields["built"] = v.BuildDate + log.WithFields(log.Fields(fields)).Infof("%s is starting", componentName) +} + // GetVersion returns the version information func GetVersion() Version { var versionStr string From eb3fb904e50ec8a635890a16ab3eaf674bf2a354 Mon Sep 17 00:00:00 2001 From: Chris Ng <2509212+chris-ng-scmp@users.noreply.github.com> Date: Wed, 29 Jun 2022 23:23:10 +0800 Subject: [PATCH 10/33] Add scmp.com to argo-cd users (#9823) --- USERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/USERS.md b/USERS.md index d2db5516c3144..eb9de32b37652 100644 --- a/USERS.md +++ b/USERS.md @@ -211,3 +211,4 @@ Currently, the following organizations are **officially** using Argo CD: 1. [Trendyol](https://www.trendyol.com/) 1. [RapidAPI](https://www.rapidapi.com/) 1. [Pismo](https://pismo.io/) +1. [South China Morning Post (SCMP)](https://www.scmp.com/) \ No newline at end of file From 8dcf71f0a789e4468697678fe81be34343607a39 Mon Sep 17 00:00:00 2001 From: Yuan Tang Date: Wed, 29 Jun 2022 11:52:28 -0400 Subject: [PATCH 11/33] feat: Treat connection reset as a retryable error (#9739) Signed-off-by: Yuan Tang --- controller/cache/cache.go | 3 ++- controller/cache/cache_test.go | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/controller/cache/cache.go b/controller/cache/cache.go index 4149cc09c1a62..4cae8a3614ace 100644 --- a/controller/cache/cache.go +++ b/controller/cache/cache.go @@ -354,7 +354,8 @@ func isTransientNetworkErr(err error) bool { } if strings.Contains(errorString, "net/http: TLS handshake timeout") || strings.Contains(errorString, "i/o timeout") || - strings.Contains(errorString, "connection timed out") { + strings.Contains(errorString, "connection timed out") || + strings.Contains(errorString, "connection reset by peer") { return true } return false diff --git a/controller/cache/cache_test.go b/controller/cache/cache_test.go index aa6f26540b618..dcff97edb2157 100644 --- a/controller/cache/cache_test.go +++ b/controller/cache/cache_test.go @@ -111,6 +111,7 @@ func TestIsRetryableError(t *testing.T) { tlsHandshakeTimeoutErr net.Error = netError("net/http: TLS handshake timeout") ioTimeoutErr net.Error = netError("i/o timeout") connectionTimedout net.Error = netError("connection timed out") + connectionReset net.Error = netError("connection reset by peer") ) t.Run("Nil", func(t *testing.T) { assert.False(t, isRetryableError(nil)) @@ -148,4 +149,7 @@ func TestIsRetryableError(t *testing.T) { t.Run("ConnectionTimeout", func(t *testing.T) { assert.True(t, isRetryableError(connectionTimedout)) }) + t.Run("ConnectionReset", func(t *testing.T) { + assert.True(t, isRetryableError(connectionReset)) + }) } From 2ac7bd3039c7dd5f299b007221bcebaa3ef66fc1 Mon Sep 17 00:00:00 2001 From: Romain Poirot <32273490+Redlinkk@users.noreply.github.com> Date: Wed, 29 Jun 2022 16:33:44 +0000 Subject: [PATCH 12/33] feat(applicationset): add short sha to PR generator (#9668) (#9669) * feat(applicationset): add short sha to PR generator Signed-off-by: Romain Poirot * feat(applicationset): add short sha to SCM generator Signed-off-by: Romain Poirot --- applicationset/generators/pull_request.go | 15 +++++-- .../generators/pull_request_test.go | 43 +++++++++++++++---- applicationset/generators/scm_provider.go | 7 +++ .../generators/scm_provider_test.go | 8 ++-- .../applicationset/Generators-Pull-Request.md | 9 ++-- .../applicationset/Generators-SCM-Provider.md | 13 +++--- 6 files changed, 70 insertions(+), 25 deletions(-) diff --git a/applicationset/generators/pull_request.go b/applicationset/generators/pull_request.go index 2091af4ccc3b7..fd38c25b14d06 100644 --- a/applicationset/generators/pull_request.go +++ b/applicationset/generators/pull_request.go @@ -80,12 +80,19 @@ func (g *PullRequestGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha "_": "-", } + var shortSHALength int for _, pull := range pulls { + shortSHALength = 8 + if len(pull.HeadSHA) < 8 { + shortSHALength = len(pull.HeadSHA) + } + params = append(params, map[string]string{ - "number": strconv.Itoa(pull.Number), - "branch": pull.Branch, - "branch_slug": slug.Make(pull.Branch), - "head_sha": pull.HeadSHA, + "number": strconv.Itoa(pull.Number), + "branch": pull.Branch, + "branch_slug": slug.Make(pull.Branch), + "head_sha": pull.HeadSHA, + "head_short_sha": pull.HeadSHA[:shortSHALength], }) } return params, nil diff --git a/applicationset/generators/pull_request_test.go b/applicationset/generators/pull_request_test.go index 0e1878fad3153..4cb18d64b3d1a 100644 --- a/applicationset/generators/pull_request_test.go +++ b/applicationset/generators/pull_request_test.go @@ -37,10 +37,11 @@ func TestPullRequestGithubGenerateParams(t *testing.T) { }, expected: []map[string]string{ { - "number": "1", - "branch": "branch1", - "branch_slug": "branch1", - "head_sha": "089d92cbf9ff857a39e6feccd32798ca700fb958", + "number": "1", + "branch": "branch1", + "branch_slug": "branch1", + "head_sha": "089d92cbf9ff857a39e6feccd32798ca700fb958", + "head_short_sha": "089d92cb", }, }, expectedErr: nil, @@ -61,10 +62,36 @@ func TestPullRequestGithubGenerateParams(t *testing.T) { }, expected: []map[string]string{ { - "number": "2", - "branch": "feat/areally+long_pull_request_name_to_test_argo_slugification_and_branch_name_shortening_feature", - "branch_slug": "feat-areally-long-pull-request-name-to-test-argo", - "head_sha": "9b34ff5bd418e57d58891eb0aa0728043ca1e8be", + "number": "2", + "branch": "feat/areally+long_pull_request_name_to_test_argo_slugification_and_branch_name_shortening_feature", + "branch_slug": "feat-areally-long-pull-request-name-to-test-argo", + "head_sha": "9b34ff5bd418e57d58891eb0aa0728043ca1e8be", + "head_short_sha": "9b34ff5b", + }, + }, + expectedErr: nil, + }, + { + selectFunc: func(context.Context, *argoprojiov1alpha1.PullRequestGenerator, *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error) { + return pullrequest.NewFakeService( + ctx, + []*pullrequest.PullRequest{ + &pullrequest.PullRequest{ + Number: 1, + Branch: "a-very-short-sha", + HeadSHA: "abcd", + }, + }, + nil, + ) + }, + expected: []map[string]string{ + { + "number": "1", + "branch": "a-very-short-sha", + "branch_slug": "a-very-short-sha", + "head_sha": "abcd", + "head_short_sha": "abcd", }, }, expectedErr: nil, diff --git a/applicationset/generators/scm_provider.go b/applicationset/generators/scm_provider.go index 17abde67c1792..bd7b7a6adb3fc 100644 --- a/applicationset/generators/scm_provider.go +++ b/applicationset/generators/scm_provider.go @@ -120,13 +120,20 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha return nil, fmt.Errorf("error listing repos: %v", err) } params := make([]map[string]string, 0, len(repos)) + var shortSHALength int for _, repo := range repos { + shortSHALength = 8 + if len(repo.SHA) < 8 { + shortSHALength = len(repo.SHA) + } + params = append(params, map[string]string{ "organization": repo.Organization, "repository": repo.Repository, "url": repo.URL, "branch": repo.Branch, "sha": repo.SHA, + "short_sha": repo.SHA[:shortSHALength], "labels": strings.Join(repo.Labels, ","), "branchNormalized": sanitizeName(repo.Branch), }) diff --git a/applicationset/generators/scm_provider_test.go b/applicationset/generators/scm_provider_test.go index 94bcec100fda9..de072241c2b8f 100644 --- a/applicationset/generators/scm_provider_test.go +++ b/applicationset/generators/scm_provider_test.go @@ -87,7 +87,7 @@ func TestSCMProviderGenerateParams(t *testing.T) { Repository: "repo1", URL: "git@github.com:myorg/repo1.git", Branch: "main", - SHA: "abcd1234", + SHA: "0bc57212c3cbbec69d20b34c507284bd300def5b", Labels: []string{"prod", "staging"}, }, { @@ -95,7 +95,7 @@ func TestSCMProviderGenerateParams(t *testing.T) { Repository: "repo2", URL: "git@github.com:myorg/repo2.git", Branch: "main", - SHA: "00000000", + SHA: "59d0", }, }, } @@ -109,7 +109,9 @@ func TestSCMProviderGenerateParams(t *testing.T) { assert.Equal(t, "repo1", params[0]["repository"]) assert.Equal(t, "git@github.com:myorg/repo1.git", params[0]["url"]) assert.Equal(t, "main", params[0]["branch"]) - assert.Equal(t, "abcd1234", params[0]["sha"]) + assert.Equal(t, "0bc57212c3cbbec69d20b34c507284bd300def5b", params[0]["sha"]) + assert.Equal(t, "0bc57212", params[0]["short_sha"]) + assert.Equal(t, "59d0", params[1]["short_sha"]) assert.Equal(t, "prod,staging", params[0]["labels"]) assert.Equal(t, "repo2", params[1]["repository"]) } diff --git a/docs/operator-manual/applicationset/Generators-Pull-Request.md b/docs/operator-manual/applicationset/Generators-Pull-Request.md index 24b68850fa9f4..6b1bdf738ad9a 100644 --- a/docs/operator-manual/applicationset/Generators-Pull-Request.md +++ b/docs/operator-manual/applicationset/Generators-Pull-Request.md @@ -16,9 +16,9 @@ spec: ``` !!! note - Know the security implications of PR generators in ApplicationSets. + 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 + 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 @@ -82,7 +82,7 @@ spec: # Labels is used to filter the MRs that you want to target. (optional) labels: - preview - # MR state is used to filter MRs only with a certain state. (optional) + # MR state is used to filter MRs only with a certain state. (optional) pullRequestState: opened requeueAfterSeconds: 1800 template: @@ -263,8 +263,9 @@ spec: * `number`: The ID number of the pull request. * `branch`: The name of the branch of the pull request head. -* `branch_slug`: The branch name will be cleaned to be conform to the DNS label standard as defined in [RFC 1123](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names), and truncated to 50 characters to give room to append/suffix-ing it with 13 more characters. +* `branch_slug`: The branch name will be cleaned to be conform to the DNS label standard as defined in [RFC 1123](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names), and truncated to 50 characters to give room to append/suffix-ing it with 13 more characters. * `head_sha`: This is the SHA of the head of the pull request. +* `head_short_sha`: This is the short SHA of the head of the pull request (8 characters long or the length of the head SHA if it's shorter). ## Webhook Configuration diff --git a/docs/operator-manual/applicationset/Generators-SCM-Provider.md b/docs/operator-manual/applicationset/Generators-SCM-Provider.md index e1a012dc60be2..2b97fe6fc22ba 100644 --- a/docs/operator-manual/applicationset/Generators-SCM-Provider.md +++ b/docs/operator-manual/applicationset/Generators-SCM-Provider.md @@ -20,9 +20,9 @@ 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 + 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 @@ -180,7 +180,7 @@ Available clone protocols are `ssh` and `https`. ## Azure DevOps -Uses the Azure DevOps API to look up eligible repositories based on a team project within an Azure DevOps organization. +Uses the Azure DevOps API to look up eligible repositories based on a team project within an Azure DevOps organization. The default Azure DevOps URL is `https://dev.azure.com`, but this can be overridden with the field `azureDevOps.api`. ```yaml @@ -277,6 +277,7 @@ spec: * `repository`: The name of the repository. * `url`: The clone URL for the repository. * `branch`: The default branch of the repository. -* `sha`: The Git commit SHA for the branch -* `labels`: A comma-separated list of repository labels +* `sha`: The Git commit SHA for the branch. +* `short_sha`: The abbreviated Git commit SHA for the branch (8 chars or the length of the `sha` if it's shorter). +* `labels`: A comma-separated list of repository labels. * `branchNormalized`: The value of `branch` normalized to contain only lowercase alphanumeric characters, '-' or '.'. From 355025240c337c291d7f636fc791a8c935039ada Mon Sep 17 00:00:00 2001 From: Jake <86763948+notfromstatefarm@users.noreply.github.com> Date: Wed, 29 Jun 2022 16:27:02 -0400 Subject: [PATCH 13/33] fix: configurable CMP tar exclusions (#9675) (#9789) * feat: configurable CMP tar exclusions Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com> * rename cmp to plugin Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com> * add test for tar stream exclusions Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com> * fix tests Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com> * update cmp guide Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com> * fully parameterize Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com> --- USERS.md | 1 + .../commands/argocd_repo_server.go | 3 ++ .../operator-manual/argocd-cmd-params-cm.yaml | 2 + .../server-commands/argocd-repo-server.md | 1 + docs/user-guide/config-management-plugins.md | 14 +++++++ .../argocd-repo-server-deployment.yaml | 6 +++ manifests/core-install.yaml | 6 +++ manifests/ha/install.yaml | 6 +++ manifests/ha/namespace-install.yaml | 6 +++ manifests/install.yaml | 6 +++ manifests/namespace-install.yaml | 6 +++ reposerver/repository/repository.go | 38 ++++++++++++------- reposerver/repository/repository_test.go | 8 ++-- util/app/discovery/discovery.go | 16 ++++---- util/app/discovery/discovery_test.go | 14 +++---- util/cmp/stream.go | 13 +++---- util/cmp/stream_test.go | 8 ++-- util/cmp/testdata/app/DUMMY.md | 1 + util/cmp/testdata/app/dummy/DUMMY2.md | 1 + util/env/env.go | 7 ++++ 20 files changed, 120 insertions(+), 43 deletions(-) create mode 100644 util/cmp/testdata/app/DUMMY.md create mode 100644 util/cmp/testdata/app/dummy/DUMMY2.md diff --git a/USERS.md b/USERS.md index eb9de32b37652..08c7ee481f5ee 100644 --- a/USERS.md +++ b/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/) diff --git a/cmd/argocd-repo-server/commands/argocd_repo_server.go b/cmd/argocd-repo-server/commands/argocd_repo_server.go index 3644151dc1dfa..02ba3af4c5227 100644 --- a/cmd/argocd-repo-server/commands/argocd_repo_server.go +++ b/cmd/argocd-repo-server/commands/argocd_repo_server.go @@ -81,6 +81,7 @@ func NewCommand() *cobra.Command { redisClient *redis.Client disableTLS bool maxCombinedDirectoryManifestsSize string + cmpTarExcludedGlobs []string ) var command = cobra.Command{ Use: cliName, @@ -121,6 +122,7 @@ func NewCommand() *cobra.Command { PauseGenerationOnFailureForRequests: getPauseGenerationOnFailureForRequests(), SubmoduleEnabled: getSubmoduleEnabled(), MaxCombinedDirectoryManifestsSize: maxCombinedDirectoryManifestsQuantity, + CMPTarExcludedGlobs: cmpTarExcludedGlobs, }, askPassServer) errors.CheckError(err) @@ -197,6 +199,7 @@ func NewCommand() *cobra.Command { 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) { diff --git a/docs/operator-manual/argocd-cmd-params-cm.yaml b/docs/operator-manual/argocd-cmd-params-cm.yaml index 5cf37748f1549..52c45cff3c35d 100644 --- a/docs/operator-manual/argocd-cmd-params-cm.yaml +++ b/docs/operator-manual/argocd-cmd-params-cm.yaml @@ -111,3 +111,5 @@ data: # 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: "" diff --git a/docs/operator-manual/server-commands/argocd-repo-server.md b/docs/operator-manual/server-commands/argocd-repo-server.md index 95b945e053004..fe4b0c7a74338 100644 --- a/docs/operator-manual/server-commands/argocd-repo-server.md +++ b/docs/operator-manual/server-commands/argocd-repo-server.md @@ -22,6 +22,7 @@ argocd-repo-server [flags] --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. diff --git a/docs/user-guide/config-management-plugins.md b/docs/user-guide/config-management-plugins.md index 06d4cbc64a9e2..f50646272c982 100644 --- a/docs/user-guide/config-management-plugins.md +++ b/docs/user-guide/config-management-plugins.md @@ -234,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. \ No newline at end of file diff --git a/manifests/base/repo-server/argocd-repo-server-deployment.yaml b/manifests/base/repo-server/argocd-repo-server-deployment.yaml index 252bc36e64c4f..72e448455de45 100644 --- a/manifests/base/repo-server/argocd-repo-server-deployment.yaml +++ b/manifests/base/repo-server/argocd-repo-server-deployment.yaml @@ -107,6 +107,12 @@ spec: 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 diff --git a/manifests/core-install.yaml b/manifests/core-install.yaml index b8570a7aa9706..00a32c751bb1a 100644 --- a/manifests/core-install.yaml +++ b/manifests/core-install.yaml @@ -9757,6 +9757,12 @@ spec: 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 diff --git a/manifests/ha/install.yaml b/manifests/ha/install.yaml index 0119c91231725..d03bc0cd710ef 100644 --- a/manifests/ha/install.yaml +++ b/manifests/ha/install.yaml @@ -10864,6 +10864,12 @@ spec: 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 diff --git a/manifests/ha/namespace-install.yaml b/manifests/ha/namespace-install.yaml index 6747aabcb8e89..9f1159cf01f35 100644 --- a/manifests/ha/namespace-install.yaml +++ b/manifests/ha/namespace-install.yaml @@ -1638,6 +1638,12 @@ spec: 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 diff --git a/manifests/install.yaml b/manifests/install.yaml index 2a8e182e047d5..c796f1fe5e939 100644 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -10206,6 +10206,12 @@ spec: 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 diff --git a/manifests/namespace-install.yaml b/manifests/namespace-install.yaml index 5c39145baff2b..a351e12c88c2e 100644 --- a/manifests/namespace-install.yaml +++ b/manifests/namespace-install.yaml @@ -980,6 +980,12 @@ spec: 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 diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index cdfb675d63d2b..27d1234137af8 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -103,6 +103,7 @@ type RepoServerInitConstants struct { PauseGenerationOnFailureForRequests int SubmoduleEnabled bool MaxCombinedDirectoryManifestsSize resource.Quantity + CMPTarExcludedGlobs []string } // NewService returns a new instance of the Manifest service @@ -213,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 } @@ -465,7 +466,7 @@ func (s *Service) runManifestGenAsync(ctx context.Context, repoRoot, commitSHA, var manifestGenResult *apiclient.ManifestResponse opContext, err := opContextSrc() if err == nil { - manifestGenResult, err = GenerateManifests(ctx, opContext.appPath, repoRoot, commitSHA, q, false, s.gitCredsStore, s.initConstants.MaxCombinedDirectoryManifestsSize, 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 @@ -872,7 +873,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 { @@ -892,6 +894,14 @@ func WithCMPTarDoneChannel(ch chan<- bool) GenerateManifestOpt { } } +// 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...) @@ -900,7 +910,7 @@ func GenerateManifests(ctx context.Context, appPath, repoRoot, revision string, 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 } @@ -924,7 +934,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()) } @@ -1058,7 +1068,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) @@ -1075,7 +1085,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 } @@ -1479,7 +1489,7 @@ func getPluginEnvs(envVars *v1alpha1.Env, q *apiclient.ManifestRequest, creds gi 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 { @@ -1487,14 +1497,14 @@ func runConfigManagementPluginSidecars(ctx context.Context, appPath, repoPath st } // detect config management plugin server (sidecar) - conn, cmpClient, err := discovery.DetectConfigManagementPlugin(ctx, appPath, env) + 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 - 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) } @@ -1512,7 +1522,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) @@ -1520,7 +1530,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) } @@ -1538,7 +1548,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 } @@ -1653,7 +1663,7 @@ func loadFileIntoIfExists(path pathutil.ResolvedFilePath, destination *string) e info, err := os.Stat(stringPath) if err == nil && !info.IsDir() { - bytes, err := ioutil.ReadFile(stringPath); + bytes, err := ioutil.ReadFile(stringPath) if err != nil { return err } diff --git a/reposerver/repository/repository_test.go b/reposerver/repository/repository_test.go index 28ac1db2df988..a57d15401da00 100644 --- a/reposerver/repository/repository_test.go +++ b/reposerver/repository/repository_test.go @@ -1049,15 +1049,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) } @@ -1582,7 +1582,7 @@ func TestGenerateManifestsWithAppParameterFile(t *testing.T) { source := &argoappv1.ApplicationSource{ Path: path, } - sourceCopy := source.DeepCopy() // make a copy in case GenerateManifest mutates it. + sourceCopy := source.DeepCopy() // make a copy in case GenerateManifest mutates it. _, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{ Repo: &argoappv1.Repository{}, ApplicationSource: sourceCopy, diff --git a/util/app/discovery/discovery.go b/util/app/discovery/discovery.go index bda4f942ae68f..c4fb0d9051d62 100644 --- a/util/app/discovery/discovery.go +++ b/util/app/discovery/discovery.go @@ -29,11 +29,11 @@ func IsManifestGenerationEnabled(sourceType v1alpha1.ApplicationSourceType, enab return enabled } -func Discover(ctx context.Context, repoPath string, enableGenerateManifests map[string]bool) (map[string]string, error) { +func Discover(ctx context.Context, repoPath string, enableGenerateManifests map[string]bool, tarExcludedGlobs []string) (map[string]string, error) { apps := make(map[string]string) // Check if it is CMP - conn, _, err := DetectConfigManagementPlugin(ctx, repoPath, []string{}) + conn, _, err := DetectConfigManagementPlugin(ctx, repoPath, []string{}, tarExcludedGlobs) if err == nil { // Found CMP io.Close(conn) @@ -65,8 +65,8 @@ func Discover(ctx context.Context, repoPath string, enableGenerateManifests map[ return apps, err } -func AppType(ctx context.Context, path string, enableGenerateManifests map[string]bool) (string, error) { - apps, err := Discover(ctx, path, enableGenerateManifests) +func AppType(ctx context.Context, path string, enableGenerateManifests map[string]bool, tarExcludedGlobs []string) (string, error) { + apps, err := Discover(ctx, path, enableGenerateManifests, tarExcludedGlobs) if err != nil { return "", err } @@ -82,7 +82,7 @@ func AppType(ctx context.Context, path string, enableGenerateManifests map[strin // 3. check isSupported(path)? // 4.a if no then close connection // 4.b if yes then return conn for detected plugin -func DetectConfigManagementPlugin(ctx context.Context, repoPath string, env []string) (io.Closer, pluginclient.ConfigManagementPluginServiceClient, error) { +func DetectConfigManagementPlugin(ctx context.Context, repoPath string, env []string, tarExcludedGlobs []string) (io.Closer, pluginclient.ConfigManagementPluginServiceClient, error) { var conn io.Closer var cmpClient pluginclient.ConfigManagementPluginServiceClient @@ -106,7 +106,7 @@ func DetectConfigManagementPlugin(ctx context.Context, repoPath string, env []st continue } - isSupported, err := matchRepositoryCMP(ctx, repoPath, cmpClient, env) + isSupported, err := matchRepositoryCMP(ctx, repoPath, cmpClient, env, tarExcludedGlobs) if err != nil { log.Errorf("repository %s is not the match because %v", repoPath, err) continue @@ -131,13 +131,13 @@ func DetectConfigManagementPlugin(ctx context.Context, repoPath string, env []st // matchRepositoryCMP will send the repoPath to the cmp-server. The cmp-server will // inspect the files and return true if the repo is supported for manifest generation. // Will return false otherwise. -func matchRepositoryCMP(ctx context.Context, repoPath string, client pluginclient.ConfigManagementPluginServiceClient, env []string) (bool, error) { +func matchRepositoryCMP(ctx context.Context, repoPath string, client pluginclient.ConfigManagementPluginServiceClient, env []string, tarExcludedGlobs []string) (bool, error) { matchRepoStream, err := client.MatchRepository(ctx, grpc_retry.Disable()) if err != nil { return false, fmt.Errorf("error getting stream client: %s", err) } - err = cmp.SendRepoStream(ctx, repoPath, repoPath, matchRepoStream, env) + err = cmp.SendRepoStream(ctx, repoPath, repoPath, matchRepoStream, env, tarExcludedGlobs) if err != nil { return false, fmt.Errorf("error sending stream: %s", err) } diff --git a/util/app/discovery/discovery_test.go b/util/app/discovery/discovery_test.go index 3509c2466d020..d6828aea73ed5 100644 --- a/util/app/discovery/discovery_test.go +++ b/util/app/discovery/discovery_test.go @@ -10,7 +10,7 @@ import ( ) func TestDiscover(t *testing.T) { - apps, err := Discover(context.Background(), "./testdata", map[string]bool{}) + apps, err := Discover(context.Background(), "./testdata", map[string]bool{}, []string{}) assert.NoError(t, err) assert.Equal(t, map[string]string{ "foo": "Kustomize", @@ -19,15 +19,15 @@ func TestDiscover(t *testing.T) { } func TestAppType(t *testing.T) { - appType, err := AppType(context.Background(), "./testdata/foo", map[string]bool{}) + appType, err := AppType(context.Background(), "./testdata/foo", map[string]bool{}, []string{}) assert.NoError(t, err) assert.Equal(t, "Kustomize", appType) - appType, err = AppType(context.Background(), "./testdata/baz", map[string]bool{}) + appType, err = AppType(context.Background(), "./testdata/baz", map[string]bool{}, []string{}) assert.NoError(t, err) assert.Equal(t, "Helm", appType) - appType, err = AppType(context.Background(), "./testdata", map[string]bool{}) + appType, err = AppType(context.Background(), "./testdata", map[string]bool{}, []string{}) assert.NoError(t, err) assert.Equal(t, "Directory", appType) } @@ -37,15 +37,15 @@ func TestAppType_Disabled(t *testing.T) { string(v1alpha1.ApplicationSourceTypeKustomize): false, string(v1alpha1.ApplicationSourceTypeHelm): false, } - appType, err := AppType(context.Background(), "./testdata/foo", enableManifestGeneration) + appType, err := AppType(context.Background(), "./testdata/foo", enableManifestGeneration, []string{}) assert.NoError(t, err) assert.Equal(t, "Directory", appType) - appType, err = AppType(context.Background(), "./testdata/baz", enableManifestGeneration) + appType, err = AppType(context.Background(), "./testdata/baz", enableManifestGeneration, []string{}) assert.NoError(t, err) assert.Equal(t, "Directory", appType) - appType, err = AppType(context.Background(), "./testdata", enableManifestGeneration) + appType, err = AppType(context.Background(), "./testdata", enableManifestGeneration, []string{}) assert.NoError(t, err) assert.Equal(t, "Directory", appType) } diff --git a/util/cmp/stream.go b/util/cmp/stream.go index 7eb5ff8605282..ad7b8b053a0f4 100644 --- a/util/cmp/stream.go +++ b/util/cmp/stream.go @@ -84,11 +84,11 @@ func WithTarDoneChan(ch chan<- bool) SenderOption { // SendRepoStream will compress the files under the given repoPath and send // them using the plugin stream sender. -func SendRepoStream(ctx context.Context, appPath, repoPath string, sender StreamSender, env []string, opts ...SenderOption) error { +func SendRepoStream(ctx context.Context, appPath, repoPath string, sender StreamSender, env []string, excludedGlobs []string, opts ...SenderOption) error { opt := newSenderOption(opts...) // compress all files in appPath in tgz - tgz, checksum, err := compressFiles(repoPath) + tgz, checksum, err := compressFiles(repoPath, excludedGlobs) if err != nil { return fmt.Errorf("error compressing repo files: %w", err) } @@ -162,11 +162,10 @@ func closeAndDelete(f *os.File) { } // compressFiles will create a tgz file with all contents of appPath -// directory excluding the .git folder. Returns the file alongside -// its sha256 hash to be used as checksum. It is the responsibility -// of the caller to close the file. -func compressFiles(appPath string) (*os.File, string, error) { - excluded := []string{".git"} +// directory excluding globs in the excluded array. Returns the file +// alongside its sha256 hash to be used as checksum. It is the +// responsibility of the caller to close the file. +func compressFiles(appPath string, excluded []string) (*os.File, string, error) { appName := filepath.Base(appPath) tempDir, err := files.CreateTempDir(os.TempDir()) if err != nil { diff --git a/util/cmp/stream_test.go b/util/cmp/stream_test.go index fb1b5137567a4..b8d82edb75a28 100644 --- a/util/cmp/stream_test.go +++ b/util/cmp/stream_test.go @@ -60,7 +60,7 @@ func TestReceiveApplicationStream(t *testing.T) { close(streamMock.messages) os.RemoveAll(workdir) }() - go streamMock.sendFile(context.Background(), t, appDir, streamMock, []string{"env1", "env2"}) + go streamMock.sendFile(context.Background(), t, appDir, streamMock, []string{"env1", "env2"}, []string{"DUMMY.md", "dum*"}) // when env, err := cmp.ReceiveRepoStream(context.Background(), streamMock, workdir) @@ -77,16 +77,18 @@ func TestReceiveApplicationStream(t *testing.T) { } assert.Contains(t, names, "README.md") assert.Contains(t, names, "applicationset") + assert.NotContains(t, names, "DUMMY.md") + assert.NotContains(t, names, "dummy") assert.NotNil(t, env) }) } -func (m *streamMock) sendFile(ctx context.Context, t *testing.T, basedir string, sender cmp.StreamSender, env []string) { +func (m *streamMock) sendFile(ctx context.Context, t *testing.T, basedir string, sender cmp.StreamSender, env []string, excludedGlobs []string) { t.Helper() defer func() { m.done <- true }() - err := cmp.SendRepoStream(ctx, basedir, basedir, sender, env) + err := cmp.SendRepoStream(ctx, basedir, basedir, sender, env, excludedGlobs) require.NoError(t, err) } diff --git a/util/cmp/testdata/app/DUMMY.md b/util/cmp/testdata/app/DUMMY.md new file mode 100644 index 0000000000000..e5fd3704bfe4e --- /dev/null +++ b/util/cmp/testdata/app/DUMMY.md @@ -0,0 +1 @@ +This file is used to test the tar stream exclusions. \ No newline at end of file diff --git a/util/cmp/testdata/app/dummy/DUMMY2.md b/util/cmp/testdata/app/dummy/DUMMY2.md new file mode 100644 index 0000000000000..45e5aa57c0eac --- /dev/null +++ b/util/cmp/testdata/app/dummy/DUMMY2.md @@ -0,0 +1 @@ +This is another file that should get excluded because the entire directory is excluded. \ No newline at end of file diff --git a/util/env/env.go b/util/env/env.go index 3c5daeee907fe..910c4525f0210 100644 --- a/util/env/env.go +++ b/util/env/env.go @@ -126,6 +126,13 @@ func StringFromEnv(env string, defaultValue string) string { return defaultValue } +func StringsFromEnv(env string, defaultValue []string, separator string) []string { + if str := os.Getenv(env); str != "" { + return strings.Split(str, separator) + } + return defaultValue +} + // ParseBoolFromEnv retrieves a boolean value from given environment envVar. // Returns default value if envVar is not set. // From 7630d434a4e053c668f5bc86b4641c989825af28 Mon Sep 17 00:00:00 2001 From: Paulo Coelho Date: Wed, 29 Jun 2022 21:35:29 +0100 Subject: [PATCH 14/33] docs: update archlinux install with official package (#9718) Signed-off-by: Paulo Coelho --- docs/cli_installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/cli_installation.md b/docs/cli_installation.md index 931cd3f0cf50c..6951202763a08 100644 --- a/docs/cli_installation.md +++ b/docs/cli_installation.md @@ -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 From 07a54b6aea259789ceba9533c789c9389b6216bf Mon Sep 17 00:00:00 2001 From: Kent Rancourt Date: Thu, 30 Jun 2022 06:16:34 -0400 Subject: [PATCH 15/33] fix: make test-tools-image work on apple silicon (#9808) Signed-off-by: Kent --- test/container/Dockerfile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/container/Dockerfile b/test/container/Dockerfile index b4ff7cdcbbc16..a07bc8d84e163 100644 --- a/test/container/Dockerfile +++ b/test/container/Dockerfile @@ -1,5 +1,10 @@ FROM docker.io/library/redis:7.0.0 as redis +# There are libraries we will want to copy from here in the final stage of the +# build, but the COPY directive does not have a way to determine system +# architecture, so we create a symlink here to facilitate copying. +RUN ln -s /usr/lib/$(uname -m)-linux-gnu /usr/lib/linux-gnu + FROM docker.io/library/node:12.18.4-buster as node FROM docker.io/library/golang:1.18 as golang @@ -66,8 +71,11 @@ COPY --from=redis /usr/local/bin/* /usr/local/bin/ # Copy redis dependencies/shared libraries # Ubuntu 22.04+ has moved to OpenSSL3 and no longer provides these libraries -COPY --from=redis /usr/lib/x86_64-linux-gnu/libssl.so.1.1 /usr/lib/x86_64-linux-gnu/ -COPY --from=redis /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 /usr/lib/x86_64-linux-gnu/ +COPY --from=redis /usr/lib/linux-gnu/libssl.so.1.1 /usr/lib/linux-gnu/ +COPY --from=redis /usr/lib/linux-gnu/libcrypto.so.1.1 /usr/lib/linux-gnu/ +RUN mv /usr/lib/linux-gnu/libssl.so.1.1 /usr/lib/$(uname -m)-linux-gnu/ && \ + mv /usr/lib/linux-gnu/libcrypto.so.1.1 /usr/lib/$(uname -m)-linux-gnu/ && \ + rm -rf /usr/lib/linux-gnu/ # Copy registry binaries to the image COPY --from=registry /bin/registry /usr/local/bin/ From 1717eb9a47dabeb7c1fba1adaa41bdddc8f88103 Mon Sep 17 00:00:00 2001 From: Max Knee Date: Thu, 30 Jun 2022 06:33:22 -0400 Subject: [PATCH 16/33] chore: adjust docs (#9829) Signed-off-by: Max Knee --- docs/developer-guide/release-process-and-cadence.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/release-process-and-cadence.md b/docs/developer-guide/release-process-and-cadence.md index fd654e1a59d99..5e495c7fe0e51 100644 --- a/docs/developer-guide/release-process-and-cadence.md +++ b/docs/developer-guide/release-process-and-cadence.md @@ -4,7 +4,7 @@ Argo CD is being developed using the following process: * Maintainers commit to work on set of features and enhancements and create GitHub milestone to track the work. * We are trying to avoid delaying release and prefer moving the feature into the next release if we cannot complete it on time. -* The new release is published every **3 month**. +* The new release is published every **3 months**. * Critical bug-fixes are cherry-picked into the release branch and delivered using patch releases as frequently as needed. ## Release Planning From c702693380558c9fa06ddf4dee60484ab65138fc Mon Sep 17 00:00:00 2001 From: Xiao Yang Date: Thu, 30 Jun 2022 21:06:30 +0800 Subject: [PATCH 17/33] fix: support resource logs and exec (#9833) Signed-off-by: Xiao Yang --- pkg/apis/application/v1alpha1/types.go | 15 ++++++++++++++- pkg/apis/application/v1alpha1/types_test.go | 11 ++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/pkg/apis/application/v1alpha1/types.go b/pkg/apis/application/v1alpha1/types.go index 29e0c565e1902..e8860128f99c5 100644 --- a/pkg/apis/application/v1alpha1/types.go +++ b/pkg/apis/application/v1alpha1/types.go @@ -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 diff --git a/pkg/apis/application/v1alpha1/types_test.go b/pkg/apis/application/v1alpha1/types_test.go index bfefa2c935594..a06facf59debf 100644 --- a/pkg/apis/application/v1alpha1/types_test.go +++ b/pkg/apis/application/v1alpha1/types_test.go @@ -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) { From ea01fd7535176f7a5293fa022f06d8c26f0e4936 Mon Sep 17 00:00:00 2001 From: Michael Crenshaw Date: Thu, 30 Jun 2022 08:15:10 -0700 Subject: [PATCH 18/33] chore: upgrade parse-url to avoid SNYK-JS-PARSEURL-2936249 (#9826) Signed-off-by: Michael Crenshaw --- ui/yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ui/yarn.lock b/ui/yarn.lock index ab0301af3b93d..cd62427a400fa 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -6984,10 +6984,10 @@ parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse-path@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.3.tgz#82d81ec3e071dcc4ab49aa9f2c9c0b8966bb22bf" - integrity sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA== +parse-path@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.4.tgz#4bf424e6b743fb080831f03b536af9fc43f0ffea" + integrity sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw== dependencies: is-ssh "^1.3.0" protocols "^1.4.0" @@ -6995,13 +6995,13 @@ parse-path@^4.0.0: query-string "^6.13.8" parse-url@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-6.0.0.tgz#f5dd262a7de9ec00914939220410b66cff09107d" - integrity sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw== + version "6.0.2" + resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-6.0.2.tgz#4a30b057bfc452af64512dfb1a7755c103db3ea1" + integrity sha512-uCSjOvD3T+6B/sPWhR+QowAZcU/o4bjPrVBQBGFxcDF6J6FraCGIaDBsdoQawiaaAVdHvtqBe3w3vKlfBKySOQ== dependencies: is-ssh "^1.3.0" normalize-url "^6.1.0" - parse-path "^4.0.0" + parse-path "^4.0.4" protocols "^1.4.0" parse5@6.0.1: From 71c1f549c4e8e6023c8bfe8e8e5033b64c5b65a2 Mon Sep 17 00:00:00 2001 From: noah Date: Thu, 30 Jun 2022 11:20:37 -0500 Subject: [PATCH 19/33] docs: custom secret must be labeled (#9835) As far as I can tell, this isn't explicitly documented anywhere (some docs mentioned this label in reference to ConfigMaps) I only figure it out by looking at the code. --- docs/operator-manual/user-management/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/operator-manual/user-management/index.md b/docs/operator-manual/user-management/index.md index 3aaa60f88aab4..baa08269cf003 100644 --- a/docs/operator-manual/user-management/index.md +++ b/docs/operator-manual/user-management/index.md @@ -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 From ee7356a20212f7709296a8e6cd8cd7e15566285d Mon Sep 17 00:00:00 2001 From: Alexander Matyushentsev Date: Thu, 30 Jun 2022 15:28:52 -0700 Subject: [PATCH 20/33] fix: make sure api server informer does not stop after setting change (#9842) Signed-off-by: Alexander Matyushentsev --- cmd/argocd-server/commands/argocd_server.go | 1 + cmd/argocd/commands/headless/headless.go | 1 + server/server.go | 9 ++++++--- server/server_norace_test.go | 4 ++++ server/server_test.go | 3 ++- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cmd/argocd-server/commands/argocd_server.go b/cmd/argocd-server/commands/argocd_server.go index 2c7b20a366880..877a24978b68c 100644 --- a/cmd/argocd-server/commands/argocd_server.go +++ b/cmd/argocd-server/commands/argocd_server.go @@ -160,6 +160,7 @@ func NewCommand() *cobra.Command { 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 { diff --git a/cmd/argocd/commands/headless/headless.go b/cmd/argocd/commands/headless/headless.go index 3f532d60cc437..e19b954de6995 100644 --- a/cmd/argocd/commands/headless/headless.go +++ b/cmd/argocd/commands/headless/headless.go @@ -215,6 +215,7 @@ func StartLocalServer(clientOpts *apiclient.ClientOptions, ctxStr string, port * ListenHost: *address, RepoClientset: &forwardRepoClientset{namespace: namespace, context: ctxStr}, }) + srv.Init(ctx) lns, err := srv.Listen() if err != nil { diff --git a/server/server.go b/server/server.go index 28485841bb333..0c90d498ef380 100644 --- a/server/server.go +++ b/server/server.go @@ -362,6 +362,12 @@ func (a *ArgoCDServer) Listen() (*Listeners, error) { return &Listeners{Main: mainLn, Metrics: metricsLn, GatewayConn: conn}, nil } +// Init starts informers used by the API server +func (a *ArgoCDServer) Init(ctx context.Context) { + go a.projInformer.Run(ctx.Done()) + go a.appInformer.Run(ctx.Done()) +} + // Run runs the API Server // We use k8s.io/code-generator/cmd/go-to-protobuf to generate the .proto files from the API types. // k8s.io/ go-to-protobuf uses protoc-gen-gogo, which comes from gogo/protobuf (a fork of @@ -429,9 +435,6 @@ func (a *ArgoCDServer) Run(ctx context.Context, listeners *Listeners) { log.Infof("argocd %s serving on port %d (url: %s, tls: %v, namespace: %s, sso: %v)", common.GetVersion(), a.ListenPort, a.settings.URL, a.useTLS(), a.Namespace, a.settings.IsSSOConfigured()) - go a.projInformer.Run(ctx.Done()) - go a.appInformer.Run(ctx.Done()) - go func() { a.checkServeErr("grpcS", grpcS.Serve(grpcL)) }() go func() { a.checkServeErr("httpS", httpS.Serve(httpL)) }() if a.useTLS() { diff --git a/server/server_norace_test.go b/server/server_norace_test.go index 737186dd44c9e..defa7f035f030 100644 --- a/server/server_norace_test.go +++ b/server/server_norace_test.go @@ -36,6 +36,7 @@ func TestUserAgent(t *testing.T) { defer cancelInformer() ctx, cancel := context.WithCancel(context.Background()) defer cancel() + s.Init(ctx) go s.Run(ctx, lns) defer func() { time.Sleep(3 * time.Second) }() @@ -101,6 +102,7 @@ func Test_StaticHeaders(t *testing.T) { defer cancelInformer() ctx, cancel := context.WithCancel(context.Background()) defer cancel() + s.Init(ctx) go s.Run(ctx, lns) defer func() { time.Sleep(3 * time.Second) }() @@ -129,6 +131,7 @@ func Test_StaticHeaders(t *testing.T) { assert.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() + s.Init(ctx) go s.Run(ctx, lns) defer func() { time.Sleep(3 * time.Second) }() @@ -157,6 +160,7 @@ func Test_StaticHeaders(t *testing.T) { assert.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() + s.Init(ctx) go s.Run(ctx, lns) defer func() { time.Sleep(3 * time.Second) }() diff --git a/server/server_test.go b/server/server_test.go index e698ec4b7b44e..51f1b05cd1ab5 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -66,7 +66,8 @@ func fakeServer() (*ArgoCDServer, func()) { ), RedisClient: redis, } - return NewServer(context.Background(), argoCDOpts), closer + srv := NewServer(context.Background(), argoCDOpts) + return srv, closer } func TestEnforceProjectToken(t *testing.T) { From 41f72a98627aa5b592a253fa2628a9626e081ec1 Mon Sep 17 00:00:00 2001 From: usernameisnull Date: Fri, 1 Jul 2022 16:40:20 +0800 Subject: [PATCH 21/33] chore: remove semicolon from end of statement (#9837) Signed-off-by: mabing Co-authored-by: mabing From ece5de6840a4f15991460bfc8eeda55056198ac3 Mon Sep 17 00:00:00 2001 From: noah Date: Fri, 1 Jul 2022 14:53:06 -0500 Subject: [PATCH 22/33] fix: missing path segments for git file generator (#9839) * fix: missing path segments for git file generator given the path: /one/two/file.yaml This change adds the params: path[1]=two path.filename=file.yaml path.filenameNormalized The use case is for symmetry with other generators (e.g., merge with a directory generator using the key path[1]). As no existing parameter values are changed it should be non-breaking. Signed-off-by: Noah Perks Sloan * fix: expose all path elements for directory generator This makes it consistent with the files generator and removes un-intuitive behavior without any breaking change. docs: clarify - can use either baseName or nth path element docs: use "directory", like the name of the generator, where "folder" was mentioned Signed-off-by: Noah Perks Sloan --- applicationset/generators/git.go | 6 +- applicationset/generators/git_test.go | 68 ++++++++++++++++--- .../applicationset/Generators-Git.md | 17 +++-- 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/applicationset/generators/git.go b/applicationset/generators/git.go index 2919f104eba04..d12f846f174e8 100644 --- a/applicationset/generators/git.go +++ b/applicationset/generators/git.go @@ -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 } diff --git a/applicationset/generators/git_test.go b/applicationset/generators/git_test.go index 2f96981a7d6d5..18dcd20538704 100644 --- a/applicationset/generators/git_test.go +++ b/applicationset/generators/git_test.go @@ -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, diff --git a/docs/operator-manual/applicationset/Generators-Git.md b/docs/operator-manual/applicationset/Generators-Git.md index 944cdc969c0d0..78de8f51b9a17 100644 --- a/docs/operator-manual/applicationset/Generators-Git.md +++ b/docs/operator-manual/applicationset/Generators-Git.md @@ -65,15 +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). -**Note**: The right-most path name always becomes `{{path.basename}}`. For example, to use `four` as a parameter from `- path: /one/two/three/four`, use `{{path.basename}}` not `{{path[3]}}`. +**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 subfolder is added to the Git repository, the ApplicationSet controller will detect this change and automatically deploy the resulting manifests within new `Application` resources. +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: @@ -207,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`. @@ -271,12 +271,15 @@ 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 path name always becomes `{{path.basename}}`. For example, to use `four` as a parameter from `- path: /one/two/three/four/config.json`, use `{{path.basename}}` not `{{path[3]}}`. +**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 From c1d81738d3089958832908e9a2460e28387cc46a Mon Sep 17 00:00:00 2001 From: jannfis Date: Fri, 1 Jul 2022 21:56:50 +0200 Subject: [PATCH 23/33] chore: Fix import of context package across codebase (#9852) * chore: fix context imports Signed-off-by: jannfis * x/net is now imported indirectly Signed-off-by: jannfis * Make sanitizerKey a unique type Signed-off-by: jannfis --- go.mod | 2 +- server/account/account.go | 2 +- server/application/application.go | 2 +- server/certificate/certificate.go | 2 +- server/cluster/cluster.go | 2 +- server/gpgkey/gpgkey.go | 2 +- server/repocreds/repocreds.go | 2 +- server/repository/repository.go | 2 +- server/server.go | 2 +- server/settings/settings.go | 2 +- server/version/version.go | 2 +- util/db/certificate.go | 2 +- util/db/cluster.go | 2 +- util/db/repository.go | 2 +- util/db/repository_legacy.go | 2 +- util/db/repository_secrets.go | 2 +- util/db/repository_secrets_test.go | 2 +- util/db/repository_test.go | 2 +- util/db/secrets.go | 2 +- util/grpc/errors.go | 2 +- util/grpc/grpc.go | 2 +- util/grpc/logging.go | 2 +- util/grpc/sanitizer.go | 7 +++++-- util/grpc/useragent.go | 2 +- 24 files changed, 28 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 4820d766fa0d6..111b030807539 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( 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-20220525230936-793ad666bf5e - golang.org/x/net v0.0.0-20220621193019-9d032be2e588 + golang.org/x/net v0.0.0-20220621193019-9d032be2e588 // indirect 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-20210927222741-03fcf44c2211 diff --git a/server/account/account.go b/server/account/account.go index 43088d0e3ed61..30d229231dbff 100644 --- a/server/account/account.go +++ b/server/account/account.go @@ -7,9 +7,9 @@ import ( "sort" "time" + "context" "github.com/google/uuid" log "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "k8s.io/kubectl/pkg/util/slice" diff --git a/server/application/application.go b/server/application/application.go index e60895e475b3d..52e8658ca0bc8 100644 --- a/server/application/application.go +++ b/server/application/application.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "context" kubecache "github.com/argoproj/gitops-engine/pkg/cache" "github.com/argoproj/gitops-engine/pkg/diff" "github.com/argoproj/gitops-engine/pkg/sync/common" @@ -19,7 +20,6 @@ import ( "github.com/argoproj/pkg/sync" jsonpatch "github.com/evanphx/json-patch" log "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" v1 "k8s.io/api/core/v1" diff --git a/server/certificate/certificate.go b/server/certificate/certificate.go index 51989b62253c9..ed2df1e91aee2 100644 --- a/server/certificate/certificate.go +++ b/server/certificate/certificate.go @@ -1,7 +1,7 @@ package certificate import ( - "golang.org/x/net/context" + "context" certificatepkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/certificate" appsv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" diff --git a/server/cluster/cluster.go b/server/cluster/cluster.go index 70aad9ed1b068..2ee2c2f816d06 100644 --- a/server/cluster/cluster.go +++ b/server/cluster/cluster.go @@ -3,9 +3,9 @@ package cluster import ( "time" + "context" "github.com/argoproj/gitops-engine/pkg/utils/kube" log "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/server/gpgkey/gpgkey.go b/server/gpgkey/gpgkey.go index 02f316717b6de..375cb1e13a032 100644 --- a/server/gpgkey/gpgkey.go +++ b/server/gpgkey/gpgkey.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "golang.org/x/net/context" + "context" gpgkeypkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/gpgkey" appsv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" diff --git a/server/repocreds/repocreds.go b/server/repocreds/repocreds.go index add37e5a38c93..a9f34dc22ef32 100644 --- a/server/repocreds/repocreds.go +++ b/server/repocreds/repocreds.go @@ -5,7 +5,7 @@ import ( "github.com/argoproj/argo-cd/v2/util/argo" - "golang.org/x/net/context" + "context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/server/repository/repository.go b/server/repository/repository.go index 15a6af7484c41..d1a00116e96a9 100644 --- a/server/repository/repository.go +++ b/server/repository/repository.go @@ -4,10 +4,10 @@ import ( "fmt" "reflect" + "context" "github.com/argoproj/gitops-engine/pkg/utils/kube" "github.com/argoproj/gitops-engine/pkg/utils/text" log "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" apierr "k8s.io/apimachinery/pkg/api/errors" diff --git a/server/server.go b/server/server.go index 0c90d498ef380..b98c7d62e30a6 100644 --- a/server/server.go +++ b/server/server.go @@ -22,6 +22,7 @@ import ( // nolint:staticcheck golang_proto "github.com/golang/protobuf/proto" + netCtx "context" "github.com/argoproj/pkg/sync" "github.com/go-redis/redis/v8" "github.com/golang-jwt/jwt/v4" @@ -35,7 +36,6 @@ import ( log "github.com/sirupsen/logrus" "github.com/soheilhy/cmux" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" - netCtx "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" diff --git a/server/settings/settings.go b/server/settings/settings.go index 9464c7389962b..148bf321c9cdb 100644 --- a/server/settings/settings.go +++ b/server/settings/settings.go @@ -1,8 +1,8 @@ package settings import ( + "context" "github.com/ghodss/yaml" - "golang.org/x/net/context" sessionmgr "github.com/argoproj/argo-cd/v2/util/session" diff --git a/server/version/version.go b/server/version/version.go index 0d7a7339c3618..dfd88093752a8 100644 --- a/server/version/version.go +++ b/server/version/version.go @@ -1,9 +1,9 @@ package version import ( + "context" "github.com/golang/protobuf/ptypes/empty" "github.com/google/go-jsonnet" - "golang.org/x/net/context" "github.com/argoproj/argo-cd/v2/common" "github.com/argoproj/argo-cd/v2/pkg/apiclient/version" diff --git a/util/db/certificate.go b/util/db/certificate.go index 0e45705984410..5ca93a3da40a5 100644 --- a/util/db/certificate.go +++ b/util/db/certificate.go @@ -5,8 +5,8 @@ import ( "regexp" "strings" + "context" "golang.org/x/crypto/ssh" - "golang.org/x/net/context" log "github.com/sirupsen/logrus" diff --git a/util/db/cluster.go b/util/db/cluster.go index 3bde48e067fd9..c3d104d89239a 100644 --- a/util/db/cluster.go +++ b/util/db/cluster.go @@ -8,8 +8,8 @@ import ( "sync" "time" + "context" log "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" apiv1 "k8s.io/api/core/v1" diff --git a/util/db/repository.go b/util/db/repository.go index b37bf99f0a34c..256d73bfd2933 100644 --- a/util/db/repository.go +++ b/util/db/repository.go @@ -4,8 +4,8 @@ import ( "fmt" "hash/fnv" + "context" log "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" apiv1 "k8s.io/api/core/v1" diff --git a/util/db/repository_legacy.go b/util/db/repository_legacy.go index 4a6e5e5054029..0b5ffd84154f7 100644 --- a/util/db/repository_legacy.go +++ b/util/db/repository_legacy.go @@ -3,8 +3,8 @@ package db import ( "strings" + "context" log "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" apiv1 "k8s.io/api/core/v1" diff --git a/util/db/repository_secrets.go b/util/db/repository_secrets.go index c538cfd6e95af..e5663b225fc65 100644 --- a/util/db/repository_secrets.go +++ b/util/db/repository_secrets.go @@ -4,8 +4,8 @@ import ( "fmt" "strings" + "context" log "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" corev1 "k8s.io/api/core/v1" diff --git a/util/db/repository_secrets_test.go b/util/db/repository_secrets_test.go index aaa887344c1ee..8f5aa33d421d7 100644 --- a/util/db/repository_secrets_test.go +++ b/util/db/repository_secrets_test.go @@ -4,8 +4,8 @@ import ( "strconv" "testing" + "context" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" corev1 "k8s.io/api/core/v1" diff --git a/util/db/repository_test.go b/util/db/repository_test.go index a80e5cc76135e..6853fbfee785a 100644 --- a/util/db/repository_test.go +++ b/util/db/repository_test.go @@ -3,8 +3,8 @@ package db import ( "testing" + "context" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/util/db/secrets.go b/util/db/secrets.go index 1d8022e90aa9c..8ff4721e22ab8 100644 --- a/util/db/secrets.go +++ b/util/db/secrets.go @@ -8,8 +8,8 @@ import ( "strings" "time" + "context" log "github.com/sirupsen/logrus" - "golang.org/x/net/context" apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" diff --git a/util/grpc/errors.go b/util/grpc/errors.go index 41d5c128a8879..c5c0a59a3448b 100644 --- a/util/grpc/errors.go +++ b/util/grpc/errors.go @@ -3,8 +3,8 @@ package grpc import ( "errors" + "context" giterr "github.com/go-git/go-git/v5/plumbing/transport" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/util/grpc/grpc.go b/util/grpc/grpc.go index 7c4a0bd0ea6f3..cc7c1abff4c49 100644 --- a/util/grpc/grpc.go +++ b/util/grpc/grpc.go @@ -7,8 +7,8 @@ import ( "strings" "time" + "context" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" diff --git a/util/grpc/logging.go b/util/grpc/logging.go index 87152d5a276af..9b8de5d205bfc 100644 --- a/util/grpc/logging.go +++ b/util/grpc/logging.go @@ -5,12 +5,12 @@ import ( "encoding/json" "fmt" + "context" "github.com/gogo/protobuf/jsonpb" "github.com/gogo/protobuf/proto" grpc_logging "github.com/grpc-ecosystem/go-grpc-middleware/logging" ctx_logrus "github.com/grpc-ecosystem/go-grpc-middleware/tags/logrus" "github.com/sirupsen/logrus" - "golang.org/x/net/context" "google.golang.org/grpc" ) diff --git a/util/grpc/sanitizer.go b/util/grpc/sanitizer.go index 90eafd62f5aac..ffad63ba9fec2 100644 --- a/util/grpc/sanitizer.go +++ b/util/grpc/sanitizer.go @@ -5,13 +5,16 @@ import ( "regexp" "strings" - "golang.org/x/net/context" + "context" + "google.golang.org/grpc" "google.golang.org/grpc/status" ) +type sanitizerKey string + const ( - contextKey = "sanitizer" + contextKey sanitizerKey = "sanitizer" ) // ErrorSanitizerUnaryServerInterceptor returns a new unary server interceptor that sanitizes error messages diff --git a/util/grpc/useragent.go b/util/grpc/useragent.go index dd6f4f1e0db05..28b37880a7251 100644 --- a/util/grpc/useragent.go +++ b/util/grpc/useragent.go @@ -3,8 +3,8 @@ package grpc import ( "strings" + "context" "github.com/Masterminds/semver/v3" - "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" From 38009fb6cebafc4d7ee4bd29a4e992d7da53c5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Didrik=20Finn=C3=B8y?= Date: Tue, 5 Jul 2022 15:19:19 +0200 Subject: [PATCH 24/33] docs: fix outdated example in helm.md (#8506) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update helm.md The `initContainer` example for installing Helm plugins broke after of version 3.32.1 of the ArgoCD Helm chart. I've updated it with a working code example. Signed-off-by: Didrik Finnøy * docs: Updated USERS.md Signed-off-by: Didrik Finnøy --- USERS.md | 1 + docs/user-guide/helm.md | 30 +++++++----------------------- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/USERS.md b/USERS.md index 08c7ee481f5ee..00f9eff028570 100644 --- a/USERS.md +++ b/USERS.md @@ -27,6 +27,7 @@ Currently, the following organizations are **officially** using Argo CD: 1. [BigPanda](https://bigpanda.io) 1. [BioBox Analytics](https://biobox.io) 1. [BMW Group](https://www.bmwgroup.com/) +1. [Bulder Bank](https://bulderbank.no) 1. [Boozt](https://www.booztgroup.com/) 1. [Boticario](https://www.boticario.com.br/) 1. [Camptocamp](https://camptocamp.com) diff --git a/docs/user-guide/helm.md b/docs/user-guide/helm.md index e2957c3b2484e..918f9b3678298 100644 --- a/docs/user-guide/helm.md +++ b/docs/user-guide/helm.md @@ -209,53 +209,37 @@ Some users find this pattern preferable to maintaining their own version of the Below is an example of how to add Helm plugins when installing ArgoCD with the [official ArgoCD helm chart](https://github.com/argoproj/argo-helm/tree/master/charts/argo-cd): ``` -# helm-gcs plugin repoServer: volumes: - - name: helm - emptyDir: {} - name: gcloud secret: secretName: helm-credentials volumeMounts: - - mountPath: /helm - name: helm - mountPath: /gcloud name: gcloud env: - - name: HELM_DATA_HOME - value: /helm - - name: HELM_CACHE_HOME - value: /helm/cache - - name: HELM_CONFIG_HOME - value: /helm/config - name: HELM_PLUGINS - value: /helm/plugins/ + value: /helm-working-dir/plugins/ - name: GOOGLE_APPLICATION_CREDENTIALS value: /gcloud/key.json initContainers: - name: install-helm-plugins - image: alpine/helm:3.6.3 + image: alpine/helm:3.8.0 volumeMounts: - - mountPath: /helm - name: helm + - mountPath: /helm-working-dir + name: helm-working-dir - mountPath: /gcloud name: gcloud env: - - name: HELM_DATA_HOME - value: /helm - - name: HELM_CACHE_HOME - value: /helm/cache - - name: HELM_CONFIG_HOME - value: /helm/config - name: GOOGLE_APPLICATION_CREDENTIALS value: /gcloud/key.json + - name: HELM_PLUGINS + value: /helm-working-dir/plugins command: ["/bin/sh", "-c"] args: - apk --no-cache add curl; helm plugin install https://github.com/hayorov/helm-gcs.git; - helm repo add my-gcs-repo gs://my-private-helm-gcs-repository; - chmod -R 777 $HELM_DATA_HOME; + helm repo add my-private-gcs-repo gs://my-private-gcs-repo; ``` ## Helm Version From ae19965ff75fd6ba199914b258d751d6b7ea876c Mon Sep 17 00:00:00 2001 From: Kent Rancourt Date: Tue, 5 Jul 2022 09:32:22 -0400 Subject: [PATCH 25/33] refactor: improve context handling in cmd/ (#9860) Signed-off-by: Kent --- .../commands/argocd_application_controller.go | 6 +- .../commands/applicationset_controller.go | 9 +- .../commands/argocd_cmp_server.go | 5 +- cmd/argocd-dex/commands/argocd_dex.go | 9 +- .../commands/argocd_git_ask_pass.go | 7 +- cmd/argocd-k8s-auth/commands/aws.go | 8 +- cmd/argocd-k8s-auth/commands/aws_test.go | 9 +- cmd/argocd-k8s-auth/commands/gcp.go | 5 +- .../commands/controller.go | 9 +- .../commands/argocd_repo_server.go | 5 +- cmd/argocd-server/commands/argocd_server.go | 7 +- cmd/argocd/commands/account.go | 36 +++-- cmd/argocd/commands/admin/app.go | 22 +-- cmd/argocd/commands/admin/app_test.go | 9 +- cmd/argocd/commands/admin/backup.go | 39 +++--- cmd/argocd/commands/admin/cluster.go | 68 +++++---- cmd/argocd/commands/admin/dashboard.go | 7 +- cmd/argocd/commands/admin/project.go | 14 +- cmd/argocd/commands/admin/project_test.go | 14 +- cmd/argocd/commands/admin/repo.go | 9 +- cmd/argocd/commands/admin/settings.go | 34 +++-- cmd/argocd/commands/admin/settings_rbac.go | 16 ++- .../commands/admin/settings_rbac_test.go | 17 ++- cmd/argocd/commands/admin/settings_test.go | 10 +- cmd/argocd/commands/app.go | 131 +++++++++++------- cmd/argocd/commands/app_actions.go | 9 +- cmd/argocd/commands/app_resources.go | 11 +- cmd/argocd/commands/cert.go | 16 ++- cmd/argocd/commands/cluster.go | 23 ++- cmd/argocd/commands/gpg.go | 17 ++- cmd/argocd/commands/headless/headless.go | 13 +- cmd/argocd/commands/login.go | 9 +- cmd/argocd/commands/project.go | 85 ++++++++---- cmd/argocd/commands/project_role.go | 57 +++++--- cmd/argocd/commands/projectwindows.go | 35 +++-- cmd/argocd/commands/relogin.go | 6 +- cmd/argocd/commands/repo.go | 19 ++- cmd/argocd/commands/repocreds.go | 13 +- cmd/argocd/commands/version.go | 10 +- 39 files changed, 519 insertions(+), 309 deletions(-) diff --git a/cmd/argocd-application-controller/commands/argocd_application_controller.go b/cmd/argocd-application-controller/commands/argocd_application_controller.go index 4eec3d1f5d3d7..4bb4c4a355594 100644 --- a/cmd/argocd-application-controller/commands/argocd_application_controller.go +++ b/cmd/argocd-application-controller/commands/argocd_application_controller.go @@ -67,6 +67,9 @@ func NewCommand() *cobra.Command { Long: "ArgoCD application controller is a Kubernetes controller that continuously monitors running applications and compares the current, live state against the desired target state (as specified in the repo). This command runs Application Controller in the foreground. It can be configured by following options.", DisableAutoGenTag: true, RunE: func(c *cobra.Command, args []string) error { + ctx, cancel := context.WithCancel(c.Context()) + defer cancel() + vers := common.GetVersion() namespace, _, err := clientConfig.Namespace() errors.CheckError(err) @@ -119,9 +122,6 @@ func NewCommand() *cobra.Command { repoClientset := apiclient.NewRepoServerClientset(repoServerAddress, repoServerTimeoutSeconds, tlsConfig) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - cache, err := cacheSrc() errors.CheckError(err) cache.Cache.SetClient(cacheutil.NewTwoLevelClient(cache.Cache.GetClient(), 10*time.Minute)) diff --git a/cmd/argocd-applicationset-controller/commands/applicationset_controller.go b/cmd/argocd-applicationset-controller/commands/applicationset_controller.go index 7a18b2d4f050d..33904748219dd 100644 --- a/cmd/argocd-applicationset-controller/commands/applicationset_controller.go +++ b/cmd/argocd-applicationset-controller/commands/applicationset_controller.go @@ -1,7 +1,6 @@ package command import ( - "context" "fmt" "net/http" "os" @@ -60,6 +59,8 @@ func NewCommand() *cobra.Command { Use: "controller", Short: "Starts Argo CD ApplicationSet controller", RunE: func(c *cobra.Command, args []string) error { + ctx := c.Context() + vers := common.GetVersion() namespace, _, err := clientConfig.Namespace() errors.CheckError(err) @@ -123,7 +124,7 @@ func NewCommand() *cobra.Command { if err != nil { return err } - argoSettingsMgr := argosettings.NewSettingsManager(context.Background(), k8sClient, namespace) + argoSettingsMgr := argosettings.NewSettingsManager(ctx, k8sClient, namespace) appSetConfig := appclientset.NewForConfigOrDie(mgr.GetConfig()) argoCDDB := db.NewDB(namespace, argoSettingsMgr, k8sClient) // start a webhook server that listens to incoming webhook payloads @@ -139,10 +140,10 @@ func NewCommand() *cobra.Command { go func() { errors.CheckError(askPassServer.Run(askpass.SocketPath)) }() terminalGenerators := map[string]generators.Generator{ "List": generators.NewListGenerator(), - "Clusters": generators.NewClusterGenerator(mgr.GetClient(), context.Background(), k8sClient, namespace), + "Clusters": generators.NewClusterGenerator(mgr.GetClient(), ctx, k8sClient, namespace), "Git": generators.NewGitGenerator(services.NewArgoCDService(argoCDDB, askPassServer, argocdRepoServer)), "SCMProvider": generators.NewSCMProviderGenerator(mgr.GetClient()), - "ClusterDecisionResource": generators.NewDuckTypeGenerator(context.Background(), dynamicClient, k8sClient, namespace), + "ClusterDecisionResource": generators.NewDuckTypeGenerator(ctx, dynamicClient, k8sClient, namespace), "PullRequest": generators.NewPullRequestGenerator(mgr.GetClient()), } diff --git a/cmd/argocd-cmp-server/commands/argocd_cmp_server.go b/cmd/argocd-cmp-server/commands/argocd_cmp_server.go index 2ba46a153e1f2..ffb5eccc2f450 100644 --- a/cmd/argocd-cmp-server/commands/argocd_cmp_server.go +++ b/cmd/argocd-cmp-server/commands/argocd_cmp_server.go @@ -1,7 +1,6 @@ package commands import ( - "context" "time" "github.com/argoproj/pkg/stats" @@ -34,6 +33,8 @@ func NewCommand() *cobra.Command { Long: "ArgoCD ConfigManagementPlugin Server is an internal service which runs as sidecar container in reposerver deployment. It can be configured by following options.", DisableAutoGenTag: true, RunE: func(c *cobra.Command, args []string) error { + ctx := c.Context() + vers := common.GetVersion() vers.LogStartupInfo("ArgoCD ConfigManagementPlugin Server", nil) @@ -46,7 +47,7 @@ func NewCommand() *cobra.Command { if otlpAddress != "" { var closer func() var err error - closer, err = traceutil.InitTracer(context.Background(), "argocd-cmp-server", otlpAddress) + closer, err = traceutil.InitTracer(ctx, "argocd-cmp-server", otlpAddress) if err != nil { log.Fatalf("failed to initialize tracing: %v", err) } diff --git a/cmd/argocd-dex/commands/argocd_dex.go b/cmd/argocd-dex/commands/argocd_dex.go index a706388fc02cf..39644e9227513 100644 --- a/cmd/argocd-dex/commands/argocd_dex.go +++ b/cmd/argocd-dex/commands/argocd_dex.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "io/ioutil" "os" @@ -51,6 +50,8 @@ func NewRunDexCommand() *cobra.Command { Use: "rundex", Short: "Runs dex generating a config using settings from the Argo CD configmap and secret", RunE: func(c *cobra.Command, args []string) error { + ctx := c.Context() + vers := common.GetVersion() namespace, _, err := clientConfig.Namespace() errors.CheckError(err) @@ -70,7 +71,7 @@ func NewRunDexCommand() *cobra.Command { config.UserAgent = fmt.Sprintf("argocd-dex/%s (%s)", vers.Version, vers.Platform) kubeClientset := kubernetes.NewForConfigOrDie(config) - settingsMgr := settings.NewSettingsManager(context.Background(), kubeClientset, namespace) + settingsMgr := settings.NewSettingsManager(ctx, kubeClientset, namespace) prevSettings, err := settingsMgr.GetSettings() errors.CheckError(err) updateCh := make(chan *settings.ArgoCDSettings, 1) @@ -131,6 +132,8 @@ func NewGenDexConfigCommand() *cobra.Command { Use: "gendexcfg", Short: "Generates a dex config from Argo CD settings", RunE: func(c *cobra.Command, args []string) error { + ctx := c.Context() + cli.SetLogFormat(cmdutil.LogFormat) cli.SetLogLevel(cmdutil.LogLevel) config, err := clientConfig.ClientConfig() @@ -138,7 +141,7 @@ func NewGenDexConfigCommand() *cobra.Command { namespace, _, err := clientConfig.Namespace() errors.CheckError(err) kubeClientset := kubernetes.NewForConfigOrDie(config) - settingsMgr := settings.NewSettingsManager(context.Background(), kubeClientset, namespace) + settingsMgr := settings.NewSettingsManager(ctx, kubeClientset, namespace) settings, err := settingsMgr.GetSettings() errors.CheckError(err) dexCfgBytes, err := dex.GenerateDexConfigYAML(settings) diff --git a/cmd/argocd-git-ask-pass/commands/argocd_git_ask_pass.go b/cmd/argocd-git-ask-pass/commands/argocd_git_ask_pass.go index 858088b548434..8f457527b78b2 100644 --- a/cmd/argocd-git-ask-pass/commands/argocd_git_ask_pass.go +++ b/cmd/argocd-git-ask-pass/commands/argocd_git_ask_pass.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "os" "strings" @@ -29,6 +28,8 @@ func NewCommand() *cobra.Command { Short: "Argo CD git credential helper", DisableAutoGenTag: true, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(os.Args) != 2 { errors.CheckError(fmt.Errorf("expected 1 argument, got %d", len(os.Args)-1)) } @@ -36,12 +37,12 @@ func NewCommand() *cobra.Command { if nonce == "" { errors.CheckError(fmt.Errorf("%s is not set", git.ASKPASS_NONCE_ENV)) } - conn, err := grpc_util.BlockingDial(context.Background(), "unix", askpass.SocketPath, nil, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc_util.BlockingDial(ctx, "unix", askpass.SocketPath, nil, grpc.WithTransportCredentials(insecure.NewCredentials())) errors.CheckError(err) defer io.Close(conn) client := askpass.NewAskPassServiceClient(conn) - creds, err := client.GetCredentials(context.Background(), &askpass.CredentialsRequest{Nonce: nonce}) + creds, err := client.GetCredentials(ctx, &askpass.CredentialsRequest{Nonce: nonce}) errors.CheckError(err) switch { case strings.HasPrefix(os.Args[1], "Username"): diff --git a/cmd/argocd-k8s-auth/commands/aws.go b/cmd/argocd-k8s-auth/commands/aws.go index c75bfa5c4a1a7..79a118d2653a3 100644 --- a/cmd/argocd-k8s-auth/commands/aws.go +++ b/cmd/argocd-k8s-auth/commands/aws.go @@ -41,7 +41,9 @@ func newAWSCommand() *cobra.Command { var command = &cobra.Command{ Use: "aws", Run: func(c *cobra.Command, args []string) { - presignedURLString, err := getSignedRequestWithRetry(time.Minute, 5*time.Second, clusterName, roleARN, getSignedRequest) + ctx := c.Context() + + presignedURLString, err := getSignedRequestWithRetry(ctx, 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 @@ -56,8 +58,8 @@ func newAWSCommand() *cobra.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) +func getSignedRequestWithRetry(ctx context.Context, timeout, interval time.Duration, clusterName, roleARN string, fn getSignedRequestFunc) (string, error) { + ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() for { signed, err := fn(clusterName, roleARN) diff --git a/cmd/argocd-k8s-auth/commands/aws_test.go b/cmd/argocd-k8s-auth/commands/aws_test.go index ea403c04b0be7..c22449eba42be 100644 --- a/cmd/argocd-k8s-auth/commands/aws_test.go +++ b/cmd/argocd-k8s-auth/commands/aws_test.go @@ -1,6 +1,7 @@ package commands import ( + "context" "fmt" "testing" "time" @@ -9,6 +10,8 @@ import ( ) func TestGetSignedRequestWithRetry(t *testing.T) { + ctx := context.Background() + t.Run("will return signed request on first attempt", func(t *testing.T) { // given t.Parallel() @@ -19,7 +22,7 @@ func TestGetSignedRequestWithRetry(t *testing.T) { } // when - signed, err := getSignedRequestWithRetry(time.Second, time.Millisecond, "cluster-name", "", mock.getSignedRequestMock) + signed, err := getSignedRequestWithRetry(ctx, time.Second, time.Millisecond, "cluster-name", "", mock.getSignedRequestMock) // then assert.NoError(t, err) @@ -38,7 +41,7 @@ func TestGetSignedRequestWithRetry(t *testing.T) { } // when - signed, err := getSignedRequestWithRetry(time.Second, time.Millisecond, "cluster-name", "", mock.getSignedRequestMock) + signed, err := getSignedRequestWithRetry(ctx, time.Second, time.Millisecond, "cluster-name", "", mock.getSignedRequestMock) // then assert.NoError(t, err) @@ -54,7 +57,7 @@ func TestGetSignedRequestWithRetry(t *testing.T) { } // when - signed, err := getSignedRequestWithRetry(time.Second, time.Millisecond, "cluster-name", "", mock.getSignedRequestMock) + signed, err := getSignedRequestWithRetry(ctx, time.Second, time.Millisecond, "cluster-name", "", mock.getSignedRequestMock) // then assert.Error(t, err) diff --git a/cmd/argocd-k8s-auth/commands/gcp.go b/cmd/argocd-k8s-auth/commands/gcp.go index 8d7bd975a9ede..65d9c9ffe3325 100644 --- a/cmd/argocd-k8s-auth/commands/gcp.go +++ b/cmd/argocd-k8s-auth/commands/gcp.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "os" @@ -27,9 +26,11 @@ func newGCPCommand() *cobra.Command { var command = &cobra.Command{ Use: "gcp", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + // Preferred way to retrieve GCP credentials // https://github.com/golang/oauth2/blob/9780585627b5122c8cc9c6a378ac9861507e7551/google/doc.go#L54-L68 - cred, err := google.FindDefaultCredentials(context.Background(), defaultGCPScopes...) + cred, err := google.FindDefaultCredentials(ctx, defaultGCPScopes...) errors.CheckError(err) token, err := cred.TokenSource.Token() errors.CheckError(err) diff --git a/cmd/argocd-notification/commands/controller.go b/cmd/argocd-notification/commands/controller.go index 4c4330d540410..4669944d2e51d 100644 --- a/cmd/argocd-notification/commands/controller.go +++ b/cmd/argocd-notification/commands/controller.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "net/http" "os" @@ -58,6 +57,8 @@ func NewCommand() *cobra.Command { Use: "controller", Short: "Starts Argo CD Notifications controller", RunE: func(c *cobra.Command, args []string) error { + ctx := c.Context() + vers := common.GetVersion() namespace, _, err := clientConfig.Namespace() errors.CheckError(err) @@ -120,13 +121,13 @@ func NewCommand() *cobra.Command { log.Infof("loading configuration %d", metricsPort) ctrl := notificationscontroller.NewController(k8sClient, dynamicClient, argocdService, namespace, appLabelSelector, registry, secretName, configMapName) - err = ctrl.Init(context.Background()) + err = ctrl.Init(ctx) if err != nil { return err } - go ctrl.Run(context.Background(), processorsCount) - <-context.Background().Done() + go ctrl.Run(ctx, processorsCount) + <-ctx.Done() return nil }, } diff --git a/cmd/argocd-repo-server/commands/argocd_repo_server.go b/cmd/argocd-repo-server/commands/argocd_repo_server.go index 02ba3af4c5227..d886f40f89bb7 100644 --- a/cmd/argocd-repo-server/commands/argocd_repo_server.go +++ b/cmd/argocd-repo-server/commands/argocd_repo_server.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "math" "net" @@ -89,6 +88,8 @@ func NewCommand() *cobra.Command { Long: "ArgoCD Repository Server is an internal service which maintains a local cache of the Git repository holding the application manifests, and is responsible for generating and returning the Kubernetes manifests. This command runs Repository Server in the foreground. It can be configured by following options.", DisableAutoGenTag: true, RunE: func(c *cobra.Command, args []string) error { + ctx := c.Context() + vers := common.GetVersion() vers.LogStartupInfo( "ArgoCD Repository Server", @@ -129,7 +130,7 @@ func NewCommand() *cobra.Command { if otlpAddress != "" { var closer func() var err error - closer, err = traceutil.InitTracer(context.Background(), "argocd-repo-server", otlpAddress) + closer, err = traceutil.InitTracer(ctx, "argocd-repo-server", otlpAddress) if err != nil { log.Fatalf("failed to initialize tracing: %v", err) } diff --git a/cmd/argocd-server/commands/argocd_server.go b/cmd/argocd-server/commands/argocd_server.go index 877a24978b68c..af85230870747 100644 --- a/cmd/argocd-server/commands/argocd_server.go +++ b/cmd/argocd-server/commands/argocd_server.go @@ -74,6 +74,8 @@ func NewCommand() *cobra.Command { Long: "The API server is a gRPC/REST server which exposes the API consumed by the Web UI, CLI, and CI/CD systems. This command runs API server in the foreground. It can be configured by following options.", DisableAutoGenTag: true, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + vers := common.GetVersion() namespace, _, err := clientConfig.Namespace() errors.CheckError(err) @@ -159,13 +161,12 @@ func NewCommand() *cobra.Command { stats.RegisterStackDumper() stats.StartStatsTicker(10 * time.Minute) stats.RegisterHeapDumper("memprofile") - argocd := server.NewServer(context.Background(), argoCDOpts) - argocd.Init(context.Background()) + argocd := server.NewServer(ctx, argoCDOpts) + argocd.Init(ctx) lns, err := argocd.Listen() errors.CheckError(err) for { var closer func() - ctx := context.Background() ctx, cancel := context.WithCancel(ctx) if otlpAddress != "" { closer, err = traceutil.InitTracer(ctx, "argocd-server", otlpAddress) diff --git a/cmd/argocd/commands/account.go b/cmd/argocd/commands/account.go index 419ac24b3e78d..33beaf840b2c2 100644 --- a/cmd/argocd/commands/account.go +++ b/cmd/argocd/commands/account.go @@ -69,6 +69,8 @@ has appropriate RBAC permissions to change other accounts. argocd account update-password --account foobar `, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -77,7 +79,7 @@ has appropriate RBAC permissions to change other accounts. conn, usrIf := acdClient.NewAccountClientOrDie() defer io.Close(conn) - userInfo := getCurrentAccount(acdClient) + userInfo := getCurrentAccount(ctx, acdClient) if userInfo.Iss == sessionutil.SessionManagerClaimsIssuer && currentPassword == "" { fmt.Printf("*** Enter password of currently logged in user (%s): ", userInfo.Username) @@ -103,7 +105,6 @@ has appropriate RBAC permissions to change other accounts. Name: account, } - ctx := context.Background() _, err := usrIf.UpdatePassword(ctx, &updatePasswordRequest) errors.CheckError(err) fmt.Printf("Password updated\n") @@ -116,7 +117,7 @@ has appropriate RBAC permissions to change other accounts. errors.CheckError(err) claims, err := configCtx.User.Claims() errors.CheckError(err) - tokenString := passwordLogin(acdClient, localconfig.GetUsername(claims.Subject), newPassword) + tokenString := passwordLogin(ctx, acdClient, localconfig.GetUsername(claims.Subject), newPassword) localCfg.UpsertUser(localconfig.User{ Name: localCfg.CurrentContext, AuthToken: tokenString, @@ -142,6 +143,8 @@ func NewAccountGetUserInfoCommand(clientOpts *argocdclient.ClientOptions) *cobra Use: "get-user-info", Short: "Get user info", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -150,7 +153,6 @@ func NewAccountGetUserInfoCommand(clientOpts *argocdclient.ClientOptions) *cobra conn, client := headless.NewClientOrDie(clientOpts, c).NewSessionClientOrDie() defer io.Close(conn) - ctx := context.Background() response, err := client.GetUserInfo(ctx, &session.GetUserInfoRequest{}) errors.CheckError(err) @@ -197,6 +199,8 @@ Actions: %v Resources: %v `, rbacpolicy.Actions, rbacpolicy.Resources), Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -205,7 +209,6 @@ Resources: %v conn, client := headless.NewClientOrDie(clientOpts, c).NewAccountClientOrDie() defer io.Close(conn) - ctx := context.Background() response, err := client.CanI(ctx, &accountpkg.CanIRequest{ Action: args[0], Resource: args[1], @@ -241,11 +244,11 @@ func NewAccountListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman Short: "List accounts", Example: "argocd account list", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() conn, client := headless.NewClientOrDie(clientOpts, c).NewAccountClientOrDie() defer io.Close(conn) - ctx := context.Background() response, err := client.ListAccounts(ctx, &accountpkg.ListAccountRequest{}) errors.CheckError(err) @@ -266,10 +269,10 @@ func NewAccountListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman return cmd } -func getCurrentAccount(clientset argocdclient.Client) session.GetUserInfoResponse { +func getCurrentAccount(ctx context.Context, clientset argocdclient.Client) session.GetUserInfoResponse { conn, client := clientset.NewSessionClientOrDie() defer io.Close(conn) - userInfo, err := client.GetUserInfo(context.Background(), &session.GetUserInfoRequest{}) + userInfo, err := client.GetUserInfo(ctx, &session.GetUserInfoRequest{}) errors.CheckError(err) return *userInfo } @@ -288,16 +291,18 @@ argocd account get # Get details for an account by name argocd account get --account `, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + clientset := headless.NewClientOrDie(clientOpts, c) if account == "" { - account = getCurrentAccount(clientset).Username + account = getCurrentAccount(ctx, clientset).Username } conn, client := clientset.NewAccountClientOrDie() defer io.Close(conn) - acc, err := client.GetAccount(context.Background(), &accountpkg.GetAccountRequest{Name: account}) + acc, err := client.GetAccount(ctx, &accountpkg.GetAccountRequest{Name: account}) errors.CheckError(err) switch output { @@ -359,16 +364,17 @@ argocd account generate-token # Generate token for the account with the specified name argocd account generate-token --account `, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() clientset := headless.NewClientOrDie(clientOpts, c) conn, client := clientset.NewAccountClientOrDie() defer io.Close(conn) if account == "" { - account = getCurrentAccount(clientset).Username + account = getCurrentAccount(ctx, clientset).Username } expiresIn, err := timeutil.ParseDuration(expiresIn) errors.CheckError(err) - response, err := client.CreateToken(context.Background(), &accountpkg.CreateTokenRequest{ + response, err := client.CreateToken(ctx, &accountpkg.CreateTokenRequest{ Name: account, ExpiresIn: int64(expiresIn.Seconds()), Id: id, @@ -396,6 +402,8 @@ argocd account delete-token ID # Delete token of the account with the specified name argocd account delete-token --account ID`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -406,9 +414,9 @@ argocd account delete-token --account ID`, conn, client := clientset.NewAccountClientOrDie() defer io.Close(conn) if account == "" { - account = getCurrentAccount(clientset).Username + account = getCurrentAccount(ctx, clientset).Username } - _, err := client.DeleteToken(context.Background(), &accountpkg.DeleteTokenRequest{Name: account, Id: id}) + _, err := client.DeleteToken(ctx, &accountpkg.DeleteTokenRequest{Name: account, Id: id}) errors.CheckError(err) }, } diff --git a/cmd/argocd/commands/admin/app.go b/cmd/argocd/commands/admin/app.go index 6073daa33f22f..83ad78b61605e 100644 --- a/cmd/argocd/commands/admin/app.go +++ b/cmd/argocd/commands/admin/app.go @@ -238,6 +238,8 @@ func NewReconcileCommand() *cobra.Command { Use: "get-reconcile-results PATH", Short: "Reconcile all applications and stores reconciliation summary in the specified file.", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + // get rid of logging error handler runtime.ErrorHandlers = runtime.ErrorHandlers[1:] @@ -266,11 +268,11 @@ func NewReconcileCommand() *cobra.Command { appClientset := appclientset.NewForConfigOrDie(cfg) kubeClientset := kubernetes.NewForConfigOrDie(cfg) - result, err = reconcileApplications(kubeClientset, appClientset, namespace, repoServerClient, selector, newLiveStateCache) + result, err = reconcileApplications(ctx, kubeClientset, appClientset, namespace, repoServerClient, selector, newLiveStateCache) errors.CheckError(err) } else { appClientset := appclientset.NewForConfigOrDie(cfg) - result, err = getReconcileResults(appClientset, namespace, selector) + result, err = getReconcileResults(ctx, appClientset, namespace, selector) } errors.CheckError(saveToFile(err, outputFormat, reconcileResults{Applications: result}, outputPath)) @@ -304,8 +306,8 @@ func saveToFile(err error, outputFormat string, result reconcileResults, outputP return ioutil.WriteFile(outputPath, data, 0644) } -func getReconcileResults(appClientset appclientset.Interface, namespace string, selector string) ([]appReconcileResult, error) { - appsList, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(context.Background(), v1.ListOptions{LabelSelector: selector}) +func getReconcileResults(ctx context.Context, appClientset appclientset.Interface, namespace string, selector string) ([]appReconcileResult, error) { + appsList, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(ctx, v1.ListOptions{LabelSelector: selector}) if err != nil { return nil, err } @@ -323,6 +325,7 @@ func getReconcileResults(appClientset appclientset.Interface, namespace string, } func reconcileApplications( + ctx context.Context, kubeClientset kubernetes.Interface, appClientset appclientset.Interface, namespace string, @@ -330,8 +333,7 @@ func reconcileApplications( selector string, createLiveStateCache func(argoDB db.ArgoDB, appInformer kubecache.SharedIndexInformer, settingsMgr *settings.SettingsManager, server *metrics.MetricsServer) cache.LiveStateCache, ) ([]appReconcileResult, error) { - - settingsMgr := settings.NewSettingsManager(context.Background(), kubeClientset, namespace) + settingsMgr := settings.NewSettingsManager(ctx, kubeClientset, namespace) argoDB := db.NewDB(namespace, settingsMgr, kubeClientset) appInformerFactory := appinformers.NewSharedInformerFactoryWithOptions( appClientset, @@ -342,9 +344,9 @@ func reconcileApplications( appInformer := appInformerFactory.Argoproj().V1alpha1().Applications().Informer() projInformer := appInformerFactory.Argoproj().V1alpha1().AppProjects().Informer() - go appInformer.Run(context.Background().Done()) - go projInformer.Run(context.Background().Done()) - if !kubecache.WaitForCacheSync(context.Background().Done(), appInformer.HasSynced, projInformer.HasSynced) { + go appInformer.Run(ctx.Done()) + go projInformer.Run(ctx.Done()) + if !kubecache.WaitForCacheSync(ctx.Done(), appInformer.HasSynced, projInformer.HasSynced) { return nil, fmt.Errorf("failed to sync cache") } @@ -372,7 +374,7 @@ func reconcileApplications( appStateManager := controller.NewAppStateManager( argoDB, appClientset, repoServerClient, namespace, kubeutil.NewKubectl(), settingsMgr, stateCache, projInformer, server, cache, time.Second, argo.NewResourceTracking()) - appsList, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(context.Background(), v1.ListOptions{LabelSelector: selector}) + appsList, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(ctx, v1.ListOptions{LabelSelector: selector}) if err != nil { return nil, err } diff --git a/cmd/argocd/commands/admin/app_test.go b/cmd/argocd/commands/admin/app_test.go index 7605796b22430..dbb0bd245915d 100644 --- a/cmd/argocd/commands/admin/app_test.go +++ b/cmd/argocd/commands/admin/app_test.go @@ -1,6 +1,7 @@ package admin import ( + "context" "testing" clustermocks "github.com/argoproj/gitops-engine/pkg/cache/mocks" @@ -27,6 +28,8 @@ import ( ) func TestGetReconcileResults(t *testing.T) { + ctx := context.Background() + appClientset := appfake.NewSimpleClientset(&v1alpha1.Application{ ObjectMeta: metav1.ObjectMeta{ Name: "test", @@ -38,7 +41,7 @@ func TestGetReconcileResults(t *testing.T) { }, }) - result, err := getReconcileResults(appClientset, "default", "") + result, err := getReconcileResults(ctx, appClientset, "default", "") if !assert.NoError(t, err) { return } @@ -52,6 +55,8 @@ func TestGetReconcileResults(t *testing.T) { } func TestGetReconcileResults_Refresh(t *testing.T) { + ctx := context.Background() + cm := corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "argocd-cm", @@ -103,7 +108,7 @@ func TestGetReconcileResults_Refresh(t *testing.T) { liveStateCache.On("GetClusterCache", mock.Anything).Return(&clusterCache, nil) liveStateCache.On("IsNamespaced", mock.Anything, mock.Anything).Return(true, nil) - result, err := reconcileApplications(kubeClientset, appClientset, "default", &repoServerClientset, "", + result, err := reconcileApplications(ctx, kubeClientset, appClientset, "default", &repoServerClientset, "", func(argoDB db.ArgoDB, appInformer cache.SharedIndexInformer, settingsMgr *settings.SettingsManager, server *metrics.MetricsServer) statecache.LiveStateCache { return &liveStateCache }, diff --git a/cmd/argocd/commands/admin/backup.go b/cmd/argocd/commands/admin/backup.go index bd7990edf0cce..f8d1543b89566 100644 --- a/cmd/argocd/commands/admin/backup.go +++ b/cmd/argocd/commands/admin/backup.go @@ -2,7 +2,6 @@ package admin import ( "bufio" - "context" "fmt" "io" "io/ioutil" @@ -33,6 +32,8 @@ func NewExportCommand() *cobra.Command { Use: "export", Short: "Export all Argo CD data to stdout (default) or a file", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + config, err := clientConfig.ClientConfig() errors.CheckError(err) namespace, _, err := clientConfig.Namespace() @@ -55,38 +56,38 @@ func NewExportCommand() *cobra.Command { } acdClients := newArgoCDClientsets(config, namespace) - acdConfigMap, err := acdClients.configMaps.Get(context.Background(), common.ArgoCDConfigMapName, v1.GetOptions{}) + acdConfigMap, err := acdClients.configMaps.Get(ctx, common.ArgoCDConfigMapName, v1.GetOptions{}) errors.CheckError(err) export(writer, *acdConfigMap) - acdRBACConfigMap, err := acdClients.configMaps.Get(context.Background(), common.ArgoCDRBACConfigMapName, v1.GetOptions{}) + acdRBACConfigMap, err := acdClients.configMaps.Get(ctx, common.ArgoCDRBACConfigMapName, v1.GetOptions{}) errors.CheckError(err) export(writer, *acdRBACConfigMap) - acdKnownHostsConfigMap, err := acdClients.configMaps.Get(context.Background(), common.ArgoCDKnownHostsConfigMapName, v1.GetOptions{}) + acdKnownHostsConfigMap, err := acdClients.configMaps.Get(ctx, common.ArgoCDKnownHostsConfigMapName, v1.GetOptions{}) errors.CheckError(err) export(writer, *acdKnownHostsConfigMap) - acdTLSCertsConfigMap, err := acdClients.configMaps.Get(context.Background(), common.ArgoCDTLSCertsConfigMapName, v1.GetOptions{}) + acdTLSCertsConfigMap, err := acdClients.configMaps.Get(ctx, common.ArgoCDTLSCertsConfigMapName, v1.GetOptions{}) errors.CheckError(err) export(writer, *acdTLSCertsConfigMap) referencedSecrets := getReferencedSecrets(*acdConfigMap) - secrets, err := acdClients.secrets.List(context.Background(), v1.ListOptions{}) + secrets, err := acdClients.secrets.List(ctx, v1.ListOptions{}) errors.CheckError(err) for _, secret := range secrets.Items { if isArgoCDSecret(referencedSecrets, secret) { export(writer, secret) } } - projects, err := acdClients.projects.List(context.Background(), v1.ListOptions{}) + projects, err := acdClients.projects.List(ctx, v1.ListOptions{}) errors.CheckError(err) for _, proj := range projects.Items { export(writer, proj) } - applications, err := acdClients.applications.List(context.Background(), v1.ListOptions{}) + applications, err := acdClients.applications.List(ctx, v1.ListOptions{}) errors.CheckError(err) for _, app := range applications.Items { export(writer, app) } - applicationSets, err := acdClients.applicationSets.List(context.Background(), v1.ListOptions{}) + applicationSets, err := acdClients.applicationSets.List(ctx, v1.ListOptions{}) if err != nil && !apierr.IsNotFound(err) { if apierr.IsForbidden(err) { log.Warn(err) @@ -121,6 +122,8 @@ func NewImportCommand() *cobra.Command { Use: "import SOURCE", Short: "Import Argo CD data from stdin (specify `-') or a file", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -150,7 +153,7 @@ func NewImportCommand() *cobra.Command { // items in this map indicates the resource should be pruned since it no longer appears // in the backup pruneObjects := make(map[kube.ResourceKey]unstructured.Unstructured) - configMaps, err := acdClients.configMaps.List(context.Background(), v1.ListOptions{}) + configMaps, err := acdClients.configMaps.List(ctx, v1.ListOptions{}) errors.CheckError(err) // referencedSecrets holds any secrets referenced in the argocd-cm configmap. These // secrets need to be imported too @@ -164,24 +167,24 @@ func NewImportCommand() *cobra.Command { } } - secrets, err := acdClients.secrets.List(context.Background(), v1.ListOptions{}) + secrets, err := acdClients.secrets.List(ctx, v1.ListOptions{}) errors.CheckError(err) for _, secret := range secrets.Items { if isArgoCDSecret(referencedSecrets, secret) { pruneObjects[kube.ResourceKey{Group: "", Kind: "Secret", Name: secret.GetName()}] = secret } } - applications, err := acdClients.applications.List(context.Background(), v1.ListOptions{}) + applications, err := acdClients.applications.List(ctx, v1.ListOptions{}) errors.CheckError(err) for _, app := range applications.Items { pruneObjects[kube.ResourceKey{Group: "argoproj.io", Kind: "Application", Name: app.GetName()}] = app } - projects, err := acdClients.projects.List(context.Background(), v1.ListOptions{}) + projects, err := acdClients.projects.List(ctx, v1.ListOptions{}) errors.CheckError(err) for _, proj := range projects.Items { pruneObjects[kube.ResourceKey{Group: "argoproj.io", Kind: "AppProject", Name: proj.GetName()}] = proj } - applicationSets, err := acdClients.applicationSets.List(context.Background(), v1.ListOptions{}) + applicationSets, err := acdClients.applicationSets.List(ctx, v1.ListOptions{}) if apierr.IsForbidden(err) || apierr.IsNotFound(err) { log.Warnf("argoproj.io/ApplicationSet: %v\n", err) } else { @@ -217,7 +220,7 @@ func NewImportCommand() *cobra.Command { if !exists { isForbidden := false if !dryRun { - _, err = dynClient.Create(context.Background(), bakObj, v1.CreateOptions{}) + _, err = dynClient.Create(ctx, bakObj, v1.CreateOptions{}) if apierr.IsForbidden(err) || apierr.IsNotFound(err) { isForbidden = true log.Warnf("%s/%s %s: %v", gvk.Group, gvk.Kind, bakObj.GetName(), err) @@ -237,7 +240,7 @@ func NewImportCommand() *cobra.Command { isForbidden := false if !dryRun { newLive := updateLive(bakObj, &liveObj, stopOperation) - _, err = dynClient.Update(context.Background(), newLive, v1.UpdateOptions{}) + _, err = dynClient.Update(ctx, newLive, v1.UpdateOptions{}) if apierr.IsForbidden(err) || apierr.IsNotFound(err) { isForbidden = true log.Warnf("%s/%s %s: %v", gvk.Group, gvk.Kind, bakObj.GetName(), err) @@ -266,7 +269,7 @@ func NewImportCommand() *cobra.Command { if finalizers := liveObj.GetFinalizers(); len(finalizers) > 0 { newLive := liveObj.DeepCopy() newLive.SetFinalizers(nil) - _, err = dynClient.Update(context.Background(), newLive, v1.UpdateOptions{}) + _, err = dynClient.Update(ctx, newLive, v1.UpdateOptions{}) if err != nil && !apierr.IsNotFound(err) { errors.CheckError(err) } @@ -279,7 +282,7 @@ func NewImportCommand() *cobra.Command { } isForbidden := false if !dryRun { - err = dynClient.Delete(context.Background(), key.Name, v1.DeleteOptions{}) + err = dynClient.Delete(ctx, key.Name, v1.DeleteOptions{}) if apierr.IsForbidden(err) || apierr.IsNotFound(err) { isForbidden = true log.Warnf("%s/%s %s: %v\n", key.Group, key.Kind, key.Name, err) diff --git a/cmd/argocd/commands/admin/cluster.go b/cmd/argocd/commands/admin/cluster.go index 1ecdb62eb8721..bcbb092307d04 100644 --- a/cmd/argocd/commands/admin/cluster.go +++ b/cmd/argocd/commands/admin/cluster.go @@ -67,11 +67,11 @@ type ClusterWithInfo struct { Namespaces []string } -func loadClusters(kubeClient *kubernetes.Clientset, appClient *versioned.Clientset, replicas int, namespace string, portForwardRedis bool, cacheSrc func() (*appstatecache.Cache, error), shard int) ([]ClusterWithInfo, error) { - settingsMgr := settings.NewSettingsManager(context.Background(), kubeClient, namespace) +func loadClusters(ctx context.Context, kubeClient *kubernetes.Clientset, appClient *versioned.Clientset, replicas int, namespace string, portForwardRedis bool, cacheSrc func() (*appstatecache.Cache, error), shard int) ([]ClusterWithInfo, error) { + settingsMgr := settings.NewSettingsManager(ctx, kubeClient, namespace) argoDB := db.NewDB(namespace, settingsMgr, kubeClient) - clustersList, err := argoDB.ListClusters(context.Background()) + clustersList, err := argoDB.ListClusters(ctx) if err != nil { return nil, err } @@ -92,13 +92,13 @@ func loadClusters(kubeClient *kubernetes.Clientset, appClient *versioned.Clients } } - appItems, err := appClient.ArgoprojV1alpha1().Applications(namespace).List(context.Background(), v1.ListOptions{}) + appItems, err := appClient.ArgoprojV1alpha1().Applications(namespace).List(ctx, v1.ListOptions{}) if err != nil { return nil, err } apps := appItems.Items for i, app := range apps { - err := argo.ValidateDestination(context.Background(), &app.Spec.Destination, argoDB) + err := argo.ValidateDestination(ctx, &app.Spec.Destination, argoDB) if err != nil { return nil, err } @@ -142,8 +142,8 @@ func loadClusters(kubeClient *kubernetes.Clientset, appClient *versioned.Clients return clusters, nil } -func getControllerReplicas(kubeClient *kubernetes.Clientset, namespace string) (int, error) { - controllerPods, err := kubeClient.CoreV1().Pods(namespace).List(context.Background(), v1.ListOptions{ +func getControllerReplicas(ctx context.Context, kubeClient *kubernetes.Clientset, namespace string) (int, error) { + controllerPods, err := kubeClient.CoreV1().Pods(namespace).List(ctx, v1.ListOptions{ LabelSelector: "app.kubernetes.io/name=argocd-application-controller"}) if err != nil { return 0, err @@ -163,6 +163,8 @@ func NewClusterShardsCommand() *cobra.Command { Use: "shards", Short: "Print information about each controller shard and portion of Kubernetes resources it is responsible for.", Run: func(cmd *cobra.Command, args []string) { + ctx := cmd.Context() + log.SetLevel(log.WarnLevel) clientCfg, err := clientConfig.ClientConfig() @@ -173,14 +175,14 @@ func NewClusterShardsCommand() *cobra.Command { appClient := versioned.NewForConfigOrDie(clientCfg) if replicas == 0 { - replicas, err = getControllerReplicas(kubeClient, namespace) + replicas, err = getControllerReplicas(ctx, kubeClient, namespace) errors.CheckError(err) } if replicas == 0 { return } - clusters, err := loadClusters(kubeClient, appClient, replicas, namespace, portForwardRedis, cacheSrc, shard) + clusters, err := loadClusters(ctx, kubeClient, appClient, replicas, namespace, portForwardRedis, cacheSrc, shard) errors.CheckError(err) if len(clusters) == 0 { return @@ -216,7 +218,7 @@ func printStatsSummary(clusters []ClusterWithInfo) { _ = w.Flush() } -func runClusterNamespacesCommand(clientConfig clientcmd.ClientConfig, action func(appClient *versioned.Clientset, argoDB db.ArgoDB, clusters map[string][]string) error) error { +func runClusterNamespacesCommand(ctx context.Context, clientConfig clientcmd.ClientConfig, action func(appClient *versioned.Clientset, argoDB db.ArgoDB, clusters map[string][]string) error) error { clientCfg, err := clientConfig.ClientConfig() if err != nil { return err @@ -229,19 +231,19 @@ func runClusterNamespacesCommand(clientConfig clientcmd.ClientConfig, action fun kubeClient := kubernetes.NewForConfigOrDie(clientCfg) appClient := versioned.NewForConfigOrDie(clientCfg) - settingsMgr := settings.NewSettingsManager(context.Background(), kubeClient, namespace) + settingsMgr := settings.NewSettingsManager(ctx, kubeClient, namespace) argoDB := db.NewDB(namespace, settingsMgr, kubeClient) - clustersList, err := argoDB.ListClusters(context.Background()) + clustersList, err := argoDB.ListClusters(ctx) if err != nil { return err } - appItems, err := appClient.ArgoprojV1alpha1().Applications(namespace).List(context.Background(), v1.ListOptions{}) + appItems, err := appClient.ArgoprojV1alpha1().Applications(namespace).List(ctx, v1.ListOptions{}) if err != nil { return err } apps := appItems.Items for i, app := range apps { - err := argo.ValidateDestination(context.Background(), &app.Spec.Destination, argoDB) + err := argo.ValidateDestination(ctx, &app.Spec.Destination, argoDB) if err != nil { return err } @@ -286,9 +288,11 @@ func NewClusterNamespacesCommand() *cobra.Command { Use: "namespaces", Short: "Print information namespaces which Argo CD manages in each cluster.", Run: func(cmd *cobra.Command, args []string) { + ctx := cmd.Context() + log.SetLevel(log.WarnLevel) - err := runClusterNamespacesCommand(clientConfig, func(appClient *versioned.Clientset, _ db.ArgoDB, clusters map[string][]string) error { + err := runClusterNamespacesCommand(ctx, clientConfig, func(appClient *versioned.Clientset, _ db.ArgoDB, clusters map[string][]string) error { w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) _, _ = fmt.Fprintf(w, "CLUSTER\tNAMESPACES\n") @@ -327,6 +331,8 @@ func NewClusterEnableNamespacedMode() *cobra.Command { Use: "enable-namespaced-mode PATTERN", Short: "Enable namespaced mode for clusters which name matches to the specified pattern.", Run: func(cmd *cobra.Command, args []string) { + ctx := cmd.Context() + log.SetLevel(log.WarnLevel) if len(args) == 0 { @@ -335,13 +341,13 @@ func NewClusterEnableNamespacedMode() *cobra.Command { } pattern := args[0] - errors.CheckError(runClusterNamespacesCommand(clientConfig, func(_ *versioned.Clientset, argoDB db.ArgoDB, clusters map[string][]string) error { + errors.CheckError(runClusterNamespacesCommand(ctx, clientConfig, func(_ *versioned.Clientset, argoDB db.ArgoDB, clusters map[string][]string) error { for server, namespaces := range clusters { if len(namespaces) == 0 || len(namespaces) > namespacesCount || !glob.Match(pattern, server) { continue } - cluster, err := argoDB.GetCluster(context.Background(), server) + cluster, err := argoDB.GetCluster(ctx, server) if err != nil { return err } @@ -349,7 +355,7 @@ func NewClusterEnableNamespacedMode() *cobra.Command { cluster.ClusterResources = clusterResources fmt.Printf("Setting cluster %s namespaces to %v...", server, namespaces) if !dryRun { - _, err = argoDB.UpdateCluster(context.Background(), cluster) + _, err = argoDB.UpdateCluster(ctx, cluster) if err != nil { return err } @@ -380,6 +386,8 @@ func NewClusterDisableNamespacedMode() *cobra.Command { Use: "disable-namespaced-mode PATTERN", Short: "Disable namespaced mode for clusters which name matches to the specified pattern.", Run: func(cmd *cobra.Command, args []string) { + ctx := cmd.Context() + log.SetLevel(log.WarnLevel) if len(args) == 0 { @@ -389,13 +397,13 @@ func NewClusterDisableNamespacedMode() *cobra.Command { pattern := args[0] - errors.CheckError(runClusterNamespacesCommand(clientConfig, func(_ *versioned.Clientset, argoDB db.ArgoDB, clusters map[string][]string) error { + errors.CheckError(runClusterNamespacesCommand(ctx, clientConfig, func(_ *versioned.Clientset, argoDB db.ArgoDB, clusters map[string][]string) error { for server := range clusters { if !glob.Match(pattern, server) { continue } - cluster, err := argoDB.GetCluster(context.Background(), server) + cluster, err := argoDB.GetCluster(ctx, server) if err != nil { return err } @@ -407,7 +415,7 @@ func NewClusterDisableNamespacedMode() *cobra.Command { cluster.Namespaces = nil fmt.Printf("Disabling namespaced mode for cluster %s...", server) if !dryRun { - _, err = argoDB.UpdateCluster(context.Background(), cluster) + _, err = argoDB.UpdateCluster(ctx, cluster) if err != nil { return err } @@ -438,6 +446,8 @@ func NewClusterStatsCommand() *cobra.Command { Use: "stats", Short: "Prints information cluster statistics and inferred shard number", Run: func(cmd *cobra.Command, args []string) { + ctx := cmd.Context() + log.SetLevel(log.WarnLevel) clientCfg, err := clientConfig.ClientConfig() @@ -448,10 +458,10 @@ func NewClusterStatsCommand() *cobra.Command { kubeClient := kubernetes.NewForConfigOrDie(clientCfg) appClient := versioned.NewForConfigOrDie(clientCfg) if replicas == 0 { - replicas, err = getControllerReplicas(kubeClient, namespace) + replicas, err = getControllerReplicas(ctx, kubeClient, namespace) errors.CheckError(err) } - clusters, err := loadClusters(kubeClient, appClient, replicas, namespace, portForwardRedis, cacheSrc, shard) + clusters, err := loadClusters(ctx, kubeClient, appClient, replicas, namespace, portForwardRedis, cacheSrc, shard) errors.CheckError(err) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) @@ -480,6 +490,8 @@ func NewClusterConfig() *cobra.Command { Short: "Generates kubeconfig for the specified cluster", DisableAutoGenTag: true, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -493,7 +505,7 @@ func NewClusterConfig() *cobra.Command { kubeclientset, err := kubernetes.NewForConfig(conf) errors.CheckError(err) - cluster, err := db.NewDB(namespace, settings.NewSettingsManager(context.Background(), kubeclientset, namespace), kubeclientset).GetCluster(context.Background(), serverUrl) + cluster, err := db.NewDB(namespace, settings.NewSettingsManager(ctx, kubeclientset, namespace), kubeclientset).GetCluster(ctx, serverUrl) errors.CheckError(err) err = kube.WriteKubeConfig(cluster.RawRestConfig(), namespace, output) errors.CheckError(err) @@ -516,6 +528,8 @@ func NewGenClusterConfigCommand(pathOpts *clientcmd.PathOptions) *cobra.Command Use: "generate-spec CONTEXT", Short: "Generate declarative config for a cluster", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + log.SetLevel(log.WarnLevel) var configAccess clientcmd.ConfigAccess = pathOpts if len(args) == 0 { @@ -578,16 +592,16 @@ func NewGenClusterConfigCommand(pathOpts *clientcmd.PathOptions) *cobra.Command clst.Shard = &clusterOpts.Shard } - settingsMgr := settings.NewSettingsManager(context.Background(), kubeClientset, ArgoCDNamespace) + settingsMgr := settings.NewSettingsManager(ctx, kubeClientset, ArgoCDNamespace) argoDB := db.NewDB(ArgoCDNamespace, settingsMgr, kubeClientset) - _, err = argoDB.CreateCluster(context.Background(), clst) + _, err = argoDB.CreateCluster(ctx, clst) errors.CheckError(err) secName, err := db.URIToSecretName("cluster", clst.Server) errors.CheckError(err) - secret, err := kubeClientset.CoreV1().Secrets(ArgoCDNamespace).Get(context.Background(), secName, v1.GetOptions{}) + secret, err := kubeClientset.CoreV1().Secrets(ArgoCDNamespace).Get(ctx, secName, v1.GetOptions{}) errors.CheckError(err) errors.CheckError(PrintResources(outputFormat, os.Stdout, secret)) diff --git a/cmd/argocd/commands/admin/dashboard.go b/cmd/argocd/commands/admin/dashboard.go index 3117653b73f60..05a85c47a0a7b 100644 --- a/cmd/argocd/commands/admin/dashboard.go +++ b/cmd/argocd/commands/admin/dashboard.go @@ -1,7 +1,6 @@ package admin import ( - "context" "fmt" "github.com/spf13/cobra" @@ -22,9 +21,11 @@ func NewDashboardCommand() *cobra.Command { Use: "dashboard", Short: "Starts Argo CD Web UI locally", Run: func(cmd *cobra.Command, args []string) { - errors.CheckError(headless.StartLocalServer(&argocdclient.ClientOptions{Core: true}, initialize.RetrieveContextIfChanged(cmd.Flag("context")), &port, &address)) + ctx := cmd.Context() + + errors.CheckError(headless.StartLocalServer(ctx, &argocdclient.ClientOptions{Core: true}, initialize.RetrieveContextIfChanged(cmd.Flag("context")), &port, &address)) println(fmt.Sprintf("Argo CD UI is available at http://%s:%d", address, port)) - <-context.Background().Done() + <-ctx.Done() }, } initialize.InitCommand(cmd) diff --git a/cmd/argocd/commands/admin/project.go b/cmd/argocd/commands/admin/project.go index e2478460a98da..f45831ba73f9a 100644 --- a/cmd/argocd/commands/admin/project.go +++ b/cmd/argocd/commands/admin/project.go @@ -100,7 +100,7 @@ func getModification(modification string, resource string, scope string, permiss return nil, fmt.Errorf("modification %s is not supported", modification) } -func saveProject(updated v1alpha1.AppProject, orig v1alpha1.AppProject, projectsIf appclient.AppProjectInterface, dryRun bool) error { +func saveProject(ctx context.Context, updated v1alpha1.AppProject, orig v1alpha1.AppProject, projectsIf appclient.AppProjectInterface, dryRun bool) error { fmt.Printf("===== %s ======\n", updated.Name) target, err := kube.ToUnstructured(&updated) errors.CheckError(err) @@ -110,7 +110,7 @@ func saveProject(updated v1alpha1.AppProject, orig v1alpha1.AppProject, projects } _ = cli.PrintDiff(updated.Name, target, live) if !dryRun { - _, err = projectsIf.Update(context.Background(), &updated, v1.UpdateOptions{}) + _, err = projectsIf.Update(ctx, &updated, v1.UpdateOptions{}) if err != nil { return err } @@ -149,6 +149,8 @@ func NewUpdatePolicyRuleCommand() *cobra.Command { argocd admin projects update-role-policy '*' remove override --role '*deployer*' `, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -170,7 +172,7 @@ func NewUpdatePolicyRuleCommand() *cobra.Command { errors.CheckError(err) projIf := appclients.ArgoprojV1alpha1().AppProjects(namespace) - err = updateProjects(projIf, projectGlob, rolePattern, action, modification, dryRun) + err = updateProjects(ctx, projIf, projectGlob, rolePattern, action, modification, dryRun) errors.CheckError(err) }, } @@ -183,8 +185,8 @@ func NewUpdatePolicyRuleCommand() *cobra.Command { return command } -func updateProjects(projIf appclient.AppProjectInterface, projectGlob string, rolePattern string, action string, modification func(string, string) string, dryRun bool) error { - projects, err := projIf.List(context.Background(), v1.ListOptions{}) +func updateProjects(ctx context.Context, projIf appclient.AppProjectInterface, projectGlob string, rolePattern string, action string, modification func(string, string) string, dryRun bool) error { + projects, err := projIf.List(ctx, v1.ListOptions{}) if err != nil { return err } @@ -221,7 +223,7 @@ func updateProjects(projIf appclient.AppProjectInterface, projectGlob string, ro proj.Spec.Roles[i] = role } if updated { - err = saveProject(proj, *origProj, projIf, dryRun) + err = saveProject(ctx, proj, *origProj, projIf, dryRun) if err != nil { return err } diff --git a/cmd/argocd/commands/admin/project_test.go b/cmd/argocd/commands/admin/project_test.go index f01ebb5c9acf0..93d8626ce1b25 100644 --- a/cmd/argocd/commands/admin/project_test.go +++ b/cmd/argocd/commands/admin/project_test.go @@ -29,31 +29,35 @@ func newProj(name string, roleNames ...string) *v1alpha1.AppProject { } func TestUpdateProjects_FindMatchingProject(t *testing.T) { + ctx := context.Background() + clientset := fake.NewSimpleClientset(newProj("foo", "test"), newProj("bar", "test")) modification, err := getModification("set", "*", "*", "allow") assert.NoError(t, err) - err = updateProjects(clientset.ArgoprojV1alpha1().AppProjects(namespace), "ba*", "*", "set", modification, false) + err = updateProjects(ctx, clientset.ArgoprojV1alpha1().AppProjects(namespace), "ba*", "*", "set", modification, false) assert.NoError(t, err) - fooProj, err := clientset.ArgoprojV1alpha1().AppProjects(namespace).Get(context.Background(), "foo", v1.GetOptions{}) + fooProj, err := clientset.ArgoprojV1alpha1().AppProjects(namespace).Get(ctx, "foo", v1.GetOptions{}) assert.NoError(t, err) assert.Len(t, fooProj.Spec.Roles[0].Policies, 0) - barProj, err := clientset.ArgoprojV1alpha1().AppProjects(namespace).Get(context.Background(), "bar", v1.GetOptions{}) + barProj, err := clientset.ArgoprojV1alpha1().AppProjects(namespace).Get(ctx, "bar", v1.GetOptions{}) assert.NoError(t, err) assert.EqualValues(t, barProj.Spec.Roles[0].Policies, []string{"p, proj:bar:test, *, set, bar/*, allow"}) } func TestUpdateProjects_FindMatchingRole(t *testing.T) { + ctx := context.Background() + clientset := fake.NewSimpleClientset(newProj("proj", "foo", "bar")) modification, err := getModification("set", "*", "*", "allow") assert.NoError(t, err) - err = updateProjects(clientset.ArgoprojV1alpha1().AppProjects(namespace), "*", "fo*", "set", modification, false) + err = updateProjects(ctx, clientset.ArgoprojV1alpha1().AppProjects(namespace), "*", "fo*", "set", modification, false) assert.NoError(t, err) - proj, err := clientset.ArgoprojV1alpha1().AppProjects(namespace).Get(context.Background(), "proj", v1.GetOptions{}) + proj, err := clientset.ArgoprojV1alpha1().AppProjects(namespace).Get(ctx, "proj", v1.GetOptions{}) assert.NoError(t, err) assert.EqualValues(t, proj.Spec.Roles[0].Policies, []string{"p, proj:proj:foo, *, set, proj/*, allow"}) assert.Len(t, proj.Spec.Roles[1].Policies, 0) diff --git a/cmd/argocd/commands/admin/repo.go b/cmd/argocd/commands/admin/repo.go index d6e3ae9339e30..b5375e29a8d0b 100644 --- a/cmd/argocd/commands/admin/repo.go +++ b/cmd/argocd/commands/admin/repo.go @@ -1,7 +1,6 @@ package admin import ( - "context" "fmt" "io/ioutil" "os" @@ -74,6 +73,8 @@ func NewGenRepoSpecCommand() *cobra.Command { Short: "Generate declarative config for a repo", Example: repoAddExamples, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + log.SetLevel(log.WarnLevel) if len(args) != 1 { c.HelpFunc()(c, args) @@ -151,13 +152,13 @@ func NewGenRepoSpecCommand() *cobra.Command { }, } kubeClientset := fake.NewSimpleClientset(argoCDCM) - settingsMgr := settings.NewSettingsManager(context.Background(), kubeClientset, ArgoCDNamespace) + settingsMgr := settings.NewSettingsManager(ctx, kubeClientset, ArgoCDNamespace) argoDB := db.NewDB(ArgoCDNamespace, settingsMgr, kubeClientset) - _, err := argoDB.CreateRepository(context.Background(), &repoOpts.Repo) + _, err := argoDB.CreateRepository(ctx, &repoOpts.Repo) errors.CheckError(err) - secret, err := kubeClientset.CoreV1().Secrets(ArgoCDNamespace).Get(context.Background(), db.RepoURLToSecretName(repoSecretPrefix, repoOpts.Repo.Repo), v1.GetOptions{}) + secret, err := kubeClientset.CoreV1().Secrets(ArgoCDNamespace).Get(ctx, db.RepoURLToSecretName(repoSecretPrefix, repoOpts.Repo.Repo), v1.GetOptions{}) errors.CheckError(err) errors.CheckError(PrintResources(outputFormat, os.Stdout, secret)) diff --git a/cmd/argocd/commands/admin/settings.go b/cmd/argocd/commands/admin/settings.go index 83fd57b4acba0..012d82f3bcc4d 100644 --- a/cmd/argocd/commands/admin/settings.go +++ b/cmd/argocd/commands/admin/settings.go @@ -40,7 +40,7 @@ type settingsOpts struct { } type commandContext interface { - createSettingsManager() (*settings.SettingsManager, error) + createSettingsManager(context.Context) (*settings.SettingsManager, error) } func collectLogs(callback func()) string { @@ -62,7 +62,7 @@ func setSettingsMeta(obj v1.Object) { obj.SetLabels(labels) } -func (opts *settingsOpts) createSettingsManager() (*settings.SettingsManager, error) { +func (opts *settingsOpts) createSettingsManager(ctx context.Context) (*settings.SettingsManager, error) { var argocdCM *corev1.ConfigMap if opts.argocdCMPath == "" && !opts.loadClusterSettings { return nil, fmt.Errorf("either --argocd-cm-path must be provided or --load-cluster-settings must be set to true") @@ -72,7 +72,7 @@ func (opts *settingsOpts) createSettingsManager() (*settings.SettingsManager, er return nil, err } - argocdCM, err = realClientset.CoreV1().ConfigMaps(ns).Get(context.Background(), common.ArgoCDConfigMapName, v1.GetOptions{}) + argocdCM, err = realClientset.CoreV1().ConfigMaps(ns).Get(ctx, common.ArgoCDConfigMapName, v1.GetOptions{}) if err != nil { return nil, err } @@ -104,7 +104,7 @@ func (opts *settingsOpts) createSettingsManager() (*settings.SettingsManager, er if err != nil { return nil, err } - argocdSecret, err = realClientset.CoreV1().Secrets(ns).Get(context.Background(), common.ArgoCDSecretName, v1.GetOptions{}) + argocdSecret, err = realClientset.CoreV1().Secrets(ns).Get(ctx, common.ArgoCDSecretName, v1.GetOptions{}) if err != nil { return nil, err } @@ -122,7 +122,7 @@ func (opts *settingsOpts) createSettingsManager() (*settings.SettingsManager, er setSettingsMeta(argocdSecret) clientset := fake.NewSimpleClientset(argocdSecret, argocdCM) - manager := settings.NewSettingsManager(context.Background(), clientset, "default") + manager := settings.NewSettingsManager(ctx, clientset, "default") errors.CheckError(manager.ResyncInformers()) return manager, nil @@ -308,7 +308,9 @@ argocd admin settings validate --argocd-cm-path ./argocd-cm.yaml #Validates accounts and plugins settings in Kubernetes cluster of current kubeconfig context argocd admin settings validate --group accounts --group plugins --load-cluster-settings`, Run: func(c *cobra.Command, args []string) { - settingsManager, err := cmdCtx.createSettingsManager() + ctx := c.Context() + + settingsManager, err := cmdCtx.createSettingsManager(ctx) errors.CheckError(err) if len(groups) == 0 { @@ -361,14 +363,14 @@ func NewResourceOverridesCommand(cmdCtx commandContext) *cobra.Command { return command } -func executeResourceOverrideCommand(cmdCtx commandContext, args []string, callback func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride)) { +func executeResourceOverrideCommand(ctx context.Context, cmdCtx commandContext, args []string, callback func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride)) { data, err := ioutil.ReadFile(args[0]) errors.CheckError(err) res := unstructured.Unstructured{} errors.CheckError(yaml.Unmarshal(data, &res)) - settingsManager, err := cmdCtx.createSettingsManager() + settingsManager, err := cmdCtx.createSettingsManager(ctx) errors.CheckError(err) overrides, err := settingsManager.GetResourceOverrides() @@ -394,12 +396,14 @@ func NewResourceIgnoreDifferencesCommand(cmdCtx commandContext) *cobra.Command { Example: ` argocd admin settings resource-overrides ignore-differences ./deploy.yaml --argocd-cm-path ./argocd-cm.yaml`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) < 1 { c.HelpFunc()(c, args) os.Exit(1) } - executeResourceOverrideCommand(cmdCtx, args, func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride) { + executeResourceOverrideCommand(ctx, cmdCtx, args, func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride) { gvk := res.GroupVersionKind() if len(override.IgnoreDifferences.JSONPointers) == 0 && len(override.IgnoreDifferences.JQPathExpressions) == 0 { _, _ = fmt.Printf("Ignore differences are not configured for '%s/%s'\n", gvk.Group, gvk.Kind) @@ -442,12 +446,14 @@ func NewResourceHealthCommand(cmdCtx commandContext) *cobra.Command { Example: ` argocd admin settings resource-overrides health ./deploy.yaml --argocd-cm-path ./argocd-cm.yaml`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) < 1 { c.HelpFunc()(c, args) os.Exit(1) } - executeResourceOverrideCommand(cmdCtx, args, func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride) { + executeResourceOverrideCommand(ctx, cmdCtx, args, func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride) { gvk := res.GroupVersionKind() if override.HealthLua == "" { _, _ = fmt.Printf("Health script is not configured for '%s/%s'\n", gvk.Group, gvk.Kind) @@ -473,12 +479,14 @@ func NewResourceActionListCommand(cmdCtx commandContext) *cobra.Command { Example: ` argocd admin settings resource-overrides action list /tmp/deploy.yaml --argocd-cm-path ./argocd-cm.yaml`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) < 1 { c.HelpFunc()(c, args) os.Exit(1) } - executeResourceOverrideCommand(cmdCtx, args, func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride) { + executeResourceOverrideCommand(ctx, cmdCtx, args, func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride) { gvk := res.GroupVersionKind() if override.Actions == "" { _, _ = fmt.Printf("Actions are not configured for '%s/%s'\n", gvk.Group, gvk.Kind) @@ -516,13 +524,15 @@ func NewResourceActionRunCommand(cmdCtx commandContext) *cobra.Command { Example: ` argocd admin settings resource-overrides action run /tmp/deploy.yaml restart --argocd-cm-path ./argocd-cm.yaml`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) < 2 { c.HelpFunc()(c, args) os.Exit(1) } action := args[1] - executeResourceOverrideCommand(cmdCtx, args, func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride) { + executeResourceOverrideCommand(ctx, cmdCtx, args, func(res unstructured.Unstructured, override v1alpha1.ResourceOverride, overrides map[string]v1alpha1.ResourceOverride) { gvk := res.GroupVersionKind() if override.Actions == "" { _, _ = fmt.Printf("Actions are not configured for '%s/%s'\n", gvk.Group, gvk.Kind) diff --git a/cmd/argocd/commands/admin/settings_rbac.go b/cmd/argocd/commands/admin/settings_rbac.go index c66e1ba50bfa8..f6ae9b3b726a8 100644 --- a/cmd/argocd/commands/admin/settings_rbac.go +++ b/cmd/argocd/commands/admin/settings_rbac.go @@ -122,6 +122,8 @@ argocd admin settings rbac can someuser create application 'default/app' --defau `, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) < 3 || len(args) > 4 { c.HelpFunc()(c, args) os.Exit(1) @@ -158,7 +160,7 @@ argocd admin settings rbac can someuser create application 'default/app' --defau log.Fatalf("could not create k8s client: %v", err) } - userPolicy, newDefaultRole, matchMode := getPolicy(policyFile, realClientset, namespace) + userPolicy, newDefaultRole, matchMode := getPolicy(ctx, policyFile, realClientset, namespace) // Use built-in policy as augmentation if requested if useBuiltin { @@ -209,11 +211,13 @@ Validates an RBAC policy for being syntactically correct. The policy must be a local file, and in either CSV or K8s ConfigMap format. `, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if policyFile == "" { c.HelpFunc()(c, args) log.Fatalf("Please specify policy to validate using --policy-file") } - userPolicy, _, _ := getPolicy(policyFile, nil, "") + userPolicy, _, _ := getPolicy(ctx, policyFile, nil, "") if userPolicy != "" { if err := rbac.ValidatePolicy(userPolicy); err == nil { fmt.Printf("Policy is valid.\n") @@ -232,7 +236,7 @@ a local file, and in either CSV or K8s ConfigMap format. // Load user policy file if requested or use Kubernetes client to get the // appropriate ConfigMap from the current context -func getPolicy(policyFile string, kubeClient kubernetes.Interface, namespace string) (userPolicy string, defaultRole string, matchMode string) { +func getPolicy(ctx context.Context, policyFile string, kubeClient kubernetes.Interface, namespace string) (userPolicy string, defaultRole string, matchMode string) { var err error if policyFile != "" { // load from file @@ -241,7 +245,7 @@ func getPolicy(policyFile string, kubeClient kubernetes.Interface, namespace str log.Fatalf("could not read policy file: %v", err) } } else { - cm, err := getPolicyConfigMap(kubeClient, namespace) + cm, err := getPolicyConfigMap(ctx, kubeClient, namespace) if err != nil { log.Fatalf("could not get configmap: %v", err) } @@ -300,8 +304,8 @@ func getPolicyFromConfigMap(cm *corev1.ConfigMap) (string, string, string) { } // getPolicyConfigMap fetches the RBAC config map from K8s cluster -func getPolicyConfigMap(client kubernetes.Interface, namespace string) (*corev1.ConfigMap, error) { - cm, err := client.CoreV1().ConfigMaps(namespace).Get(context.Background(), common.ArgoCDRBACConfigMapName, v1.GetOptions{}) +func getPolicyConfigMap(ctx context.Context, client kubernetes.Interface, namespace string) (*corev1.ConfigMap, error) { + cm, err := client.CoreV1().ConfigMaps(namespace).Get(ctx, common.ArgoCDRBACConfigMapName, v1.GetOptions{}) if err != nil { return nil, err } diff --git a/cmd/argocd/commands/admin/settings_rbac_test.go b/cmd/argocd/commands/admin/settings_rbac_test.go index ae58c7a34bc5e..5de89236bbb9f 100644 --- a/cmd/argocd/commands/admin/settings_rbac_test.go +++ b/cmd/argocd/commands/admin/settings_rbac_test.go @@ -1,6 +1,7 @@ package admin import ( + "context" "io/ioutil" "testing" @@ -40,20 +41,26 @@ func Test_isValidRBACResource(t *testing.T) { } func Test_PolicyFromCSV(t *testing.T) { - uPol, dRole, matchMode := getPolicy("testdata/rbac/policy.csv", nil, "") + ctx := context.Background() + + uPol, dRole, matchMode := getPolicy(ctx, "testdata/rbac/policy.csv", nil, "") require.NotEmpty(t, uPol) require.Empty(t, dRole) require.Empty(t, matchMode) } func Test_PolicyFromYAML(t *testing.T) { - uPol, dRole, matchMode := getPolicy("testdata/rbac/argocd-rbac-cm.yaml", nil, "") + ctx := context.Background() + + uPol, dRole, matchMode := getPolicy(ctx, "testdata/rbac/argocd-rbac-cm.yaml", nil, "") require.NotEmpty(t, uPol) require.Equal(t, "role:unknown", dRole) require.Empty(t, matchMode) } func Test_PolicyFromK8s(t *testing.T) { + ctx := context.Background() + data, err := ioutil.ReadFile("testdata/rbac/policy.csv") require.NoError(t, err) kubeclientset := fake.NewSimpleClientset(&v1.ConfigMap{ @@ -66,7 +73,7 @@ func Test_PolicyFromK8s(t *testing.T) { "policy.default": "role:unknown", }, }) - uPol, dRole, matchMode := getPolicy("", kubeclientset, "argocd") + uPol, dRole, matchMode := getPolicy(ctx, "", kubeclientset, "argocd") require.NotEmpty(t, uPol) require.Equal(t, "role:unknown", dRole) require.Equal(t, "", matchMode) @@ -98,6 +105,8 @@ func Test_PolicyFromK8s(t *testing.T) { } func Test_PolicyFromK8sUsingRegex(t *testing.T) { + ctx := context.Background() + policy := ` p, role:user, clusters, get, .+, allow p, role:user, clusters, get, https://kubernetes.*, deny @@ -115,7 +124,7 @@ p, role:user, applications, create, .*/.*, allow` "policy.matchMode": "regex", }, }) - uPol, dRole, matchMode := getPolicy("", kubeclientset, "argocd") + uPol, dRole, matchMode := getPolicy(ctx, "", kubeclientset, "argocd") require.NotEmpty(t, uPol) require.Equal(t, "role:unknown", dRole) require.Equal(t, "regex", matchMode) diff --git a/cmd/argocd/commands/admin/settings_test.go b/cmd/argocd/commands/admin/settings_test.go index 9f5da58a42725..fbd4869069d56 100644 --- a/cmd/argocd/commands/admin/settings_test.go +++ b/cmd/argocd/commands/admin/settings_test.go @@ -44,6 +44,8 @@ func captureStdout(callback func()) (string, error) { } func newSettingsManager(data map[string]string) *settings.SettingsManager { + ctx := context.Background() + clientset := fake.NewSimpleClientset(&v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Namespace: "default", @@ -63,7 +65,7 @@ func newSettingsManager(data map[string]string) *settings.SettingsManager { "server.secretkey": []byte("test"), }, }) - return settings.NewSettingsManager(context.Background(), clientset, "default") + return settings.NewSettingsManager(ctx, clientset, "default") } type fakeCmdContext struct { @@ -76,7 +78,7 @@ func newCmdContext(data map[string]string) *fakeCmdContext { return &fakeCmdContext{mgr: newSettingsManager(data)} } -func (ctx *fakeCmdContext) createSettingsManager() (*settings.SettingsManager, error) { +func (ctx *fakeCmdContext) createSettingsManager(context.Context) (*settings.SettingsManager, error) { return ctx.mgr, nil } @@ -88,6 +90,8 @@ type validatorTestCase struct { } func TestCreateSettingsManager(t *testing.T) { + ctx := context.Background() + f, closer, err := tempFile(`apiVersion: v1 kind: ConfigMap metadata: @@ -100,7 +104,7 @@ data: defer utils.Close(closer) opts := settingsOpts{argocdCMPath: f} - settingsManager, err := opts.createSettingsManager() + settingsManager, err := opts.createSettingsManager(ctx) if !assert.NoError(t, err) { return diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 504c15b104c47..8d20fd7531ffb 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -140,6 +140,8 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra. argocd app create kasane --repo https://github.com/argoproj/argocd-example-apps.git --path plugins/kasane --dest-namespace default --dest-server https://kubernetes.default.svc --config-management-plugin kasane `, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + argocdClient := headless.NewClientOrDie(clientOpts, c) apps, err := cmdutil.ConstructApps(fileURL, appName, labels, annotations, args, appOpts, c.Flags()) @@ -160,7 +162,7 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra. Upsert: &upsert, Validate: &appOpts.Validate, } - created, err := appIf.Create(context.Background(), &appCreateRequest) + created, err := appIf.Create(ctx, &appCreateRequest) errors.CheckError(err) fmt.Printf("application '%s' created\n", created.ObjectMeta.Name) } @@ -222,6 +224,8 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com Use: "get APPNAME", Short: "Get application details", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -230,12 +234,12 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com conn, appIf := acdClient.NewApplicationClientOrDie() defer argoio.Close(conn) appName := args[0] - app, err := appIf.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName, Refresh: getRefreshType(refresh, hardRefresh)}) + app, err := appIf.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName, Refresh: getRefreshType(refresh, hardRefresh)}) errors.CheckError(err) pConn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(pConn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: app.Spec.Project}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: app.Spec.Project}) errors.CheckError(err) windows := proj.Spec.SyncWindows.Matches(app) @@ -245,7 +249,7 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com err := PrintResource(app, output) errors.CheckError(err) case "wide", "": - aURL := appURL(acdClient, app.Name) + aURL := appURL(ctx, acdClient, app.Name) printAppSummaryTable(app, aURL, windows) if len(app.Status.Conditions) > 0 { @@ -300,6 +304,8 @@ func NewApplicationLogsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Use: "logs APPNAME", Short: "Get logs of application pods", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -312,7 +318,7 @@ func NewApplicationLogsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co retry := true for retry { retry = false - stream, err := appIf.PodLogs(context.Background(), &applicationpkg.ApplicationPodLogsQuery{ + stream, err := appIf.PodLogs(ctx, &applicationpkg.ApplicationPodLogsQuery{ Name: &appName, Group: &group, Namespace: pointer.String(namespace), @@ -482,10 +488,10 @@ func appURLDefault(acdClient argocdclient.Client, appName string) string { } // appURL returns the URL of an application -func appURL(acdClient argocdclient.Client, appName string) string { +func appURL(ctx context.Context, acdClient argocdclient.Client, appName string) string { conn, settingsIf := acdClient.NewSettingsClientOrDie() defer argoio.Close(conn) - argoSettings, err := settingsIf.Get(context.Background(), &settingspkg.SettingsQuery{}) + argoSettings, err := settingsIf.Get(ctx, &settingspkg.SettingsQuery{}) errors.CheckError(err) if argoSettings.URL != "" { @@ -537,11 +543,12 @@ func NewApplicationSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com Use: "set APPNAME", Short: "Set application parameters", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) } - ctx := context.Background() appName := args[0] argocdClient := headless.NewClientOrDie(clientOpts, c) conn, appIf := argocdClient.NewApplicationClientOrDie() @@ -598,6 +605,8 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C argocd app unset my-app -p COMPONENT=PARAM`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -605,7 +614,7 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C appName := args[0] conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) - app, err := appIf.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName}) + app, err := appIf.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName}) errors.CheckError(err) updated, nothingToUnset := unset(&app.Spec.Source, opts) @@ -618,7 +627,7 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C } cmdutil.SetAppSpecOptions(c.Flags(), &app.Spec, &appOpts) - _, err = appIf.UpdateSpec(context.Background(), &applicationpkg.ApplicationUpdateSpecRequest{ + _, err = appIf.UpdateSpec(ctx, &applicationpkg.ApplicationUpdateSpecRequest{ Name: &app.Name, Spec: &app.Spec, Validate: &appOpts.Validate, @@ -738,9 +747,9 @@ func targetObjects(resources []*argoappv1.ResourceDiff) ([]*unstructured.Unstruc return objs, nil } -func getLocalObjects(app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions, +func getLocalObjects(ctx context.Context, app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions, configManagementPlugins []*argoappv1.ConfigManagementPlugin, trackingMethod string) []*unstructured.Unstructured { - manifestStrings := getLocalObjectsString(app, local, localRepoRoot, appLabelKey, kubeVersion, apiVersions, kustomizeOptions, configManagementPlugins, trackingMethod) + manifestStrings := getLocalObjectsString(ctx, app, local, localRepoRoot, appLabelKey, kubeVersion, apiVersions, kustomizeOptions, configManagementPlugins, trackingMethod) objs := make([]*unstructured.Unstructured, len(manifestStrings)) for i := range manifestStrings { obj := unstructured.Unstructured{} @@ -751,10 +760,10 @@ func getLocalObjects(app *argoappv1.Application, local, localRepoRoot, appLabelK return objs } -func getLocalObjectsString(app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions, +func getLocalObjectsString(ctx context.Context, app *argoappv1.Application, local, localRepoRoot, appLabelKey, kubeVersion string, apiVersions []string, kustomizeOptions *argoappv1.KustomizeOptions, configManagementPlugins []*argoappv1.ConfigManagementPlugin, trackingMethod string) []string { - res, err := repository.GenerateManifests(context.Background(), local, localRepoRoot, app.Spec.Source.TargetRevision, &repoapiclient.ManifestRequest{ + res, err := repository.GenerateManifests(ctx, local, localRepoRoot, app.Spec.Source.TargetRevision, &repoapiclient.ManifestRequest{ Repo: &argoappv1.Repository{Repo: app.Spec.Source.RepoURL}, AppLabelKey: appLabelKey, AppName: app.Name, @@ -823,6 +832,8 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Short: shortDesc, Long: shortDesc + "\nUses 'diff' to render the difference. KUBECTL_EXTERNAL_DIFF environment variable can be used to select your own diff tool.\nReturns the following exit codes: 2 on general errors, 1 when a diff is found, and 0 when no diff is found", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(2) @@ -831,13 +842,13 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co conn, appIf := clientset.NewApplicationClientOrDie() defer argoio.Close(conn) appName := args[0] - app, err := appIf.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName, Refresh: getRefreshType(refresh, hardRefresh)}) + app, err := appIf.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName, Refresh: getRefreshType(refresh, hardRefresh)}) errors.CheckError(err) - resources, err := appIf.ManagedResources(context.Background(), &applicationpkg.ResourcesQuery{ApplicationName: &appName}) + resources, err := appIf.ManagedResources(ctx, &applicationpkg.ResourcesQuery{ApplicationName: &appName}) errors.CheckError(err) conn, settingsIf := clientset.NewSettingsClientOrDie() defer argoio.Close(conn) - argoSettings, err := settingsIf.Get(context.Background(), &settingspkg.SettingsQuery{}) + argoSettings, err := settingsIf.Get(ctx, &settingspkg.SettingsQuery{}) errors.CheckError(err) diffOption := &DifferenceOption{} if revision != "" { @@ -845,7 +856,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Name: &appName, Revision: &revision, } - res, err := appIf.GetManifests(context.Background(), &q) + res, err := appIf.GetManifests(ctx, &q) errors.CheckError(err) diffOption.res = res diffOption.revision = revision @@ -853,13 +864,13 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co if local != "" { conn, clusterIf := clientset.NewClusterClientOrDie() defer argoio.Close(conn) - cluster, err := clusterIf.Get(context.Background(), &clusterpkg.ClusterQuery{Name: app.Spec.Destination.Name, Server: app.Spec.Destination.Server}) + cluster, err := clusterIf.Get(ctx, &clusterpkg.ClusterQuery{Name: app.Spec.Destination.Name, Server: app.Spec.Destination.Server}) errors.CheckError(err) diffOption.local = local diffOption.localRepoRoot = localRepoRoot diffOption.cluster = cluster } - foundDiffs := findandPrintDiff(app, resources, argoSettings, appName, diffOption) + foundDiffs := findandPrintDiff(ctx, app, resources, argoSettings, appName, diffOption) if foundDiffs && exitCode { os.Exit(1) } @@ -884,13 +895,13 @@ type DifferenceOption struct { } // findandPrintDiff ... Prints difference between application current state and state stored in git or locally, returns boolean as true if difference is found else returns false -func findandPrintDiff(app *argoappv1.Application, resources *applicationpkg.ManagedResourcesResponse, argoSettings *settingspkg.Settings, appName string, diffOptions *DifferenceOption) bool { +func findandPrintDiff(ctx context.Context, app *argoappv1.Application, resources *applicationpkg.ManagedResourcesResponse, argoSettings *settingspkg.Settings, appName string, diffOptions *DifferenceOption) bool { var foundDiffs bool liveObjs, err := cmdutil.LiveObjects(resources.Items) errors.CheckError(err) items := make([]objKeyLiveTarget, 0) if diffOptions.local != "" { - localObjs := groupObjsByKey(getLocalObjects(app, diffOptions.local, diffOptions.localRepoRoot, argoSettings.AppLabelKey, diffOptions.cluster.Info.ServerVersion, diffOptions.cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.ConfigManagementPlugins, argoSettings.TrackingMethod), liveObjs, app.Spec.Destination.Namespace) + localObjs := groupObjsByKey(getLocalObjects(ctx, app, diffOptions.local, diffOptions.localRepoRoot, argoSettings.AppLabelKey, diffOptions.cluster.Info.ServerVersion, diffOptions.cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.ConfigManagementPlugins, argoSettings.TrackingMethod), liveObjs, app.Spec.Destination.Namespace) items = groupObjsForDiff(resources, localObjs, items, argoSettings, appName) } else if diffOptions.revision != "" { var unstructureds []*unstructured.Unstructured @@ -1005,6 +1016,8 @@ func NewApplicationDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra. Use: "delete APPNAME", Short: "Delete an application", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -1049,14 +1062,14 @@ func NewApplicationDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra. } } if lowercaseAnswer == "y" || lowercaseAnswer == "yes" { - _, err := appIf.Delete(context.Background(), &appDeleteReq) + _, err := appIf.Delete(ctx, &appDeleteReq) errors.CheckError(err) fmt.Printf("application '%s' deleted\n", appName) } else { fmt.Println("The command to delete '" + appName + "' was cancelled.") } } else { - _, err := appIf.Delete(context.Background(), &appDeleteReq) + _, err := appIf.Delete(ctx, &appDeleteReq) errors.CheckError(err) } } @@ -1123,9 +1136,11 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co # List apps by label, in this example we listing apps that are children of another app (aka app-of-apps) argocd app list -l app.kubernetes.io/instance=my-app`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) - apps, err := appIf.List(context.Background(), &applicationpkg.ApplicationQuery{Selector: pointer.String(selector)}) + apps, err := appIf.List(ctx, &applicationpkg.ApplicationQuery{Selector: pointer.String(selector)}) errors.CheckError(err) appList := apps.Items if len(projects) != 0 { @@ -1269,6 +1284,8 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co # Wait for apps by label, in this example we waiting for apps that are children of another app (aka app-of-apps) argocd app wait -l app.kubernetes.io/instance=apps`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 && selector == "" { c.HelpFunc()(c, args) os.Exit(1) @@ -1281,14 +1298,14 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co closer, appIf := acdClient.NewApplicationClientOrDie() defer argoio.Close(closer) if selector != "" { - list, err := appIf.List(context.Background(), &applicationpkg.ApplicationQuery{Selector: pointer.String(selector)}) + list, err := appIf.List(ctx, &applicationpkg.ApplicationQuery{Selector: pointer.String(selector)}) errors.CheckError(err) for _, i := range list.Items { appNames = append(appNames, i.Name) } } for _, appName := range appNames { - _, err := waitOnApplicationStatus(acdClient, appName, timeout, watch, selectedResources) + _, err := waitOnApplicationStatus(ctx, acdClient, appName, timeout, watch, selectedResources) errors.CheckError(err) } }, @@ -1354,6 +1371,8 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co # Specify namespace if the application has resources with the same name in different namespaces argocd app sync my-app --resource argoproj.io:Rollout:my-namespace/my-rollout`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 && selector == "" { c.HelpFunc()(c, args) os.Exit(1) @@ -1367,7 +1386,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co appNames := args if selector != "" { - list, err := appIf.List(context.Background(), &applicationpkg.ApplicationQuery{Selector: pointer.String(selector)}) + list, err := appIf.List(ctx, &applicationpkg.ApplicationQuery{Selector: pointer.String(selector)}) errors.CheckError(err) // unlike list, we'd want to fail if nothing was found if len(list.Items) == 0 { @@ -1381,8 +1400,6 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co for _, appName := range appNames { if len(selectedLabels) > 0 { - ctx := context.Background() - q := applicationpkg.ApplicationManifestQuery{ Name: &appName, Revision: &revision, @@ -1418,7 +1435,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co var localObjsStrings []string diffOption := &DifferenceOption{} if local != "" { - app, err := appIf.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName}) + app, err := appIf.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName}) errors.CheckError(err) if app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.Automated != nil && !dryRun { log.Fatal("Cannot use local sync when Automatic Sync Policy is enabled except with --dry-run") @@ -1426,16 +1443,16 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co errors.CheckError(err) conn, settingsIf := acdClient.NewSettingsClientOrDie() - argoSettings, err := settingsIf.Get(context.Background(), &settingspkg.SettingsQuery{}) + argoSettings, err := settingsIf.Get(ctx, &settingspkg.SettingsQuery{}) errors.CheckError(err) argoio.Close(conn) conn, clusterIf := acdClient.NewClusterClientOrDie() defer argoio.Close(conn) - cluster, err := clusterIf.Get(context.Background(), &clusterpkg.ClusterQuery{Name: app.Spec.Destination.Name, Server: app.Spec.Destination.Server}) + cluster, err := clusterIf.Get(ctx, &clusterpkg.ClusterQuery{Name: app.Spec.Destination.Name, Server: app.Spec.Destination.Server}) errors.CheckError(err) argoio.Close(conn) - localObjsStrings = getLocalObjectsString(app, local, localRepoRoot, argoSettings.AppLabelKey, cluster.Info.ServerVersion, cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.ConfigManagementPlugins, argoSettings.TrackingMethod) + localObjsStrings = getLocalObjectsString(ctx, app, local, localRepoRoot, argoSettings.AppLabelKey, cluster.Info.ServerVersion, cluster.Info.APIVersions, argoSettings.KustomizeOptions, argoSettings.ConfigManagementPlugins, argoSettings.TrackingMethod) errors.CheckError(err) diffOption.local = local diffOption.localRepoRoot = localRepoRoot @@ -1489,17 +1506,17 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co } } if diffChanges { - app, err := appIf.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName}) + app, err := appIf.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName}) errors.CheckError(err) - resources, err := appIf.ManagedResources(context.Background(), &applicationpkg.ResourcesQuery{ApplicationName: &appName}) + resources, err := appIf.ManagedResources(ctx, &applicationpkg.ResourcesQuery{ApplicationName: &appName}) errors.CheckError(err) conn, settingsIf := acdClient.NewSettingsClientOrDie() defer argoio.Close(conn) - argoSettings, err := settingsIf.Get(context.Background(), &settingspkg.SettingsQuery{}) + argoSettings, err := settingsIf.Get(ctx, &settingspkg.SettingsQuery{}) errors.CheckError(err) foundDiffs := false fmt.Printf("====== Previewing differences between live and desired state of application %s ======\n", appName) - foundDiffs = findandPrintDiff(app, resources, argoSettings, appName, diffOption) + foundDiffs = findandPrintDiff(ctx, app, resources, argoSettings, appName, diffOption) if foundDiffs { if !diffChangesConfirm { yesno := cli.AskToProceed(fmt.Sprintf("Please review changes to application %s shown above. Do you want to continue the sync process? (y/n): ", appName)) @@ -1511,12 +1528,11 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co fmt.Printf("====== No Differences found ======\n") } } - ctx := context.Background() _, err = appIf.Sync(ctx, &syncReq) errors.CheckError(err) if !async { - app, err := waitOnApplicationStatus(acdClient, appName, timeout, watchOpts{operation: true}, selectedResources) + app, err := waitOnApplicationStatus(ctx, acdClient, appName, timeout, watchOpts{operation: true}, selectedResources) errors.CheckError(err) if !dryRun { @@ -1690,8 +1706,8 @@ func checkResourceStatus(watch watchOpts, healthStatus string, syncStatus string const waitFormatString = "%s\t%5s\t%10s\t%10s\t%20s\t%8s\t%7s\t%10s\t%s\n" -func waitOnApplicationStatus(acdClient argocdclient.Client, appName string, timeout uint, watch watchOpts, selectedResources []*argoappv1.SyncOperationResource) (*argoappv1.Application, error) { - ctx, cancel := context.WithCancel(context.Background()) +func waitOnApplicationStatus(ctx context.Context, acdClient argocdclient.Client, appName string, timeout uint, watch watchOpts, selectedResources []*argoappv1.SyncOperationResource) (*argoappv1.Application, error) { + ctx, cancel := context.WithCancel(ctx) defer cancel() // refresh controls whether or not we refresh the app before printing the final status. @@ -1704,13 +1720,13 @@ func waitOnApplicationStatus(acdClient argocdclient.Client, appName string, time if refresh { conn, appClient := acdClient.NewApplicationClientOrDie() refreshType := string(argoappv1.RefreshTypeNormal) - app, err = appClient.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName, Refresh: &refreshType}) + app, err = appClient.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName, Refresh: &refreshType}) errors.CheckError(err) _ = conn.Close() } fmt.Println() - printAppSummaryTable(app, appURL(acdClient, appName), nil) + printAppSummaryTable(app, appURL(ctx, acdClient, appName), nil) fmt.Println() if watch.operation { printOperationResult(app.Status.OperationState) @@ -1873,6 +1889,8 @@ func NewApplicationHistoryCommand(clientOpts *argocdclient.ClientOptions) *cobra Use: "history APPNAME", Short: "Show application deployment history", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -1880,7 +1898,7 @@ func NewApplicationHistoryCommand(clientOpts *argocdclient.ClientOptions) *cobra conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) appName := args[0] - app, err := appIf.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName}) + app, err := appIf.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName}) errors.CheckError(err) if output == "id" { printApplicationHistoryIds(app.Status.History) @@ -1920,6 +1938,8 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr Use: "rollback APPNAME [ID]", Short: "Rollback application to a previous deployed version by History ID, omitted will Rollback to the previous version", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -1934,7 +1954,6 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr acdClient := headless.NewClientOrDie(clientOpts, c) conn, appIf := acdClient.NewApplicationClientOrDie() defer argoio.Close(conn) - ctx := context.Background() app, err := appIf.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName}) errors.CheckError(err) @@ -1948,7 +1967,7 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr }) errors.CheckError(err) - _, err = waitOnApplicationStatus(acdClient, appName, timeout, watchOpts{ + _, err = waitOnApplicationStatus(ctx, acdClient, appName, timeout, watchOpts{ operation: true, }, nil) errors.CheckError(err) @@ -1995,6 +2014,8 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob Use: "manifests APPNAME", Short: "Print manifests of an application", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -2002,8 +2023,7 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob appName := args[0] conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) - ctx := context.Background() - resources, err := appIf.ManagedResources(context.Background(), &applicationpkg.ResourcesQuery{ApplicationName: &appName}) + resources, err := appIf.ManagedResources(ctx, &applicationpkg.ResourcesQuery{ApplicationName: &appName}) errors.CheckError(err) var unstructureds []*unstructured.Unstructured @@ -2053,6 +2073,8 @@ func NewApplicationTerminateOpCommand(clientOpts *argocdclient.ClientOptions) *c Use: "terminate-op APPNAME", Short: "Terminate running operation of an application", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -2060,7 +2082,6 @@ func NewApplicationTerminateOpCommand(clientOpts *argocdclient.ClientOptions) *c appName := args[0] conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) - ctx := context.Background() _, err := appIf.TerminateOperation(ctx, &applicationpkg.OperationTerminateRequest{Name: &appName}) errors.CheckError(err) fmt.Printf("Application '%s' operation terminating\n", appName) @@ -2074,6 +2095,8 @@ func NewApplicationEditCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Use: "edit APPNAME", Short: "Edit application", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -2081,7 +2104,7 @@ func NewApplicationEditCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co appName := args[0] conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) - app, err := appIf.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName}) + app, err := appIf.Get(ctx, &applicationpkg.ApplicationQuery{Name: &appName}) errors.CheckError(err) appData, err := json.Marshal(app.Spec) errors.CheckError(err) @@ -2101,7 +2124,7 @@ func NewApplicationEditCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co var appOpts cmdutil.AppOptions cmdutil.SetAppSpecOptions(c.Flags(), &app.Spec, &appOpts) - _, err = appIf.UpdateSpec(context.Background(), &applicationpkg.ApplicationUpdateSpecRequest{Name: &app.Name, Spec: &updatedSpec, Validate: &appOpts.Validate}) + _, err = appIf.UpdateSpec(ctx, &applicationpkg.ApplicationUpdateSpecRequest{Name: &app.Name, Spec: &updatedSpec, Validate: &appOpts.Validate}) if err != nil { return fmt.Errorf("Failed to update application spec:\n%v", err) } @@ -2126,6 +2149,8 @@ func NewApplicationPatchCommand(clientOpts *argocdclient.ClientOptions) *cobra.C # Update an application's repository target revision using merge patch argocd app patch myapplication --patch '{"spec": { "source": { "targetRevision": "master" } }}' --type merge`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -2134,7 +2159,7 @@ func NewApplicationPatchCommand(clientOpts *argocdclient.ClientOptions) *cobra.C conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) - patchedApp, err := appIf.Patch(context.Background(), &applicationpkg.ApplicationPatchRequest{ + patchedApp, err := appIf.Patch(ctx, &applicationpkg.ApplicationPatchRequest{ Name: &appName, Patch: &patch, PatchType: &patchType, diff --git a/cmd/argocd/commands/app_actions.go b/cmd/argocd/commands/app_actions.go index 3039e63a24196..28217438cf3b2 100644 --- a/cmd/argocd/commands/app_actions.go +++ b/cmd/argocd/commands/app_actions.go @@ -1,7 +1,6 @@ package commands import ( - "context" "encoding/json" "fmt" "os" @@ -57,6 +56,8 @@ func NewApplicationResourceActionsListCommand(clientOpts *argocdclient.ClientOpt Short: "Lists available actions on a resource", } command.Run = func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -64,7 +65,6 @@ func NewApplicationResourceActionsListCommand(clientOpts *argocdclient.ClientOpt appName := args[0] conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer io.Close(conn) - ctx := context.Background() resources, err := appIf.ManagedResources(ctx, &applicationpkg.ResourcesQuery{ApplicationName: &appName}) errors.CheckError(err) filteredObjects, err := util.FilterResources(command.Flags().Changed("group"), resources.Items, group, kind, namespace, resourceName, true) @@ -141,6 +141,8 @@ func NewApplicationResourceActionsRunCommand(clientOpts *argocdclient.ClientOpti command.Flags().BoolVar(&all, "all", false, "Indicates whether to run the action on multiple matching resources") command.Run = func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -150,7 +152,6 @@ func NewApplicationResourceActionsRunCommand(clientOpts *argocdclient.ClientOpti conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer io.Close(conn) - ctx := context.Background() resources, err := appIf.ManagedResources(ctx, &applicationpkg.ResourcesQuery{ApplicationName: &appName}) errors.CheckError(err) filteredObjects, err := util.FilterResources(command.Flags().Changed("group"), resources.Items, group, kind, namespace, resourceName, all) @@ -166,7 +167,7 @@ func NewApplicationResourceActionsRunCommand(clientOpts *argocdclient.ClientOpti obj := filteredObjects[i] gvk := obj.GroupVersionKind() objResourceName := obj.GetName() - _, err := appIf.RunResourceAction(context.Background(), &applicationpkg.ResourceActionRunRequest{ + _, err := appIf.RunResourceAction(ctx, &applicationpkg.ResourceActionRunRequest{ Name: &appName, Namespace: pointer.String(obj.GetNamespace()), ResourceName: pointer.String(objResourceName), diff --git a/cmd/argocd/commands/app_resources.go b/cmd/argocd/commands/app_resources.go index 1cdb740e42193..5bbfa8a8c02b8 100644 --- a/cmd/argocd/commands/app_resources.go +++ b/cmd/argocd/commands/app_resources.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "os" @@ -48,6 +47,8 @@ func NewApplicationPatchResourceCommand(clientOpts *argocdclient.ClientOptions) command.Flags().StringVar(&namespace, "namespace", "", "Namespace") command.Flags().BoolVar(&all, "all", false, "Indicates whether to patch multiple matching of resources") command.Run = func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -56,7 +57,6 @@ func NewApplicationPatchResourceCommand(clientOpts *argocdclient.ClientOptions) conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) - ctx := context.Background() resources, err := appIf.ManagedResources(ctx, &applicationpkg.ResourcesQuery{ApplicationName: &appName}) errors.CheckError(err) objectsToPatch, err := util.FilterResources(command.Flags().Changed("group"), resources.Items, group, kind, namespace, resourceName, all) @@ -105,6 +105,8 @@ func NewApplicationDeleteResourceCommand(clientOpts *argocdclient.ClientOptions) command.Flags().BoolVar(&orphan, "orphan", false, "Indicates whether to force delete the resource") command.Flags().BoolVar(&all, "all", false, "Indicates whether to patch multiple matching of resources") command.Run = func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -113,7 +115,6 @@ func NewApplicationDeleteResourceCommand(clientOpts *argocdclient.ClientOptions) conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) - ctx := context.Background() resources, err := appIf.ManagedResources(ctx, &applicationpkg.ResourcesQuery{ApplicationName: &appName}) errors.CheckError(err) objectsToDelete, err := util.FilterResources(command.Flags().Changed("group"), resources.Items, group, kind, namespace, resourceName, all) @@ -165,6 +166,8 @@ func NewApplicationListResourcesCommand(clientOpts *argocdclient.ClientOptions) Use: "resources APPNAME", Short: "List resource of application", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -173,7 +176,7 @@ func NewApplicationListResourcesCommand(clientOpts *argocdclient.ClientOptions) appName := args[0] conn, appIf := headless.NewClientOrDie(clientOpts, c).NewApplicationClientOrDie() defer argoio.Close(conn) - appResourceTree, err := appIf.ResourceTree(context.Background(), &applicationpkg.ResourcesQuery{ApplicationName: &appName}) + appResourceTree, err := appIf.ResourceTree(ctx, &applicationpkg.ResourcesQuery{ApplicationName: &appName}) errors.CheckError(err) printResources(listAll, orphaned, appResourceTree) }, diff --git a/cmd/argocd/commands/cert.go b/cmd/argocd/commands/cert.go index a32e77ae79285..17f13a87d2a7d 100644 --- a/cmd/argocd/commands/cert.go +++ b/cmd/argocd/commands/cert.go @@ -1,7 +1,6 @@ package commands import ( - "context" "crypto/x509" "fmt" "os" @@ -65,6 +64,8 @@ func NewCertAddTLSCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command Use: "add-tls SERVERNAME", Short: "Add TLS certificate data for connecting to repository server SERVERNAME", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + conn, certIf := headless.NewClientOrDie(clientOpts, c).NewCertClientOrDie() defer io.Close(conn) @@ -116,7 +117,7 @@ func NewCertAddTLSCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command CertType: "https", CertData: []byte(strings.Join(certificateArray, "\n")), }) - certificates, err := certIf.CreateCertificate(context.Background(), &certificatepkg.RepositoryCertificateCreateRequest{ + certificates, err := certIf.CreateCertificate(ctx, &certificatepkg.RepositoryCertificateCreateRequest{ Certificates: &appsv1.RepositoryCertificateList{ Items: certificateList, }, @@ -147,6 +148,7 @@ func NewCertAddSSHCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command Use: "add-ssh --batch", Short: "Add SSH known host entries for repository servers", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() conn, certIf := headless.NewClientOrDie(clientOpts, c).NewCertClientOrDie() defer io.Close(conn) @@ -191,7 +193,7 @@ func NewCertAddSSHCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command } certList := &appsv1.RepositoryCertificateList{Items: certificates} - response, err := certIf.CreateCertificate(context.Background(), &certificatepkg.RepositoryCertificateCreateRequest{ + response, err := certIf.CreateCertificate(ctx, &certificatepkg.RepositoryCertificateCreateRequest{ Certificates: certList, Upsert: upsert, }) @@ -216,6 +218,8 @@ func NewCertRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command Use: "rm REPOSERVER", Short: "Remove certificate of TYPE for REPOSERVER", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) < 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -237,7 +241,7 @@ func NewCertRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command CertType: certType, CertSubType: certSubType, } - removed, err := certIf.DeleteCertificate(context.Background(), &certQuery) + removed, err := certIf.DeleteCertificate(ctx, &certQuery) errors.CheckError(err) if len(removed.Items) > 0 { for _, cert := range removed.Items { @@ -265,6 +269,8 @@ func NewCertListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Use: "list", Short: "List configured certificates", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if certType != "" { switch certType { case "ssh": @@ -277,7 +283,7 @@ func NewCertListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { conn, certIf := headless.NewClientOrDie(clientOpts, c).NewCertClientOrDie() defer io.Close(conn) - certificates, err := certIf.ListCertificates(context.Background(), &certificatepkg.RepositoryCertificateQuery{HostNamePattern: hostNamePattern, CertType: certType}) + certificates, err := certIf.ListCertificates(ctx, &certificatepkg.RepositoryCertificateQuery{HostNamePattern: hostNamePattern, CertType: certType}) errors.CheckError(err) switch output { diff --git a/cmd/argocd/commands/cluster.go b/cmd/argocd/commands/cluster.go index ff0a3c6678e37..ca746d87b8922 100644 --- a/cmd/argocd/commands/cluster.go +++ b/cmd/argocd/commands/cluster.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "os" "regexp" @@ -71,6 +70,8 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie Use: "add CONTEXT", Short: fmt.Sprintf("%s cluster add CONTEXT", cliName), Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + var configAccess clientcmd.ConfigAccess = pathOpts if len(args) == 0 { log.Error("Choose a context name from:") @@ -144,7 +145,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie Cluster: clst, Upsert: clusterOpts.Upsert, } - _, err = clusterIf.Create(context.Background(), &clstCreateReq) + _, err = clusterIf.Create(ctx, &clstCreateReq) errors.CheckError(err) fmt.Printf("Cluster '%s' added\n", clst.Server) }, @@ -195,6 +196,8 @@ func NewClusterGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command Example: `argocd cluster get https://12.34.567.89 argocd cluster get in-cluster`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -203,7 +206,7 @@ argocd cluster get in-cluster`, defer io.Close(conn) clusters := make([]argoappv1.Cluster, 0) for _, clusterSelector := range args { - clst, err := clusterIf.Get(context.Background(), getQueryBySelector(clusterSelector)) + clst, err := clusterIf.Get(ctx, getQueryBySelector(clusterSelector)) errors.CheckError(err) clusters = append(clusters, *clst) } @@ -265,6 +268,8 @@ func NewClusterRemoveCommand(clientOpts *argocdclient.ClientOptions, pathOpts *c Example: `argocd cluster rm https://12.34.567.89 argocd cluster rm cluster-name`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -276,11 +281,11 @@ argocd cluster rm cluster-name`, clusterQuery := getQueryBySelector(clusterSelector) // get the cluster name to use as context to delete RBAC on cluster - clst, err := clusterIf.Get(context.Background(), clusterQuery) + clst, err := clusterIf.Get(ctx, clusterQuery) errors.CheckError(err) // remove cluster - _, err = clusterIf.Delete(context.Background(), clusterQuery) + _, err = clusterIf.Delete(ctx, clusterQuery) errors.CheckError(err) fmt.Printf("Cluster '%s' removed\n", clusterSelector) @@ -341,9 +346,11 @@ func NewClusterListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman Use: "list", Short: "List configured clusters", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + conn, clusterIf := headless.NewClientOrDie(clientOpts, c).NewClusterClientOrDie() defer io.Close(conn) - clusters, err := clusterIf.List(context.Background(), &clusterpkg.ClusterQuery{}) + clusters, err := clusterIf.List(ctx, &clusterpkg.ClusterQuery{}) errors.CheckError(err) switch output { case "yaml", "json": @@ -369,6 +376,8 @@ func NewClusterRotateAuthCommand(clientOpts *argocdclient.ClientOptions) *cobra. Short: fmt.Sprintf("%s cluster rotate-auth SERVER", cliName), Example: fmt.Sprintf("%s cluster rotate-auth https://12.34.567.89", cliName), Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -378,7 +387,7 @@ func NewClusterRotateAuthCommand(clientOpts *argocdclient.ClientOptions) *cobra. clusterQuery := clusterpkg.ClusterQuery{ Server: args[0], } - _, err := clusterIf.RotateAuth(context.Background(), &clusterQuery) + _, err := clusterIf.RotateAuth(ctx, &clusterQuery) errors.CheckError(err) fmt.Printf("Cluster '%s' rotated auth\n", clusterQuery.Server) }, diff --git a/cmd/argocd/commands/gpg.go b/cmd/argocd/commands/gpg.go index 3cdc579924a65..fd4efa0864c65 100644 --- a/cmd/argocd/commands/gpg.go +++ b/cmd/argocd/commands/gpg.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "io/ioutil" "os" @@ -45,9 +44,11 @@ func NewGPGListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Use: "list", Short: "List configured GPG public keys", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + conn, gpgIf := headless.NewClientOrDie(clientOpts, c).NewGPGKeyClientOrDie() defer argoio.Close(conn) - keys, err := gpgIf.List(context.Background(), &gpgkeypkg.GnuPGPublicKeyQuery{}) + keys, err := gpgIf.List(ctx, &gpgkeypkg.GnuPGPublicKeyQuery{}) errors.CheckError(err) switch output { case "yaml", "json": @@ -73,12 +74,14 @@ func NewGPGGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Use: "get KEYID", Short: "Get the GPG public key with ID from the server", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { errors.CheckError(fmt.Errorf("Missing KEYID argument")) } conn, gpgIf := headless.NewClientOrDie(clientOpts, c).NewGPGKeyClientOrDie() defer argoio.Close(conn) - key, err := gpgIf.Get(context.Background(), &gpgkeypkg.GnuPGPublicKeyQuery{KeyID: args[0]}) + key, err := gpgIf.Get(ctx, &gpgkeypkg.GnuPGPublicKeyQuery{KeyID: args[0]}) errors.CheckError(err) switch output { case "yaml", "json": @@ -108,6 +111,8 @@ func NewGPGAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Use: "add", Short: "Adds a GPG public key to the server's keyring", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if fromFile == "" { errors.CheckError(fmt.Errorf("--from is mandatory")) } @@ -117,7 +122,7 @@ func NewGPGAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { } conn, gpgIf := headless.NewClientOrDie(clientOpts, c).NewGPGKeyClientOrDie() defer argoio.Close(conn) - resp, err := gpgIf.Create(context.Background(), &gpgkeypkg.GnuPGPublicKeyCreateRequest{Publickey: &appsv1.GnuPGPublicKey{KeyData: string(keyData)}}) + resp, err := gpgIf.Create(ctx, &gpgkeypkg.GnuPGPublicKeyCreateRequest{Publickey: &appsv1.GnuPGPublicKey{KeyData: string(keyData)}}) errors.CheckError(err) fmt.Printf("Created %d key(s) from input file", len(resp.Created.Items)) if len(resp.Skipped) > 0 { @@ -137,12 +142,14 @@ func NewGPGDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command Use: "rm KEYID", Short: "Removes a GPG public key from the server's keyring", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { errors.CheckError(fmt.Errorf("Missing KEYID argument")) } conn, gpgIf := headless.NewClientOrDie(clientOpts, c).NewGPGKeyClientOrDie() defer argoio.Close(conn) - _, err := gpgIf.Delete(context.Background(), &gpgkeypkg.GnuPGPublicKeyQuery{KeyID: args[0]}) + _, err := gpgIf.Delete(ctx, &gpgkeypkg.GnuPGPublicKeyQuery{KeyID: args[0]}) errors.CheckError(err) fmt.Printf("Deleted key with key ID %s\n", args[0]) }, diff --git a/cmd/argocd/commands/headless/headless.go b/cmd/argocd/commands/headless/headless.go index e19b954de6995..f8d4b3b23d601 100644 --- a/cmd/argocd/commands/headless/headless.go +++ b/cmd/argocd/commands/headless/headless.go @@ -123,7 +123,7 @@ func (c *forwardRepoClientset) NewRepoServerClient() (io.Closer, repoapiclient.R return c.repoClientset.NewRepoServerClient() } -func testAPI(clientOpts *apiclient.ClientOptions) error { +func testAPI(ctx context.Context, clientOpts *apiclient.ClientOptions) error { apiClient, err := apiclient.NewClient(clientOpts) if err != nil { return err @@ -133,13 +133,13 @@ func testAPI(clientOpts *apiclient.ClientOptions) error { return err } defer io.Close(closer) - _, err = versionClient.Version(context.Background(), &empty.Empty{}) + _, err = versionClient.Version(ctx, &empty.Empty{}) return err } // StartLocalServer allows executing command in a headless mode: on the fly starts Argo CD API server and // changes provided client options to use started API server port -func StartLocalServer(clientOpts *apiclient.ClientOptions, ctxStr string, port *int, address *string) error { +func StartLocalServer(ctx context.Context, clientOpts *apiclient.ClientOptions, ctxStr string, port *int, address *string) error { flags := pflag.NewFlagSet("tmp", pflag.ContinueOnError) clientConfig := cli.AddKubectlFlagsToSet(flags) startInProcessAPI := clientOpts.Core @@ -200,7 +200,6 @@ func StartLocalServer(clientOpts *apiclient.ClientOptions, ctxStr string, port * if err != nil { return err } - ctx := context.Background() appstateCache := appstatecache.NewCache(cache.NewCache(&forwardCacheClient{namespace: namespace, context: ctxStr}), time.Hour) srv := server.NewServer(ctx, server.ArgoCDServerOpts{ EnableGZip: false, @@ -229,7 +228,7 @@ func StartLocalServer(clientOpts *apiclient.ClientOptions, ctxStr string, port * } tries := 5 for i := 0; i < tries; i++ { - err = testAPI(clientOpts) + err = testAPI(ctx, clientOpts) if err == nil { break } @@ -240,8 +239,10 @@ func StartLocalServer(clientOpts *apiclient.ClientOptions, ctxStr string, port * // NewClientOrDie creates a new API client from a set of config options, or fails fatally if the new client creation fails. func NewClientOrDie(opts *apiclient.ClientOptions, c *cobra.Command) apiclient.Client { + ctx := c.Context() + ctxStr := initialize.RetrieveContextIfChanged(c.Flag("context")) - err := StartLocalServer(opts, ctxStr, nil, nil) + err := StartLocalServer(ctx, opts, ctxStr, nil, nil) if err != nil { log.Fatal(err) } diff --git a/cmd/argocd/commands/login.go b/cmd/argocd/commands/login.go index d58b8ebc0a938..1d669b3d285ee 100644 --- a/cmd/argocd/commands/login.go +++ b/cmd/argocd/commands/login.go @@ -55,6 +55,8 @@ argocd login cd.argoproj.io --sso # Configure direct access using Kubernetes API server argocd login cd.argoproj.io --core`, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + var server string if len(args) != 1 && !globalClientOpts.PortForward && !globalClientOpts.Core { @@ -117,9 +119,8 @@ argocd login cd.argoproj.io --core`, setConn, setIf := acdClient.NewSettingsClientOrDie() defer io.Close(setConn) if !sso { - tokenString = passwordLogin(acdClient, username, password) + tokenString = passwordLogin(ctx, acdClient, username, password) } else { - ctx := context.Background() httpClient, err := acdClient.HTTPClient() errors.CheckError(err) ctx = oidc.ClientContext(ctx, httpClient) @@ -328,7 +329,7 @@ func oauth2Login(ctx context.Context, port int, oidcSettings *settingspkg.OIDCCo return tokenString, refreshToken } -func passwordLogin(acdClient argocdclient.Client, username, password string) string { +func passwordLogin(ctx context.Context, acdClient argocdclient.Client, username, password string) string { username, password = cli.PromptCredentials(username, password) sessConn, sessionIf := acdClient.NewSessionClientOrDie() defer io.Close(sessConn) @@ -336,7 +337,7 @@ func passwordLogin(acdClient argocdclient.Client, username, password string) str Username: username, Password: password, } - createdSession, err := sessionIf.Create(context.Background(), &sessionRequest) + createdSession, err := sessionIf.Create(ctx, &sessionRequest) errors.CheckError(err) return createdSession.Token } diff --git a/cmd/argocd/commands/project.go b/cmd/argocd/commands/project.go index cb8f7a073848c..785fa5aa24c69 100644 --- a/cmd/argocd/commands/project.go +++ b/cmd/argocd/commands/project.go @@ -1,7 +1,6 @@ package commands import ( - "context" "encoding/json" "fmt" "io" @@ -90,12 +89,14 @@ func NewProjectCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comm Use: "create PROJECT", Short: "Create a project", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + proj, err := cmdutil.ConstructAppProj(fileURL, args, opts, c) errors.CheckError(err) conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - _, err = projIf.Create(context.Background(), &projectpkg.ProjectCreateRequest{Project: proj, Upsert: upsert}) + _, err = projIf.Create(ctx, &projectpkg.ProjectCreateRequest{Project: proj, Upsert: upsert}) errors.CheckError(err) }, } @@ -118,6 +119,8 @@ func NewProjectSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command Use: "set PROJECT", Short: "Set project parameters", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -126,7 +129,7 @@ func NewProjectSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) if visited := cmdutil.SetProjSpecOptions(c.Flags(), &proj.Spec, &opts); visited == 0 { @@ -135,7 +138,7 @@ func NewProjectSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command os.Exit(1) } - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -149,6 +152,8 @@ func NewProjectAddSignatureKeyCommand(clientOpts *argocdclient.ClientOptions) *c Use: "add-signature-key PROJECT KEY-ID", Short: "Add GnuPG signature key to project", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -163,7 +168,7 @@ func NewProjectAddSignatureKeyCommand(clientOpts *argocdclient.ClientOptions) *c conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) for _, key := range proj.Spec.SignatureKeys { @@ -172,7 +177,7 @@ func NewProjectAddSignatureKeyCommand(clientOpts *argocdclient.ClientOptions) *c } } proj.Spec.SignatureKeys = append(proj.Spec.SignatureKeys, v1alpha1.SignatureKey{KeyID: signatureKey}) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -185,6 +190,8 @@ func NewProjectRemoveSignatureKeyCommand(clientOpts *argocdclient.ClientOptions) Use: "remove-signature-key PROJECT KEY-ID", Short: "Remove GnuPG signature key from project", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -195,7 +202,7 @@ func NewProjectRemoveSignatureKeyCommand(clientOpts *argocdclient.ClientOptions) conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) index := -1 @@ -209,7 +216,7 @@ func NewProjectRemoveSignatureKeyCommand(clientOpts *argocdclient.ClientOptions) log.Fatal("Specified signature key is not configured for project") } else { proj.Spec.SignatureKeys = append(proj.Spec.SignatureKeys[:index], proj.Spec.SignatureKeys[index+1:]...) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) } }, @@ -233,6 +240,8 @@ func NewProjectAddDestinationCommand(clientOpts *argocdclient.ClientOptions) *co Use: "add-destination PROJECT SERVER/NAME NAMESPACE", Short: "Add project destination", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -243,7 +252,7 @@ func NewProjectAddDestinationCommand(clientOpts *argocdclient.ClientOptions) *co conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) for _, dest := range proj.Spec.Destinations { @@ -254,7 +263,7 @@ func NewProjectAddDestinationCommand(clientOpts *argocdclient.ClientOptions) *co } } proj.Spec.Destinations = append(proj.Spec.Destinations, destination) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -268,6 +277,8 @@ func NewProjectRemoveDestinationCommand(clientOpts *argocdclient.ClientOptions) Use: "remove-destination PROJECT SERVER NAMESPACE", Short: "Remove project destination", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -278,7 +289,7 @@ func NewProjectRemoveDestinationCommand(clientOpts *argocdclient.ClientOptions) conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) index := -1 @@ -292,7 +303,7 @@ func NewProjectRemoveDestinationCommand(clientOpts *argocdclient.ClientOptions) log.Fatal("Specified destination does not exist in project") } else { proj.Spec.Destinations = append(proj.Spec.Destinations[:index], proj.Spec.Destinations[index+1:]...) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) } }, @@ -310,6 +321,8 @@ func NewProjectAddOrphanedIgnoreCommand(clientOpts *argocdclient.ClientOptions) Use: "add-orphaned-ignore PROJECT GROUP KIND", Short: "Add a resource to orphaned ignore list", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -320,7 +333,7 @@ func NewProjectAddOrphanedIgnoreCommand(clientOpts *argocdclient.ClientOptions) conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) if proj.Spec.OrphanedResources == nil { @@ -336,7 +349,7 @@ func NewProjectAddOrphanedIgnoreCommand(clientOpts *argocdclient.ClientOptions) } proj.Spec.OrphanedResources.Ignore = append(proj.Spec.OrphanedResources.Ignore, v1alpha1.OrphanedResourceKey{Group: group, Kind: kind, Name: name}) } - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -353,6 +366,8 @@ func NewProjectRemoveOrphanedIgnoreCommand(clientOpts *argocdclient.ClientOption Use: "remove-orphaned-ignore PROJECT GROUP KIND NAME", Short: "Remove a resource from orphaned ignore list", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -363,7 +378,7 @@ func NewProjectRemoveOrphanedIgnoreCommand(clientOpts *argocdclient.ClientOption conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) if proj.Spec.OrphanedResources == nil { @@ -382,7 +397,7 @@ func NewProjectRemoveOrphanedIgnoreCommand(clientOpts *argocdclient.ClientOption log.Fatal("Specified resource does not exist in the orphaned ignore of project") } else { proj.Spec.OrphanedResources.Ignore = append(proj.Spec.OrphanedResources.Ignore[:index], proj.Spec.OrphanedResources.Ignore[index+1:]...) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) } }, @@ -397,6 +412,8 @@ func NewProjectAddSourceCommand(clientOpts *argocdclient.ClientOptions) *cobra.C Use: "add-source PROJECT URL", Short: "Add project source repository", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -406,7 +423,7 @@ func NewProjectAddSourceCommand(clientOpts *argocdclient.ClientOptions) *cobra.C conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) for _, item := range proj.Spec.SourceRepos { @@ -420,7 +437,7 @@ func NewProjectAddSourceCommand(clientOpts *argocdclient.ClientOptions) *cobra.C } } proj.Spec.SourceRepos = append(proj.Spec.SourceRepos, url) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -470,6 +487,8 @@ func modifyResourceListCmd(cmdUse, cmdDesc string, clientOpts *argocdclient.Clie Use: cmdUse, Short: cmdDesc, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -478,7 +497,7 @@ func modifyResourceListCmd(cmdUse, cmdDesc string, clientOpts *argocdclient.Clie conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) var list, allowList, denyList *[]metav1.GroupKind var listAction, listDesc string @@ -502,7 +521,7 @@ func modifyResourceListCmd(cmdUse, cmdDesc string, clientOpts *argocdclient.Clie } if modifyResourcesList(list, add, listAction+" "+listDesc, group, kind) { - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) } }, @@ -545,6 +564,8 @@ func NewProjectRemoveSourceCommand(clientOpts *argocdclient.ClientOptions) *cobr Use: "remove-source PROJECT URL", Short: "Remove project source repository", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -554,7 +575,7 @@ func NewProjectRemoveSourceCommand(clientOpts *argocdclient.ClientOptions) *cobr conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) index := -1 @@ -568,7 +589,7 @@ func NewProjectRemoveSourceCommand(clientOpts *argocdclient.ClientOptions) *cobr fmt.Printf("Source repository '%s' does not exist in project\n", url) } else { proj.Spec.SourceRepos = append(proj.Spec.SourceRepos[:index], proj.Spec.SourceRepos[index+1:]...) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) } }, @@ -583,6 +604,8 @@ func NewProjectDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comm Use: "delete PROJECT", Short: "Delete project", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -590,7 +613,7 @@ func NewProjectDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comm conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) for _, name := range args { - _, err := projIf.Delete(context.Background(), &projectpkg.ProjectQuery{Name: name}) + _, err := projIf.Delete(ctx, &projectpkg.ProjectQuery{Name: name}) errors.CheckError(err) } }, @@ -624,9 +647,11 @@ func NewProjectListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman Use: "list", Short: "List projects", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - projects, err := projIf.List(context.Background(), &projectpkg.ProjectQuery{}) + projects, err := projIf.List(ctx, &projectpkg.ProjectQuery{}) errors.CheckError(err) switch output { case "yaml", "json": @@ -787,6 +812,8 @@ func NewProjectGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command Use: "get PROJECT", Short: "Get project details", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -794,7 +821,7 @@ func NewProjectGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command projName := args[0] conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - detailedProject, err := projIf.GetDetailedProject(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + detailedProject, err := projIf.GetDetailedProject(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) switch output { @@ -817,6 +844,8 @@ func NewProjectEditCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman Use: "edit PROJECT", Short: "Edit project", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -824,7 +853,7 @@ func NewProjectEditCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman projName := args[0] conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer argoio.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) projData, err := json.Marshal(proj.Spec) errors.CheckError(err) @@ -841,12 +870,12 @@ func NewProjectEditCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman if err != nil { return err } - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) if err != nil { return err } proj.Spec = updatedSpec - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) if err != nil { return fmt.Errorf("Failed to update project:\n%v", err) } diff --git a/cmd/argocd/commands/project_role.go b/cmd/argocd/commands/project_role.go index 2cb47921ab48e..987e61914d858 100644 --- a/cmd/argocd/commands/project_role.go +++ b/cmd/argocd/commands/project_role.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "os" "strconv" @@ -58,6 +57,8 @@ func NewProjectRoleAddPolicyCommand(clientOpts *argocdclient.ClientOptions) *cob Use: "add-policy PROJECT ROLE-NAME", Short: "Add a policy to a project role", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -67,7 +68,7 @@ func NewProjectRoleAddPolicyCommand(clientOpts *argocdclient.ClientOptions) *cob conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) role, roleIndex, err := proj.GetRoleByName(roleName) @@ -76,7 +77,7 @@ func NewProjectRoleAddPolicyCommand(clientOpts *argocdclient.ClientOptions) *cob policy := fmt.Sprintf(policyTemplate, proj.Name, role.Name, opts.action, proj.Name, opts.object, opts.permission) proj.Spec.Roles[roleIndex].Policies = append(role.Policies, policy) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -93,6 +94,8 @@ func NewProjectRoleRemovePolicyCommand(clientOpts *argocdclient.ClientOptions) * Use: "remove-policy PROJECT ROLE-NAME", Short: "Remove a policy from a role within a project", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -102,7 +105,7 @@ func NewProjectRoleRemovePolicyCommand(clientOpts *argocdclient.ClientOptions) * conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) role, roleIndex, err := proj.GetRoleByName(roleName) @@ -121,7 +124,7 @@ func NewProjectRoleRemovePolicyCommand(clientOpts *argocdclient.ClientOptions) * } role.Policies[duplicateIndex] = role.Policies[len(role.Policies)-1] proj.Spec.Roles[roleIndex].Policies = role.Policies[:len(role.Policies)-1] - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -138,6 +141,8 @@ func NewProjectRoleCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra. Use: "create PROJECT ROLE-NAME", Short: "Create a project role", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -147,7 +152,7 @@ func NewProjectRoleCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra. conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) _, _, err = proj.GetRoleByName(roleName) @@ -157,7 +162,7 @@ func NewProjectRoleCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra. } proj.Spec.Roles = append(proj.Spec.Roles, v1alpha1.ProjectRole{Name: roleName, Description: description}) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) fmt.Printf("Role '%s' created\n", roleName) }, @@ -172,6 +177,8 @@ func NewProjectRoleDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra. Use: "delete PROJECT ROLE-NAME", Short: "Delete a project role", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -181,7 +188,7 @@ func NewProjectRoleDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra. conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) _, index, err := proj.GetRoleByName(roleName) @@ -192,7 +199,7 @@ func NewProjectRoleDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra. proj.Spec.Roles[index] = proj.Spec.Roles[len(proj.Spec.Roles)-1] proj.Spec.Roles = proj.Spec.Roles[:len(proj.Spec.Roles)-1] - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) fmt.Printf("Role '%s' deleted\n", roleName) }, @@ -220,6 +227,8 @@ func NewProjectRoleCreateTokenCommand(clientOpts *argocdclient.ClientOptions) *c Short: "Create a project token", Aliases: []string{"token-create"}, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -233,7 +242,7 @@ func NewProjectRoleCreateTokenCommand(clientOpts *argocdclient.ClientOptions) *c } duration, err := timeutil.ParseDuration(expiresIn) errors.CheckError(err) - tokenResponse, err := projIf.CreateToken(context.Background(), &projectpkg.ProjectTokenCreateRequest{ + tokenResponse, err := projIf.CreateToken(ctx, &projectpkg.ProjectTokenCreateRequest{ Project: projName, Role: roleName, ExpiresIn: int64(duration.Seconds()), @@ -283,6 +292,8 @@ func NewProjectRoleListTokensCommand(clientOpts *argocdclient.ClientOptions) *co Short: "List tokens for a given role.", Aliases: []string{"list-token", "token-list"}, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -293,7 +304,7 @@ func NewProjectRoleListTokensCommand(clientOpts *argocdclient.ClientOptions) *co conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) role, _, err := proj.GetRoleByName(roleName) errors.CheckError(err) @@ -332,6 +343,8 @@ func NewProjectRoleDeleteTokenCommand(clientOpts *argocdclient.ClientOptions) *c Short: "Delete a project token", Aliases: []string{"token-delete", "remove-token"}, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -344,7 +357,7 @@ func NewProjectRoleDeleteTokenCommand(clientOpts *argocdclient.ClientOptions) *c conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - _, err = projIf.DeleteToken(context.Background(), &projectpkg.ProjectTokenDeleteRequest{Project: projName, Role: roleName, Iat: issuedAt}) + _, err = projIf.DeleteToken(ctx, &projectpkg.ProjectTokenDeleteRequest{Project: projName, Role: roleName, Iat: issuedAt}) errors.CheckError(err) }, } @@ -377,6 +390,8 @@ func NewProjectRoleListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Use: "list PROJECT", Short: "List all the roles in a project", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -385,7 +400,7 @@ func NewProjectRoleListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - project, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + project, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) switch output { case "json", "yaml": @@ -410,6 +425,8 @@ func NewProjectRoleGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com Use: "get PROJECT ROLE-NAME", Short: "Get the details of a specific role", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -419,7 +436,7 @@ func NewProjectRoleGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) role, _, err := proj.GetRoleByName(roleName) @@ -453,6 +470,8 @@ func NewProjectRoleAddGroupCommand(clientOpts *argocdclient.ClientOptions) *cobr Use: "add-group PROJECT ROLE-NAME GROUP-CLAIM", Short: "Add a group claim to a project role", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -460,7 +479,7 @@ func NewProjectRoleAddGroupCommand(clientOpts *argocdclient.ClientOptions) *cobr projName, roleName, groupName := args[0], args[1], args[2] conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) updated, err := proj.AddGroupToRole(roleName, groupName) errors.CheckError(err) @@ -468,7 +487,7 @@ func NewProjectRoleAddGroupCommand(clientOpts *argocdclient.ClientOptions) *cobr fmt.Printf("Group '%s' already present in role '%s'\n", groupName, roleName) return } - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) fmt.Printf("Group '%s' added to role '%s'\n", groupName, roleName) }, @@ -482,6 +501,8 @@ func NewProjectRoleRemoveGroupCommand(clientOpts *argocdclient.ClientOptions) *c Use: "remove-group PROJECT ROLE-NAME GROUP-CLAIM", Short: "Remove a group claim from a role within a project", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 3 { c.HelpFunc()(c, args) os.Exit(1) @@ -489,7 +510,7 @@ func NewProjectRoleRemoveGroupCommand(clientOpts *argocdclient.ClientOptions) *c projName, roleName, groupName := args[0], args[1], args[2] conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) updated, err := proj.RemoveGroupFromRole(roleName, groupName) errors.CheckError(err) @@ -497,7 +518,7 @@ func NewProjectRoleRemoveGroupCommand(clientOpts *argocdclient.ClientOptions) *c fmt.Printf("Group '%s' not present in role '%s'\n", groupName, roleName) return } - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) fmt.Printf("Group '%s' removed from role '%s'\n", groupName, roleName) }, diff --git a/cmd/argocd/commands/projectwindows.go b/cmd/argocd/commands/projectwindows.go index a7c6e555b4b20..0bc867cc6cf68 100644 --- a/cmd/argocd/commands/projectwindows.go +++ b/cmd/argocd/commands/projectwindows.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "os" "strconv" @@ -44,6 +43,8 @@ func NewProjectWindowsDisableManualSyncCommand(clientOpts *argocdclient.ClientOp Short: "Disable manual sync for a sync window", Long: "Disable manual sync for a sync window. Requires ID which can be found by running \"argocd proj windows list PROJECT\"", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -56,7 +57,7 @@ func NewProjectWindowsDisableManualSyncCommand(clientOpts *argocdclient.ClientOp conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) for i, window := range proj.Spec.SyncWindows { @@ -65,7 +66,7 @@ func NewProjectWindowsDisableManualSyncCommand(clientOpts *argocdclient.ClientOp } } - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -79,6 +80,8 @@ func NewProjectWindowsEnableManualSyncCommand(clientOpts *argocdclient.ClientOpt Short: "Enable manual sync for a sync window", Long: "Enable manual sync for a sync window. Requires ID which can be found by running \"argocd proj windows list PROJECT\"", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -91,7 +94,7 @@ func NewProjectWindowsEnableManualSyncCommand(clientOpts *argocdclient.ClientOpt conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) for i, window := range proj.Spec.SyncWindows { @@ -100,7 +103,7 @@ func NewProjectWindowsEnableManualSyncCommand(clientOpts *argocdclient.ClientOpt } } - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -123,6 +126,8 @@ func NewProjectWindowsAddWindowCommand(clientOpts *argocdclient.ClientOptions) * Use: "add PROJECT", Short: "Add a sync window to a project", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -131,13 +136,13 @@ func NewProjectWindowsAddWindowCommand(clientOpts *argocdclient.ClientOptions) * conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) err = proj.Spec.AddWindow(kind, schedule, duration, applications, namespaces, clusters, manualSync, timeZone) errors.CheckError(err) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -159,6 +164,8 @@ func NewProjectWindowsDeleteCommand(clientOpts *argocdclient.ClientOptions) *cob Use: "delete PROJECT ID", Short: "Delete a sync window from a project. Requires ID which can be found by running \"argocd proj windows list PROJECT\"", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -171,13 +178,13 @@ func NewProjectWindowsDeleteCommand(clientOpts *argocdclient.ClientOptions) *cob conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) err = proj.Spec.DeleteWindow(id) errors.CheckError(err) - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -199,6 +206,8 @@ func NewProjectWindowsUpdateCommand(clientOpts *argocdclient.ClientOptions) *cob Short: "Update a project sync window", Long: "Update a project sync window. Requires ID which can be found by running \"argocd proj windows list PROJECT\"", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 2 { c.HelpFunc()(c, args) os.Exit(1) @@ -211,7 +220,7 @@ func NewProjectWindowsUpdateCommand(clientOpts *argocdclient.ClientOptions) *cob conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) for i, window := range proj.Spec.SyncWindows { @@ -223,7 +232,7 @@ func NewProjectWindowsUpdateCommand(clientOpts *argocdclient.ClientOptions) *cob } } - _, err = projIf.Update(context.Background(), &projectpkg.ProjectUpdateRequest{Project: proj}) + _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) errors.CheckError(err) }, } @@ -245,6 +254,8 @@ func NewProjectWindowsListCommand(clientOpts *argocdclient.ClientOptions) *cobra Use: "list PROJECT", Short: "List project sync windows", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -253,7 +264,7 @@ func NewProjectWindowsListCommand(clientOpts *argocdclient.ClientOptions) *cobra conn, projIf := headless.NewClientOrDie(clientOpts, c).NewProjectClientOrDie() defer io.Close(conn) - proj, err := projIf.Get(context.Background(), &projectpkg.ProjectQuery{Name: projName}) + proj, err := projIf.Get(ctx, &projectpkg.ProjectQuery{Name: projName}) errors.CheckError(err) switch output { case "yaml", "json": diff --git a/cmd/argocd/commands/relogin.go b/cmd/argocd/commands/relogin.go index 69cfa4aa06209..bb1e9e20ed06e 100644 --- a/cmd/argocd/commands/relogin.go +++ b/cmd/argocd/commands/relogin.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "os" @@ -29,6 +28,8 @@ func NewReloginCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Comm Short: "Refresh an expired authenticate token", Long: "Refresh an expired authenticate token", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -59,12 +60,11 @@ func NewReloginCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Comm errors.CheckError(err) if claims.Issuer == session.SessionManagerClaimsIssuer { fmt.Printf("Relogging in as '%s'\n", localconfig.GetUsername(claims.Subject)) - tokenString = passwordLogin(acdClient, localconfig.GetUsername(claims.Subject), password) + tokenString = passwordLogin(ctx, acdClient, localconfig.GetUsername(claims.Subject), password) } else { fmt.Println("Reinitiating SSO login") setConn, setIf := acdClient.NewSettingsClientOrDie() defer argoio.Close(setConn) - ctx := context.Background() httpClient, err := acdClient.HTTPClient() errors.CheckError(err) ctx = oidc.ClientContext(ctx, httpClient) diff --git a/cmd/argocd/commands/repo.go b/cmd/argocd/commands/repo.go index 37a7c46ffdf34..8b46b03c8e1e7 100644 --- a/cmd/argocd/commands/repo.go +++ b/cmd/argocd/commands/repo.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "io/ioutil" "os" @@ -79,6 +78,8 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Short: "Add git repository connection parameters", Example: repoAddExamples, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -185,7 +186,7 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Proxy: repoOpts.Proxy, Project: repoOpts.Repo.Project, } - _, err := repoIf.ValidateAccess(context.Background(), &repoAccessReq) + _, err := repoIf.ValidateAccess(ctx, &repoAccessReq) errors.CheckError(err) repoCreateReq := repositorypkg.RepoCreateRequest{ @@ -193,7 +194,7 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Upsert: repoOpts.Upsert, } - createdRepo, err := repoIf.CreateRepository(context.Background(), &repoCreateReq) + createdRepo, err := repoIf.CreateRepository(ctx, &repoCreateReq) errors.CheckError(err) fmt.Printf("Repository '%s' added\n", createdRepo.Repo) }, @@ -209,6 +210,8 @@ func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command Use: "rm REPO", Short: "Remove repository credentials", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -216,7 +219,7 @@ func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command conn, repoIf := headless.NewClientOrDie(clientOpts, c).NewRepoClientOrDie() defer io.Close(conn) for _, repoURL := range args { - _, err := repoIf.DeleteRepository(context.Background(), &repositorypkg.RepoQuery{Repo: repoURL}) + _, err := repoIf.DeleteRepository(ctx, &repositorypkg.RepoQuery{Repo: repoURL}) errors.CheckError(err) fmt.Printf("Repository '%s' removed\n", repoURL) } @@ -262,6 +265,8 @@ func NewRepoListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Use: "list", Short: "List configured repositories", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + conn, repoIf := headless.NewClientOrDie(clientOpts, c).NewRepoClientOrDie() defer io.Close(conn) forceRefresh := false @@ -273,7 +278,7 @@ func NewRepoListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { err := fmt.Errorf("--refresh must be one of: 'hard'") errors.CheckError(err) } - repos, err := repoIf.ListRepositories(context.Background(), &repositorypkg.RepoQuery{ForceRefresh: forceRefresh}) + repos, err := repoIf.ListRepositories(ctx, &repositorypkg.RepoQuery{ForceRefresh: forceRefresh}) errors.CheckError(err) switch output { case "yaml", "json": @@ -304,6 +309,8 @@ func NewRepoGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { Use: "get", Short: "Get a configured repository by URL", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -322,7 +329,7 @@ func NewRepoGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { err := fmt.Errorf("--refresh must be one of: 'hard'") errors.CheckError(err) } - repo, err := repoIf.Get(context.Background(), &repositorypkg.RepoQuery{Repo: repoURL, ForceRefresh: forceRefresh}) + repo, err := repoIf.Get(ctx, &repositorypkg.RepoQuery{Repo: repoURL, ForceRefresh: forceRefresh}) errors.CheckError(err) switch output { case "yaml", "json": diff --git a/cmd/argocd/commands/repocreds.go b/cmd/argocd/commands/repocreds.go index 0386047ed16bf..ba6e61803e63a 100644 --- a/cmd/argocd/commands/repocreds.go +++ b/cmd/argocd/commands/repocreds.go @@ -1,7 +1,6 @@ package commands import ( - "context" "fmt" "io/ioutil" "os" @@ -71,6 +70,8 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma Short: "Add git repository connection parameters", Example: repocredsAddExamples, Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) != 1 { c.HelpFunc()(c, args) os.Exit(1) @@ -141,7 +142,7 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma Upsert: upsert, } - createdRepo, err := repoIf.CreateRepositoryCredentials(context.Background(), &repoCreateReq) + createdRepo, err := repoIf.CreateRepositoryCredentials(ctx, &repoCreateReq) errors.CheckError(err) fmt.Printf("Repository credentials for '%s' added\n", createdRepo.URL) }, @@ -167,6 +168,8 @@ func NewRepoCredsRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Use: "rm CREDSURL", Short: "Remove repository credentials", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + if len(args) == 0 { c.HelpFunc()(c, args) os.Exit(1) @@ -174,7 +177,7 @@ func NewRepoCredsRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co conn, repoIf := headless.NewClientOrDie(clientOpts, c).NewRepoCredsClientOrDie() defer io.Close(conn) for _, repoURL := range args { - _, err := repoIf.DeleteRepositoryCredentials(context.Background(), &repocredspkg.RepoCredsDeleteRequest{Url: repoURL}) + _, err := repoIf.DeleteRepositoryCredentials(ctx, &repocredspkg.RepoCredsDeleteRequest{Url: repoURL}) errors.CheckError(err) fmt.Printf("Repository credentials for '%s' removed\n", repoURL) } @@ -212,9 +215,11 @@ func NewRepoCredsListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comm Use: "list", Short: "List configured repository credentials", Run: func(c *cobra.Command, args []string) { + ctx := c.Context() + conn, repoIf := headless.NewClientOrDie(clientOpts, c).NewRepoCredsClientOrDie() defer io.Close(conn) - repos, err := repoIf.ListRepositoryCredentials(context.Background(), &repocredspkg.RepoCredsQuery{}) + repos, err := repoIf.ListRepositoryCredentials(ctx, &repocredspkg.RepoCredsQuery{}) errors.CheckError(err) switch output { case "yaml", "json": diff --git a/cmd/argocd/commands/version.go b/cmd/argocd/commands/version.go index a86c36898e763..eab17c7d4e588 100644 --- a/cmd/argocd/commands/version.go +++ b/cmd/argocd/commands/version.go @@ -40,6 +40,8 @@ func NewVersionCmd(clientOpts *argocdclient.ClientOptions) *cobra.Command { argocd version --short -o yaml `, Run: func(cmd *cobra.Command, args []string) { + ctx := cmd.Context() + cv := common.GetVersion() switch output { case "yaml", "json": @@ -52,7 +54,7 @@ func NewVersionCmd(clientOpts *argocdclient.ClientOptions) *cobra.Command { } if !client { - sv := getServerVersion(clientOpts, cmd) + sv := getServerVersion(ctx, clientOpts, cmd) if short { v["server"] = map[string]string{"argocd-server": sv.Version} @@ -67,7 +69,7 @@ func NewVersionCmd(clientOpts *argocdclient.ClientOptions) *cobra.Command { printClientVersion(&cv, short || (output == "short")) if !client { - sv := getServerVersion(clientOpts, cmd) + sv := getServerVersion(ctx, clientOpts, cmd) printServerVersion(sv, short || (output == "short")) } default: @@ -81,11 +83,11 @@ func NewVersionCmd(clientOpts *argocdclient.ClientOptions) *cobra.Command { return &versionCmd } -func getServerVersion(options *argocdclient.ClientOptions, c *cobra.Command) *version.VersionMessage { +func getServerVersion(ctx context.Context, options *argocdclient.ClientOptions, c *cobra.Command) *version.VersionMessage { conn, versionIf := headless.NewClientOrDie(options, c).NewVersionClientOrDie() defer argoio.Close(conn) - v, err := versionIf.Version(context.Background(), &empty.Empty{}) + v, err := versionIf.Version(ctx, &empty.Empty{}) errors.CheckError(err) return v From 792308c32769e1e80184456f262dfb8ba0f06b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Didrik=20Finn=C3=B8y?= Date: Tue, 5 Jul 2022 16:47:38 +0200 Subject: [PATCH 26/33] docs: Document the possibility of rendering Helm charts with Kustomize (#9841) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update kustomize.md Resolves #7835. Signed-off-by: Didrik Finnøy * Removed unnecessary command flag from example. Minor text edits. Signed-off-by: Didrik Finnøy * spelling Signed-off-by: Didrik Finnøy --- docs/user-guide/kustomize.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/user-guide/kustomize.md b/docs/user-guide/kustomize.md index 0b62a0ff6c8f3..e377c9886b91a 100644 --- a/docs/user-guide/kustomize.md +++ b/docs/user-guide/kustomize.md @@ -85,3 +85,22 @@ argocd app set --kustomize-version v3.5.4 ## Build Environment Kustomize does not support parameters and therefore cannot support the standard [build environment](build-environment.md). + +## Kustomizing Helm charts + +It's possible to [render Helm charts with Kustomize](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/chart.md). +Doing so requires that you pass the `--enable-helm` flag to the `kustomize build` command. +This flag is not part of the Kustomize options within Argo CD. +If you would like to render Helm charts through Kustomize in an Argo CD application, you have two options: +You can either create a [custom plugin](https://argo-cd.readthedocs.io/en/stable/user-guide/config-management-plugins/), or modify the `argocd-cm` ConfigMap to include the `--enable-helm` flag globally for all Kustomize applications: + +``` +apiVersion: v1 +kind: ConfigMap +metadata: + name: argocd-cm + namespace: argocd +data: + kustomize.buildOptions: --enable-helm +``` + From 61f321cd2ee5b70306135b5552233fee5dc5c493 Mon Sep 17 00:00:00 2001 From: Jake <86763948+notfromstatefarm@users.noreply.github.com> Date: Tue, 5 Jul 2022 10:48:31 -0400 Subject: [PATCH 27/33] docs: small fix for plugin stream filtering (#9871) Signed-off-by: notfromstatefarm <86763948+notfromstatefarm@users.noreply.github.com> --- docs/user-guide/config-management-plugins.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/user-guide/config-management-plugins.md b/docs/user-guide/config-management-plugins.md index f50646272c982..a2dd91b136265 100644 --- a/docs/user-guide/config-management-plugins.md +++ b/docs/user-guide/config-management-plugins.md @@ -235,16 +235,17 @@ If you don't need to set any environment variables, you can set an empty plugin 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 +## Plugin tar stream exclusions 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. +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. \ No newline at end of file From f13fc39650d1af819154ebb1e711698a5a2081ad Mon Sep 17 00:00:00 2001 From: YaytayAtWork Date: Tue, 5 Jul 2022 19:04:29 +0100 Subject: [PATCH 28/33] #9429: Adding blank line so list is formatted correctly. (#9880) --- docs/getting_started.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/getting_started.md b/docs/getting_started.md index 0eca3cbecf8be..b327d796263ce 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -31,6 +31,7 @@ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/st This default installation will have a self-signed certificate and cannot be accessed without a bit of extra work. Do one of: + * Follow the [instructions to configure a certificate](./operator-manual/tls) (and ensure that the client OS trusts it). * Configure the client OS to trust the self signed certificate. * Use the --insecure flag on all Argo CD CLI operations in this guide. From 2389e5bf99f72481ca20e9125b1d1178d3b8e15d Mon Sep 17 00:00:00 2001 From: jannfis Date: Wed, 6 Jul 2022 14:49:33 +0200 Subject: [PATCH 29/33] test: Remove circular symlinks from testdata (#9886) * test: Remove circular symlinks from testdata Signed-off-by: jannfis * Another test case Signed-off-by: jannfis * Use defer for changing back to original workdir Signed-off-by: jannfis * Abort the test on error in defer Signed-off-by: jannfis --- reposerver/repository/repository_test.go | 39 ++++++++++++++++++- .../repository/testdata/circular-link/.keep | 0 .../repository/testdata/circular-link/a.json | 1 - .../repository/testdata/circular-link/b.json | 1 - 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 reposerver/repository/testdata/circular-link/.keep delete mode 120000 reposerver/repository/testdata/circular-link/a.json delete mode 120000 reposerver/repository/testdata/circular-link/b.json diff --git a/reposerver/repository/repository_test.go b/reposerver/repository/repository_test.go index a57d15401da00..de03fb8c24fd1 100644 --- a/reposerver/repository/repository_test.go +++ b/reposerver/repository/repository_test.go @@ -133,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("../..") @@ -2008,7 +2033,12 @@ func Test_getPotentiallyValidManifests(t *testing.T) { }) t.Run("circular link should throw an error", func(t *testing.T) { - require.DirExists(t, "./testdata/circular-link") + 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) @@ -2103,7 +2133,12 @@ func Test_findManifests(t *testing.T) { }) t.Run("circular link should throw an error", func(t *testing.T) { - require.DirExists(t, "./testdata/circular-link") + 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) diff --git a/reposerver/repository/testdata/circular-link/.keep b/reposerver/repository/testdata/circular-link/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/reposerver/repository/testdata/circular-link/a.json b/reposerver/repository/testdata/circular-link/a.json deleted file mode 120000 index ce080bc5ebcc3..0000000000000 --- a/reposerver/repository/testdata/circular-link/a.json +++ /dev/null @@ -1 +0,0 @@ -b.json \ No newline at end of file diff --git a/reposerver/repository/testdata/circular-link/b.json b/reposerver/repository/testdata/circular-link/b.json deleted file mode 120000 index 8eacec086127a..0000000000000 --- a/reposerver/repository/testdata/circular-link/b.json +++ /dev/null @@ -1 +0,0 @@ -a.json \ No newline at end of file From f457dbbebd940f96e53feaf4cfeaba38213708b5 Mon Sep 17 00:00:00 2001 From: Shunki <75064402+shunki-fujita@users.noreply.github.com> Date: Wed, 6 Jul 2022 21:59:10 +0900 Subject: [PATCH 30/33] fix: argo-cd git submodule is using SSH auth instead of HTTPs (#3118) (#9821) * fix: argo-cd git submodule is using SSH auth instead of HTTPs (#3118) Signed-off-by: shunki-fujita * Add submodule functions and unit tests Signed-off-by: shunki-fujita --- util/git/client.go | 14 ++++- util/git/client_test.go | 115 +++++++++++++++++++++++++++++++++++++++ util/git/mocks/Client.go | 17 +++++- 3 files changed, 143 insertions(+), 3 deletions(-) diff --git a/util/git/client.go b/util/git/client.go index 98c40c20641ca..8b288ae4550d6 100644 --- a/util/git/client.go +++ b/util/git/client.go @@ -60,6 +60,7 @@ type Client interface { Root() string Init() error Fetch(revision string) error + Submodule() error Checkout(revision string, submoduleEnabled bool) error LsRefs() (*Refs, error) LsRemote(revision string) (string, error) @@ -382,6 +383,17 @@ func (m *nativeGitClient) LsLargeFiles() ([]string, error) { return ss, nil } +// Submodule embed other repositories into this repository +func (m *nativeGitClient) Submodule() error { + if err := m.runCredentialedCmd("git", "submodule", "sync", "--recursive"); err != nil { + return err + } + if err := m.runCredentialedCmd("git", "submodule", "update", "--init", "--recursive"); err != nil { + return err + } + return nil +} + // Checkout checkout specified revision func (m *nativeGitClient) Checkout(revision string, submoduleEnabled bool) error { if revision == "" || revision == "HEAD" { @@ -405,7 +417,7 @@ func (m *nativeGitClient) Checkout(revision string, submoduleEnabled bool) error } if _, err := os.Stat(m.root + "/.gitmodules"); !os.IsNotExist(err) { if submoduleEnabled { - if err := m.runCredentialedCmd("git", "submodule", "update", "--init", "--recursive"); err != nil { + if err := m.Submodule(); err != nil { return err } } diff --git a/util/git/client_test.go b/util/git/client_test.go index 6cd690764d32d..7e7dbb5ca2122 100644 --- a/util/git/client_test.go +++ b/util/git/client_test.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "os/exec" + "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -93,6 +94,120 @@ func Test_nativeGitClient_Fetch_Prune(t *testing.T) { assert.NoError(t, err) } +func Test_nativeGitClient_Submodule(t *testing.T) { + tempDir, err := os.MkdirTemp("", "") + require.NoError(t, err) + + foo := filepath.Join(tempDir, "foo") + err = os.Mkdir(foo, 0755) + require.NoError(t, err) + + cmd := exec.Command("git", "init") + cmd.Dir = foo + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + require.NoError(t, err) + + bar := filepath.Join(tempDir, "bar") + err = os.Mkdir(bar, 0755) + require.NoError(t, err) + + cmd = exec.Command("git", "init") + cmd.Dir = bar + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + require.NoError(t, err) + + cmd = exec.Command("git", "commit", "-m", "Initial commit", "--allow-empty") + cmd.Dir = bar + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + require.NoError(t, err) + + // Embed repository bar into repository foo + cmd = exec.Command("git", "submodule", "add", bar) + cmd.Dir = foo + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + require.NoError(t, err) + + cmd = exec.Command("git", "commit", "-m", "Initial commit") + cmd.Dir = foo + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + require.NoError(t, err) + + tempDir, err = os.MkdirTemp("", "") + require.NoError(t, err) + + // Clone foo + cmd = exec.Command("git", "clone", foo) + cmd.Dir = tempDir + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + require.NoError(t, err) + + client, err := NewClient(fmt.Sprintf("file://%s", foo), NopCreds{}, true, false, "") + require.NoError(t, err) + + err = client.Init() + require.NoError(t, err) + + err = client.Fetch("") + assert.NoError(t, err) + + commitSHA, err := client.LsRemote("HEAD") + assert.NoError(t, err) + + // Call Checkout() with submoduleEnabled=false. + err = client.Checkout(commitSHA, false) + assert.NoError(t, err) + + // Check if submodule url does not exist in .git/config + cmd = exec.Command("git", "config", "submodule.bar.url") + cmd.Dir = client.Root() + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + assert.Error(t, err) + + // Call Submodule() via Checkout() with submoduleEnabled=true. + err = client.Checkout(commitSHA, true) + assert.NoError(t, err) + + // Check if the .gitmodule URL is reflected in .git/config + cmd = exec.Command("git", "config", "submodule.bar.url") + cmd.Dir = client.Root() + result, err := cmd.Output() + assert.NoError(t, err) + assert.Equal(t, bar+"\n", string(result)) + + // Change URL of submodule bar + cmd = exec.Command("git", "config", "--file=.gitmodules", "submodule.bar.url", bar+"baz") + cmd.Dir = client.Root() + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + require.NoError(t, err) + + // Call Submodule() + err = client.Submodule() + assert.NoError(t, err) + + // Check if the URL change in .gitmodule is reflected in .git/config + cmd = exec.Command("git", "config", "submodule.bar.url") + cmd.Dir = client.Root() + result, err = cmd.Output() + assert.NoError(t, err) + assert.Equal(t, bar+"baz\n", string(result)) +} + func TestNewClient_invalidSSHURL(t *testing.T) { client, err := NewClient("ssh://bitbucket.org:org/repo", NopCreds{}, false, false, "") assert.Nil(t, client) diff --git a/util/git/mocks/Client.go b/util/git/mocks/Client.go index c1624df0617a8..3d4471b1f23c1 100644 --- a/util/git/mocks/Client.go +++ b/util/git/mocks/Client.go @@ -3,9 +3,8 @@ package mocks import ( - mock "github.com/stretchr/testify/mock" - git "github.com/argoproj/argo-cd/v2/util/git" + mock "github.com/stretchr/testify/mock" ) // Client is an autogenerated mock type for the Client type @@ -203,6 +202,20 @@ func (_m *Client) Root() string { return r0 } +// Submodule provides a mock function with given fields: +func (_m *Client) Submodule() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + // VerifyCommitSignature provides a mock function with given fields: _a0 func (_m *Client) VerifyCommitSignature(_a0 string) (string, error) { ret := _m.Called(_a0) From b8b7e91ccd93aaba8ebbfce585dbe8daad4bc840 Mon Sep 17 00:00:00 2001 From: jannfis Date: Wed, 6 Jul 2022 18:33:06 +0200 Subject: [PATCH 31/33] chore: Replace deprecated ioutil in hacks (#9851) Signed-off-by: jannfis --- hack/dev-mounter/main.go | 3 +-- hack/gen-catalog/main.go | 11 +++++------ hack/gen-crd-spec/main.go | 3 +-- hack/gen-docs/main.go | 5 ++--- hack/gen-resources/generators/repo_generator.go | 4 ++-- hack/gen-resources/util/gen_options_parser.go | 4 ++-- hack/known_types/main.go | 5 ++--- 7 files changed, 15 insertions(+), 20 deletions(-) diff --git a/hack/dev-mounter/main.go b/hack/dev-mounter/main.go index 59212f20579ce..bd01ae939e5b9 100644 --- a/hack/dev-mounter/main.go +++ b/hack/dev-mounter/main.go @@ -3,7 +3,6 @@ package main import ( "context" "fmt" - "io/ioutil" "os" "path" "path/filepath" @@ -88,7 +87,7 @@ func newCommand() *cobra.Command { // Create or update files that are specified in ConfigMap for name, data := range cm.Data { p := path.Join(destPath, name) - err := ioutil.WriteFile(p, []byte(data), 0644) + err := os.WriteFile(p, []byte(data), 0644) if err != nil { log.Warnf("Failed to create file %s: %v", p, err) } diff --git a/hack/gen-catalog/main.go b/hack/gen-catalog/main.go index 5b13ee1932f89..d07c4f34f694b 100644 --- a/hack/gen-catalog/main.go +++ b/hack/gen-catalog/main.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "os" "path" "path/filepath" @@ -82,7 +81,7 @@ func newCatalogCommand() *cobra.Command { d, err := yaml.Marshal(cm) dieOnError(err, "Failed to marshal final configmap") - err = ioutil.WriteFile(target, d, 0644) + err = os.WriteFile(target, d, 0644) dieOnError(err, "Failed to write builtin configmap") }, @@ -103,14 +102,14 @@ func newDocsCommand() *cobra.Command { notificationTemplates, notificationTriggers, err := buildConfigFromFS(templatesDir, triggersDir) dieOnError(err, "Failed to build builtin config") generateBuiltInTriggersDocs(&builtItDocsData, notificationTriggers, notificationTemplates) - if err := ioutil.WriteFile("./docs/operator-manual/notifications/catalog.md", builtItDocsData.Bytes(), 0644); err != nil { + if err := os.WriteFile("./docs/operator-manual/notifications/catalog.md", builtItDocsData.Bytes(), 0644); err != nil { log.Fatal(err) } var commandDocs bytes.Buffer if err := generateCommandsDocs(&commandDocs); err != nil { log.Fatal(err) } - if err := ioutil.WriteFile("./docs/operator-manual/notifications/troubleshooting-commands.md", commandDocs.Bytes(), 0644); err != nil { + if err := os.WriteFile("./docs/operator-manual/notifications/troubleshooting-commands.md", commandDocs.Bytes(), 0644); err != nil { log.Fatal(err) } }, @@ -185,7 +184,7 @@ func buildConfigFromFS(templatesDir string, triggersDir string) (map[string]serv if info.IsDir() { return nil } - data, err := ioutil.ReadFile(p) + data, err := os.ReadFile(p) if err != nil { return err } @@ -209,7 +208,7 @@ func buildConfigFromFS(templatesDir string, triggersDir string) (map[string]serv if info.IsDir() { return nil } - data, err := ioutil.ReadFile(p) + data, err := os.ReadFile(p) if err != nil { return err } diff --git a/hack/gen-crd-spec/main.go b/hack/gen-crd-spec/main.go index 44e3c76ec828b..eaa4b7b51e9f0 100644 --- a/hack/gen-crd-spec/main.go +++ b/hack/gen-crd-spec/main.go @@ -3,7 +3,6 @@ package main import ( "encoding/json" "fmt" - "io/ioutil" "os" "os/exec" "strings" @@ -132,7 +131,7 @@ func writeCRDintoFile(crd *extensionsobj.CustomResourceDefinition, path string) yamlBytes, err := yaml.JSONToYAML(jsonBytes) checkErr(err) - err = ioutil.WriteFile(path, yamlBytes, 0644) + err = os.WriteFile(path, yamlBytes, 0644) checkErr(err) } diff --git a/hack/gen-docs/main.go b/hack/gen-docs/main.go index f82bf242a7ac5..180b02fffec4f 100644 --- a/hack/gen-docs/main.go +++ b/hack/gen-docs/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "io/ioutil" "log" "os" "sort" @@ -35,7 +34,7 @@ func generateNotificationsDocs() { func updateMkDocsNav(parent string, child string, subchild string, files []string) error { trimPrefixes(files, "docs/") sort.Strings(files) - data, err := ioutil.ReadFile("mkdocs.yml") + data, err := os.ReadFile("mkdocs.yml") if err != nil { return err } @@ -62,7 +61,7 @@ func updateMkDocsNav(parent string, child string, subchild string, files []strin if err != nil { return err } - return ioutil.WriteFile("mkdocs.yml", newmkdocs, 0644) + return os.WriteFile("mkdocs.yml", newmkdocs, 0644) } func trimPrefixes(files []string, prefix string) { diff --git a/hack/gen-resources/generators/repo_generator.go b/hack/gen-resources/generators/repo_generator.go index 9292c8feaae26..390dd27052069 100644 --- a/hack/gen-resources/generators/repo_generator.go +++ b/hack/gen-resources/generators/repo_generator.go @@ -5,7 +5,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "log" "net/http" @@ -39,7 +39,7 @@ func fetchRepos(token string, page int) ([]Repo, error) { if err != nil { return nil, err } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/hack/gen-resources/util/gen_options_parser.go b/hack/gen-resources/util/gen_options_parser.go index d2938f4520325..4a39703c3d03d 100644 --- a/hack/gen-resources/util/gen_options_parser.go +++ b/hack/gen-resources/util/gen_options_parser.go @@ -1,7 +1,7 @@ package util import ( - "io/ioutil" + "os" "gopkg.in/yaml.v2" ) @@ -46,7 +46,7 @@ type GenerateOpts struct { } func Parse(opts *GenerateOpts, file string) error { - fp, err := ioutil.ReadFile(file) + fp, err := os.ReadFile(file) if err != nil { return err } diff --git a/hack/known_types/main.go b/hack/known_types/main.go index 9a6f804eba009..a2e4665a0eb1a 100644 --- a/hack/known_types/main.go +++ b/hack/known_types/main.go @@ -5,7 +5,6 @@ import ( "fmt" "go/importer" "go/types" - "io/ioutil" "os" "strings" @@ -78,12 +77,12 @@ import corev1 "k8s.io/api/core/v1" func init() {%s }`, strings.Join(mapItems, "")) if docsOutputPath != "" { - if err = ioutil.WriteFile(docsOutputPath, []byte(strings.Join(docs, "\n")), 0644); err != nil { + if err = os.WriteFile(docsOutputPath, []byte(strings.Join(docs, "\n")), 0644); err != nil { return err } } - return ioutil.WriteFile(outputPath, []byte(res), 0644) + return os.WriteFile(outputPath, []byte(res), 0644) }, } command.Flags().StringVar(&docsOutputPath, "docs", "", "Docs output file path") From f34687bd80a8977052f2ce9cd145c8f0265d9b59 Mon Sep 17 00:00:00 2001 From: jannfis Date: Wed, 6 Jul 2022 18:45:04 +0200 Subject: [PATCH 32/33] chore: Replace deprecated ioutil in util packages (#9848) Signed-off-by: jannfis --- .../normalizers/knowntypes_normalizer_test.go | 4 +-- util/argo/resource_tracking_test.go | 12 +++---- util/cert/cert_test.go | 13 ++++---- util/cli/cli.go | 13 ++++---- util/clusterauth/clusterauth_test.go | 6 ++-- util/cmp/stream.go | 5 ++- util/cmp/stream_test.go | 3 +- util/config/reader.go | 10 +++--- util/config/reader_test.go | 3 +- util/db/gpgkeys.go | 5 ++- util/dex/dex.go | 6 ++-- util/git/creds.go | 11 +++---- util/git/creds_test.go | 7 ++--- util/git/git_test.go | 12 +++---- util/gpg/gpg.go | 15 +++++---- util/gpg/gpg_test.go | 29 +++++++++-------- util/helm/client.go | 24 +++++++------- util/helm/cmd.go | 31 +++++++++---------- util/helm/helm.go | 3 +- util/io/files/tar_test.go | 7 ++--- util/kube/kube_test.go | 14 ++++----- util/lua/custom_actions_test.go | 3 +- util/lua/health_test.go | 5 ++- util/oidc/oidc_test.go | 4 +-- util/tls/tls.go | 3 +- util/webhook/webhook_test.go | 23 +++++++------- 26 files changed, 128 insertions(+), 143 deletions(-) diff --git a/util/argo/normalizers/knowntypes_normalizer_test.go b/util/argo/normalizers/knowntypes_normalizer_test.go index ce6acfeff4c32..b6151d67f1005 100644 --- a/util/argo/normalizers/knowntypes_normalizer_test.go +++ b/util/argo/normalizers/knowntypes_normalizer_test.go @@ -2,7 +2,7 @@ package normalizers import ( "fmt" - "io/ioutil" + "os" "strings" "testing" @@ -286,7 +286,7 @@ func TestOverrideKeyWithoutGroup(t *testing.T) { } func TestKnownTypes(t *testing.T) { - typesData, err := ioutil.ReadFile("./diffing_known_types.txt") + typesData, err := os.ReadFile("./diffing_known_types.txt") if !assert.NoError(t, err) { return } diff --git a/util/argo/resource_tracking_test.go b/util/argo/resource_tracking_test.go index 17291eeee1144..e737e831fb255 100644 --- a/util/argo/resource_tracking_test.go +++ b/util/argo/resource_tracking_test.go @@ -1,7 +1,7 @@ package argo import ( - "io/ioutil" + "os" "testing" "github.com/argoproj/argo-cd/v2/util/kube" @@ -14,7 +14,7 @@ import ( ) func TestSetAppInstanceLabel(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") assert.Nil(t, err) var obj unstructured.Unstructured @@ -30,7 +30,7 @@ func TestSetAppInstanceLabel(t *testing.T) { } func TestSetAppInstanceAnnotation(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") assert.Nil(t, err) var obj unstructured.Unstructured @@ -47,7 +47,7 @@ func TestSetAppInstanceAnnotation(t *testing.T) { } func TestSetAppInstanceAnnotationAndLabel(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") assert.Nil(t, err) var obj unstructured.Unstructured err = yaml.Unmarshal(yamlBytes, &obj) @@ -63,7 +63,7 @@ func TestSetAppInstanceAnnotationAndLabel(t *testing.T) { } func TestSetAppInstanceAnnotationNotFound(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") assert.Nil(t, err) var obj unstructured.Unstructured @@ -108,7 +108,7 @@ func TestParseAppInstanceValueCorrectFormat(t *testing.T) { } func sampleResource() *unstructured.Unstructured { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") if err != nil { panic(err) } diff --git a/util/cert/cert_test.go b/util/cert/cert_test.go index dd461eccede8e..040798392edd1 100644 --- a/util/cert/cert_test.go +++ b/util/cert/cert_test.go @@ -2,7 +2,6 @@ package cert import ( "fmt" - "io/ioutil" "os" "path" "testing" @@ -473,11 +472,11 @@ func TestGetSSHKnownHostsDataPath(t *testing.T) { func TestGetCertificateForConnect(t *testing.T) { t.Run("Success", func(t *testing.T) { temppath := t.TempDir() - cert, err := ioutil.ReadFile("../../test/fixture/certs/argocd-test-server.crt") + cert, err := os.ReadFile("../../test/fixture/certs/argocd-test-server.crt") if err != nil { panic(err) } - err = ioutil.WriteFile(path.Join(temppath, "127.0.0.1"), cert, 0666) + err = os.WriteFile(path.Join(temppath, "127.0.0.1"), cert, 0666) if err != nil { panic(err) } @@ -497,7 +496,7 @@ func TestGetCertificateForConnect(t *testing.T) { t.Run("No valid cert in file", func(t *testing.T) { temppath := t.TempDir() - err := ioutil.WriteFile(path.Join(temppath, "127.0.0.1"), []byte("foobar"), 0666) + err := os.WriteFile(path.Join(temppath, "127.0.0.1"), []byte("foobar"), 0666) if err != nil { panic(err) } @@ -513,11 +512,11 @@ func TestGetCertificateForConnect(t *testing.T) { func TestGetCertBundlePathForRepository(t *testing.T) { t.Run("Success", func(t *testing.T) { temppath := t.TempDir() - cert, err := ioutil.ReadFile("../../test/fixture/certs/argocd-test-server.crt") + cert, err := os.ReadFile("../../test/fixture/certs/argocd-test-server.crt") if err != nil { panic(err) } - err = ioutil.WriteFile(path.Join(temppath, "127.0.0.1"), cert, 0666) + err = os.WriteFile(path.Join(temppath, "127.0.0.1"), cert, 0666) if err != nil { panic(err) } @@ -537,7 +536,7 @@ func TestGetCertBundlePathForRepository(t *testing.T) { t.Run("No valid cert in file", func(t *testing.T) { temppath := t.TempDir() - err := ioutil.WriteFile(path.Join(temppath, "127.0.0.1"), []byte("foobar"), 0666) + err := os.WriteFile(path.Join(temppath, "127.0.0.1"), []byte("foobar"), 0666) if err != nil { panic(err) } diff --git a/util/cli/cli.go b/util/cli/cli.go index e05a379c71f4b..83c8076a97743 100644 --- a/util/cli/cli.go +++ b/util/cli/cli.go @@ -7,7 +7,6 @@ import ( "bytes" "flag" "fmt" - "io/ioutil" "os" "os/exec" "path" @@ -180,7 +179,7 @@ func SetGLogLevel(glogLevel int) { } func writeToTempFile(pattern string, data []byte) string { - f, err := ioutil.TempFile("", pattern) + f, err := os.CreateTemp("", pattern) errors.CheckError(err) defer io.Close(f) _, err = f.Write(data) @@ -252,10 +251,10 @@ func InteractiveEdit(filePattern string, data []byte, save func(input []byte) er err := (term.TTY{In: os.Stdin, TryDev: true}).Safe(cmd.Run) errors.CheckError(err) - updated, err := ioutil.ReadFile(tempFile) + updated, err := os.ReadFile(tempFile) errors.CheckError(err) if string(updated) == "" || string(updated) == string(data) { - errors.CheckError(fmt.Errorf("Edit cancelled, no valid changes were saved.")) + errors.CheckError(fmt.Errorf("edit cancelled, no valid changes were saved")) break } else { data = stripComments(updated) @@ -272,7 +271,7 @@ func InteractiveEdit(filePattern string, data []byte, save func(input []byte) er // PrintDiff prints a diff between two unstructured objects to stdout using an external diff utility // Honors the diff utility set in the KUBECTL_EXTERNAL_DIFF environment variable func PrintDiff(name string, live *unstructured.Unstructured, target *unstructured.Unstructured) error { - tempDir, err := ioutil.TempDir("", "argocd-diff") + tempDir, err := os.MkdirTemp("", "argocd-diff") if err != nil { return err } @@ -284,7 +283,7 @@ func PrintDiff(name string, live *unstructured.Unstructured, target *unstructure return err } } - err = ioutil.WriteFile(targetFile, targetData, 0644) + err = os.WriteFile(targetFile, targetData, 0644) if err != nil { return err } @@ -296,7 +295,7 @@ func PrintDiff(name string, live *unstructured.Unstructured, target *unstructure return err } } - err = ioutil.WriteFile(liveFile, liveData, 0644) + err = os.WriteFile(liveFile, liveData, 0644) if err != nil { return err } diff --git a/util/clusterauth/clusterauth_test.go b/util/clusterauth/clusterauth_test.go index cb1699c765541..390c28fb887b8 100644 --- a/util/clusterauth/clusterauth_test.go +++ b/util/clusterauth/clusterauth_test.go @@ -2,7 +2,7 @@ package clusterauth import ( "context" - "io/ioutil" + "os" "testing" "time" @@ -36,7 +36,7 @@ var ( ) func newServiceAccount() *corev1.ServiceAccount { - saBytes, err := ioutil.ReadFile("./testdata/argocd-manager-sa.yaml") + saBytes, err := os.ReadFile("./testdata/argocd-manager-sa.yaml") errors.CheckError(err) var sa corev1.ServiceAccount err = yaml.Unmarshal(saBytes, &sa) @@ -45,7 +45,7 @@ func newServiceAccount() *corev1.ServiceAccount { } func newServiceAccountSecret() *corev1.Secret { - secretBytes, err := ioutil.ReadFile("./testdata/argocd-manager-sa-token.yaml") + secretBytes, err := os.ReadFile("./testdata/argocd-manager-sa-token.yaml") errors.CheckError(err) var secret corev1.Secret err = yaml.Unmarshal(secretBytes, &secret) diff --git a/util/cmp/stream.go b/util/cmp/stream.go index ad7b8b053a0f4..e53f667c6d889 100644 --- a/util/cmp/stream.go +++ b/util/cmp/stream.go @@ -7,7 +7,6 @@ import ( "encoding/hex" "fmt" "io" - "io/ioutil" "os" "path/filepath" "strings" @@ -171,7 +170,7 @@ func compressFiles(appPath string, excluded []string) (*os.File, string, error) if err != nil { return nil, "", fmt.Errorf("error creating tempDir for compressing files: %s", err) } - tgzFile, err := ioutil.TempFile(tempDir, appName) + tgzFile, err := os.CreateTemp(tempDir, appName) if err != nil { return nil, "", fmt.Errorf("error creating app temp tgz file: %w", err) } @@ -198,7 +197,7 @@ func compressFiles(appPath string, excluded []string) (*os.File, string, error) // It is responsibility of the caller to close the returned file. func receiveFile(ctx context.Context, receiver StreamReceiver, checksum, dst string) (*os.File, error) { hasher := sha256.New() - file, err := ioutil.TempFile(dst, "") + file, err := os.CreateTemp(dst, "") if err != nil { return nil, fmt.Errorf("error creating file: %w", err) } diff --git a/util/cmp/stream_test.go b/util/cmp/stream_test.go index b8d82edb75a28..7033890a18f3d 100644 --- a/util/cmp/stream_test.go +++ b/util/cmp/stream_test.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "io" - "io/ioutil" "os" "path/filepath" "testing" @@ -68,7 +67,7 @@ func TestReceiveApplicationStream(t *testing.T) { // then require.NoError(t, err) assert.NotEmpty(t, workdir) - files, err := ioutil.ReadDir(workdir) + files, err := os.ReadDir(workdir) require.NoError(t, err) require.Equal(t, 2, len(files)) names := []string{} diff --git a/util/config/reader.go b/util/config/reader.go index 050a2e58bbe75..d780df90bc8af 100644 --- a/util/config/reader.go +++ b/util/config/reader.go @@ -3,15 +3,15 @@ package config import ( "encoding/json" "io" - "io/ioutil" "net/http" + "os" "github.com/ghodss/yaml" ) // UnmarshalReader is used to read manifests from stdin func UnmarshalReader(reader io.Reader, obj interface{}) error { - data, err := ioutil.ReadAll(reader) + data, err := io.ReadAll(reader) if err != nil { return err } @@ -44,7 +44,7 @@ func unmarshalObject(data []byte, obj interface{}) error { func MarshalLocalYAMLFile(path string, obj interface{}) error { yamlData, err := yaml.Marshal(obj) if err == nil { - err = ioutil.WriteFile(path, yamlData, 0600) + err = os.WriteFile(path, yamlData, 0600) } return err } @@ -52,7 +52,7 @@ func MarshalLocalYAMLFile(path string, obj interface{}) error { // UnmarshalLocalFile retrieves JSON or YAML from a file on disk. // The caller is responsible for checking error return values. func UnmarshalLocalFile(path string, obj interface{}) error { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err == nil { err = unmarshalObject(data, obj) } @@ -82,7 +82,7 @@ func ReadRemoteFile(url string) ([]byte, error) { defer func() { _ = resp.Body.Close() }() - data, err = ioutil.ReadAll(resp.Body) + data, err = io.ReadAll(resp.Body) } return data, err } diff --git a/util/config/reader_test.go b/util/config/reader_test.go index 16417af584df5..f24eed9e4f622 100644 --- a/util/config/reader_test.go +++ b/util/config/reader_test.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net" "net/http" "os" @@ -21,7 +20,7 @@ func TestUnmarshalLocalFile(t *testing.T) { ) sentinel := fmt.Sprintf("---\nfield1: %q\nfield2: %d", field1, field2) - file, err := ioutil.TempFile(os.TempDir(), "") + file, err := os.CreateTemp(os.TempDir(), "") if err != nil { panic(err) } diff --git a/util/db/gpgkeys.go b/util/db/gpgkeys.go index 31f28dd249bbf..8a03c35bd45ca 100644 --- a/util/db/gpgkeys.go +++ b/util/db/gpgkeys.go @@ -3,7 +3,6 @@ package db import ( "context" "fmt" - "io/ioutil" "os" log "github.com/sirupsen/logrus" @@ -15,13 +14,13 @@ import ( // Validates a single GnuPG key and returns the key's ID func validatePGPKey(keyData string) (*appsv1.GnuPGPublicKey, error) { - f, err := ioutil.TempFile("", "gpg-public-key") + f, err := os.CreateTemp("", "gpg-public-key") if err != nil { return nil, err } defer os.Remove(f.Name()) - err = ioutil.WriteFile(f.Name(), []byte(keyData), 0600) + err = os.WriteFile(f.Name(), []byte(keyData), 0600) if err != nil { return nil, err } diff --git a/util/dex/dex.go b/util/dex/dex.go index 3f109b225cfc6..b0b817153d911 100644 --- a/util/dex/dex.go +++ b/util/dex/dex.go @@ -3,7 +3,7 @@ package dex import ( "bytes" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httputil" "net/url" @@ -34,7 +34,7 @@ func NewDexHTTPReverseProxy(serverAddr string, baseHRef string) func(writer http proxy := httputil.NewSingleHostReverseProxy(target) proxy.ModifyResponse = func(resp *http.Response) error { if resp.StatusCode == 500 { - b, err := ioutil.ReadAll(resp.Body) + b, err := io.ReadAll(resp.Body) if err != nil { return err } @@ -47,7 +47,7 @@ func NewDexHTTPReverseProxy(serverAddr string, baseHRef string) func(writer http resp.Header.Set("Content-Length", strconv.Itoa(0)) resp.Header.Set("Location", fmt.Sprintf("%s?has_sso_error=true", path.Join(baseHRef, "login"))) resp.StatusCode = http.StatusSeeOther - resp.Body = ioutil.NopCloser(bytes.NewReader(make([]byte, 0))) + resp.Body = io.NopCloser(bytes.NewReader(make([]byte, 0))) return nil } return nil diff --git a/util/git/creds.go b/util/git/creds.go index 1d94325c7d693..b3109b97de2ea 100644 --- a/util/git/creds.go +++ b/util/git/creds.go @@ -5,7 +5,6 @@ import ( "crypto/sha256" "fmt" "io" - "io/ioutil" "os" "strconv" "strings" @@ -153,10 +152,10 @@ func (c HTTPSCreds) Environ() (io.Closer, []string, error) { // We need to actually create two temp files, one for storing cert data and // another for storing the key. If we fail to create second fail, the first // must be removed. - certFile, err := ioutil.TempFile(argoio.TempDir, "") + certFile, err := os.CreateTemp(argoio.TempDir, "") if err == nil { defer certFile.Close() - keyFile, err = ioutil.TempFile(argoio.TempDir, "") + keyFile, err = os.CreateTemp(argoio.TempDir, "") if err != nil { removeErr := os.Remove(certFile.Name()) if removeErr != nil { @@ -244,7 +243,7 @@ func (f authFilePaths) Close() error { func (c SSHCreds) Environ() (io.Closer, []string, error) { // use the SHM temp dir from util, more secure - file, err := ioutil.TempFile(argoio.TempDir, "") + file, err := os.CreateTemp(argoio.TempDir, "") if err != nil { return nil, nil, err } @@ -315,10 +314,10 @@ func (g GitHubAppCreds) Environ() (io.Closer, []string, error) { // We need to actually create two temp files, one for storing cert data and // another for storing the key. If we fail to create second fail, the first // must be removed. - certFile, err := ioutil.TempFile(argoio.TempDir, "") + certFile, err := os.CreateTemp(argoio.TempDir, "") if err == nil { defer certFile.Close() - keyFile, err = ioutil.TempFile(argoio.TempDir, "") + keyFile, err = os.CreateTemp(argoio.TempDir, "") if err != nil { removeErr := os.Remove(certFile.Name()) if removeErr != nil { diff --git a/util/git/creds_test.go b/util/git/creds_test.go index 59e2b25d3adbc..7a57ae333db51 100644 --- a/util/git/creds_test.go +++ b/util/git/creds_test.go @@ -2,7 +2,6 @@ package git import ( "fmt" - "io/ioutil" "os" "path" "regexp" @@ -47,7 +46,7 @@ func TestHTTPSCreds_Environ_no_cert_cleanup(t *testing.T) { var nonce string for _, envVar := range env { if strings.HasPrefix(envVar, ASKPASS_NONCE_ENV) { - nonce = envVar[len(ASKPASS_NONCE_ENV) + 1:] + nonce = envVar[len(ASKPASS_NONCE_ENV)+1:] break } } @@ -109,10 +108,10 @@ func TestHTTPSCreds_Environ_clientCert(t *testing.T) { assert.NotEmpty(t, cert) assert.NotEmpty(t, key) - certBytes, err := ioutil.ReadFile(cert) + certBytes, err := os.ReadFile(cert) assert.NoError(t, err) assert.Equal(t, "clientCertData", string(certBytes)) - keyBytes, err := ioutil.ReadFile(key) + keyBytes, err := os.ReadFile(key) assert.Equal(t, "clientCertKey", string(keyBytes)) assert.NoError(t, err) diff --git a/util/git/git_test.go b/util/git/git_test.go index ef51ac9e4fce1..fd7396fee04f0 100644 --- a/util/git/git_test.go +++ b/util/git/git_test.go @@ -2,7 +2,7 @@ package git import ( "fmt" - "io/ioutil" + "io" "net/http" "os" "path/filepath" @@ -138,11 +138,11 @@ func TestCustomHTTPClient(t *testing.T) { assert.NoError(t, err) assert.NotEqual(t, "", keyFile) - certData, err := ioutil.ReadFile(certFile) + certData, err := os.ReadFile(certFile) assert.NoError(t, err) assert.NotEqual(t, "", string(certData)) - keyData, err := ioutil.ReadFile(keyFile) + keyData, err := os.ReadFile(keyFile) assert.NoError(t, err) assert.NotEqual(t, "", string(keyData)) @@ -205,11 +205,11 @@ func TestCustomHTTPClient(t *testing.T) { assert.Equal(t, "http://proxy-from-env:7878", proxy.String()) } // GetRepoHTTPClient with root ca - cert, err := ioutil.ReadFile("../../test/fixture/certs/argocd-test-server.crt") + cert, err := os.ReadFile("../../test/fixture/certs/argocd-test-server.crt") assert.NoError(t, err) temppath := t.TempDir() defer os.RemoveAll(temppath) - err = ioutil.WriteFile(filepath.Join(temppath, "127.0.0.1"), cert, 0666) + err = os.WriteFile(filepath.Join(temppath, "127.0.0.1"), cert, 0666) assert.NoError(t, err) os.Setenv(common.EnvVarTLSDataPath, temppath) client = GetRepoHTTPClient("https://127.0.0.1", false, creds, "") @@ -290,7 +290,7 @@ func TestLFSClient(t *testing.T) { assert.NoError(t, err) if err == nil { defer fileHandle.Close() - text, err := ioutil.ReadAll(fileHandle) + text, err := io.ReadAll(fileHandle) assert.NoError(t, err) if err == nil { assert.Equal(t, "This is not a YAML, sorry.\n", string(text)) diff --git a/util/gpg/gpg.go b/util/gpg/gpg.go index 2b1cb6b22cff2..28902a4081720 100644 --- a/util/gpg/gpg.go +++ b/util/gpg/gpg.go @@ -4,7 +4,6 @@ import ( "bufio" "encoding/hex" "fmt" - "io/ioutil" "os" "os/exec" "path" @@ -154,12 +153,12 @@ func getGPGEnviron() []string { // Helper function to write some data to a temp file and return its path func writeKeyToFile(keyData string) (string, error) { - f, err := ioutil.TempFile("", "gpg-public-key") + f, err := os.CreateTemp("", "gpg-public-key") if err != nil { return "", err } - err = ioutil.WriteFile(f.Name(), []byte(keyData), 0600) + err = os.WriteFile(f.Name(), []byte(keyData), 0600) if err != nil { os.Remove(f.Name()) return "", err @@ -244,12 +243,12 @@ func InitializeGnuPG() error { } } - err = ioutil.WriteFile(filepath.Join(gnuPgHome, canaryMarkerFilename), []byte("canary"), 0644) + err = os.WriteFile(filepath.Join(gnuPgHome, canaryMarkerFilename), []byte("canary"), 0644) if err != nil { return fmt.Errorf("could not create canary: %v", err) } - f, err := ioutil.TempFile("", "gpg-key-recipe") + f, err := os.CreateTemp("", "gpg-key-recipe") if err != nil { return err } @@ -271,7 +270,7 @@ func InitializeGnuPG() error { } func ImportPGPKeysFromString(keyData string) ([]*appsv1.GnuPGPublicKey, error) { - f, err := ioutil.TempFile("", "gpg-key-import") + f, err := os.CreateTemp("", "gpg-key-import") if err != nil { return nil, err } @@ -339,7 +338,7 @@ func ValidatePGPKeysFromString(keyData string) (map[string]*appsv1.GnuPGPublicKe // is, they contain all relevant information func ValidatePGPKeys(keyFile string) (map[string]*appsv1.GnuPGPublicKey, error) { keys := make(map[string]*appsv1.GnuPGPublicKey) - tempHome, err := ioutil.TempDir("", "gpg-verify-key") + tempHome, err := os.MkdirTemp("", "gpg-verify-key") if err != nil { return nil, err } @@ -386,7 +385,7 @@ func SetPGPTrustLevel(pgpKeys []*appsv1.GnuPGPublicKey, trustLevel string) error } // We need to store ownertrust specification in a temp file. Format is : - f, err := ioutil.TempFile("", "gpg-key-fps") + f, err := os.CreateTemp("", "gpg-key-fps") if err != nil { return err } diff --git a/util/gpg/gpg_test.go b/util/gpg/gpg_test.go index 18b2e0b3b8b05..2a88c22c217ae 100644 --- a/util/gpg/gpg_test.go +++ b/util/gpg/gpg_test.go @@ -3,7 +3,6 @@ package gpg import ( "fmt" "io" - "io/ioutil" "os" "os/exec" "path" @@ -31,7 +30,7 @@ var syncTestSources = map[string]string{ func initTempDir(t *testing.T) string { // Intentionally avoid using t.TempDir. That function creates really long paths, which can exceed the socket file // path length on some OSes. The GPG tests rely on sockets. - p, err := ioutil.TempDir(os.TempDir(), "") + p, err := os.MkdirTemp(os.TempDir(), "") if err != nil { panic(err) } @@ -87,7 +86,7 @@ func Test_GPG_InitializeGnuPG(t *testing.T) { assert.Equal(t, keys[0].Trust, "ultimate") // GNUPGHOME is a file - we need to error out - f, err := ioutil.TempFile("", "gpg-test") + f, err := os.CreateTemp("", "gpg-test") assert.NoError(t, err) defer os.Remove(f.Name()) @@ -303,7 +302,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Good case { - c, err := ioutil.ReadFile("testdata/good_signature.txt") + c, err := os.ReadFile("testdata/good_signature.txt") if err != nil { panic(err.Error()) } @@ -317,7 +316,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Signature with unknown key - considered invalid { - c, err := ioutil.ReadFile("testdata/unknown_signature1.txt") + c, err := os.ReadFile("testdata/unknown_signature1.txt") if err != nil { panic(err.Error()) } @@ -331,7 +330,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Signature with unknown key and additional fields - considered invalid { - c, err := ioutil.ReadFile("testdata/unknown_signature2.txt") + c, err := os.ReadFile("testdata/unknown_signature2.txt") if err != nil { panic(err.Error()) } @@ -345,7 +344,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Bad signature with known key { - c, err := ioutil.ReadFile("testdata/bad_signature_bad.txt") + c, err := os.ReadFile("testdata/bad_signature_bad.txt") if err != nil { panic(err.Error()) } @@ -359,7 +358,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Bad case: Manipulated/invalid clear text signature { - c, err := ioutil.ReadFile("testdata/bad_signature_manipulated.txt") + c, err := os.ReadFile("testdata/bad_signature_manipulated.txt") if err != nil { panic(err.Error()) } @@ -370,7 +369,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Bad case: Incomplete signature data #1 { - c, err := ioutil.ReadFile("testdata/bad_signature_preeof1.txt") + c, err := os.ReadFile("testdata/bad_signature_preeof1.txt") if err != nil { panic(err.Error()) } @@ -381,7 +380,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Bad case: Incomplete signature data #2 { - c, err := ioutil.ReadFile("testdata/bad_signature_preeof2.txt") + c, err := os.ReadFile("testdata/bad_signature_preeof2.txt") if err != nil { panic(err.Error()) } @@ -392,7 +391,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Bad case: No signature data #1 { - c, err := ioutil.ReadFile("testdata/bad_signature_nodata.txt") + c, err := os.ReadFile("testdata/bad_signature_nodata.txt") if err != nil { panic(err.Error()) } @@ -403,7 +402,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Bad case: Malformed signature data #1 { - c, err := ioutil.ReadFile("testdata/bad_signature_malformed1.txt") + c, err := os.ReadFile("testdata/bad_signature_malformed1.txt") if err != nil { panic(err.Error()) } @@ -414,7 +413,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Bad case: Malformed signature data #2 { - c, err := ioutil.ReadFile("testdata/bad_signature_malformed2.txt") + c, err := os.ReadFile("testdata/bad_signature_malformed2.txt") if err != nil { panic(err.Error()) } @@ -425,7 +424,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Bad case: Malformed signature data #3 { - c, err := ioutil.ReadFile("testdata/bad_signature_malformed3.txt") + c, err := os.ReadFile("testdata/bad_signature_malformed3.txt") if err != nil { panic(err.Error()) } @@ -436,7 +435,7 @@ func Test_GPG_ParseGitCommitVerification(t *testing.T) { // Bad case: Invalid key ID in signature { - c, err := ioutil.ReadFile("testdata/bad_signature_badkeyid.txt") + c, err := os.ReadFile("testdata/bad_signature_badkeyid.txt") if err != nil { panic(err.Error()) } diff --git a/util/helm/client.go b/util/helm/client.go index 5bb8721d0df49..e0075e24329a9 100644 --- a/util/helm/client.go +++ b/util/helm/client.go @@ -7,7 +7,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "os" @@ -23,7 +23,7 @@ import ( "github.com/argoproj/argo-cd/v2/util/cache" executil "github.com/argoproj/argo-cd/v2/util/exec" - "github.com/argoproj/argo-cd/v2/util/io" + argoio "github.com/argoproj/argo-cd/v2/util/io" "github.com/argoproj/argo-cd/v2/util/io/files" "github.com/argoproj/argo-cd/v2/util/proxy" ) @@ -49,7 +49,7 @@ type indexCache interface { type Client interface { CleanChartCache(chart string, version string) error - ExtractChart(chart string, version string, passCredentials bool) (string, io.Closer, error) + ExtractChart(chart string, version string, passCredentials bool) (string, argoio.Closer, error) GetIndex(noCache bool) (*Index, error) TestHelmOCI() (bool, error) } @@ -62,7 +62,7 @@ func WithIndexCache(indexCache indexCache) ClientOpts { } } -func WithChartPaths(chartPaths *io.TempPaths) ClientOpts { +func WithChartPaths(chartPaths *argoio.TempPaths) ClientOpts { return func(c *nativeHelmChart) { c.chartCachePaths = chartPaths } @@ -79,7 +79,7 @@ func NewClientWithLock(repoURL string, creds Creds, repoLock sync.KeyLock, enabl repoLock: repoLock, enableOci: enableOci, proxy: proxy, - chartCachePaths: io.NewTempPaths(os.TempDir()), + chartCachePaths: argoio.NewTempPaths(os.TempDir()), } for i := range opts { opts[i](c) @@ -90,7 +90,7 @@ func NewClientWithLock(repoURL string, creds Creds, repoLock sync.KeyLock, enabl var _ Client = &nativeHelmChart{} type nativeHelmChart struct { - chartCachePaths *io.TempPaths + chartCachePaths *argoio.TempPaths repoURL string creds Creds repoLock sync.KeyLock @@ -118,7 +118,7 @@ func (c *nativeHelmChart) CleanChartCache(chart string, version string) error { return os.RemoveAll(cachePath) } -func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredentials bool) (string, io.Closer, error) { +func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredentials bool) (string, argoio.Closer, error) { // always use Helm V3 since we don't have chart content to determine correct Helm version helmCmd, err := NewCmdWithVersion("", HelmV3, c.enableOci, c.proxy) @@ -185,7 +185,7 @@ func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredent } // 'helm pull/fetch' file downloads chart into the tgz file and we move that to where we want it - infos, err := ioutil.ReadDir(tempDest) + infos, err := os.ReadDir(tempDest) if err != nil { return "", nil, err } @@ -205,7 +205,7 @@ func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredent _ = os.RemoveAll(tempDir) return "", nil, err } - return path.Join(tempDir, normalizeChartName(chart)), io.NewCloser(func() error { + return path.Join(tempDir, normalizeChartName(chart)), argoio.NewCloser(func() error { return os.RemoveAll(tempDir) }), nil } @@ -249,7 +249,7 @@ func (c *nativeHelmChart) GetIndex(noCache bool) (*Index, error) { func (c *nativeHelmChart) TestHelmOCI() (bool, error) { start := time.Now() - tmpDir, err := ioutil.TempDir("", "helm") + tmpDir, err := os.MkdirTemp("", "helm") if err != nil { return false, err } @@ -311,14 +311,14 @@ func (c *nativeHelmChart) loadRepoIndex() ([]byte, error) { if resp.StatusCode != 200 { return nil, errors.New("failed to get index: " + resp.Status) } - return ioutil.ReadAll(resp.Body) + return io.ReadAll(resp.Body) } func newTLSConfig(creds Creds) (*tls.Config, error) { tlsConfig := &tls.Config{InsecureSkipVerify: creds.InsecureSkipVerify} if creds.CAPath != "" { - caData, err := ioutil.ReadFile(creds.CAPath) + caData, err := os.ReadFile(creds.CAPath) if err != nil { return nil, err } diff --git a/util/helm/cmd.go b/util/helm/cmd.go index 4e91d41572040..af1b2dc505229 100644 --- a/util/helm/cmd.go +++ b/util/helm/cmd.go @@ -2,7 +2,6 @@ package helm import ( "fmt" - "io/ioutil" "os" "os/exec" "path" @@ -10,7 +9,7 @@ import ( "regexp" executil "github.com/argoproj/argo-cd/v2/util/exec" - "github.com/argoproj/argo-cd/v2/util/io" + argoio "github.com/argoproj/argo-cd/v2/util/io" pathutil "github.com/argoproj/argo-cd/v2/util/io/path" "github.com/argoproj/argo-cd/v2/util/proxy" ) @@ -36,7 +35,7 @@ func NewCmd(workDir string, version string, proxy string) (*Cmd, error) { } func NewCmdWithVersion(workDir string, version HelmVer, isHelmOci bool, proxy string) (*Cmd, error) { - tmpDir, err := ioutil.TempDir("", "helm") + tmpDir, err := os.MkdirTemp("", "helm") if err != nil { return nil, err } @@ -95,7 +94,7 @@ func (c *Cmd) RegistryLogin(repo string, creds Creds) (string, error) { if err != nil { return "", err } - defer io.Close(closer) + defer argoio.Close(closer) args = append(args, "--cert-file", filePath) } if len(creds.KeyData) > 0 { @@ -103,7 +102,7 @@ func (c *Cmd) RegistryLogin(repo string, creds Creds) (string, error) { if err != nil { return "", err } - defer io.Close(closer) + defer argoio.Close(closer) args = append(args, "--key-file", filePath) } @@ -125,7 +124,7 @@ func (c *Cmd) RegistryLogout(repo string, creds Creds) (string, error) { if err != nil { return "", err } - defer io.Close(closer) + defer argoio.Close(closer) args = append(args, "--cert-file", filePath) } if len(creds.KeyData) > 0 { @@ -133,7 +132,7 @@ func (c *Cmd) RegistryLogout(repo string, creds Creds) (string, error) { if err != nil { return "", err } - defer io.Close(closer) + defer argoio.Close(closer) args = append(args, "--key-file", filePath) } @@ -141,7 +140,7 @@ func (c *Cmd) RegistryLogout(repo string, creds Creds) (string, error) { } func (c *Cmd) RepoAdd(name string, url string, opts Creds, passCredentials bool) (string, error) { - tmp, err := ioutil.TempDir("", "helm") + tmp, err := os.MkdirTemp("", "helm") if err != nil { return "", err } @@ -166,7 +165,7 @@ func (c *Cmd) RepoAdd(name string, url string, opts Creds, passCredentials bool) } if len(opts.CertData) > 0 { - certFile, err := ioutil.TempFile("", "helm") + certFile, err := os.CreateTemp("", "helm") if err != nil { return "", err } @@ -179,7 +178,7 @@ func (c *Cmd) RepoAdd(name string, url string, opts Creds, passCredentials bool) } if len(opts.KeyData) > 0 { - keyFile, err := ioutil.TempFile("", "helm") + keyFile, err := os.CreateTemp("", "helm") if err != nil { return "", err } @@ -200,18 +199,18 @@ func (c *Cmd) RepoAdd(name string, url string, opts Creds, passCredentials bool) return c.run(args...) } -func writeToTmp(data []byte) (string, io.Closer, error) { - file, err := ioutil.TempFile("", "") +func writeToTmp(data []byte) (string, argoio.Closer, error) { + file, err := os.CreateTemp("", "") if err != nil { return "", nil, err } - err = ioutil.WriteFile(file.Name(), data, 0644) + err = os.WriteFile(file.Name(), data, 0644) if err != nil { _ = os.RemoveAll(file.Name()) return "", nil, err } defer file.Close() - return file.Name(), io.NewCloser(func() error { + return file.Name(), argoio.NewCloser(func() error { return os.RemoveAll(file.Name()) }), nil } @@ -241,7 +240,7 @@ func (c *Cmd) Fetch(repo, chartName, version, destination string, creds Creds, p if err != nil { return "", err } - defer io.Close(closer) + defer argoio.Close(closer) args = append(args, "--cert-file", filePath) } if len(creds.KeyData) > 0 { @@ -249,7 +248,7 @@ func (c *Cmd) Fetch(repo, chartName, version, destination string, creds Creds, p if err != nil { return "", err } - defer io.Close(closer) + defer argoio.Close(closer) args = append(args, "--key-file", filePath) } if passCredentials && c.helmPassCredentialsSupported { diff --git a/util/helm/helm.go b/util/helm/helm.go index 0d9e8f9c52165..baa898b2cd7cb 100644 --- a/util/helm/helm.go +++ b/util/helm/helm.go @@ -2,7 +2,6 @@ package helm import ( "fmt" - "io/ioutil" "net/url" "os" "os/exec" @@ -153,7 +152,7 @@ func (h *helm) GetParameters(valuesFiles []pathutil.ResolvedFilePath, appPath, r if _, err := os.Stat(file); os.IsNotExist(err) { continue } - fileValues, err = ioutil.ReadFile(file) + fileValues, err = os.ReadFile(file) } if err != nil { return nil, fmt.Errorf("failed to read value file %s: %s", file, err) diff --git a/util/io/files/tar_test.go b/util/io/files/tar_test.go index 10487eda0a097..498853a17b9be 100644 --- a/util/io/files/tar_test.go +++ b/util/io/files/tar_test.go @@ -5,7 +5,6 @@ import ( "compress/gzip" "fmt" "io" - "io/ioutil" "os" "path/filepath" "testing" @@ -24,7 +23,7 @@ func TestTgz(t *testing.T) { setup := func(t *testing.T) *fixture { t.Helper() testDir := getTestDataDir(t) - f, err := ioutil.TempFile(testDir, "") + f, err := os.CreateTemp(testDir, "") require.NoError(t, err) return &fixture{ file: f, @@ -103,7 +102,7 @@ func TestTgz(t *testing.T) { func TestUntgz(t *testing.T) { createTmpDir := func(t *testing.T) string { t.Helper() - tmpDir, err := ioutil.TempDir(getTestDataDir(t), "") + tmpDir, err := os.MkdirTemp(getTestDataDir(t), "") if err != nil { t.Fatalf("error creating tmpDir: %s", err) } @@ -118,7 +117,7 @@ func TestUntgz(t *testing.T) { } createTgz := func(t *testing.T, fromDir, destDir string) *os.File { t.Helper() - f, err := ioutil.TempFile(destDir, "") + f, err := os.CreateTemp(destDir, "") if err != nil { t.Fatalf("error creating tmpFile in %q: %s", destDir, err) } diff --git a/util/kube/kube_test.go b/util/kube/kube_test.go index 50ec2b9e8c7a5..fb7ebe08d4486 100644 --- a/util/kube/kube_test.go +++ b/util/kube/kube_test.go @@ -2,8 +2,8 @@ package kube import ( "encoding/json" - "io/ioutil" "log" + "os" "testing" "github.com/ghodss/yaml" @@ -108,7 +108,7 @@ func TestSetLegacyLabels(t *testing.T) { } func TestSetLegacyJobLabel(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/job.yaml") + yamlBytes, err := os.ReadFile("testdata/job.yaml") assert.Nil(t, err) var obj unstructured.Unstructured err = yaml.Unmarshal(yamlBytes, &obj) @@ -134,7 +134,7 @@ func TestSetLegacyJobLabel(t *testing.T) { } func TestSetSvcLabel(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") assert.Nil(t, err) var obj unstructured.Unstructured err = yaml.Unmarshal(yamlBytes, &obj) @@ -163,7 +163,7 @@ func TestIsValidResourceName(t *testing.T) { } func TestSetAppInstanceAnnotation(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") assert.Nil(t, err) var obj unstructured.Unstructured err = yaml.Unmarshal(yamlBytes, &obj) @@ -185,7 +185,7 @@ func TestSetAppInstanceAnnotation(t *testing.T) { } func TestGetAppInstanceAnnotation(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") assert.Nil(t, err) var obj unstructured.Unstructured err = yaml.Unmarshal(yamlBytes, &obj) @@ -197,7 +197,7 @@ func TestGetAppInstanceAnnotation(t *testing.T) { } func TestGetAppInstanceLabel(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") assert.Nil(t, err) var obj unstructured.Unstructured err = yaml.Unmarshal(yamlBytes, &obj) @@ -208,7 +208,7 @@ func TestGetAppInstanceLabel(t *testing.T) { } func TestRemoveLabel(t *testing.T) { - yamlBytes, err := ioutil.ReadFile("testdata/svc.yaml") + yamlBytes, err := os.ReadFile("testdata/svc.yaml") assert.Nil(t, err) var obj unstructured.Unstructured err = yaml.Unmarshal(yamlBytes, &obj) diff --git a/util/lua/custom_actions_test.go b/util/lua/custom_actions_test.go index 3108ec5909e82..e5a10700e181b 100644 --- a/util/lua/custom_actions_test.go +++ b/util/lua/custom_actions_test.go @@ -2,7 +2,6 @@ package lua import ( "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -48,7 +47,7 @@ func TestLuaResourceActionsScript(t *testing.T) { assert.NoError(t, err) dir := filepath.Dir(path) //TODO: Change to path - yamlBytes, err := ioutil.ReadFile(dir + "/action_test.yaml") + yamlBytes, err := os.ReadFile(dir + "/action_test.yaml") assert.NoError(t, err) var resourceTest ActionTestStructure err = yaml.Unmarshal(yamlBytes, &resourceTest) diff --git a/util/lua/health_test.go b/util/lua/health_test.go index 732f053e39f14..1052f5c8fa95a 100644 --- a/util/lua/health_test.go +++ b/util/lua/health_test.go @@ -1,7 +1,6 @@ package lua import ( - "io/ioutil" "os" "path/filepath" "strings" @@ -25,7 +24,7 @@ type IndividualTest struct { } func getObj(path string) *unstructured.Unstructured { - yamlBytes, err := ioutil.ReadFile(path) + yamlBytes, err := os.ReadFile(path) errors.CheckError(err) obj := make(map[string]interface{}) err = yaml.Unmarshal(yamlBytes, &obj) @@ -40,7 +39,7 @@ func TestLuaHealthScript(t *testing.T) { } errors.CheckError(err) dir := filepath.Dir(path) - yamlBytes, err := ioutil.ReadFile(dir + "/health_test.yaml") + yamlBytes, err := os.ReadFile(dir + "/health_test.yaml") errors.CheckError(err) var resourceTest TestStructure err = yaml.Unmarshal(yamlBytes, &resourceTest) diff --git a/util/oidc/oidc_test.go b/util/oidc/oidc_test.go index 5c94a661c4161..ba2ed54cbbae4 100644 --- a/util/oidc/oidc_test.go +++ b/util/oidc/oidc_test.go @@ -3,10 +3,10 @@ package oidc import ( "encoding/hex" "encoding/json" - "io/ioutil" "net/http" "net/http/httptest" "net/url" + "os" "testing" gooidc "github.com/coreos/go-oidc" @@ -24,7 +24,7 @@ import ( func TestInferGrantType(t *testing.T) { for _, path := range []string{"dex", "okta", "auth0", "onelogin"} { t.Run(path, func(t *testing.T) { - rawConfig, err := ioutil.ReadFile("testdata/" + path + ".json") + rawConfig, err := os.ReadFile("testdata/" + path + ".json") assert.NoError(t, err) var config OIDCConfiguration err = json.Unmarshal(rawConfig, &config) diff --git a/util/tls/tls.go b/util/tls/tls.go index 9e73d1dd77895..f803099bfa08a 100644 --- a/util/tls/tls.go +++ b/util/tls/tls.go @@ -12,7 +12,6 @@ import ( "encoding/pem" "errors" "fmt" - "io/ioutil" "math/big" "net" "os" @@ -349,7 +348,7 @@ func LoadX509CertPool(paths ...string) (*x509.CertPool, error) { // ...but everything else is considered an error return nil, fmt.Errorf("could not load TLS certificate: %v", err) } else { - f, err := ioutil.ReadFile(path) + f, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("failure to load TLS certificates from %s: %v", path, err) } diff --git a/util/webhook/webhook_test.go b/util/webhook/webhook_test.go index f5161d7e9f561..5ee3122b33e62 100644 --- a/util/webhook/webhook_test.go +++ b/util/webhook/webhook_test.go @@ -4,9 +4,10 @@ import ( "bytes" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" + "os" "testing" "time" @@ -59,9 +60,9 @@ func TestGitHubCommitEvent(t *testing.T) { h := NewMockHandler() req := httptest.NewRequest("POST", "/api/webhook", nil) req.Header.Set("X-GitHub-Event", "push") - eventJSON, err := ioutil.ReadFile("github-commit-event.json") + eventJSON, err := os.ReadFile("github-commit-event.json") assert.NoError(t, err) - req.Body = ioutil.NopCloser(bytes.NewReader(eventJSON)) + req.Body = io.NopCloser(bytes.NewReader(eventJSON)) w := httptest.NewRecorder() h.Handler(w, req) assert.Equal(t, w.Code, http.StatusOK) @@ -75,9 +76,9 @@ func TestGitHubTagEvent(t *testing.T) { h := NewMockHandler() req := httptest.NewRequest("POST", "/api/webhook", nil) req.Header.Set("X-GitHub-Event", "push") - eventJSON, err := ioutil.ReadFile("github-tag-event.json") + eventJSON, err := os.ReadFile("github-tag-event.json") assert.NoError(t, err) - req.Body = ioutil.NopCloser(bytes.NewReader(eventJSON)) + req.Body = io.NopCloser(bytes.NewReader(eventJSON)) w := httptest.NewRecorder() h.Handler(w, req) assert.Equal(t, w.Code, http.StatusOK) @@ -91,9 +92,9 @@ func TestBitbucketServerRepositoryReferenceChangedEvent(t *testing.T) { h := NewMockHandler() req := httptest.NewRequest("POST", "/api/webhook", nil) req.Header.Set("X-Event-Key", "repo:refs_changed") - eventJSON, err := ioutil.ReadFile("bitbucket-server-event.json") + eventJSON, err := os.ReadFile("bitbucket-server-event.json") assert.NoError(t, err) - req.Body = ioutil.NopCloser(bytes.NewReader(eventJSON)) + req.Body = io.NopCloser(bytes.NewReader(eventJSON)) w := httptest.NewRecorder() h.Handler(w, req) assert.Equal(t, w.Code, http.StatusOK) @@ -123,9 +124,9 @@ func TestGogsPushEvent(t *testing.T) { h := NewMockHandler() req := httptest.NewRequest("POST", "/api/webhook", nil) req.Header.Set("X-Gogs-Event", "push") - eventJSON, err := ioutil.ReadFile("gogs-event.json") + eventJSON, err := os.ReadFile("gogs-event.json") assert.NoError(t, err) - req.Body = ioutil.NopCloser(bytes.NewReader(eventJSON)) + req.Body = io.NopCloser(bytes.NewReader(eventJSON)) w := httptest.NewRecorder() h.Handler(w, req) assert.Equal(t, w.Code, http.StatusOK) @@ -139,9 +140,9 @@ func TestGitLabPushEvent(t *testing.T) { h := NewMockHandler() req := httptest.NewRequest("POST", "/api/webhook", nil) req.Header.Set("X-Gitlab-Event", "Push Hook") - eventJSON, err := ioutil.ReadFile("gitlab-event.json") + eventJSON, err := os.ReadFile("gitlab-event.json") assert.NoError(t, err) - req.Body = ioutil.NopCloser(bytes.NewReader(eventJSON)) + req.Body = io.NopCloser(bytes.NewReader(eventJSON)) w := httptest.NewRecorder() h.Handler(w, req) assert.Equal(t, w.Code, http.StatusOK) From 2a3c69279f478612bea2fcf64800d036d7747c75 Mon Sep 17 00:00:00 2001 From: jannfis Date: Wed, 6 Jul 2022 18:53:38 +0200 Subject: [PATCH 33/33] fix: Make change of tracking method work at runtime (#9820) * fix: Make change of tracking method work at runtime Signed-off-by: jannfis * GetAppName() will figure tracking label or annotation on its own Signed-off-by: jannfis * Correct test comments and add another test Signed-off-by: jannfis * Add a read lock before getting cache settings Signed-off-by: jannfis --- controller/cache/cache.go | 9 +- test/e2e/app_management_test.go | 187 ++++++++++++++++++++++++++++++++ test/e2e/fixture/app/actions.go | 10 ++ test/e2e/fixture/app/context.go | 5 + test/e2e/fixture/fixture.go | 7 ++ util/argo/resource_tracking.go | 2 +- util/settings/settings.go | 3 + 7 files changed, 219 insertions(+), 4 deletions(-) diff --git a/controller/cache/cache.go b/controller/cache/cache.go index 4cae8a3614ace..c288aceb2310d 100644 --- a/controller/cache/cache.go +++ b/controller/cache/cache.go @@ -176,6 +176,7 @@ func NewLiveStateCache( type cacheSettings struct { clusterSettings clustercache.Settings appInstanceLabelKey string + trackingMethod appv1.TrackingMethod } type liveStateCache struct { @@ -210,7 +211,7 @@ func (c *liveStateCache) loadCacheSettings() (*cacheSettings, error) { ResourceHealthOverride: lua.ResourceHealthOverrides(resourceOverrides), ResourcesFilter: resourcesFilter, } - return &cacheSettings{clusterSettings, appInstanceLabelKey}, nil + return &cacheSettings{clusterSettings, appInstanceLabelKey, argo.GetTrackingMethod(c.settingsMgr)}, nil } func asResourceNode(r *clustercache.Resource) appv1.ResourceNode { @@ -388,7 +389,6 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e return nil, fmt.Errorf("controller is configured to ignore cluster %s", cluster.Server) } - trackingMethod := argo.GetTrackingMethod(c.settingsMgr) clusterCacheOpts := []clustercache.UpdateSettingsFunc{ clustercache.SetListSemaphore(semaphore.NewWeighted(clusterCacheListSemaphoreSize)), clustercache.SetListPageSize(clusterCacheListPageSize), @@ -401,9 +401,12 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e clustercache.SetPopulateResourceInfoHandler(func(un *unstructured.Unstructured, isRoot bool) (interface{}, bool) { res := &ResourceInfo{} populateNodeInfo(un, res) + c.lock.RLock() + cacheSettings := c.cacheSettings + c.lock.RUnlock() res.Health, _ = health.GetResourceHealth(un, cacheSettings.clusterSettings.ResourceHealthOverride) - appName := c.resourceTracking.GetAppName(un, cacheSettings.appInstanceLabelKey, trackingMethod) + appName := c.resourceTracking.GetAppName(un, cacheSettings.appInstanceLabelKey, cacheSettings.trackingMethod) if isRoot && appName != "" { res.AppName = appName } diff --git a/test/e2e/app_management_test.go b/test/e2e/app_management_test.go index 116e0c9b55f97..815f486573619 100644 --- a/test/e2e/app_management_test.go +++ b/test/e2e/app_management_test.go @@ -38,6 +38,7 @@ import ( projectFixture "github.com/argoproj/argo-cd/v2/test/e2e/fixture/project" repoFixture "github.com/argoproj/argo-cd/v2/test/e2e/fixture/repos" "github.com/argoproj/argo-cd/v2/test/e2e/testdata" + "github.com/argoproj/argo-cd/v2/util/argo" . "github.com/argoproj/argo-cd/v2/util/argo" . "github.com/argoproj/argo-cd/v2/util/errors" "github.com/argoproj/argo-cd/v2/util/io" @@ -2063,3 +2064,189 @@ func TestDisableManifestGeneration(t *testing.T) { assert.Equal(t, app.Status.SourceType, ApplicationSourceTypeDirectory) }) } + +func TestSwitchTrackingMethod(t *testing.T) { + ctx := Given(t) + + ctx. + SetTrackingMethod(string(argo.TrackingMethodAnnotation)). + Path("deployment"). + When(). + CreateApp(). + Sync(). + Refresh(RefreshTypeNormal). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Add resource with tracking annotation. This should put the + // application OutOfSync. + FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "other-configmap", + Annotations: map[string]string{ + common.AnnotationKeyAppInstance: fmt.Sprintf("%s:/ConfigMap:%s/other-configmap", Name(), DeploymentNamespace()), + }, + }, + }, metav1.CreateOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeOutOfSync)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Delete resource to bring application back in sync + FailOnErr(nil, KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Delete(context.Background(), "other-configmap", metav1.DeleteOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + SetTrackingMethod(string(argo.TrackingMethodLabel)). + Sync(). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Add a resource with a tracking annotation. This should not + // affect the application, because we now use the tracking method + // "label". + FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "other-configmap", + Annotations: map[string]string{ + common.AnnotationKeyAppInstance: fmt.Sprintf("%s:/ConfigMap:%s/other-configmap", Name(), DeploymentNamespace()), + }, + }, + }, metav1.CreateOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Add a resource with the tracking label. The app should become + // OutOfSync. + FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "extra-configmap", + Labels: map[string]string{ + common.LabelKeyAppInstance: Name(), + }, + }, + }, metav1.CreateOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeOutOfSync)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Delete resource to bring application back in sync + FailOnErr(nil, KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Delete(context.Background(), "extra-configmap", metav1.DeleteOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)) +} + +func TestSwitchTrackingLabel(t *testing.T) { + ctx := Given(t) + + ctx. + Path("deployment"). + When(). + CreateApp(). + Sync(). + Refresh(RefreshTypeNormal). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Add extra resource that carries the default tracking label + // We expect the app to go out of sync. + FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "other-configmap", + Labels: map[string]string{ + common.LabelKeyAppInstance: Name(), + }, + }, + }, metav1.CreateOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeOutOfSync)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Delete resource to bring application back in sync + FailOnErr(nil, KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Delete(context.Background(), "other-configmap", metav1.DeleteOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + // Change tracking label + SetTrackingLabel("argocd.tracking"). + Sync(). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Create resource with the new tracking label, the application + // is expected to go out of sync + FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "other-configmap", + Labels: map[string]string{ + "argocd.tracking": Name(), + }, + }, + }, metav1.CreateOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeOutOfSync)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Delete resource to bring application back in sync + FailOnErr(nil, KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Delete(context.Background(), "other-configmap", metav1.DeleteOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)). + When(). + And(func() { + // Add extra resource that carries the default tracking label + // We expect the app to stay in sync, because the configured + // label is different. + FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "other-configmap", + Labels: map[string]string{ + common.LabelKeyAppInstance: Name(), + }, + }, + }, metav1.CreateOptions{})) + }). + Then(). + Expect(OperationPhaseIs(OperationSucceeded)). + Expect(SyncStatusIs(SyncStatusCodeSynced)). + Expect(HealthIs(health.HealthStatusHealthy)) +} diff --git a/test/e2e/fixture/app/actions.go b/test/e2e/fixture/app/actions.go index a58a8e25dc0ce..dbb7031606ec8 100644 --- a/test/e2e/fixture/app/actions.go +++ b/test/e2e/fixture/app/actions.go @@ -341,3 +341,13 @@ func (a *Actions) verifyAction() { a.Then().Expect(Success("")) } } + +func (a *Actions) SetTrackingMethod(trackingMethod string) *Actions { + fixture.SetTrackingMethod(trackingMethod) + return a +} + +func (a *Actions) SetTrackingLabel(trackingLabel string) *Actions { + fixture.SetTrackingLabel(trackingLabel) + return a +} diff --git a/test/e2e/fixture/app/context.go b/test/e2e/fixture/app/context.go index fafff85a4c916..a527405ea6aee 100644 --- a/test/e2e/fixture/app/context.go +++ b/test/e2e/fixture/app/context.go @@ -308,3 +308,8 @@ func (c *Context) HelmSkipCrds() *Context { c.helmSkipCrds = true return c } + +func (c *Context) SetTrackingMethod(trackingMethod string) *Context { + fixture.SetTrackingMethod(trackingMethod) + return c +} diff --git a/test/e2e/fixture/fixture.go b/test/e2e/fixture/fixture.go index f910d6b91c701..6acb1c26825f6 100644 --- a/test/e2e/fixture/fixture.go +++ b/test/e2e/fixture/fixture.go @@ -357,6 +357,13 @@ func SetTrackingMethod(trackingMethod string) { }) } +func SetTrackingLabel(trackingLabel string) { + updateSettingConfigMap(func(cm *corev1.ConfigMap) error { + cm.Data["application.instanceLabelKey"] = trackingLabel + return nil + }) +} + func SetResourceOverridesSplitKeys(overrides map[string]v1alpha1.ResourceOverride) { updateSettingConfigMap(func(cm *corev1.ConfigMap) error { for k, v := range overrides { diff --git a/util/argo/resource_tracking.go b/util/argo/resource_tracking.go index 9c8f4a75d8f80..fce9a45102e27 100644 --- a/util/argo/resource_tracking.go +++ b/util/argo/resource_tracking.go @@ -54,7 +54,7 @@ func NewResourceTracking() ResourceTracking { // GetTrackingMethod retrieve tracking method from settings func GetTrackingMethod(settingsMgr *settings.SettingsManager) v1alpha1.TrackingMethod { tm, err := settingsMgr.GetTrackingMethod() - if err != nil { + if err != nil || tm == "" { return TrackingMethodLabel } return v1alpha1.TrackingMethod(tm) diff --git a/util/settings/settings.go b/util/settings/settings.go index 63b2aaa1169e6..3f82c402f317a 100644 --- a/util/settings/settings.go +++ b/util/settings/settings.go @@ -99,6 +99,8 @@ type ArgoCDSettings struct { ServerRBACLogEnforceEnable bool `json:"serverRBACLogEnforceEnable"` // ExecEnabled indicates whether the UI exec feature is enabled ExecEnabled bool `json:"execEnabled"` + // TrackingMethod defines the resource tracking method to be used + TrackingMethod string `json:"application.resourceTrackingMethod,omitempty"` } type GoogleAnalytics struct { @@ -1271,6 +1273,7 @@ func updateSettingsFromConfigMap(settings *ArgoCDSettings, argoCDCM *apiv1.Confi } settings.InClusterEnabled = argoCDCM.Data[inClusterEnabledKey] != "false" settings.ExecEnabled = argoCDCM.Data[execEnabledKey] == "true" + settings.TrackingMethod = argoCDCM.Data[settingsResourceTrackingMethodKey] } // validateExternalURL ensures the external URL that is set on the configmap is valid