From ebe5a67c6e7e261aa89ac803d53562e122f341d5 Mon Sep 17 00:00:00 2001 From: Cheng Fang Date: Mon, 16 Jun 2025 22:51:13 -0400 Subject: [PATCH 001/383] chore(cli): fix `argocd admin repo` command usage docs and examples (#23375) Signed-off-by: Cheng Fang Signed-off-by: Mangaal --- cmd/argocd/commands/admin/repo.go | 6 +++--- cmd/argocd/commands/repocreds.go | 2 +- cmd/util/repo.go | 2 +- .../commands/argocd_admin_repo_generate-spec.md | 8 ++++---- docs/user-guide/commands/argocd_repo_add.md | 2 +- docs/user-guide/commands/argocd_repocreds_add.md | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cmd/argocd/commands/admin/repo.go b/cmd/argocd/commands/admin/repo.go index 43fbe76251bac..e02ae6fcd2b56 100644 --- a/cmd/argocd/commands/admin/repo.go +++ b/cmd/argocd/commands/admin/repo.go @@ -70,13 +70,13 @@ func NewGenRepoSpecCommand() *cobra.Command { argocd admin repo generate-spec helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type helm --name stable --enable-oci --username test --password test # Add a private HTTPS OCI repository named 'stable' - argocd repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test + argocd admin repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test # Add a private OCI repository named 'stable' without verifying the server's TLS certificate - argocd repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-skip-server-verification + argocd admin repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-skip-server-verification # Add a private HTTP OCI repository named 'stable' - argocd repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-oci-force-http + argocd admin repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-oci-force-http ` command := &cobra.Command{ diff --git a/cmd/argocd/commands/repocreds.go b/cmd/argocd/commands/repocreds.go index 835009d2bd41c..778b5be008349 100644 --- a/cmd/argocd/commands/repocreds.go +++ b/cmd/argocd/commands/repocreds.go @@ -189,7 +189,7 @@ func NewRepoCredsAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comma command.Flags().StringVar(&repo.BearerToken, "bearer-token", "", "bearer token to the Git repository") command.Flags().StringVar(&sshPrivateKeyPath, "ssh-private-key-path", "", "path to the private ssh key (e.g. ~/.ssh/id_rsa)") command.Flags().StringVar(&tlsClientCertPath, "tls-client-cert-path", "", "path to the TLS client cert (must be PEM format)") - command.Flags().StringVar(&tlsClientCertKeyPath, "tls-client-cert-key-path", "", "path to the TLS client cert's key path (must be PEM format)") + command.Flags().StringVar(&tlsClientCertKeyPath, "tls-client-cert-key-path", "", "path to the TLS client cert's key (must be PEM format)") command.Flags().Int64Var(&repo.GithubAppId, "github-app-id", 0, "id of the GitHub Application") command.Flags().Int64Var(&repo.GithubAppInstallationId, "github-app-installation-id", 0, "installation id of the GitHub Application") command.Flags().StringVar(&githubAppPrivateKeyPath, "github-app-private-key-path", "", "private key of the GitHub Application") diff --git a/cmd/util/repo.go b/cmd/util/repo.go index 15fe8aefe448c..10637b8602395 100644 --- a/cmd/util/repo.go +++ b/cmd/util/repo.go @@ -38,7 +38,7 @@ func AddRepoFlags(command *cobra.Command, opts *RepoOptions) { command.Flags().StringVar(&opts.Repo.BearerToken, "bearer-token", "", "bearer token to the Git BitBucket Data Center repository") command.Flags().StringVar(&opts.SshPrivateKeyPath, "ssh-private-key-path", "", "path to the private ssh key (e.g. ~/.ssh/id_rsa)") command.Flags().StringVar(&opts.TlsClientCertPath, "tls-client-cert-path", "", "path to the TLS client cert (must be PEM format)") - command.Flags().StringVar(&opts.TlsClientCertKeyPath, "tls-client-cert-key-path", "", "path to the TLS client cert's key path (must be PEM format)") + command.Flags().StringVar(&opts.TlsClientCertKeyPath, "tls-client-cert-key-path", "", "path to the TLS client cert's key (must be PEM format)") command.Flags().BoolVar(&opts.InsecureIgnoreHostKey, "insecure-ignore-host-key", false, "disables SSH strict host key checking (deprecated, use --insecure-skip-server-verification instead)") command.Flags().BoolVar(&opts.InsecureSkipServerVerification, "insecure-skip-server-verification", false, "disables server certificate and host key checks") command.Flags().BoolVar(&opts.EnableLfs, "enable-lfs", false, "enable git-lfs (Large File Support) on this repository") diff --git a/docs/user-guide/commands/argocd_admin_repo_generate-spec.md b/docs/user-guide/commands/argocd_admin_repo_generate-spec.md index ffd5a7bac26c4..f9a26090b60c4 100644 --- a/docs/user-guide/commands/argocd_admin_repo_generate-spec.md +++ b/docs/user-guide/commands/argocd_admin_repo_generate-spec.md @@ -37,13 +37,13 @@ argocd admin repo generate-spec REPOURL [flags] argocd admin repo generate-spec helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type helm --name stable --enable-oci --username test --password test # Add a private HTTPS OCI repository named 'stable' - argocd repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test + argocd admin repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test # Add a private OCI repository named 'stable' without verifying the server's TLS certificate - argocd repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-skip-server-verification + argocd admin repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-skip-server-verification # Add a private HTTP OCI repository named 'stable' - argocd repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-oci-force-http + argocd admin repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-oci-force-http ``` @@ -70,7 +70,7 @@ argocd admin repo generate-spec REPOURL [flags] --project string project of the repository --proxy string use proxy to access repository --ssh-private-key-path string path to the private ssh key (e.g. ~/.ssh/id_rsa) - --tls-client-cert-key-path string path to the TLS client cert's key path (must be PEM format) + --tls-client-cert-key-path string path to the TLS client cert's key (must be PEM format) --tls-client-cert-path string path to the TLS client cert (must be PEM format) --type string type of the repository, "git", "oci" or "helm" (default "git") --use-azure-workload-identity whether to use azure workload identity for authentication diff --git a/docs/user-guide/commands/argocd_repo_add.md b/docs/user-guide/commands/argocd_repo_add.md index 16e2c532521e2..6def99e5ce9a3 100644 --- a/docs/user-guide/commands/argocd_repo_add.md +++ b/docs/user-guide/commands/argocd_repo_add.md @@ -80,7 +80,7 @@ argocd repo add REPOURL [flags] --project string project of the repository --proxy string use proxy to access repository --ssh-private-key-path string path to the private ssh key (e.g. ~/.ssh/id_rsa) - --tls-client-cert-key-path string path to the TLS client cert's key path (must be PEM format) + --tls-client-cert-key-path string path to the TLS client cert's key (must be PEM format) --tls-client-cert-path string path to the TLS client cert (must be PEM format) --type string type of the repository, "git", "oci" or "helm" (default "git") --upsert Override an existing repository with the same name even if the spec differs diff --git a/docs/user-guide/commands/argocd_repocreds_add.md b/docs/user-guide/commands/argocd_repocreds_add.md index 033f6de091182..5fcc0fa61487a 100644 --- a/docs/user-guide/commands/argocd_repocreds_add.md +++ b/docs/user-guide/commands/argocd_repocreds_add.md @@ -49,7 +49,7 @@ argocd repocreds add REPOURL [flags] --password string password to the repository --proxy-url string If provided, this URL will be used to connect via proxy --ssh-private-key-path string path to the private ssh key (e.g. ~/.ssh/id_rsa) - --tls-client-cert-key-path string path to the TLS client cert's key path (must be PEM format) + --tls-client-cert-key-path string path to the TLS client cert's key (must be PEM format) --tls-client-cert-path string path to the TLS client cert (must be PEM format) --type string type of the repository, "git" or "helm" (default "git") --upsert Override an existing repository with the same name even if the spec differs From 19f73c40140af33691dedf73abe2dbd6f6443763 Mon Sep 17 00:00:00 2001 From: Mangaal Date: Thu, 19 Jun 2025 11:17:43 +0530 Subject: [PATCH 002/383] option to read secret from volume Signed-off-by: Mangaal --- argocd-redis.yaml | 156 ++++++++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 +- util/cache/cache.go | 90 +++++++++++++++++++++---- 4 files changed, 235 insertions(+), 17 deletions(-) create mode 100644 argocd-redis.yaml diff --git a/argocd-redis.yaml b/argocd-redis.yaml new file mode 100644 index 0000000000000..8b80a8147521f --- /dev/null +++ b/argocd-redis.yaml @@ -0,0 +1,156 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: redis + app.kubernetes.io/name: argocd-redis + app.kubernetes.io/part-of: argocd + name: argocd-redis + namespace: argocd +spec: + progressDeadlineSeconds: 600 + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/name: argocd-redis + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + creationTimestamp: null + labels: + app.kubernetes.io/name: argocd-redis + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/name: argocd-redis + topologyKey: kubernetes.io/hostname + weight: 100 + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/part-of: argocd + topologyKey: kubernetes.io/hostname + weight: 5 + containers: + - name: redis + image: redis:7.0.15-alpine # Your specified image version + imagePullPolicy: Always + command: ["sh", "-c"] + args: + - | + mkdir -p /var/redis-config-temp/config + cat < /var/redis-config-temp/config/redis.conf + # General Redis Configuration + port 6379 + bind 0.0.0.0 + + # Security: Require password for client connections. + # The password is read from the 'auth' key of the 'argocd-redis' Secret, + # which is mounted as a file at /etc/redis-secret/auth. + requirepass $(cat /etc/redis-secret/auth) + + # Example RDB snapshot persistence: + # save 900 1 # Save if 1 key changes in 15 minutes + # save 300 10 # Save if 10 keys change in 5 minutes + # save 60 10000 # Save if 10000 keys change in 1 minute + + # Example AOF (Append Only File) persistence: + # appendonly yes # Enable AOF persistence + # appendfsync everysec # Sync AOF to disk every second (good balance of performance/safety) + + EOF + + # Start the Redis server using the dynamically generated configuration file. + redis-server /var/redis-config-temp/config/redis.conf + ports: + - containerPort: 6379 + protocol: TCP + resources: + requests: + cpu: 100m # Request 100 millicores of CPU + memory: 128Mi # Request 128 MiB of memory (should be less than maxmemory) + limits: + cpu: 200m # Limit to 200 millicores of CPU + memory: 512Mi # Limit to 512 MiB of memory (should be >= maxmemory + overhead) + # ---------------------------------------------------- + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true # Retains your existing security context + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + # Mount the Kubernetes Secret containing the Redis password. + # This provides read-only access to the password file. + - name: redis-password-volume + mountPath: /etc/redis-secret # The directory where the secret's data will appear as files + readOnly: true # Crucially, this mount is read-only for security. + # Mount a temporary, writable volume. This is where the redis.conf will be + # dynamically generated and where Redis might store temporary files. + # Data in an emptyDir is lost when the pod is restarted or deleted. + - name: redis-temp-volume + mountPath: /var/redis-config-temp # Ensure this path is writable by the container's user + # If you require persistent storage for Redis data (e.g., for RDB/AOF files), + # you would uncomment and configure a PersistentVolumeClaim here. + # The mountPath here must match the 'dir' specified in your redis.conf. + # - name: redis-data-pvc-volume + # mountPath: /data # Example: Mount a PVC to /data for persistence + # --- END OF MODIFIED SECTION --- + dnsPolicy: ClusterFirst + initContainers: + - command: + - argocd + - admin + - redis-initial-password + image: quay.io/argoproj/argocd:v2.12.0 + imagePullPolicy: IfNotPresent + name: secret-init + resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + restartPolicy: Always + schedulerName: default-scheduler + securityContext: + runAsNonRoot: true + runAsUser: 999 + seccompProfile: + type: RuntimeDefault + serviceAccount: argocd-redis + serviceAccountName: argocd-redis + terminationGracePeriodSeconds: 30 + volumes: + # Define the volume that mounts the Secret containing the Redis password. + - name: redis-password-volume + secret: + secretName: argocd-redis # This must match your existing Secret name + items: + - key: auth # This is the key within your Secret that holds the password + path: auth # The filename it will appear as inside the mounted directory (/etc/redis-secret/auth) + # Define the temporary writable volume (emptyDir) for dynamic config and temporary files. + - name: redis-temp-volume + emptyDir: {} # Data in this volume is temporary and will be lost on pod restart. + # If you need persistent storage for Redis data (e.g., RDB/AOF files), + # define the PersistentVolumeClaim (PVC) volume here. + # - name: redis-data-pvc-volume + # persistentVolumeClaim: + # claimName: your-redis-pvc-name # Replace with the actual name of your PVC \ No newline at end of file diff --git a/go.mod b/go.mod index 7c94b6f02a24f..c458004ef01dc 100644 --- a/go.mod +++ b/go.mod @@ -273,7 +273,7 @@ require ( gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gomodules.xyz/notify v0.1.1 // indirect google.golang.org/api v0.223.0 // indirect - google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/go.sum b/go.sum index 7ae136df3dce6..bc8d35b35ea94 100644 --- a/go.sum +++ b/go.sum @@ -1404,8 +1404,8 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= +google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= diff --git a/util/cache/cache.go b/util/cache/cache.go index a4fb5ff153ccb..ddf721482539b 100644 --- a/util/cache/cache.go +++ b/util/cache/cache.go @@ -8,6 +8,7 @@ import ( "fmt" "math" "os" + "path/filepath" "strings" "time" @@ -24,7 +25,7 @@ const ( // envRedisPassword is an env variable name which stores redis password envRedisPassword = "REDIS_PASSWORD" // envRedisUsername is an env variable name which stores redis username (for acl setup) - envRedisUsername = "REDIS_USERNAME" + envRedisUsername = "REDIS_PASSWORD" // envRedisRetryCount is an env variable name which stores redis retry count envRedisRetryCount = "REDIS_RETRY_COUNT" // defaultRedisRetryCount holds default number of retries @@ -33,6 +34,8 @@ const ( envRedisSentinelPassword = "REDIS_SENTINEL_PASSWORD" // envRedisSentinelUsername is an env variable name which stores redis sentinel username envRedisSentinelUsername = "REDIS_SENTINEL_USERNAME" + // envRedisCredsFilePath is an env variable name which stores path to redis credentials file + envRedisCredsFilePath = "REDIS_CREDS_FILE_PATH" ) const ( @@ -40,6 +43,13 @@ const ( CLIFlagRedisCompress = "redis-compress" ) +type RedisCreds struct { + Password string + Username string + SentinelUsername string + SentinelPassword string +} + func NewCache(client CacheClient) *Cache { return &Cache{client} } @@ -129,6 +139,27 @@ func getFlagVal[T any](cmd *cobra.Command, o Options, name string, getVal func(n } } +// loadRedisCredsFromSecret loads Redis credentials from a file mounted at the specified path. +func loadRedisCredsFromSecret(mountPath string) *RedisCreds { + creds := &RedisCreds{} + readAuthDetailsFromFile := func(filename string) string { + data, err := os.ReadFile(filepath.Join(mountPath, filename)) + if err != nil { + log.WithFields(log.Fields{ + "file": filename, + "error": err, + }).Warn("Unable to read Redis credential from file; falling back to environment variables") + return "" + } + return strings.TrimSpace(string(data)) + } + creds.Password = readAuthDetailsFromFile("auth") + creds.Username = readAuthDetailsFromFile("auth_username") + creds.SentinelUsername = readAuthDetailsFromFile("sentinel_username") + creds.SentinelPassword = readAuthDetailsFromFile("sentinel_auth") + return creds +} + // AddCacheFlagsToCmd adds flags which control caching to the specified command func AddCacheFlagsToCmd(cmd *cobra.Command, opts ...Options) func() (*Cache, error) { redisAddress := "" @@ -206,25 +237,56 @@ func AddCacheFlagsToCmd(cmd *cobra.Command, opts ...Options) func() (*Cache, err } } } - password := os.Getenv(envRedisPassword) - username := os.Getenv(envRedisUsername) - sentinelUsername := os.Getenv(envRedisSentinelUsername) - sentinelPassword := os.Getenv(envRedisSentinelPassword) + var password, username, sentinelUsername, sentinelPassword string + credsFilePath := os.Getenv(envRedisCredsFilePath) if opt.FlagPrefix != "" { - if val := os.Getenv(opt.getEnvPrefix() + envRedisUsername); val != "" { - username = val + if val := os.Getenv(opt.getEnvPrefix() + envRedisCredsFilePath); val != "" { + credsFilePath = val + } + } + // Try to read credentials from the file first + if credsFilePath != "" { + log.Info("Loading Redis credentials from file: ", credsFilePath) + creds := loadRedisCredsFromSecret(credsFilePath) + password = creds.Password + username = creds.Username + sentinelUsername = creds.SentinelUsername + sentinelPassword = creds.SentinelPassword + } + // If credentials were not successfully loaded from file, or if file path was not provided, + // then read from individual environment variables. Environment variables also override file if specified via flag. + if username == "" { // Only fall back if not set by file + username = os.Getenv(envRedisUsername) + if opt.FlagPrefix != "" { + if val := os.Getenv(opt.getEnvPrefix() + envRedisUsername); val != "" { + username = val + } } - if val := os.Getenv(opt.getEnvPrefix() + envRedisPassword); val != "" { - password = val + } + if password == "" { // Only fall back if not set by file + password = os.Getenv(envRedisPassword) + if opt.FlagPrefix != "" { + if val := os.Getenv(opt.getEnvPrefix() + envRedisPassword); val != "" { + password = val + } } - if val := os.Getenv(opt.getEnvPrefix() + envRedisSentinelUsername); val != "" { - sentinelUsername = val + } + if sentinelUsername == "" { // Only fall back if not set by file + sentinelUsername = os.Getenv(envRedisSentinelUsername) + if opt.FlagPrefix != "" { + if val := os.Getenv(opt.getEnvPrefix() + envRedisSentinelUsername); val != "" { + sentinelUsername = val + } } - if val := os.Getenv(opt.getEnvPrefix() + envRedisSentinelPassword); val != "" { - sentinelPassword = val + } + if sentinelPassword == "" { // Only fall back if not set by file + sentinelPassword = os.Getenv(envRedisSentinelPassword) + if opt.FlagPrefix != "" { + if val := os.Getenv(opt.getEnvPrefix() + envRedisSentinelPassword); val != "" { + sentinelPassword = val + } } } - maxRetries := env.ParseNumFromEnv(envRedisRetryCount, defaultRedisRetryCount, 0, math.MaxInt32) compression, err := CompressionTypeFromString(compressionStr) if err != nil { From 56fdbba28456cc95d180302dd1e494cbddab674c Mon Sep 17 00:00:00 2001 From: Mangaal Date: Thu, 19 Jun 2025 16:23:59 +0530 Subject: [PATCH 003/383] add unit test. make redisCreds private Signed-off-by: Mangaal --- argocd-redis.yaml | 156 --------------------------------------- util/cache/cache.go | 38 +++++----- util/cache/cache_test.go | 22 ++++++ 3 files changed, 39 insertions(+), 177 deletions(-) delete mode 100644 argocd-redis.yaml diff --git a/argocd-redis.yaml b/argocd-redis.yaml deleted file mode 100644 index 8b80a8147521f..0000000000000 --- a/argocd-redis.yaml +++ /dev/null @@ -1,156 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/component: redis - app.kubernetes.io/name: argocd-redis - app.kubernetes.io/part-of: argocd - name: argocd-redis - namespace: argocd -spec: - progressDeadlineSeconds: 600 - replicas: 1 - revisionHistoryLimit: 10 - selector: - matchLabels: - app.kubernetes.io/name: argocd-redis - strategy: - rollingUpdate: - maxSurge: 25% - maxUnavailable: 25% - type: RollingUpdate - template: - metadata: - creationTimestamp: null - labels: - app.kubernetes.io/name: argocd-redis - spec: - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchLabels: - app.kubernetes.io/name: argocd-redis - topologyKey: kubernetes.io/hostname - weight: 100 - - podAffinityTerm: - labelSelector: - matchLabels: - app.kubernetes.io/part-of: argocd - topologyKey: kubernetes.io/hostname - weight: 5 - containers: - - name: redis - image: redis:7.0.15-alpine # Your specified image version - imagePullPolicy: Always - command: ["sh", "-c"] - args: - - | - mkdir -p /var/redis-config-temp/config - cat < /var/redis-config-temp/config/redis.conf - # General Redis Configuration - port 6379 - bind 0.0.0.0 - - # Security: Require password for client connections. - # The password is read from the 'auth' key of the 'argocd-redis' Secret, - # which is mounted as a file at /etc/redis-secret/auth. - requirepass $(cat /etc/redis-secret/auth) - - # Example RDB snapshot persistence: - # save 900 1 # Save if 1 key changes in 15 minutes - # save 300 10 # Save if 10 keys change in 5 minutes - # save 60 10000 # Save if 10000 keys change in 1 minute - - # Example AOF (Append Only File) persistence: - # appendonly yes # Enable AOF persistence - # appendfsync everysec # Sync AOF to disk every second (good balance of performance/safety) - - EOF - - # Start the Redis server using the dynamically generated configuration file. - redis-server /var/redis-config-temp/config/redis.conf - ports: - - containerPort: 6379 - protocol: TCP - resources: - requests: - cpu: 100m # Request 100 millicores of CPU - memory: 128Mi # Request 128 MiB of memory (should be less than maxmemory) - limits: - cpu: 200m # Limit to 200 millicores of CPU - memory: 512Mi # Limit to 512 MiB of memory (should be >= maxmemory + overhead) - # ---------------------------------------------------- - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true # Retains your existing security context - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - volumeMounts: - # Mount the Kubernetes Secret containing the Redis password. - # This provides read-only access to the password file. - - name: redis-password-volume - mountPath: /etc/redis-secret # The directory where the secret's data will appear as files - readOnly: true # Crucially, this mount is read-only for security. - # Mount a temporary, writable volume. This is where the redis.conf will be - # dynamically generated and where Redis might store temporary files. - # Data in an emptyDir is lost when the pod is restarted or deleted. - - name: redis-temp-volume - mountPath: /var/redis-config-temp # Ensure this path is writable by the container's user - # If you require persistent storage for Redis data (e.g., for RDB/AOF files), - # you would uncomment and configure a PersistentVolumeClaim here. - # The mountPath here must match the 'dir' specified in your redis.conf. - # - name: redis-data-pvc-volume - # mountPath: /data # Example: Mount a PVC to /data for persistence - # --- END OF MODIFIED SECTION --- - dnsPolicy: ClusterFirst - initContainers: - - command: - - argocd - - admin - - redis-initial-password - image: quay.io/argoproj/argocd:v2.12.0 - imagePullPolicy: IfNotPresent - name: secret-init - resources: {} - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - restartPolicy: Always - schedulerName: default-scheduler - securityContext: - runAsNonRoot: true - runAsUser: 999 - seccompProfile: - type: RuntimeDefault - serviceAccount: argocd-redis - serviceAccountName: argocd-redis - terminationGracePeriodSeconds: 30 - volumes: - # Define the volume that mounts the Secret containing the Redis password. - - name: redis-password-volume - secret: - secretName: argocd-redis # This must match your existing Secret name - items: - - key: auth # This is the key within your Secret that holds the password - path: auth # The filename it will appear as inside the mounted directory (/etc/redis-secret/auth) - # Define the temporary writable volume (emptyDir) for dynamic config and temporary files. - - name: redis-temp-volume - emptyDir: {} # Data in this volume is temporary and will be lost on pod restart. - # If you need persistent storage for Redis data (e.g., RDB/AOF files), - # define the PersistentVolumeClaim (PVC) volume here. - # - name: redis-data-pvc-volume - # persistentVolumeClaim: - # claimName: your-redis-pvc-name # Replace with the actual name of your PVC \ No newline at end of file diff --git a/util/cache/cache.go b/util/cache/cache.go index ddf721482539b..e0a6dabfd13a4 100644 --- a/util/cache/cache.go +++ b/util/cache/cache.go @@ -43,11 +43,11 @@ const ( CLIFlagRedisCompress = "redis-compress" ) -type RedisCreds struct { - Password string - Username string - SentinelUsername string - SentinelPassword string +type redisCreds struct { + password string + username string + sentinelUsername string + sentinelPassword string } func NewCache(client CacheClient) *Cache { @@ -139,24 +139,20 @@ func getFlagVal[T any](cmd *cobra.Command, o Options, name string, getVal func(n } } -// loadRedisCredsFromSecret loads Redis credentials from a file mounted at the specified path. -func loadRedisCredsFromSecret(mountPath string) *RedisCreds { - creds := &RedisCreds{} +// loadRedisCredsFromFile loads Redis credentials from a file mounted at the specified path. +func loadRedisCredsFromFile(mountPath string) *redisCreds { + creds := &redisCreds{} readAuthDetailsFromFile := func(filename string) string { data, err := os.ReadFile(filepath.Join(mountPath, filename)) if err != nil { - log.WithFields(log.Fields{ - "file": filename, - "error": err, - }).Warn("Unable to read Redis credential from file; falling back to environment variables") return "" } return strings.TrimSpace(string(data)) } - creds.Password = readAuthDetailsFromFile("auth") - creds.Username = readAuthDetailsFromFile("auth_username") - creds.SentinelUsername = readAuthDetailsFromFile("sentinel_username") - creds.SentinelPassword = readAuthDetailsFromFile("sentinel_auth") + creds.password = readAuthDetailsFromFile("auth") + creds.username = readAuthDetailsFromFile("auth_username") + creds.sentinelUsername = readAuthDetailsFromFile("sentinel_username") + creds.sentinelPassword = readAuthDetailsFromFile("sentinel_auth") return creds } @@ -247,11 +243,11 @@ func AddCacheFlagsToCmd(cmd *cobra.Command, opts ...Options) func() (*Cache, err // Try to read credentials from the file first if credsFilePath != "" { log.Info("Loading Redis credentials from file: ", credsFilePath) - creds := loadRedisCredsFromSecret(credsFilePath) - password = creds.Password - username = creds.Username - sentinelUsername = creds.SentinelUsername - sentinelPassword = creds.SentinelPassword + creds := loadRedisCredsFromFile(credsFilePath) + password = creds.password + username = creds.username + sentinelUsername = creds.sentinelUsername + sentinelPassword = creds.sentinelPassword } // If credentials were not successfully loaded from file, or if file path was not provided, // then read from individual environment variables. Environment variables also override file if specified via flag. diff --git a/util/cache/cache_test.go b/util/cache/cache_test.go index bcd6d5136cea8..b465d5829facd 100644 --- a/util/cache/cache_test.go +++ b/util/cache/cache_test.go @@ -1,6 +1,8 @@ package cache import ( + "os" + "path/filepath" "testing" "time" @@ -87,3 +89,23 @@ func TestGenerateCacheKey(t *testing.T) { testKey := cache.generateFullKey("testkey") assert.Equal(t, "testkey|"+common.CacheVersion, testKey) } + +// Test loading Redis credentials from a file +func TestLoadRedisCredsFromFile(t *testing.T) { + dir := t.TempDir() + // Helper to write a file + writeFile := func(name, content string) { + require.NoError(t, os.WriteFile(filepath.Join(dir, name), []byte(content), 0600)) + } + // Write all files + writeFile("auth", "mypassword\n") + writeFile("auth_username", "myuser") + writeFile("sentinel_username", "sentineluser") + writeFile("sentinel_auth", "sentinelpass") + + creds := loadRedisCredsFromFile(dir) + assert.Equal(t, "mypassword", creds.password) + assert.Equal(t, "myuser", creds.username) + assert.Equal(t, "sentineluser", creds.sentinelUsername) + assert.Equal(t, "sentinelpass", creds.sentinelPassword) +} From 37058727d4b5ab42951193cf21838aa9612aa17d Mon Sep 17 00:00:00 2001 From: Kanika Rana <46766610+ranakan19@users.noreply.github.com> Date: Tue, 17 Jun 2025 07:56:58 -0400 Subject: [PATCH 004/383] chore(finalizers): remove hardcoding of application and applicationset finalizers (#23420) Signed-off-by: Kanika Rana Signed-off-by: Mangaal --- .../controllers/template/patch_test.go | 8 +-- applicationset/utils/utils.go | 2 +- applicationset/utils/utils_test.go | 18 +++---- cmd/argocd/commands/admin/app.go | 2 +- cmd/argocd/commands/app.go | 2 +- test/e2e/app_management_ns_test.go | 2 +- test/e2e/app_management_test.go | 2 +- test/e2e/applicationset_git_generator_test.go | 30 +++++------ test/e2e/applicationset_test.go | 50 +++++++++---------- test/e2e/cluster_generator_test.go | 12 ++--- test/e2e/clusterdecisiongenerator_e2e_test.go | 10 ++-- test/e2e/matrix_e2e_test.go | 8 +-- test/e2e/merge_e2e_test.go | 6 +-- 13 files changed, 76 insertions(+), 76 deletions(-) diff --git a/applicationset/controllers/template/patch_test.go b/applicationset/controllers/template/patch_test.go index 35c88fe650fa4..d252924d47554 100644 --- a/applicationset/controllers/template/patch_test.go +++ b/applicationset/controllers/template/patch_test.go @@ -27,7 +27,7 @@ func Test_ApplyTemplatePatch(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: "namespace", - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{appv1.ResourcesFinalizerName}, }, Spec: appv1.ApplicationSpec{ Project: "default", @@ -72,7 +72,7 @@ func Test_ApplyTemplatePatch(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: "namespace", - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{appv1.ResourcesFinalizerName}, Annotations: map[string]string{ "annotation-some-key": "annotation-some-value", }, @@ -112,7 +112,7 @@ func Test_ApplyTemplatePatch(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: "namespace", - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{appv1.ResourcesFinalizerName}, }, Spec: appv1.ApplicationSpec{ Project: "default", @@ -148,7 +148,7 @@ spec: ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: "namespace", - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{appv1.ResourcesFinalizerName}, Annotations: map[string]string{ "annotation-some-key": "annotation-some-value", }, diff --git a/applicationset/utils/utils.go b/applicationset/utils/utils.go index cfc26720b4f4e..c8491e2956a01 100644 --- a/applicationset/utils/utils.go +++ b/applicationset/utils/utils.go @@ -276,7 +276,7 @@ func (r *Render) RenderTemplateParams(tmpl *argoappsv1.Application, syncPolicy * // See TestRenderTemplateParamsFinalizers in util_test.go for test-based definition of behaviour if (syncPolicy == nil || !syncPolicy.PreserveResourcesOnDeletion) && len(replacedTmpl.Finalizers) == 0 { - replacedTmpl.Finalizers = []string{"resources-finalizer.argocd.argoproj.io"} + replacedTmpl.Finalizers = []string{argoappsv1.ResourcesFinalizerName} } return replacedTmpl, nil diff --git a/applicationset/utils/utils_test.go b/applicationset/utils/utils_test.go index 351d144e2f288..1554defb5e5b0 100644 --- a/applicationset/utils/utils_test.go +++ b/applicationset/utils/utils_test.go @@ -752,35 +752,35 @@ func TestRenderTemplateParamsFinalizers(t *testing.T) { }, { testName: "background finalizer should be preserved", - existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + existingFinalizers: []string{argoappsv1.BackgroundPropagationPolicyFinalizer}, syncPolicy: nil, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + expectedFinalizers: []string{argoappsv1.BackgroundPropagationPolicyFinalizer}, }, { testName: "empty finalizer and empty sync should use standard finalizer", existingFinalizers: nil, syncPolicy: nil, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + expectedFinalizers: []string{argoappsv1.ResourcesFinalizerName}, }, { testName: "standard finalizer should be preserved", - existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + existingFinalizers: []string{argoappsv1.ResourcesFinalizerName}, syncPolicy: nil, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + expectedFinalizers: []string{argoappsv1.ResourcesFinalizerName}, }, { testName: "empty array finalizers should use standard finalizer", existingFinalizers: []string{}, syncPolicy: nil, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + expectedFinalizers: []string{argoappsv1.ResourcesFinalizerName}, }, { testName: "non-nil sync policy should use standard finalizer", existingFinalizers: nil, syncPolicy: &argoappsv1.ApplicationSetSyncPolicy{}, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + expectedFinalizers: []string{argoappsv1.ResourcesFinalizerName}, }, { testName: "preserveResourcesOnDeletion should not have a finalizer", @@ -792,11 +792,11 @@ func TestRenderTemplateParamsFinalizers(t *testing.T) { }, { testName: "user-specified finalizer should overwrite preserveResourcesOnDeletion", - existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + existingFinalizers: []string{argoappsv1.BackgroundPropagationPolicyFinalizer}, syncPolicy: &argoappsv1.ApplicationSetSyncPolicy{ PreserveResourcesOnDeletion: true, }, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + expectedFinalizers: []string{argoappsv1.BackgroundPropagationPolicyFinalizer}, }, } { t.Run(c.testName, func(t *testing.T) { diff --git a/cmd/argocd/commands/admin/app.go b/cmd/argocd/commands/admin/app.go index 0b14449e46f53..535112e3634ca 100644 --- a/cmd/argocd/commands/admin/app.go +++ b/cmd/argocd/commands/admin/app.go @@ -117,7 +117,7 @@ func NewGenAppSpecCommand() *cobra.Command { os.Exit(1) } if setFinalizer { - app.Finalizers = append(app.Finalizers, "resources-finalizer.argocd.argoproj.io") + app.Finalizers = append(app.Finalizers, v1alpha1.ResourcesFinalizerName) } out, closer, err := getOutWriter(inline, fileURL) errors.CheckError(err) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index cf1b82dec978f..cb1bdc54caed1 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -167,7 +167,7 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra. app.Namespace = appNamespace } if setFinalizer { - app.Finalizers = append(app.Finalizers, "resources-finalizer.argocd.argoproj.io") + app.Finalizers = append(app.Finalizers, argoappv1.ResourcesFinalizerName) } conn, appIf := argocdClient.NewApplicationClientOrDie() defer utilio.Close(conn) diff --git a/test/e2e/app_management_ns_test.go b/test/e2e/app_management_ns_test.go index 3cf9b939854f9..ad81a35150cd3 100644 --- a/test/e2e/app_management_ns_test.go +++ b/test/e2e/app_management_ns_test.go @@ -2131,7 +2131,7 @@ spec: And(func(app *Application) { assert.Equal(t, map[string]string{"labels.local/from-file": "file", "labels.local/from-args": "args"}, app.Labels) assert.Equal(t, map[string]string{"annotations.local/from-file": "file"}, app.Annotations) - assert.Equal(t, []string{"resources-finalizer.argocd.argoproj.io"}, app.Finalizers) + assert.Equal(t, []string{ResourcesFinalizerName}, app.Finalizers) assert.Equal(t, path, app.Spec.GetSource().Path) assert.Equal(t, []HelmParameter{{Name: "foo", Value: "foo"}}, app.Spec.GetSource().Helm.Parameters) }) diff --git a/test/e2e/app_management_test.go b/test/e2e/app_management_test.go index 434918ec35f5a..0c6b97e6bb780 100644 --- a/test/e2e/app_management_test.go +++ b/test/e2e/app_management_test.go @@ -2350,7 +2350,7 @@ spec: And(func(app *Application) { assert.Equal(t, map[string]string{"labels.local/from-file": "file", "labels.local/from-args": "args"}, app.Labels) assert.Equal(t, map[string]string{"annotations.local/from-file": "file"}, app.Annotations) - assert.Equal(t, []string{"resources-finalizer.argocd.argoproj.io"}, app.Finalizers) + assert.Equal(t, []string{ResourcesFinalizerName}, app.Finalizers) assert.Equal(t, path, app.Spec.GetSource().Path) assert.Equal(t, []HelmParameter{{Name: "foo", Value: "foo"}}, app.Spec.GetSource().Helm.Parameters) }) diff --git a/test/e2e/applicationset_git_generator_test.go b/test/e2e/applicationset_git_generator_test.go index 37f875108ad70..7d9541a470e13 100644 --- a/test/e2e/applicationset_git_generator_test.go +++ b/test/e2e/applicationset_git_generator_test.go @@ -40,7 +40,7 @@ func TestSimpleGitDirectoryGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -149,7 +149,7 @@ func TestSimpleGitDirectoryGeneratorGoTemplate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -281,7 +281,7 @@ func TestSimpleGitDirectoryGeneratorGPGEnabledUnsignedCommits(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -379,7 +379,7 @@ func TestSimpleGitDirectoryGeneratorGPGEnabledWithoutKnownKeys(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -463,7 +463,7 @@ func TestSimpleGitFilesGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -595,7 +595,7 @@ func TestSimpleGitFilesGeneratorGPGEnabledUnsignedCommits(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: project, @@ -693,7 +693,7 @@ func TestSimpleGitFilesGeneratorGPGEnabledWithoutKnownKeys(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: project, @@ -772,7 +772,7 @@ func TestSimpleGitFilesGeneratorGoTemplate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1003,7 +1003,7 @@ func TestGitGeneratorPrivateRepo(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1080,7 +1080,7 @@ func TestGitGeneratorPrivateRepoGoTemplate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1157,7 +1157,7 @@ func TestSimpleGitGeneratorPrivateRepoWithNoRepo(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1232,7 +1232,7 @@ func TestSimpleGitGeneratorPrivateRepoWithMatchingProject(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1308,7 +1308,7 @@ func TestSimpleGitGeneratorPrivateRepoWithMismatchingProject(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1384,7 +1384,7 @@ func TestGitGeneratorPrivateRepoWithTemplatedProject(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1471,7 +1471,7 @@ func TestGitGeneratorPrivateRepoWithTemplatedProjectAndProjectScopedRepo(t *test ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", diff --git a/test/e2e/applicationset_test.go b/test/e2e/applicationset_test.go index f9d3aace48a05..e285656c315b7 100644 --- a/test/e2e/applicationset_test.go +++ b/test/e2e/applicationset_test.go @@ -60,7 +60,7 @@ func TestSimpleListGeneratorExternalNamespace(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: externalNamespace, - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -162,7 +162,7 @@ func TestSimpleListGeneratorExternalNamespaceNoConflict(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: externalNamespace, - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -186,7 +186,7 @@ func TestSimpleListGeneratorExternalNamespaceNoConflict(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: externalNamespace2, - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -345,7 +345,7 @@ func TestSimpleListGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -436,7 +436,7 @@ func TestSimpleListGeneratorGoTemplate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -528,7 +528,7 @@ func TestRenderHelmValuesObject(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -603,7 +603,7 @@ func TestTemplatePatch(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, Annotations: map[string]string{ "annotation-some-key": "annotation-some-value", }, @@ -730,7 +730,7 @@ func TestUpdateHelmValuesObject(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -815,7 +815,7 @@ func TestSyncPolicyCreateUpdate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook-sync-policy-create-update", Namespace: utils.ArgoCDNamespace, - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -844,7 +844,7 @@ func TestSyncPolicyCreateUpdate(t *testing.T) { Template: v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{ Name: "{{.cluster}}-guestbook-sync-policy-create-update", - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -929,7 +929,7 @@ func TestSyncPolicyCreateDelete(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook-sync-policy-create-delete", Namespace: utils.ArgoCDNamespace, - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1028,7 +1028,7 @@ func TestSyncPolicyCreateOnly(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook-sync-policy-create-only", Namespace: utils.ArgoCDNamespace, - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1056,7 +1056,7 @@ func TestSyncPolicyCreateOnly(t *testing.T) { Template: v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{ Name: "{{.cluster}}-guestbook-sync-policy-create-only", - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1342,7 +1342,7 @@ func TestSimpleSCMProviderGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "argo-cd-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1417,7 +1417,7 @@ func TestSimpleSCMProviderGeneratorGoTemplate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "argo-cd-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1487,7 +1487,7 @@ func TestSCMProviderGeneratorSCMProviderNotAllowed(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "argo-cd-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1563,7 +1563,7 @@ func TestCustomApplicationFinalizers(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + Finalizers: []string{v1alpha1.BackgroundPropagationPolicyFinalizer}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1589,7 +1589,7 @@ func TestCustomApplicationFinalizers(t *testing.T) { Template: v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{ Name: "{{cluster}}-guestbook", - Finalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + Finalizers: []string{v1alpha1.BackgroundPropagationPolicyFinalizer}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1630,7 +1630,7 @@ func TestCustomApplicationFinalizersGoTemplate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "my-cluster-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + Finalizers: []string{v1alpha1.BackgroundPropagationPolicyFinalizer}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1657,7 +1657,7 @@ func TestCustomApplicationFinalizersGoTemplate(t *testing.T) { Template: v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{ Name: "{{.cluster}}-guestbook", - Finalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + Finalizers: []string{v1alpha1.BackgroundPropagationPolicyFinalizer}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1744,7 +1744,7 @@ func TestSimpleSCMProviderGeneratorTokenRefStrictOk(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "argo-cd-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -1846,7 +1846,7 @@ func TestSimpleSCMProviderGeneratorTokenRefStrictKo(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "argo-cd-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, Labels: map[string]string{ common.LabelKeyAppInstance: "simple-scm-provider-generator-strict-ko", }, @@ -1955,7 +1955,7 @@ func TestSimplePullRequestGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "guestbook-1", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -2033,7 +2033,7 @@ func TestSimplePullRequestGeneratorGoTemplate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "guestbook-1", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, Labels: map[string]string{"app": "preview"}, }, Spec: v1alpha1.ApplicationSpec{ @@ -2109,7 +2109,7 @@ func TestPullRequestGeneratorNotAllowedSCMProvider(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "guestbook-1", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, Labels: map[string]string{ "app": "preview", }, diff --git a/test/e2e/cluster_generator_test.go b/test/e2e/cluster_generator_test.go index e1dc84b2035f4..ea47644f7c84e 100644 --- a/test/e2e/cluster_generator_test.go +++ b/test/e2e/cluster_generator_test.go @@ -24,7 +24,7 @@ func TestSimpleClusterGeneratorExternalNamespace(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "cluster1-guestbook", Namespace: externalNamespace, - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -124,7 +124,7 @@ func TestSimpleClusterGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "cluster1-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -218,7 +218,7 @@ func TestClusterGeneratorWithLocalCluster(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "in-cluster-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -335,7 +335,7 @@ func TestSimpleClusterGeneratorAddingCluster(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "{{name}}-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -417,7 +417,7 @@ func TestSimpleClusterGeneratorDeletingCluster(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "{{name}}-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -501,7 +501,7 @@ func TestClusterGeneratorWithFlatListMode(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "flat-clusters", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", diff --git a/test/e2e/clusterdecisiongenerator_e2e_test.go b/test/e2e/clusterdecisiongenerator_e2e_test.go index db7951ac46106..59c375e291c18 100644 --- a/test/e2e/clusterdecisiongenerator_e2e_test.go +++ b/test/e2e/clusterdecisiongenerator_e2e_test.go @@ -27,7 +27,7 @@ func TestSimpleClusterDecisionResourceGeneratorExternalNamespace(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "cluster1-guestbook", Namespace: externalNamespace, - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -135,7 +135,7 @@ func TestSimpleClusterDecisionResourceGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "cluster1-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -237,7 +237,7 @@ func TestSimpleClusterDecisionResourceGeneratorAddingCluster(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "{{name}}-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -332,7 +332,7 @@ func TestSimpleClusterDecisionResourceGeneratorDeletingClusterSecret(t *testing. ObjectMeta: metav1.ObjectMeta{ Name: "{{name}}-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -429,7 +429,7 @@ func TestSimpleClusterDecisionResourceGeneratorDeletingClusterFromResource(t *te ObjectMeta: metav1.ObjectMeta{ Name: "{{name}}-guestbook", Namespace: fixture.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", diff --git a/test/e2e/matrix_e2e_test.go b/test/e2e/matrix_e2e_test.go index 534c74938b253..189e51beca150 100644 --- a/test/e2e/matrix_e2e_test.go +++ b/test/e2e/matrix_e2e_test.go @@ -24,7 +24,7 @@ func TestListMatrixGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s", cluster, name), Namespace: utils.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -147,7 +147,7 @@ func TestClusterMatrixGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s", cluster, name), Namespace: utils.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -273,7 +273,7 @@ func TestMatrixTerminalMatrixGeneratorSelector(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s", cluster, name), Namespace: utils.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -414,7 +414,7 @@ func TestMatrixTerminalMergeGeneratorSelector(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s", name, nameSuffix), Namespace: utils.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", diff --git a/test/e2e/merge_e2e_test.go b/test/e2e/merge_e2e_test.go index e799c95fdd08a..ef933ab6b28c0 100644 --- a/test/e2e/merge_e2e_test.go +++ b/test/e2e/merge_e2e_test.go @@ -25,7 +25,7 @@ func TestListMergeGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s", name, nameSuffix), Namespace: utils.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -146,7 +146,7 @@ func TestClusterMergeGenerator(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s-%s", cluster, name, nameSuffix), Namespace: utils.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", @@ -290,7 +290,7 @@ func TestMergeTerminalMergeGeneratorSelector(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s", name, nameSuffix), Namespace: utils.TestNamespace(), - Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Finalizers: []string{v1alpha1.ResourcesFinalizerName}, }, Spec: v1alpha1.ApplicationSpec{ Project: "default", From 053d73d8571a54ade9fe901cd7a9da98b8b03994 Mon Sep 17 00:00:00 2001 From: Eric Fortin Date: Tue, 17 Jun 2025 10:42:17 -0400 Subject: [PATCH 005/383] docs: regroup generators reference fixes #23439 (#23440) Signed-off-by: Eric Fortin Signed-off-by: Mangaal --- docs/operator-manual/applicationset.yaml | 257 +++++++++++++---------- 1 file changed, 143 insertions(+), 114 deletions(-) diff --git a/docs/operator-manual/applicationset.yaml b/docs/operator-manual/applicationset.yaml index dbe36e076ca2e..14046713bb46b 100644 --- a/docs/operator-manual/applicationset.yaml +++ b/docs/operator-manual/applicationset.yaml @@ -5,31 +5,66 @@ metadata: namespace: argocd spec: generators: + # The list generator generates a set of two application which then filter by the key value to only select the env with value staging + - list: + elements: + - cluster: engineering-dev + url: https://kubernetes.default.svc + env: staging + - cluster: engineering-prod + url: https://kubernetes.default.svc + env: prod + # The generator's template field takes precedence over the spec's template fields + template: + metadata: {} + spec: + project: "default" + source: + revision: HEAD + repoURL: https://github.com/argoproj/argo-cd.git + # New path value is generated here: + path: 'applicationset/examples/template-override/{{cluster}}-override' + destination: {} - # Using a generator plugin without combining it with Matrix or Merge - # Plugins allow you to provide your own generator - - plugin: - # Specify the configMap where the plugin configuration is located. - configMapRef: - name: my-plugin - # You can pass arbitrary parameters to the plugin. `input.parameters` is a map, but values may be any type. - # These parameters will also be available on the generator's output under the `generator.input.parameters` key. - input: - parameters: - key1: "value1" - key2: "value2" - list: ["list", "of", "values"] - boolean: true - map: - key1: "value1" - key2: "value2" - key3: "value3" - # You can also attach arbitrary values to the generator's output under the `values` key. These values will be - # available in templates under the `values` key. + # Selector allows to post-filter all generator. + selector: + matchLabels: + env: staging + + # It is also possible to use matchExpressions for more powerful selectors + - clusters: {} + selector: + matchExpressions: + - key: server + operator: In + values: + - https://kubernetes.default.svc + - https://some-other-cluster + + # Git generator generates parametes either from directory structure of files within a git repo + - git: + repoURL: https://github.com/argoproj/argo-cd.git + # OPTIONAL: use directory structure of git repo to generate parameters + directories: + - path: applicationset/examples/git-generator-directory/excludes/cluster-addons/* + - path: applicationset/examples/git-generator-directory/excludes/cluster-addons/exclude-helm-guestbook + exclude: true # Exclude directory when generating parameters + # OPTIONAL: generates parameters using the contents of JSON/YAML files found in git repo + files: + - path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json" + - path: "applicationset/examples/git-generator-files-discovery/cluster-config/*/dev/config.json" + exclude: true # Exclude file when generating parameters + revision: HEAD + # OPTIONAL: Checks for changes every 60sec (default 3min) + requeueAfterSeconds: 60 + # The generator's template field takes precedence over the spec's template fields + template: + # OPTIONAL: all path-related parameter names will be prefixed with the specified value and a dot separator + pathParamPrefix: myRepo + # OPTIONAL: Values contains key/value pairs which are passed directly as parameters to the template values: - value1: something - # When using a Plugin generator, the ApplicationSet controller polls every `requeueAfterSeconds` interval (defaulting to every 30 minutes) to detect changes. - requeueAfterSeconds: 30 + cluster: '{{.path.basename}}' + # to automatically discover repositories within an organization - scmProvider: @@ -76,6 +111,65 @@ spec: - repositoryMatch: ^otherapp pathsExist: [helm] pathsDoNotExist: [disabledrepo.txt] + + # Cluster-decision-resource-based ApplicationSet generator + - clusterDecisionResource: + # ConfigMap with GVK information for the duck type resource + configMapRef: my-configmap + name: quak # Choose either "name" of the resource or "labelSelector" + labelSelector: + matchLabels: # OPTIONAL + duck: spotted + matchExpressions: # OPTIONAL + - key: duck + operator: In + values: + - "spotted" + - "canvasback" + # OPTIONAL: Checks for changes every 60sec (default 3min) + requeueAfterSeconds: 60 + + # The Pull Request generator uses the API of an SCMaaS provider to automatically discover open pull requests within a repository + - pullRequest: + # When using a Pull Request generator, the ApplicationSet controller polls every `requeueAfterSeconds` interval (defaulting to every 30 minutes) to detect changes. + requeueAfterSeconds: 1800 + # See below for provider specific options. + # Specify the repository from which to fetch the GitHub Pull requests. + github: + # The GitHub organization or user. + owner: myorg + # The Github repository + repo: myrepository + # For GitHub Enterprise (optional) + api: https://git.example.com/ + # Reference to a Secret containing an access token. (optional) + tokenRef: + secretName: github-token + key: token + # (optional) use a GitHub App to access the API instead of a PAT. + appSecretName: github-app-repo-creds + # Labels is used to filter the PRs that you want to target. (optional) + labels: + - preview + + # Filters allow selecting which pull requests to generate for + # Include any pull request ending with "argocd". (optional) + filters: + - branchMatch: ".*-argocd" + + # Specify the project from which to fetch the GitLab merge requests. + gitlab: + # Specify the repository from which to fetch the Gitea Pull requests. + gitea: + # Fetch pull requests from a repo hosted on a Bitbucket Server (not the same as Bitbucket Cloud). + bitbucketServer: + # Fetch pull requests from a repo hosted on a Bitbucket Cloud. + bitbucket: + # Specify the organization, project and repository from which you want to fetch pull requests. + azuredevops: + # Fetch pull requests from AWS CodeCommit repositories. + awsCodeCommit: + # matrix 'parent' generator - matrix: generators: @@ -106,6 +200,31 @@ spec: elements: - server: https://2.4.6.8 values.redis: 'true' + + # Using a generator plugin without combining it with Matrix or Merge + # Plugins allow you to provide your own generator + - plugin: + # Specify the configMap where the plugin configuration is located. + configMapRef: + name: my-plugin + # You can pass arbitrary parameters to the plugin. `input.parameters` is a map, but values may be any type. + # These parameters will also be available on the generator's output under the `generator.input.parameters` key. + input: + parameters: + key1: "value1" + key2: "value2" + list: ["list", "of", "values"] + boolean: true + map: + key1: "value1" + key2: "value2" + key3: "value3" + # You can also attach arbitrary values to the generator's output under the `values` key. These values will be + # available in templates under the `values` key. + values: + value1: something + # When using a Plugin generator, the ApplicationSet controller polls every `requeueAfterSeconds` interval (defaulting to every 30 minutes) to detect changes. + requeueAfterSeconds: 30 # Determines whether go templating will be used in the `template` field below. @@ -206,94 +325,4 @@ spec: jqPathExpressions: - .spec.source.helm.values - # Cluster-decision-resource-based ApplicationSet generator - - clusterDecisionResource: - # ConfigMap with GVK information for the duck type resource - configMapRef: my-configmap - name: quak # Choose either "name" of the resource or "labelSelector" - labelSelector: - matchLabels: # OPTIONAL - duck: spotted - matchExpressions: # OPTIONAL - - key: duck - operator: In - values: - - "spotted" - - "canvasback" - # OPTIONAL: Checks for changes every 60sec (default 3min) - requeueAfterSeconds: 60 - - # The Pull Request generator uses the API of an SCMaaS provider to automatically discover open pull requests within a repository - - pullRequest: - # When using a Pull Request generator, the ApplicationSet controller polls every `requeueAfterSeconds` interval (defaulting to every 30 minutes) to detect changes. - requeueAfterSeconds: 1800 - # See below for provider specific options. - # Specify the repository from which to fetch the GitHub Pull requests. - github: - # The GitHub organization or user. - owner: myorg - # The Github repository - repo: myrepository - # For GitHub Enterprise (optional) - api: https://git.example.com/ - # Reference to a Secret containing an access token. (optional) - tokenRef: - secretName: github-token - key: token - # (optional) use a GitHub App to access the API instead of a PAT. - appSecretName: github-app-repo-creds - # Labels is used to filter the PRs that you want to target. (optional) - labels: - - preview - - # Filters allow selecting which pull requests to generate for - # Include any pull request ending with "argocd". (optional) - filters: - - branchMatch: ".*-argocd" - - # Specify the project from which to fetch the GitLab merge requests. - gitlab: - # Specify the repository from which to fetch the Gitea Pull requests. - gitea: - # Fetch pull requests from a repo hosted on a Bitbucket Server (not the same as Bitbucket Cloud). - bitbucketServer: - # Fetch pull requests from a repo hosted on a Bitbucket Cloud. - bitbucket: - # Specify the organization, project and repository from which you want to fetch pull requests. - azuredevops: - # Fetch pull requests from AWS CodeCommit repositories. - awsCodeCommit: - -# The list generator generates a set of two application which then filter by the key value to only select the env with value staging - - list: - elements: - - cluster: engineering-dev - url: https://kubernetes.default.svc - env: staging - - cluster: engineering-prod - url: https://kubernetes.default.svc - env: prod - # The generator's template field takes precedence over the spec's template fields - template: - metadata: {} - spec: - project: "default" - source: - revision: HEAD - repoURL: https://github.com/argoproj/argo-cd.git - # New path value is generated here: - path: 'applicationset/examples/template-override/{{cluster}}-override' - destination: {} - - selector: - matchLabels: - env: staging - # It is also possible to use matchExpressions for more powerful selectors - - clusters: {} - selector: - matchExpressions: - - key: server - operator: In - values: - - https://kubernetes.default.svc - - https://some-other-cluster + \ No newline at end of file From 01b48b8eba5845933ffd84852f506a74ac71bf96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 10:42:51 -0400 Subject: [PATCH 006/383] chore(deps): bump github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus from 1.0.1 to 1.1.0 (#23441) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Mangaal --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c458004ef01dc..403831ba12149 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( github.com/gorilla/handlers v1.5.2 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 github.com/gosimple/slug v1.15.0 - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 + github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/go-retryablehttp v0.7.7 diff --git a/go.sum b/go.sum index bc8d35b35ea94..cff33288e1610 100644 --- a/go.sum +++ b/go.sum @@ -503,8 +503,8 @@ github.com/gregdel/pushover v1.3.1/go.mod h1:EcaO66Nn1StkpEm1iKtBTV3d2A16SoMsVER github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= From 4013520c763ffae844bf12f82d6e355871b7d0ee Mon Sep 17 00:00:00 2001 From: Mason Liu Date: Tue, 17 Jun 2025 15:55:27 +0100 Subject: [PATCH 007/383] fix: #23041 Add resource support to 'argocd proj role add-policy/remove-policy' (#23213) Signed-off-by: Mason Liu Signed-off-by: Mangaal --- cmd/argocd/commands/project.go | 2 + cmd/argocd/commands/project_role.go | 42 ++++++++++++++++--- .../commands/argocd_proj_role_add-policy.md | 16 +++++++ .../argocd_proj_role_remove-policy.md | 17 ++++++++ 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/cmd/argocd/commands/project.go b/cmd/argocd/commands/project.go index 3477d3eecb49e..bb3b5b04bc8c1 100644 --- a/cmd/argocd/commands/project.go +++ b/cmd/argocd/commands/project.go @@ -35,6 +35,7 @@ type policyOpts struct { action string permission string object string + resource string } // NewProjectCommand returns a new instance of an `argocd proj` command @@ -91,6 +92,7 @@ func addPolicyFlags(command *cobra.Command, opts *policyOpts) { command.Flags().StringVarP(&opts.action, "action", "a", "", "Action to grant/deny permission on (e.g. get, create, list, update, delete)") command.Flags().StringVarP(&opts.permission, "permission", "p", "allow", "Whether to allow or deny access to object with the action. This can only be 'allow' or 'deny'") command.Flags().StringVarP(&opts.object, "object", "o", "", "Object within the project to grant/deny access. Use '*' for a wildcard. Will want access to '/'") + command.Flags().StringVarP(&opts.resource, "resource", "r", "applications", "Resource e.g. 'applications', 'applicationsets', 'logs', 'exec', etc.") } func humanizeTimestamp(epoch int64) string { diff --git a/cmd/argocd/commands/project_role.go b/cmd/argocd/commands/project_role.go index d506afce9af21..4e4c4c898410d 100644 --- a/cmd/argocd/commands/project_role.go +++ b/cmd/argocd/commands/project_role.go @@ -19,11 +19,12 @@ import ( "github.com/argoproj/argo-cd/v3/util/errors" utilio "github.com/argoproj/argo-cd/v3/util/io" "github.com/argoproj/argo-cd/v3/util/jwt" + "github.com/argoproj/argo-cd/v3/util/rbac" "github.com/argoproj/argo-cd/v3/util/templates" ) const ( - policyTemplate = "p, proj:%s:%s, applications, %s, %s/%s, %s" + policyTemplate = "p, proj:%s:%s, %s, %s, %s/%s, %s" ) // NewProjectRoleCommand returns a new instance of the `argocd proj role` command @@ -79,11 +80,26 @@ p, proj:test-project:test-role, applications, update, test-project/project, allo JWT Tokens: ID ISSUED-AT EXPIRES-AT 1696759698 2023-10-08T11:08:18+01:00 (3 hours ago) + +# Add a new policy to allow get logs to the project +$ argocd proj role add-policy test-project test-role -a get -p allow -o project -r logs + +# Policy should be updated +$ argocd proj role get test-project test-role +Role Name: test-role +Description: +Policies: +p, proj:test-project:test-role, projects, get, test-project, allow +p, proj:test-project:test-role, applications, update, test-project/project, allow +p, proj:test-project:test-role, logs, get, test-project/project, allow +JWT Tokens: +ID ISSUED-AT EXPIRES-AT +1696759698 2023-10-08T11:08:18+01:00 (3 hours ago) `, Run: func(c *cobra.Command, args []string) { ctx := c.Context() - if len(args) != 2 { + if len(args) != 2 || !rbac.ProjectScoped[opts.resource] { c.HelpFunc()(c, args) os.Exit(1) } @@ -98,7 +114,7 @@ ID ISSUED-AT EXPIRES-AT role, roleIndex, err := proj.GetRoleByName(roleName) errors.CheckError(err) - policy := fmt.Sprintf(policyTemplate, proj.Name, role.Name, opts.action, proj.Name, opts.object, opts.permission) + policy := fmt.Sprintf(policyTemplate, proj.Name, role.Name, opts.resource, opts.action, proj.Name, opts.object, opts.permission) proj.Spec.Roles[roleIndex].Policies = append(role.Policies, policy) _, err = projIf.Update(ctx, &projectpkg.ProjectUpdateRequest{Project: proj}) @@ -122,6 +138,7 @@ Description: Policies: p, proj:test-project:test-role, projects, get, test-project, allow p, proj:test-project:test-role, applications, update, test-project/project, allow +p, proj:test-project:test-role, logs, get, test-project/project, allow JWT Tokens: ID ISSUED-AT EXPIRES-AT 1696759698 2023-10-08T11:08:18+01:00 (3 hours ago) @@ -129,6 +146,21 @@ ID ISSUED-AT EXPIRES-AT # Remove the policy to allow update to objects $ argocd proj role remove-policy test-project test-role -a update -p allow -o project +# The role should be removed now. +$ argocd proj role get test-project test-role +Role Name: test-role +Description: +Policies: +p, proj:test-project:test-role, projects, get, test-project, allow +p, proj:test-project:test-role, logs, get, test-project/project, allow +JWT Tokens: +ID ISSUED-AT EXPIRES-AT +1696759698 2023-10-08T11:08:18+01:00 (4 hours ago) + + +# Remove the logs read policy +$ argocd proj role remove-policy test-project test-role -a get -p allow -o project -r logs + # The role should be removed now. $ argocd proj role get test-project test-role Role Name: test-role @@ -142,7 +174,7 @@ ID ISSUED-AT EXPIRES-AT Run: func(c *cobra.Command, args []string) { ctx := c.Context() - if len(args) != 2 { + if len(args) != 2 || !rbac.ProjectScoped[opts.resource] { c.HelpFunc()(c, args) os.Exit(1) } @@ -157,7 +189,7 @@ ID ISSUED-AT EXPIRES-AT role, roleIndex, err := proj.GetRoleByName(roleName) errors.CheckError(err) - policyToRemove := fmt.Sprintf(policyTemplate, proj.Name, role.Name, opts.action, proj.Name, opts.object, opts.permission) + policyToRemove := fmt.Sprintf(policyTemplate, proj.Name, role.Name, opts.resource, opts.action, proj.Name, opts.object, opts.permission) duplicateIndex := -1 for i, policy := range role.Policies { if policy == policyToRemove { diff --git a/docs/user-guide/commands/argocd_proj_role_add-policy.md b/docs/user-guide/commands/argocd_proj_role_add-policy.md index 36d2b4f07c55a..eaa5b6c4f70e8 100644 --- a/docs/user-guide/commands/argocd_proj_role_add-policy.md +++ b/docs/user-guide/commands/argocd_proj_role_add-policy.md @@ -35,6 +35,21 @@ JWT Tokens: ID ISSUED-AT EXPIRES-AT 1696759698 2023-10-08T11:08:18+01:00 (3 hours ago) +# Add a new policy to allow get logs to the project +$ argocd proj role add-policy test-project test-role -a get -p allow -o project -r logs + +# Policy should be updated +$ argocd proj role get test-project test-role +Role Name: test-role +Description: +Policies: +p, proj:test-project:test-role, projects, get, test-project, allow +p, proj:test-project:test-role, applications, update, test-project/project, allow +p, proj:test-project:test-role, logs, get, test-project/project, allow +JWT Tokens: +ID ISSUED-AT EXPIRES-AT +1696759698 2023-10-08T11:08:18+01:00 (3 hours ago) + ``` ### Options @@ -44,6 +59,7 @@ ID ISSUED-AT EXPIRES-AT -h, --help help for add-policy -o, --object string Object within the project to grant/deny access. Use '*' for a wildcard. Will want access to '/' -p, --permission string Whether to allow or deny access to object with the action. This can only be 'allow' or 'deny' (default "allow") + -r, --resource string Resource e.g. 'applications', 'applicationsets', 'logs', 'exec', etc. (default "applications") ``` ### Options inherited from parent commands diff --git a/docs/user-guide/commands/argocd_proj_role_remove-policy.md b/docs/user-guide/commands/argocd_proj_role_remove-policy.md index 9de0fc478d170..d8ff627dbc8a4 100644 --- a/docs/user-guide/commands/argocd_proj_role_remove-policy.md +++ b/docs/user-guide/commands/argocd_proj_role_remove-policy.md @@ -18,6 +18,7 @@ Description: Policies: p, proj:test-project:test-role, projects, get, test-project, allow p, proj:test-project:test-role, applications, update, test-project/project, allow +p, proj:test-project:test-role, logs, get, test-project/project, allow JWT Tokens: ID ISSUED-AT EXPIRES-AT 1696759698 2023-10-08T11:08:18+01:00 (3 hours ago) @@ -25,6 +26,21 @@ ID ISSUED-AT EXPIRES-AT # Remove the policy to allow update to objects $ argocd proj role remove-policy test-project test-role -a update -p allow -o project +# The role should be removed now. +$ argocd proj role get test-project test-role +Role Name: test-role +Description: +Policies: +p, proj:test-project:test-role, projects, get, test-project, allow +p, proj:test-project:test-role, logs, get, test-project/project, allow +JWT Tokens: +ID ISSUED-AT EXPIRES-AT +1696759698 2023-10-08T11:08:18+01:00 (4 hours ago) + + +# Remove the logs read policy +$ argocd proj role remove-policy test-project test-role -a get -p allow -o project -r logs + # The role should be removed now. $ argocd proj role get test-project test-role Role Name: test-role @@ -44,6 +60,7 @@ ID ISSUED-AT EXPIRES-AT -h, --help help for remove-policy -o, --object string Object within the project to grant/deny access. Use '*' for a wildcard. Will want access to '/' -p, --permission string Whether to allow or deny access to object with the action. This can only be 'allow' or 'deny' (default "allow") + -r, --resource string Resource e.g. 'applications', 'applicationsets', 'logs', 'exec', etc. (default "applications") ``` ### Options inherited from parent commands From 924680d067cbdc428e3705a08f9c529fbe12f22d Mon Sep 17 00:00:00 2001 From: Codey Jenkins Date: Tue, 17 Jun 2025 11:19:50 -0400 Subject: [PATCH 008/383] chore: initial support for tilt based development (#22337) (#23002) Signed-off-by: Codey Jenkins Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com> Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com> Signed-off-by: Mangaal --- .gitignore | 1 + Dockerfile.tilt | 62 ++++++ Dockerfile.ui.tilt | 9 + Tiltfile | 282 ++++++++++++++++++++++++++ docs/developer-guide/tilt.md | 148 ++++++++++++++ manifests/dev-tilt/kustomization.yaml | 141 +++++++++++++ manifests/dev-tilt/namespace.yaml | 4 + manifests/dev-tilt/ui-deployment.yaml | 24 +++ manifests/dev-tilt/ui-service.yaml | 10 + mkdocs.yml | 1 + 10 files changed, 682 insertions(+) create mode 100644 Dockerfile.tilt create mode 100644 Dockerfile.ui.tilt create mode 100644 Tiltfile create mode 100644 docs/developer-guide/tilt.md create mode 100644 manifests/dev-tilt/kustomization.yaml create mode 100644 manifests/dev-tilt/namespace.yaml create mode 100644 manifests/dev-tilt/ui-deployment.yaml create mode 100644 manifests/dev-tilt/ui-service.yaml diff --git a/.gitignore b/.gitignore index b8aa4aaabcc6c..33698c9c5a1cc 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ ui/dist/app/* !ui/dist/app/gitkeep site/ *.iml +.tilt-bin/ # delve debug binaries cmd/**/debug debug.test diff --git a/Dockerfile.tilt b/Dockerfile.tilt new file mode 100644 index 0000000000000..6e1b2d4624763 --- /dev/null +++ b/Dockerfile.tilt @@ -0,0 +1,62 @@ +FROM docker.io/library/golang:1.24.1@sha256:c5adecdb7b3f8c5ca3c88648a861882849cc8b02fed68ece31e25de88ad13418 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN echo 'deb http://archive.debian.org/debian buster-backports main' >> /etc/apt/sources.list + +RUN apt-get update && apt-get install --no-install-recommends -y \ + curl \ + openssh-server \ + nginx \ + unzip \ + fcgiwrap \ + git \ + git-lfs \ + make \ + wget \ + gcc \ + sudo \ + zip \ + tini \ + gpg \ + tzdata \ + connect-proxy + +RUN go install github.com/go-delve/delve/cmd/dlv@latest + +COPY hack/install.sh hack/tool-versions.sh ./ +COPY hack/installers installers + +RUN ./install.sh helm && \ + INSTALL_PATH=/usr/local/bin ./install.sh kustomize + +COPY hack/gpg-wrapper.sh \ + hack/git-verify-wrapper.sh \ + entrypoint.sh \ + /usr/local/bin/ + +# support for mounting configuration from a configmap +WORKDIR /app/config/ssh +RUN touch ssh_known_hosts && \ + ln -s /app/config/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts + +WORKDIR /app/config +RUN mkdir -p tls && \ + mkdir -p gpg/source && \ + mkdir -p gpg/keys + +COPY .tilt-bin/argocd_linux /usr/local/bin/argocd + +RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-repo-server && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-application-controller && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-dex && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-notifications && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-commit-server + +# directory for Tilt restart file +RUN mkdir -p /tilt + +# overridden by Tiltfile +ENTRYPOINT ["/usr/bin/tini", "-s", "--", "dlv", "exec", "--continue", "--accept-multiclient", "--headless", "--listen=:2345", "--api-version=2"] \ No newline at end of file diff --git a/Dockerfile.ui.tilt b/Dockerfile.ui.tilt new file mode 100644 index 0000000000000..bef84b99b8041 --- /dev/null +++ b/Dockerfile.ui.tilt @@ -0,0 +1,9 @@ +FROM node:20 + +WORKDIR /app/ui + +COPY ui /app/ui + +RUN yarn install + +ENTRYPOINT ["yarn", "start"] \ No newline at end of file diff --git a/Tiltfile b/Tiltfile new file mode 100644 index 0000000000000..31b57323a3fad --- /dev/null +++ b/Tiltfile @@ -0,0 +1,282 @@ +load('ext://restart_process', 'docker_build_with_restart') +load('ext://uibutton', 'cmd_button', 'location') + +# add ui button in web ui to run make codegen-local (top nav) +cmd_button( + 'make codegen-local', + argv=['sh', '-c', 'make codegen-local'], + location=location.NAV, + icon_name='terminal', + text='make codegen-local', +) + +# add ui button in web ui to run make codegen-local (top nav) +cmd_button( + 'make cli-local', + argv=['sh', '-c', 'make cli-local'], + location=location.NAV, + icon_name='terminal', + text='make cli-local', +) + +# detect cluster architecture for build +cluster_version = decode_yaml(local('kubectl version -o yaml')) +platform = cluster_version['serverVersion']['platform'] +arch = platform.split('/')[1] + +# build the argocd binary on code changes +code_deps = [ + 'applicationset', + 'cmd', + 'cmpserver', + 'commitserver', + 'common', + 'controller', + 'notification-controller', + 'pkg', + 'reposerver', + 'server', + 'util', + 'go.mod', + 'go.sum', +] +local_resource( + 'build', + 'CGO_ENABLED=0 GOOS=linux GOARCH=' + arch + ' go build -gcflags="all=-N -l" -mod=readonly -o .tilt-bin/argocd_linux cmd/main.go', + deps = code_deps, + allow_parallel=True, +) + +# deploy the argocd manifests +k8s_yaml(kustomize('manifests/dev-tilt')) + +# build dev image +docker_build_with_restart( + 'argocd', + context='.', + dockerfile='Dockerfile.tilt', + entrypoint=[ + "/usr/bin/tini", + "-s", + "--", + "dlv", + "exec", + "--continue", + "--accept-multiclient", + "--headless", + "--listen=:2345", + "--api-version=2" + ], + platform=platform, + live_update=[ + sync('.tilt-bin/argocd_linux_amd64', '/usr/local/bin/argocd'), + ], + only=[ + '.tilt-bin', + 'hack', + 'entrypoint.sh', + ], + restart_file='/tilt/.restart-proc' +) + +# build image for argocd-cli jobs +docker_build( + 'argocd-job', + context='.', + dockerfile='Dockerfile.tilt', + platform=platform, + only=[ + '.tilt-bin', + 'hack', + 'entrypoint.sh', + ] +) + +# track argocd-server resources and port forward +k8s_resource( + workload='argocd-server', + objects=[ + 'argocd-server:serviceaccount', + 'argocd-server:role', + 'argocd-server:rolebinding', + 'argocd-cm:configmap', + 'argocd-cmd-params-cm:configmap', + 'argocd-gpg-keys-cm:configmap', + 'argocd-rbac-cm:configmap', + 'argocd-ssh-known-hosts-cm:configmap', + 'argocd-tls-certs-cm:configmap', + 'argocd-secret:secret', + 'argocd-server-network-policy:networkpolicy', + 'argocd-server:clusterrolebinding', + 'argocd-server:clusterrole', + ], + port_forwards=[ + '8080:8080', + '9345:2345', + '8083:8083' + ], +) + +# track crds +k8s_resource( + new_name='cluster-resources', + objects=[ + 'applications.argoproj.io:customresourcedefinition', + 'applicationsets.argoproj.io:customresourcedefinition', + 'appprojects.argoproj.io:customresourcedefinition', + 'argocd:namespace' + ] +) + +# track argocd-repo-server resources and port forward +k8s_resource( + workload='argocd-repo-server', + objects=[ + 'argocd-repo-server:serviceaccount', + 'argocd-repo-server-network-policy:networkpolicy', + ], + port_forwards=[ + '8081:8081', + '9346:2345', + '8084:8084' + ], +) + +# track argocd-redis resources and port forward +k8s_resource( + workload='argocd-redis', + objects=[ + 'argocd-redis:serviceaccount', + 'argocd-redis:role', + 'argocd-redis:rolebinding', + 'argocd-redis-network-policy:networkpolicy', + ], + port_forwards=[ + '6379:6379', + ], +) + +# track argocd-applicationset-controller resources +k8s_resource( + workload='argocd-applicationset-controller', + objects=[ + 'argocd-applicationset-controller:serviceaccount', + 'argocd-applicationset-controller-network-policy:networkpolicy', + 'argocd-applicationset-controller:role', + 'argocd-applicationset-controller:rolebinding', + 'argocd-applicationset-controller:clusterrolebinding', + 'argocd-applicationset-controller:clusterrole', + ], + port_forwards=[ + '9347:2345', + '8085:8080', + '7000:7000' + ], +) + +# track argocd-application-controller resources +k8s_resource( + workload='argocd-application-controller', + objects=[ + 'argocd-application-controller:serviceaccount', + 'argocd-application-controller-network-policy:networkpolicy', + 'argocd-application-controller:role', + 'argocd-application-controller:rolebinding', + 'argocd-application-controller:clusterrolebinding', + 'argocd-application-controller:clusterrole', + ], + port_forwards=[ + '9348:2345', + '8086:8082', + ], +) + +# track argocd-notifications-controller resources +k8s_resource( + workload='argocd-notifications-controller', + objects=[ + 'argocd-notifications-controller:serviceaccount', + 'argocd-notifications-controller-network-policy:networkpolicy', + 'argocd-notifications-controller:role', + 'argocd-notifications-controller:rolebinding', + 'argocd-notifications-cm:configmap', + 'argocd-notifications-secret:secret', + ], + port_forwards=[ + '9349:2345', + '8087:9001', + ], +) + +# track argocd-dex-server resources +k8s_resource( + workload='argocd-dex-server', + objects=[ + 'argocd-dex-server:serviceaccount', + 'argocd-dex-server-network-policy:networkpolicy', + 'argocd-dex-server:role', + 'argocd-dex-server:rolebinding', + ], +) + +# track argocd-commit-server resources +k8s_resource( + workload='argocd-commit-server', + objects=[ + 'argocd-commit-server:serviceaccount', + 'argocd-commit-server-network-policy:networkpolicy', + ], + port_forwards=[ + '9350:2345', + '8088:8087', + '8089:8086', + ], +) + +# docker for ui +docker_build( + 'argocd-ui', + context='.', + dockerfile='Dockerfile.ui.tilt', + entrypoint=['sh', '-c', 'cd /app/ui && yarn start'], + only=['ui'], + live_update=[ + sync('ui', '/app/ui'), + run('sh -c "cd /app/ui && yarn install"', trigger=['/app/ui/package.json', '/app/ui/yarn.lock']), + ], +) + +# track argocd-ui resources and port forward +k8s_resource( + workload='argocd-ui', + port_forwards=[ + '4000:4000', + ], +) + +# linting +local_resource( + 'lint', + 'make lint-local', + deps = code_deps, + allow_parallel=True, +) + +local_resource( + 'lint-ui', + 'make lint-ui-local', + deps = [ + 'ui', + ], + allow_parallel=True, +) + +local_resource( + 'vendor', + 'go mod vendor', + deps = [ + 'go.mod', + 'go.sum', + ], +) + diff --git a/docs/developer-guide/tilt.md b/docs/developer-guide/tilt.md new file mode 100644 index 0000000000000..96751fe5a4440 --- /dev/null +++ b/docs/developer-guide/tilt.md @@ -0,0 +1,148 @@ +# Tilt Development + +[Tilt](https://tilt.dev/) provides a real-time web UI that offers better visibility into logs, health status, and dependencies, making debugging easier compared to relying solely on terminal outputs. With a single `tilt up` command, developers can spin up all required services without managing multiple processes manually, simplifying the local development workflow. Tilt also integrates seamlessly with Docker and Kubernetes, allowing for efficient container-based development. Unlike goreman, which lacks dynamic config reloading, Tilt can detect and apply changes to Kubernetes YAML and Helm charts without full restarts, making it more efficient for iterative development. + +### Prerequisites +* kubernetes environment (kind, minikube, k3d, etc.) +* tilt (`brew install tilt`) +* kustomize +* kubectl + +### Running +1. Spin up environment by running `tilt up` in the root directory of the repo + * Resources will be deployed into the `argocd` namespace in the cluster that your `kubeconfig` is currently pointed to. + +2. Use `ctrl+c` to close tilt which stops watching files for changes and closes port-forwards. Everything deployed to the local cluster will be left in tact and continue to run. Run `tilt up` again to start up another session and pick up where you left off. + +### Cleanup +To remove all deployed resources in your local cluster including CRDs, run `tilt down` from the root of the repo. + +### Port Forwarding +Port forwarding is automatically setup from the cluster to localhost host for the folling ports: + +| Deployment | API | Metrics | Webhook | Debug | +|------------|-----|---------|---------|-------| +| argocd-server | 8080 | 8083 | | 9345 | +| argocd-repo-server | 8081 | 8084 | | 9346 | +| argocd-redis | 6379 | | | | +| argocd-applicationset-controller | | 8085 | 7000 | 9347 | +| argocd-application-controller | | 8086 | | 9348 | +| argocd-notifications-controller | | 8087 | | 9349 | +| argocd-commit-server | 8089 | 8088 | | 9350 | + +### Debugging ArgoCD +Each deployed pod running ArgoCD components uses delve to expose a debug port. Tilt is configured to forward each of those ports locally to `localhost`. IDEs can attach to the corresponding application to set break points and debug code running inside the cluster. + +| Deployment | Debug Host Port | +|-----------|------------| +| argocd-server | localhost:9345 | +| argocd-repo-server | localhost:9346 | +| argocd-applicationset-controller | localhost:9347 | +| argocd-application-controller | localhost:9348 | +| argocd-notifications-controller | localhost:9349 | +| argocd-commit-server | localhost:9350 | + + +#### VS Code +Add a `.vscode/launch.json` file with these configurations to support attaching to running pods corresponding to the service. + + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Connect to server", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9345, + "host": "127.0.0.1" + }, + { + "name": "Connect to repo-server", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9346, + "host": "127.0.0.1" + }, + { + "name": "Connect to applicationset-controller", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9347, + "host": "127.0.0.1" + }, + { + "name": "Connect to application-controller", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9348, + "host": "127.0.0.1" + }, + { + "name": "Connect to notifications-controller", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9349, + "host": "127.0.0.1" + }, + { + "name": "Connect to commit-server", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9350, + "host": "127.0.0.1" + } + ] +} +``` + +#### Goland +Add a `.run/remote-debugging.run.xml` file with these configurations to support attaching to running pods corresponding to the service. + +```xml + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/manifests/dev-tilt/kustomization.yaml b/manifests/dev-tilt/kustomization.yaml new file mode 100644 index 0000000000000..d5eb1926caa15 --- /dev/null +++ b/manifests/dev-tilt/kustomization.yaml @@ -0,0 +1,141 @@ +# This manifest is used by Tilt to deploy the argocd resources to the cluster. +namespace: argocd + +resources: + - namespace.yaml + - ui-deployment.yaml + - ../cluster-install-with-hydrator + +patches: + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-server + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-repo-server + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: replace + path: /spec/template/spec/initContainers/0/image + value: argocd-job + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: remove + path: /spec/template/spec/initContainers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-commit-server + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + + - target: + group: apps + version: v1 + kind: StatefulSet + name: argocd-application-controller + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-dex-server + patch: |- + - op: replace + path: /spec/template/spec/initContainers/0/image + value: argocd-job + - op: remove + path: /spec/template/spec/initContainers/0/securityContext + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-notifications-controller + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: remove + path: /spec/template/spec/securityContext + - op: add + path: /spec/template/spec/containers/0/ports + value: + - name: debug + containerPort: 2345 + - name: metrics + containerPort: 9001 + + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-applicationset-controller + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-redis + patch: |- + - op: replace + path: /spec/template/spec/initContainers/0/image + value: argocd-job + - op: remove + path: /spec/template/spec/initContainers/0/securityContext diff --git a/manifests/dev-tilt/namespace.yaml b/manifests/dev-tilt/namespace.yaml new file mode 100644 index 0000000000000..a040f2ba582a9 --- /dev/null +++ b/manifests/dev-tilt/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: argocd diff --git a/manifests/dev-tilt/ui-deployment.yaml b/manifests/dev-tilt/ui-deployment.yaml new file mode 100644 index 0000000000000..d98b7adad2cc0 --- /dev/null +++ b/manifests/dev-tilt/ui-deployment.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: argocd-ui +spec: + selector: + matchLabels: + app: argocd-ui + template: + metadata: + labels: + app: argocd-ui + spec: + containers: + - name: argocd-ui + image: argocd-ui + env: + - name: ARGOCD_API_URL + value: https://argocd-server + - name: ARGOCD_E2E_YARN_HOST + value: "0.0.0.0" + ports: + - containerPort: 4000 + name: http diff --git a/manifests/dev-tilt/ui-service.yaml b/manifests/dev-tilt/ui-service.yaml new file mode 100644 index 0000000000000..76c9c08ce5665 --- /dev/null +++ b/manifests/dev-tilt/ui-service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: argocd-ui +spec: + selector: + app: argocd-ui + ports: + - port: 4000 + targetPort: http diff --git a/mkdocs.yml b/mkdocs.yml index 76d82e85cf9e2..99a4585e10c7e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -222,6 +222,7 @@ nav: - developer-guide/extensions/ui-extensions.md - developer-guide/extensions/proxy-extensions.md - developer-guide/faq.md + - developer-guide/tilt.md - faq.md - security_considerations.md - Support: SUPPORT.md From 1dca653dd386ae5bbd13015a102aafa8d95caf18 Mon Sep 17 00:00:00 2001 From: Bob Du Date: Tue, 17 Jun 2025 23:23:51 +0800 Subject: [PATCH 009/383] docs: Clarify Google Directory API scope requirements in documentation (#23386) Signed-off-by: Bob Du Signed-off-by: Alexandre Gaudreault Co-authored-by: Alexandre Gaudreault Co-authored-by: Nitish Kumar Signed-off-by: Mangaal --- docs/operator-manual/user-management/google.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/operator-manual/user-management/google.md b/docs/operator-manual/user-management/google.md index a23becd5917be..97242d743845d 100644 --- a/docs/operator-manual/user-management/google.md +++ b/docs/operator-manual/user-management/google.md @@ -162,7 +162,7 @@ Go through the same steps as in [OpenID Connect using Dex](#openid-connect-using ### Set up Directory API access 1. Follow [Google instructions to create a service account with Domain-Wide Delegation](https://developers.google.com/admin-sdk/directory/v1/guides/delegation) - - When assigning API scopes to the service account assign **only** the `https://www.googleapis.com/auth/admin.directory.group.readonly` scope and nothing else. If you assign any other scopes, you won't be able to fetch information from the API + - When assigning API scopes to the service account, the scope must **strictly include** `https://www.googleapis.com/auth/admin.directory.group.readonly`. If you assign only the [broader scope] (https://www.googleapis.com/auth/admin.directory.group), you will not be able to retrieve data from the API - Create the credentials in JSON format and store them in a safe place, we'll need them later 2. Enable the [Admin SDK](https://console.developers.google.com/apis/library/admin.googleapis.com/) From 4860490cff05202431a5ec5be6d84d06e285639e Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Tue, 17 Jun 2025 17:46:50 +0200 Subject: [PATCH 010/383] chore(lint): enable sloppyReassign rule from go-critic (#23443) Signed-off-by: Matthieu MOREL Signed-off-by: Mangaal --- .golangci.yaml | 1 - cmpserver/plugin/config.go | 3 ++- server/application/application.go | 6 ++++-- server/applicationset/applicationset.go | 9 ++++++--- util/argo/normalizers/knowntypes_normalizer.go | 3 ++- util/cache/appstate/cache.go | 3 ++- util/db/cluster.go | 3 ++- util/db/repository.go | 3 ++- util/oci/client.go | 3 ++- 9 files changed, 22 insertions(+), 12 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index a8f5b0e60cc3b..b7a09583ba328 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -64,7 +64,6 @@ linters: - importShadow - paramTypeCombine # Leave disabled, there are too many failures to be worth fixing. - rangeValCopy - - sloppyReassign - tooManyResultsChecker - unnamedResult - whyNoLint diff --git a/cmpserver/plugin/config.go b/cmpserver/plugin/config.go index ed1ee8b5ea122..cc6a1714cf97e 100644 --- a/cmpserver/plugin/config.go +++ b/cmpserver/plugin/config.go @@ -74,7 +74,8 @@ func ReadPluginConfig(filePath string) (*PluginConfig, error) { return nil, err } - if err = ValidatePluginConfig(config); err != nil { + err = ValidatePluginConfig(config) + if err != nil { return nil, err } diff --git a/server/application/application.go b/server/application/application.go index 53fcc093a497f..abfb718a6108d 100644 --- a/server/application/application.go +++ b/server/application/application.go @@ -1067,7 +1067,8 @@ func (s *Server) Patch(ctx context.Context, q *application.ApplicationPatchReque return nil, err } - if err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplications, rbac.ActionUpdate, app.RBACName(s.ns)); err != nil { + err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplications, rbac.ActionUpdate, app.RBACName(s.ns)) + if err != nil { return nil, err } @@ -2455,7 +2456,8 @@ func (s *Server) getUnstructuredLiveResourceOrApp(ctx context.Context, rbacReque if err != nil { return nil, nil, nil, nil, err } - if err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplications, rbacRequest, app.RBACName(s.ns)); err != nil { + err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplications, rbacRequest, app.RBACName(s.ns)) + if err != nil { return nil, nil, nil, nil, err } config, err = s.getApplicationClusterConfig(ctx, app) diff --git a/server/applicationset/applicationset.go b/server/applicationset/applicationset.go index 714137033b7e2..8cdf96b214f1a 100644 --- a/server/applicationset/applicationset.go +++ b/server/applicationset/applicationset.go @@ -122,7 +122,8 @@ func (s *Server) Get(ctx context.Context, q *applicationset.ApplicationSetGetQue if err != nil { return nil, fmt.Errorf("error getting ApplicationSet: %w", err) } - if err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplicationSets, rbac.ActionGet, a.RBACName(s.ns)); err != nil { + err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplicationSets, rbac.ActionGet, a.RBACName(s.ns)) + if err != nil { return nil, err } @@ -248,7 +249,8 @@ func (s *Server) Create(ctx context.Context, q *applicationset.ApplicationSetCre if !q.Upsert { return nil, status.Errorf(codes.InvalidArgument, "existing ApplicationSet spec is different, use upsert flag to force update") } - if err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplicationSets, rbac.ActionUpdate, appset.RBACName(s.ns)); err != nil { + err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplicationSets, rbac.ActionUpdate, appset.RBACName(s.ns)) + if err != nil { return nil, err } updated, err := s.updateAppSet(ctx, existing, appset, true) @@ -347,7 +349,8 @@ func (s *Server) ResourceTree(ctx context.Context, q *applicationset.Application if err != nil { return nil, fmt.Errorf("error getting ApplicationSet: %w", err) } - if err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplicationSets, rbac.ActionGet, a.RBACName(s.ns)); err != nil { + err = s.enf.EnforceErr(ctx.Value("claims"), rbac.ResourceApplicationSets, rbac.ActionGet, a.RBACName(s.ns)) + if err != nil { return nil, err } diff --git a/util/argo/normalizers/knowntypes_normalizer.go b/util/argo/normalizers/knowntypes_normalizer.go index 97a5362c6bd53..39f4dfc475b2a 100644 --- a/util/argo/normalizers/knowntypes_normalizer.go +++ b/util/argo/normalizers/knowntypes_normalizer.go @@ -102,7 +102,8 @@ func normalize(obj map[string]any, field knownTypeField, fieldPath []string) err } items[j] = newItem } else { - if err = normalize(item, field, subPath); err != nil { + err = normalize(item, field, subPath) + if err != nil { return err } } diff --git a/util/cache/appstate/cache.go b/util/cache/appstate/cache.go index 02f57f71b442f..f501b1c8c0895 100644 --- a/util/cache/appstate/cache.go +++ b/util/cache/appstate/cache.go @@ -88,7 +88,8 @@ func (c *Cache) GetAppResourcesTree(appName string, res *appv1.ApplicationTree) if res.ShardsCount > 1 { for i := int64(1); i < res.ShardsCount; i++ { var shard appv1.ApplicationTree - if err = c.GetItem(appResourcesTreeKey(appName, i), &shard); err != nil { + err = c.GetItem(appResourcesTreeKey(appName, i), &shard) + if err != nil { return err } res.Merge(&shard) diff --git a/util/db/cluster.go b/util/db/cluster.go index a0259d98ac31d..947f2b553e160 100644 --- a/util/db/cluster.go +++ b/util/db/cluster.go @@ -112,7 +112,8 @@ func (db *db) CreateCluster(ctx context.Context, c *appv1.Cluster) (*appv1.Clust }, } - if err = clusterToSecret(c, clusterSecret); err != nil { + err = clusterToSecret(c, clusterSecret) + if err != nil { return nil, err } diff --git a/util/db/repository.go b/util/db/repository.go index 930afefd73c2f..651cecfb881b9 100644 --- a/util/db/repository.go +++ b/util/db/repository.go @@ -180,7 +180,8 @@ func (db *db) listRepositories(ctx context.Context, repoType *string, writeCreds if err != nil { return nil, err } - if err = db.enrichCredsToRepos(ctx, repositories); err != nil { + err = db.enrichCredsToRepos(ctx, repositories) + if err != nil { return nil, err } diff --git a/util/oci/client.go b/util/oci/client.go index 641db5b0b8aa7..f5c8721dd5846 100644 --- a/util/oci/client.go +++ b/util/oci/client.go @@ -434,7 +434,8 @@ func saveCompressedImageToPath(ctx context.Context, digest string, repo oras.Rea } // Remove redundant ingest folder; this is an artifact from the oras.Copy call above - if err = os.RemoveAll(path.Join(tempDir, "ingest")); err != nil { + err = os.RemoveAll(path.Join(tempDir, "ingest")) + if err != nil { return err } From b9f3696c2cb83ce216aab634a677e1f88529ce02 Mon Sep 17 00:00:00 2001 From: Oleksandr Tkachenko <44292573+korsar182@users.noreply.github.com> Date: Tue, 17 Jun 2025 18:51:05 +0300 Subject: [PATCH 011/383] fix(ui): make Name column wider (argoproj#21080) (#21375) Signed-off-by: Oleksandr Tkachenko Signed-off-by: Mangaal --- .../application-details/application-resource-list.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/src/app/applications/components/application-details/application-resource-list.tsx b/ui/src/app/applications/components/application-details/application-resource-list.tsx index 2230e31bacea1..53f92148d8a1d 100644 --- a/ui/src/app/applications/components/application-details/application-resource-list.tsx +++ b/ui/src/app/applications/components/application-details/application-resource-list.tsx @@ -59,12 +59,12 @@ export const ApplicationResourceList = (props: ApplicationResourceListProps) =>
-
NAME
+
NAME
GROUP/KIND
SYNC ORDER
NAMESPACE
{isSameKind && props.resources[0].kind === 'ReplicaSet' &&
REVISION
} -
CREATED AT
+
CREATED AT
STATUS
@@ -88,7 +88,7 @@ export const ApplicationResourceList = (props: ApplicationResourceListProps) =>
-
+
{res.name} {res.kind === 'Application' && ( @@ -128,7 +128,7 @@ export const ApplicationResourceList = (props: ApplicationResourceListProps) => ); })} -
+
{res.createdAt && ( From 4c551d219e284c70ff2b496aeca53359d54d2e2a Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Tue, 17 Jun 2025 10:23:36 -0600 Subject: [PATCH 012/383] docs: Docs usage fix (#23450) Signed-off-by: Tanner Stirrat Signed-off-by: Mangaal --- docs/user-guide/best_practices.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user-guide/best_practices.md b/docs/user-guide/best_practices.md index 718ab022f3e50..14cecb4ea292d 100644 --- a/docs/user-guide/best_practices.md +++ b/docs/user-guide/best_practices.md @@ -14,8 +14,8 @@ from your application source code, is highly recommended for the following reaso cleaner Git history of what changes were made, without the noise coming from check-ins due to normal development activity. -3. Your application may be comprised of services built from multiple Git repositories, but is - deployed as a single unit. Oftentimes, microservices applications are comprised of services +3. Your application may comprise services built from multiple Git repositories, but is + deployed as a single unit. Oftentimes, microservices applications comprise services with different versioning schemes, and release cycles (e.g. ELK, Kafka + ZooKeeper). It may not make sense to store the manifests in one of the source code repositories of a single component. From 0c950f47b31f503ea791945e415e51f1547834ac Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Tue, 17 Jun 2025 19:32:44 +0200 Subject: [PATCH 013/383] chore(lint): enable filepathJoin rule from go-critic (#23453) Signed-off-by: Matthieu MOREL Signed-off-by: Mangaal --- .golangci.yaml | 1 - applicationset/services/scm_provider/aws_codecommit.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index b7a09583ba328..62b8e31e12bea 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -59,7 +59,6 @@ linters: - deferInLoop - exitAfterDefer - exposedSyncMutex - - filepathJoin - hugeParam - importShadow - paramTypeCombine # Leave disabled, there are too many failures to be worth fixing. diff --git a/applicationset/services/scm_provider/aws_codecommit.go b/applicationset/services/scm_provider/aws_codecommit.go index 6c5f106573d9a..acc80a1076327 100644 --- a/applicationset/services/scm_provider/aws_codecommit.go +++ b/applicationset/services/scm_provider/aws_codecommit.go @@ -340,7 +340,7 @@ func toAbsolutePath(path string) string { if filepath.IsAbs(path) { return path } - return filepath.ToSlash(filepath.Join("/", path)) + return filepath.ToSlash(filepath.Join("/", path)) //nolint:gocritic // Prepend slash to have an absolute path } func createAWSDiscoveryClients(_ context.Context, role string, region string) (*resourcegroupstaggingapi.ResourceGroupsTaggingAPI, *codecommit.CodeCommit, error) { From e1afcfee98e25514a2d8dfeac6eb8087e2aca681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Roberto=20Santos?= Date: Tue, 17 Jun 2025 18:33:45 +0100 Subject: [PATCH 014/383] docs: Explain repo definition for source hydrators (#23454) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Flávio Santos Co-authored-by: Flávio Santos Signed-off-by: Mangaal --- docs/user-guide/source-hydrator.md | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/docs/user-guide/source-hydrator.md b/docs/user-guide/source-hydrator.md index 06a59f8019cae..0a13d7c93d776 100644 --- a/docs/user-guide/source-hydrator.md +++ b/docs/user-guide/source-hydrator.md @@ -6,12 +6,9 @@ Tools like Helm and Kustomize allow users to express their Kubernetes manifests (keeping it DRY - Don't Repeat Yourself). However, these tools can obscure the actual Kubernetes manifests that are applied to the cluster. -The "rendered manifest pattern" is a way to push the hydrated manifests to git before syncing them to the cluster. This +The "rendered manifest pattern" is a feature of Argo CD that allows users to push the hydrated manifests to git before syncing them to the cluster. This allows users to see the actual Kubernetes manifests that are applied to the cluster. -The source hydrator is a feature of Argo CD that allows users to push the hydrated manifests to git before syncing them -to the cluster. - ## Enabling the Source Hydrator The source hydrator is disabled by default. @@ -49,7 +46,7 @@ With hydrator: https://raw.githubusercontent.com/argoproj/argo-cd/stable/mani ## Using the Source Hydrator -To use the source hydrator, you must first install a push secret. This example uses a GitHub App for authentication, but +To use the source hydrator, you must first install a push and a pull secret. This example uses a GitHub App for authentication, but you can use [any authentication method that Argo CD supports for repository access](../operator-manual/declarative-setup.md#repositories). ```yaml @@ -61,6 +58,22 @@ metadata: labels: argocd.argoproj.io/secret-type: repository-write type: Opaque +stringData: + url: "https://github.com" + type: "git" + githubAppID: "" + githubAppInstallationID: "" + githubAppPrivateKey: | + +--- +apiVersion: v1 +kind: Secret +metadata: + name: my-pull-secret + namespace: argocd + labels: + argocd.argoproj.io/secret-type: repository +type: Opaque stringData: url: "https://github.com" type: "git" @@ -70,10 +83,11 @@ stringData: ``` -The label `argocd.argoproj.io/secret-type: repository-write` causes this Secret to be used for pushing manifests to git -instead of pulling from git. +The only difference between the secrets above, besides the resource name, is that the push secret contains the label +`argocd.argoproj.io/secret-type: repository-write`, which causes the Secret to be used for pushing manifests to git +instead of pulling from git. Argo CD requires different secrets for pushing and pulling to provide better isolation. -Once your push secret is installed, set the `spec.sourceHydrator` field of the Application. For example: +Once your secrets are installed, set the `spec.sourceHydrator` field of the Application. For example: ```yaml apiVersion: argoproj.io/v1alpha1 From 4b49708b4323e4b719719cd9d3d51ab126394903 Mon Sep 17 00:00:00 2001 From: Yann Soubeyrand <8511577+yann-soubeyrand@users.noreply.github.com> Date: Tue, 17 Jun 2025 20:18:24 +0200 Subject: [PATCH 015/383] chore: move OIDC PKCE support from UI to backend (#21729) Signed-off-by: Yann Soubeyrand <8511577+yann-soubeyrand@users.noreply.github.com> Signed-off-by: Alexandre Gaudreault Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com> Co-authored-by: Alexandre Gaudreault Signed-off-by: Mangaal --- .../assets/keycloak-configure-client-pkce.png | Bin 103126 -> 161221 bytes docs/operator-manual/upgrading/3.0-3.1.md | 18 ++ docs/operator-manual/user-management/index.md | 7 +- .../user-management/keycloak.md | 1 - server/server_test.go | 2 +- ui/package.json | 1 - ui/src/app/app.tsx | 20 +- ui/src/app/login/components/login.tsx | 16 +- ui/src/app/login/components/pkce-verify.scss | 8 - ui/src/app/login/components/pkce-verify.tsx | 47 ----- ui/src/app/login/components/utils.ts | 177 ------------------ ui/src/app/shared/models.ts | 4 - ui/yarn.lock | 5 - util/dex/config.go | 2 +- util/oidc/oidc.go | 45 +++-- util/oidc/oidc_test.go | 84 +++++++-- util/session/sessionmanager_test.go | 2 +- util/settings/settings.go | 7 + util/test/testutil.go | 13 +- 19 files changed, 146 insertions(+), 313 deletions(-) delete mode 100644 ui/src/app/login/components/pkce-verify.scss delete mode 100644 ui/src/app/login/components/pkce-verify.tsx delete mode 100644 ui/src/app/login/components/utils.ts diff --git a/docs/assets/keycloak-configure-client-pkce.png b/docs/assets/keycloak-configure-client-pkce.png index 6b6e50cefc8c1fecb8bcff0ae2b4544999ee08e8..0aff85f5322bf4a2eb7aff66bbbc1590efd7a4fa 100644 GIT binary patch literal 161221 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%0A1_# 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

-PZe}6bf#{cT1Q*QeX<_~xIyh(y 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

    -~^_j{d+aKO7ZxG{<&m!KCr)*_;ckZye59~ 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

    FtB@m-JVb3JMXHr9P0ak9(N}&M_J0Zf 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
    E{D1(}@K0~n9qVE;uno*%Pzl1rJ)qp` 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 K8U=SAz4;$@fem;7 diff --git a/docs/operator-manual/upgrading/3.0-3.1.md b/docs/operator-manual/upgrading/3.0-3.1.md index f42321435dd0d..0f01a6a8daadd 100644 --- a/docs/operator-manual/upgrading/3.0-3.1.md +++ b/docs/operator-manual/upgrading/3.0-3.1.md @@ -19,3 +19,21 @@ However, since Argo CD now sends unmodified kubeVersions to Helm, the generated The `--staticassets` directory in the API server (`/app/shared` by default) is now protected against out-of-bounds symlinks. This is to help protect against symlink attacks. If you have any symlinks in your `--staticassets` directory to a location outside the directory, they will return a 500 error starting with 3.1. + +## OpenID Connect authorization code flow with PKCE is now handled by the server instead of the UI + +Previously, when PKCE was enabled, the authorization code flow (the process which happens when you log in to Argo CD using OpenID Connect) was handled by the UI, whereas this flow was handled by the server if PKCE was not enabled. The server now always handles this flow, PKCE being enabled or not. + +### Detection + +To check whether PKCE is used or not, run the following command: + +```shell +kubectl get cm argocd-cm -o=jsonpath="{.data.oidc\.config}" | grep enablePKCEAuthentication +``` + +If it returns `"enablePKCEAuthentication": true`, then PKCE is used. + +### Remediation + +On your identity provider, ensure that the OIDC client used for Argo CD has the `/auth/callback` endpoint of your Argo CD URL (e.g. https://argocd.example.com/auth/callback) in the redirect URIs. diff --git a/docs/operator-manual/user-management/index.md b/docs/operator-manual/user-management/index.md index c8285326f300d..24bc7a4acaae1 100644 --- a/docs/operator-manual/user-management/index.md +++ b/docs/operator-manual/user-management/index.md @@ -347,10 +347,9 @@ data: # use the same clientID as the Argo CD server cliClientID: vvvvwwwwxxxxyyyyzzzz - # PKCE authentication flow processes authorization flow from browser only - default false - # uses the clientID - # make sure the Identity Provider (IdP) is public and doesn't need clientSecret - # make sure the Identity Provider (IdP) has this redirect URI registered: https://argocd.example.com/pkce/verify + # PKCE is an OIDC extension to prevent authorization code interception attacks. + # Make sure the identity provider supports it and that it is activated for Argo CD OIDC client. + # Default is false. enablePKCEAuthentication: true ``` diff --git a/docs/operator-manual/user-management/keycloak.md b/docs/operator-manual/user-management/keycloak.md index 4511dcf7f6a2b..02b0049c0b50a 100644 --- a/docs/operator-manual/user-management/keycloak.md +++ b/docs/operator-manual/user-management/keycloak.md @@ -107,7 +107,6 @@ Also you can set __Home URL__ to _/applications_ path and __Valid Post logout re The Valid Redirect URIs should be set to: - http://localhost:8085/auth/callback (needed for argo-cd cli, depends on value from [--sso-port](../../user-guide/commands/argocd_login.md)) - https://{hostname}/auth/callback -- https://{hostname}/pkce/verify ![Keycloak configure client](../../assets/keycloak-configure-client-pkce.png "Keycloak configure client") diff --git a/server/server_test.go b/server/server_test.go index f195bdeb14074..bc11f0f71c4ed 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -622,7 +622,7 @@ func getTestServer(t *testing.T, anonymousEnabled bool, withFakeSSO bool, useDex }) oidcServer := ts if !useDexForSSO { - oidcServer = testutil.GetOIDCTestServer(t) + oidcServer = testutil.GetOIDCTestServer(t, nil) } if withFakeSSO { cm.Data["url"] = ts.URL diff --git a/ui/package.json b/ui/package.json index f56b6a5ac899c..f66a38d7a3efb 100644 --- a/ui/package.json +++ b/ui/package.json @@ -31,7 +31,6 @@ "minimatch": "^3.1.2", "moment": "^2.29.4", "monaco-editor": "^0.33.0", - "oauth4webapi": "^2.3.0", "path": "^0.12.7", "prop-types": "^15.8.1", "react": "^16.9.3", diff --git a/ui/src/app/app.tsx b/ui/src/app/app.tsx index bc3629ffc5aee..54434bc15e498 100644 --- a/ui/src/app/app.tsx +++ b/ui/src/app/app.tsx @@ -1,4 +1,4 @@ -import {DataLoader, NavigationManager, NotificationType, Notifications, NotificationsManager, PageContext, Popup, PopupManager, PopupProps} from 'argo-ui'; +import {DataLoader, NavigationManager, Notifications, NotificationsManager, PageContext, Popup, PopupManager, PopupProps} from 'argo-ui'; import {createBrowserHistory} from 'history'; import * as PropTypes from 'prop-types'; import * as React from 'react'; @@ -19,8 +19,6 @@ import {hashCode} from './shared/utils'; import {Banner} from './ui-banner/ui-banner'; import userInfo from './user-info'; import {AuthSettings} from './shared/models'; -import {PKCEVerification} from './login/components/pkce-verify'; -import {getPKCERedirectURI, pkceLogin} from './login/components/utils'; import {SystemLevelExtension} from './shared/services/extensions-service'; services.viewPreferences.init(); @@ -36,8 +34,7 @@ const routes: Routes = { '/applications': {component: applications.component}, '/settings': {component: settings.component}, '/user-info': {component: userInfo.component}, - '/help': {component: help.component}, - '/pkce/verify': {component: PKCEVerification, noLayout: true} + '/help': {component: help.component} }; interface NavItem { @@ -250,18 +247,7 @@ export class App extends React.Component<{}, {popupProps: PopupProps; showVersio // If basehref is the default `/` it will become an empty string. const basehref = document.querySelector('head > base').getAttribute('href').replace(/\/$/, ''); if (isSSO) { - const authSettings = await services.authService.settings(); - - if (authSettings?.oidcConfig?.enablePKCEAuthentication) { - pkceLogin(authSettings.oidcConfig, getPKCERedirectURI().toString()).catch(err => { - this.getChildContext().apis.notifications.show({ - type: NotificationType.Error, - content: err?.message || JSON.stringify(err) - }); - }); - } else { - window.location.href = `${basehref}/auth/login?return_url=${encodeURIComponent(location.href)}`; - } + window.location.href = `${basehref}/auth/login?return_url=${encodeURIComponent(location.href)}`; } else { history.push(`/login?return_url=${encodeURIComponent(location.href)}`); } diff --git a/ui/src/app/login/components/login.tsx b/ui/src/app/login/components/login.tsx index 6d3bb97fae05c..1b6641836201b 100644 --- a/ui/src/app/login/components/login.tsx +++ b/ui/src/app/login/components/login.tsx @@ -1,4 +1,4 @@ -import {FormField, NotificationType} from 'argo-ui'; +import {FormField} from 'argo-ui'; import * as PropTypes from 'prop-types'; import * as React from 'react'; import {Form, Text} from 'react-form'; @@ -7,7 +7,6 @@ import {RouteComponentProps} from 'react-router'; import {AppContext} from '../../shared/context'; import {AuthSettings} from '../../shared/models'; import {services} from '../../shared/services'; -import {getPKCERedirectURI, pkceLogin} from './utils'; require('./login.scss'); @@ -62,18 +61,7 @@ export class Login extends React.Component, State> {

{ssoConfigured && (
- - pkceLogin(authSettings.oidcConfig, getPKCERedirectURI().toString()).catch(err => { - this.appContext.apis.notifications.show({ - type: NotificationType.Error, - content: err?.message || JSON.stringify(err) - }); - }) - } - : {href: `auth/login?return_url=${encodeURIComponent(this.state.returnUrl)}`})}> + - )} -
- -
-
+ {!yamlMode && ( + + )} +
+ +
+
+ +
+
+ +
+
+ +
+
+ + + +
+
+ ); + + const repoType = api.getFormState().values.spec.source.repoURL.startsWith('oci://') + ? 'oci' + : (api.getFormState().values.spec.source.hasOwnProperty('chart') && 'helm') || 'git'; + const sourcePanel = () => ( +
+

SOURCE

+
+
-
- -
-
- -
-
- - - -
-
- ); - - const repoType = api.getFormState().values.spec.source.repoURL.startsWith('oci://') - ? 'oci' - : (api.getFormState().values.spec.source.hasOwnProperty('chart') && 'helm') || 'git'; - const sourcePanel = () => ( -
-

SOURCE

-
-
- -
-
-
- {(repoInfo && ( - - {(repoInfo.type || 'git').toUpperCase()} - - )) || ( - ( -

- {repoType.toUpperCase()} -

- )} - qeId='application-create-dropdown-source-repository' - items={['git', 'helm', 'oci'].map((type: 'git' | 'helm' | 'oci') => ({ - title: type.toUpperCase(), - action: () => { - if (repoType !== type) { - const updatedApp = api.getFormState().values as models.Application; - if (normalizeAppSource(updatedApp, type)) { - api.setAllValues(updatedApp); - } +
+
+ {(repoInfo && ( + + {(repoInfo.type || 'git').toUpperCase()} + + )) || ( + ( +

+ {repoType.toUpperCase()} +

+ )} + qeId='application-create-dropdown-source-repository' + items={['git', 'helm', 'oci'].map((type: 'git' | 'helm' | 'oci') => ({ + title: type.toUpperCase(), + action: () => { + if (repoType !== type) { + const updatedApp = api.getFormState().values as models.Application; + if (normalizeAppSource(updatedApp, type)) { + api.setAllValues(updatedApp); } } - }))} + } + }))} + /> + )} +
+
+
+ {(repoType === 'oci' && ( + + +
+ + src.repoURL && + // TODO: for autocomplete we need to fetch paths that are used by other apps within the same project making use of the same OCI repo + new Array() + }> + {(paths: string[]) => ( + )} -
+
-
- {(repoType === 'oci' && ( + + )) || + (repoType === 'git' && (
- src.repoURL && - // TODO: for autocomplete we need to fetch paths that are used by other apps within the same project making use of the same OCI repo + (src.repoURL && + services.repos + .apps(src.repoURL, src.revision, app.metadata.name, app.spec.project) + .then(apps => Array.from(new Set(apps.map(item => item.path))).sort()) + .catch(() => new Array())) || new Array() }> - {(paths: string[]) => ( + {(apps: string[]) => ( @@ -383,241 +403,209 @@ export const ApplicationCreatePanel = (props: {
- )) || - (repoType === 'git' && ( - - -
- - (src.repoURL && - services.repos - .apps(src.repoURL, src.revision, app.metadata.name, app.spec.project) - .then(apps => Array.from(new Set(apps.map(item => item.path))).sort()) - .catch(() => new Array())) || - new Array() - }> - {(apps: string[]) => ( + )) || ( + + (src.repoURL && services.repos.charts(src.repoURL).catch(() => new Array())) || + new Array() + }> + {(charts: models.HelmChart[]) => { + const selectedChart = charts.find(chart => chart.name === api.getFormState().values.spec.source.chart); + return ( +
+
chart.name), filterSuggestions: true }} /> - )} - -
- - )) || ( - - (src.repoURL && services.repos.charts(src.repoURL).catch(() => new Array())) || - new Array() - }> - {(charts: models.HelmChart[]) => { - const selectedChart = charts.find(chart => chart.name === api.getFormState().values.spec.source.chart); - return ( -
-
- chart.name), - filterSuggestions: true - }} - /> -
-
- - -
- ); +
+ + +
+
+ ); + }} +
+ )} +
+ ); + const destinationPanel = () => ( +
+

DESTINATION

+
+ {(destinationComboValue.toUpperCase() === 'URL' && ( +
+ cluster.server), + filterSuggestions: true }} - - )} -
- ); - const destinationPanel = () => ( -
-

DESTINATION

-
- {(destinationComboValue.toUpperCase() === 'URL' && ( -
- cluster.server), - filterSuggestions: true - }} - component={AutocompleteField} - /> -
- )) || ( -
- cluster.name), - filterSuggestions: true - }} - component={AutocompleteField} - /> -
- )} -
-
- ( -

- {destinationComboValue} -

- )} - qeId='application-create-dropdown-destination' - items={['URL', 'NAME'].map((type: 'URL' | 'NAME') => ({ - title: type, - action: () => { - if (destinationComboValue !== type) { - destinationComboValue = type; - comboSwitchedFromPanel.current = true; - setDestinationFieldChanges({destFormat: type, destFormatChanged: 'changed'}); - } + component={AutocompleteField} + /> +
+ )) || ( +
+ cluster.name), + filterSuggestions: true + }} + component={AutocompleteField} + /> +
+ )} +
+
+ ( +

+ {destinationComboValue} +

+ )} + qeId='application-create-dropdown-destination' + items={['URL', 'NAME'].map((type: 'URL' | 'NAME') => ({ + title: type, + action: () => { + if (destinationComboValue !== type) { + destinationComboValue = type; + comboSwitchedFromPanel.current = true; + setDestinationFieldChanges({destFormat: type, destFormatChanged: 'changed'}); } - }))} - /> -
+ } + }))} + />
-
- -
- ); +
+ +
+
+ ); - const typePanel = () => ( - { - if (src.repoURL && src.targetRevision && (src.path || src.chart)) { - return services.repos.appDetails(src, src.appName, app.spec.project, 0, 0).catch(() => ({ - type: 'Directory', - details: {} - })); - } else { - return { - type: 'Directory', - details: {} - }; - } - }}> - {(details: models.RepoAppDetails) => { - const type = (explicitPathType && explicitPathType.path === app.spec.source.path && explicitPathType.type) || details.type; - if (details.type !== type) { - switch (type) { - case 'Helm': - details = { - type, - path: details.path, - helm: {name: '', valueFiles: [], path: '', parameters: [], fileParameters: []} - }; - break; - case 'Kustomize': - details = {type, path: details.path, kustomize: {path: ''}}; - break; - case 'Plugin': - details = {type, path: details.path, plugin: {name: '', env: []}}; - break; - // Directory - default: - details = {type, path: details.path, directory: {}}; - break; - } + const typePanel = () => ( + { + if (src.repoURL && src.targetRevision && (src.path || src.chart)) { + return services.repos.appDetails(src, src.appName, app.spec.project, 0, 0).catch(() => ({ + type: 'Directory', + details: {} + })); + } else { + return { + type: 'Directory', + details: {} + }; + } + }}> + {(details: models.RepoAppDetails) => { + const type = (explicitPathType && explicitPathType.path === app.spec.source.path && explicitPathType.type) || details.type; + if (details.type !== type) { + switch (type) { + case 'Helm': + details = { + type, + path: details.path, + helm: {name: '', valueFiles: [], path: '', parameters: [], fileParameters: []} + }; + break; + case 'Kustomize': + details = {type, path: details.path, kustomize: {path: ''}}; + break; + case 'Plugin': + details = {type, path: details.path, plugin: {name: '', env: []}}; + break; + // Directory + default: + details = {type, path: details.path, directory: {}}; + break; } - return ( - - ( -

- {type} -

- )} - qeId='application-create-dropdown-source' - items={appTypes.map(item => ({ - title: item.type, - action: () => { - setExplicitPathType({type: item.type, path: app.spec.source.path}); - normalizeTypeFields(api, item.type); - } - }))} - /> - { - api.setAllValues(updatedApp); - }} - /> -
- ); - }} -
- ); + } + return ( + + ( +

+ {type} +

+ )} + qeId='application-create-dropdown-source' + items={appTypes.map(item => ({ + title: item.type, + action: () => { + setExplicitPathType({type: item.type, path: app.spec.source.path}); + normalizeTypeFields(api, item.type); + } + }))} + /> + { + api.setAllValues(updatedApp); + }} + /> +
+ ); + }} +
+ ); - return ( - - {generalPanel()} + return ( + + {generalPanel()} - {sourcePanel()} + {sourcePanel()} - {destinationPanel()} + {destinationPanel()} - {typePanel()} - - ); - }} - - )} -
- ); - }} - - + {typePanel()} + + ); + }} + + )} +
+ ); + }} + ); }; diff --git a/ui/src/app/applications/components/application-create-panel/set-finalizer-on-application.tsx b/ui/src/app/applications/components/application-create-panel/set-finalizer-on-application.tsx index ced113d0040fe..d1e512cf9c637 100644 --- a/ui/src/app/applications/components/application-create-panel/set-finalizer-on-application.tsx +++ b/ui/src/app/applications/components/application-create-panel/set-finalizer-on-application.tsx @@ -12,29 +12,27 @@ export const SetFinalizerOnApplication = ReactForm.FormField((props: {fieldApi: const isChecked = index < 0 ? false : true; return (
- - { - const value = getValue() || []; - if (!state) { - const i = value.findIndex((item: string) => item === finalizerVal); - if (i >= 0) { - const tmp = value.slice(); - tmp.splice(i, 1); - setValue(tmp); - } - } else { + { + const value = getValue() || []; + if (!state) { + const i = value.findIndex((item: string) => item === finalizerVal); + if (i >= 0) { const tmp = value.slice(); - tmp.push(finalizerVal); + tmp.splice(i, 1); setValue(tmp); } - }} - /> - - - + } else { + const tmp = value.slice(); + tmp.push(finalizerVal); + setValue(tmp); + } + }} + /> + +
); }); diff --git a/ui/src/app/applications/components/application-deployment-history/application-deployment-history-details.tsx b/ui/src/app/applications/components/application-deployment-history/application-deployment-history-details.tsx index 41fe11fe63ca8..95c0f18630f7b 100644 --- a/ui/src/app/applications/components/application-deployment-history/application-deployment-history-details.tsx +++ b/ui/src/app/applications/components/application-deployment-history/application-deployment-history-details.tsx @@ -61,17 +61,15 @@ export const ApplicationDeploymentHistoryDetails = ({app, info, index}: props) = const getExpandedSection = (index?: number): React.ReactFragment => { return ( - -
- { - setShowParameterDetails(!showParameterDetails); - updateMap(index); - }} - /> -
-
+
+ { + setShowParameterDetails(!showParameterDetails); + updateMap(index); + }} + /> +
); }; diff --git a/ui/src/app/applications/components/application-node-info/application-node-info.tsx b/ui/src/app/applications/components/application-node-info/application-node-info.tsx index e98a56aaf14b0..62789de8ceb54 100644 --- a/ui/src/app/applications/components/application-node-info/application-node-info.tsx +++ b/ui/src/app/applications/components/application-node-info/application-node-info.tsx @@ -60,12 +60,9 @@ const RenderContainerState = (props: {container: any}) => { {' '} It exited with exit code {props.container.state.terminated.exitCode}. - )} - <> - {' '} - It is {props.container?.started ? 'started' : 'not started'} - {status === 'Completed' ? '.' : props.container?.ready ? ' and ready.' : ' and not ready.'} - + )}{' '} + It is {props.container?.started ? 'started' : 'not started'} + {status === 'Completed' ? '.' : props.container?.ready ? ' and ready.' : ' and not ready.'}
{lastState && ( <> diff --git a/ui/src/app/applications/components/application-parameters/application-parameters-source.tsx b/ui/src/app/applications/components/application-parameters/application-parameters-source.tsx index 2d494af941d3d..856e0d2c57161 100644 --- a/ui/src/app/applications/components/application-parameters/application-parameters-source.tsx +++ b/ui/src/app/applications/components/application-parameters/application-parameters-source.tsx @@ -50,29 +50,27 @@ export class ApplicationParametersSource extends React.Component (
{this.props.floatingTitle &&
{this.props.floatingTitle}
} - - this.onModeSwitch()} - noReadonlyMode={this.props.noReadonlyMode} - edit={this.props.editTop} - collapsible={this.props.collapsible} - ctx={ctx} - isTopSection={true} - disabledState={this.state.editTop || this.state.editTop === null} - disabledDelete={this.props.numberOfSources <= 1} - updateButtons={editClicked => { - this.setState({editBottom: editClicked}); - }} - deleteSource={this.props.deleteSource} - /> - + this.onModeSwitch()} + noReadonlyMode={this.props.noReadonlyMode} + edit={this.props.editTop} + collapsible={this.props.collapsible} + ctx={ctx} + isTopSection={true} + disabledState={this.state.editTop || this.state.editTop === null} + disabledDelete={this.props.numberOfSources <= 1} + updateButtons={editClicked => { + this.setState({editBottom: editClicked}); + }} + deleteSource={this.props.deleteSource} + /> {this.props.itemsTop && (
@@ -81,27 +79,25 @@ export class ApplicationParametersSource extends React.Component )} - - this.onModeSwitch()} - noReadonlyMode={this.props.noReadonlyMode} - edit={this.props.editBottom} - collapsible={this.props.collapsible} - ctx={ctx} - isTopSection={false} - disabledState={this.state.editBottom || this.state.editBottom === null} - updateButtons={editClicked => { - this.setState({editTop: editClicked}); - }} - /> - + this.onModeSwitch()} + noReadonlyMode={this.props.noReadonlyMode} + edit={this.props.editBottom} + collapsible={this.props.collapsible} + ctx={ctx} + isTopSection={false} + disabledState={this.state.editBottom || this.state.editBottom === null} + updateButtons={editClicked => { + this.setState({editTop: editClicked}); + }} + />
)} diff --git a/ui/src/app/applications/components/application-parameters/application-parameters.tsx b/ui/src/app/applications/components/application-parameters/application-parameters.tsx index a47e295c02dc3..dac7335b99939 100644 --- a/ui/src/app/applications/components/application-parameters/application-parameters.tsx +++ b/ui/src/app/applications/components/application-parameters/application-parameters.tsx @@ -318,16 +318,14 @@ export const ApplicationParameters = (props: {
{collapsible && ( - -
- { - props.handleCollapse(index, !props.collapsedSources[index]); - }} - /> -
-
+
+ { + props.handleCollapse(index, !props.collapsedSources[index]); + }} + /> +
)} - Promise.all([services.repos.list()]).then(([reposInfo]) => ({reposInfo}))}> - {({reposInfo}) => { - const repos = reposInfo.map(info => info.repo).sort(); - return ( -
-
{ - let samePath = false; - let sameChartVersion = false; - let pathError = null; - let chartError = null; - if (a.spec.source.repoURL && a.spec.source.path) { - props.appCurrent.spec.sources.forEach(source => { - if (source.repoURL === a.spec.source.repoURL && source.path === a.spec.source.path) { - samePath = true; - pathError = 'Provided path in the selected repository URL was already added to this multi-source application'; - } - }); - } - if (a.spec?.source?.repoURL && a.spec?.source?.chart) { - props.appCurrent.spec.sources.forEach(source => { - if ( - source?.repoURL === a.spec?.source?.repoURL && - source?.chart === a.spec?.source?.chart && - source?.targetRevision === a.spec?.source?.targetRevision - ) { - sameChartVersion = true; - chartError = - 'Version ' + - source?.targetRevision + - ' of chart ' + - source?.chart + - ' from the selected repository was already added to this multi-source application'; - } - }); - } - if (!samePath) { - if (!a.spec?.source?.path && !a.spec?.source?.chart && !a.spec?.source?.ref) { - pathError = 'Path or Ref is required'; + Promise.all([services.repos.list()]).then(([reposInfo]) => ({reposInfo}))}> + {({reposInfo}) => { + const repos = reposInfo.map(info => info.repo).sort(); + return ( +
+ { + let samePath = false; + let sameChartVersion = false; + let pathError = null; + let chartError = null; + if (a.spec.source.repoURL && a.spec.source.path) { + props.appCurrent.spec.sources.forEach(source => { + if (source.repoURL === a.spec.source.repoURL && source.path === a.spec.source.path) { + samePath = true; + pathError = 'Provided path in the selected repository URL was already added to this multi-source application'; } - } - if (!sameChartVersion) { - if (!a.spec?.source?.chart && !a.spec?.source?.path && !a.spec?.source?.ref) { - chartError = 'Chart is required'; + }); + } + if (a.spec?.source?.repoURL && a.spec?.source?.chart) { + props.appCurrent.spec.sources.forEach(source => { + if ( + source?.repoURL === a.spec?.source?.repoURL && + source?.chart === a.spec?.source?.chart && + source?.targetRevision === a.spec?.source?.targetRevision + ) { + sameChartVersion = true; + chartError = + 'Version ' + + source?.targetRevision + + ' of chart ' + + source?.chart + + ' from the selected repository was already added to this multi-source application'; } + }); + } + if (!samePath) { + if (!a.spec?.source?.path && !a.spec?.source?.chart && !a.spec?.source?.ref) { + pathError = 'Path or Ref is required'; } - return { - 'spec.source.repoURL': !a.spec?.source?.repoURL && 'Repository URL is required', - // eslint-disable-next-line no-prototype-builtins - 'spec.source.targetRevision': !a.spec?.source?.targetRevision && a.spec?.source?.hasOwnProperty('chart') && 'Version is required', - 'spec.source.path': pathError, - 'spec.source.chart': chartError - }; - }} - defaultValues={appInEdit} - onSubmitFailure={(errors: FormErrors) => { - let errorString: string = ''; - let i = 0; - for (const key in errors) { - if (errors[key]) { - i++; - errorString = errorString.concat(i + '. ' + errors[key] + ' '); - } + } + if (!sameChartVersion) { + if (!a.spec?.source?.chart && !a.spec?.source?.path && !a.spec?.source?.ref) { + chartError = 'Chart is required'; } - props.onSubmitFailure(errorString); - }} - onSubmit={values => { - props.updateApp(values as models.Application); - }} - getApi={props.getFormApi}> - {api => { - const repoType = api.getFormState().values.spec?.source?.repoURL.startsWith('oci://') - ? 'oci' - : (api.getFormState().values.spec?.source?.chart && 'helm') || 'git'; - const repoInfo = reposInfo.find(info => info.repo === api.getFormState().values.spec?.source?.repoURL); - if (repoInfo) { - normalizeAppSource(appInEdit, repoInfo.type || 'git'); + } + return { + 'spec.source.repoURL': !a.spec?.source?.repoURL && 'Repository URL is required', + // eslint-disable-next-line no-prototype-builtins + 'spec.source.targetRevision': !a.spec?.source?.targetRevision && a.spec?.source?.hasOwnProperty('chart') && 'Version is required', + 'spec.source.path': pathError, + 'spec.source.chart': chartError + }; + }} + defaultValues={appInEdit} + onSubmitFailure={(errors: FormErrors) => { + let errorString: string = ''; + let i = 0; + for (const key in errors) { + if (errors[key]) { + i++; + errorString = errorString.concat(i + '. ' + errors[key] + ' '); } - const sourcePanel = () => ( -
-

SOURCE

-
-
- -
-
-
- {(repoInfo && ( - - {(repoInfo.type || 'git').toUpperCase()} - - )) || ( - ( -

- {repoType.toUpperCase()} -

- )} - items={['git', 'helm', 'oci'].map((type: 'git' | 'helm' | 'oci') => ({ - title: type.toUpperCase(), - action: () => { - if (repoType !== type) { - const updatedApp = api.getFormState().values as models.Application; - if (normalizeAppSource(updatedApp, type)) { - api.setAllValues(updatedApp); - } + } + props.onSubmitFailure(errorString); + }} + onSubmit={values => { + props.updateApp(values as models.Application); + }} + getApi={props.getFormApi}> + {api => { + const repoType = api.getFormState().values.spec?.source?.repoURL.startsWith('oci://') + ? 'oci' + : (api.getFormState().values.spec?.source?.chart && 'helm') || 'git'; + const repoInfo = reposInfo.find(info => info.repo === api.getFormState().values.spec?.source?.repoURL); + if (repoInfo) { + normalizeAppSource(appInEdit, repoInfo.type || 'git'); + } + const sourcePanel = () => ( +
+

SOURCE

+
+
+ +
+
+
+ {(repoInfo && ( + + {(repoInfo.type || 'git').toUpperCase()} + + )) || ( + ( +

+ {repoType.toUpperCase()} +

+ )} + items={['git', 'helm', 'oci'].map((type: 'git' | 'helm' | 'oci') => ({ + title: type.toUpperCase(), + action: () => { + if (repoType !== type) { + const updatedApp = api.getFormState().values as models.Application; + if (normalizeAppSource(updatedApp, type)) { + api.setAllValues(updatedApp); } } - }))} + } + }))} + /> + )} +
+
+
+
+
+ +
+
+ {(repoType === 'oci' && ( + + +
+ + src.repoURL && + // TODO: for autocomplete we need to fetch paths that are used by other apps within the same project making use of the same OCI repo + new Array() + }> + {(paths: string[]) => ( + )} -
+
-
-
-
- +
+
-
- {(repoType === 'oci' && ( + + )) || + (repoType === 'git' && ( - src.repoURL && - // TODO: for autocomplete we need to fetch paths that are used by other apps within the same project making use of the same OCI repo + (src.repoURL && + (await services.repos + .apps(src.repoURL, src.revision, appInEdit.metadata.name, props.appCurrent.spec.project) + .then(apps => Array.from(new Set(apps.map(item => item.path))).sort()) + .catch(() => new Array()))) || new Array() }> - {(paths: string[]) => ( + {(apps: string[]) => ( @@ -249,178 +289,136 @@ export const SourcePanel = (props: {
- )) || - (repoType === 'git' && ( - - -
- - (src.repoURL && - (await services.repos - .apps(src.repoURL, src.revision, appInEdit.metadata.name, props.appCurrent.spec.project) - .then(apps => Array.from(new Set(apps.map(item => item.path))).sort()) - .catch(() => new Array()))) || - new Array() - }> - {(apps: string[]) => ( + )) || ( + + (src.repoURL && services.repos.charts(src.repoURL).catch(() => new Array())) || + new Array() + }> + {(charts: models.HelmChart[]) => { + const selectedChart = charts.find(chart => chart.name === api.getFormState().values.spec?.source?.chart); + return ( +
+
chart.name), filterSuggestions: true }} /> - )} - -
-
- -
- - )) || ( - - (src.repoURL && services.repos.charts(src.repoURL).catch(() => new Array())) || - new Array() - }> - {(charts: models.HelmChart[]) => { - const selectedChart = charts.find(chart => chart.name === api.getFormState().values.spec?.source?.chart); - return ( -
-
- chart.name), - filterSuggestions: true - }} - /> -
-
- - -
- ); - }} -
- )} -
- ); +
+ + +
+
+ ); + }} + + )} +
+ ); - const typePanel = () => ( - { - if (src?.repoURL && src?.targetRevision && (src?.path || src?.chart)) { - return services.repos.appDetails(src, src?.appName, props.appCurrent.spec?.project, 0, 0).catch(() => ({ - type: 'Directory', - details: {} - })); - } else { - return { - type: 'Directory', - details: {} - }; - } - }}> - {(details: models.RepoAppDetails) => { - const type = (explicitPathType && explicitPathType.path === appInEdit.spec?.source?.path && explicitPathType.type) || details.type; - if (details.type !== type) { - switch (type) { - case 'Helm': - details = { - type, - path: details.path, - helm: {name: '', valueFiles: [], path: '', parameters: [], fileParameters: []} - }; - break; - case 'Kustomize': - details = {type, path: details.path, kustomize: {path: ''}}; - break; - case 'Plugin': - details = {type, path: details.path, plugin: {name: '', env: []}}; - break; - // Directory - default: - details = {type, path: details.path, directory: {}}; - break; - } + const typePanel = () => ( + { + if (src?.repoURL && src?.targetRevision && (src?.path || src?.chart)) { + return services.repos.appDetails(src, src?.appName, props.appCurrent.spec?.project, 0, 0).catch(() => ({ + type: 'Directory', + details: {} + })); + } else { + return { + type: 'Directory', + details: {} + }; + } + }}> + {(details: models.RepoAppDetails) => { + const type = (explicitPathType && explicitPathType.path === appInEdit.spec?.source?.path && explicitPathType.type) || details.type; + if (details.type !== type) { + switch (type) { + case 'Helm': + details = { + type, + path: details.path, + helm: {name: '', valueFiles: [], path: '', parameters: [], fileParameters: []} + }; + break; + case 'Kustomize': + details = {type, path: details.path, kustomize: {path: ''}}; + break; + case 'Plugin': + details = {type, path: details.path, plugin: {name: '', env: []}}; + break; + // Directory + default: + details = {type, path: details.path, directory: {}}; + break; } - return ( - - ( -

- {type} -

- )} - items={appTypes.map(item => ({ - title: item.type, - action: () => { - setExplicitPathType({type: item.type, path: appInEdit.spec?.source?.path}); - normalizeTypeFields(api, item.type); - } - }))} - /> - { - api.setAllValues(updatedApp); - }} - /> -
- ); - }} -
- ); + } + return ( + + ( +

+ {type} +

+ )} + items={appTypes.map(item => ({ + title: item.type, + action: () => { + setExplicitPathType({type: item.type, path: appInEdit.spec?.source?.path}); + normalizeTypeFields(api, item.type); + } + }))} + /> + { + api.setAllValues(updatedApp); + }} + /> +
+ ); + }} +
+ ); - return ( - - {sourcePanel()} + return ( + + {sourcePanel()} - {typePanel()} - - ); - }} - -
- ); - }} - - + {typePanel()} + + ); + }} + +
+ ); + }} + ); }; diff --git a/ui/src/app/applications/components/application-pod-view/pod-view.tsx b/ui/src/app/applications/components/application-pod-view/pod-view.tsx index 8784da60b8bd6..b7ce3ad959697 100644 --- a/ui/src/app/applications/components/application-pod-view/pod-view.tsx +++ b/ui/src/app/applications/components/application-pod-view/pod-view.tsx @@ -122,7 +122,7 @@ export class PodView extends React.Component {
{groups.map(group => { if (group.type === 'node' && group.name === 'Unschedulable' && podPrefs.hideUnschedulable) { - return ; + return null; } return (
diff --git a/ui/src/app/applications/components/application-status-panel/application-status-panel.tsx b/ui/src/app/applications/components/application-status-panel/application-status-panel.tsx index af65bb6caa056..10ccb032a3aae 100644 --- a/ui/src/app/applications/components/application-status-panel/application-status-panel.tsx +++ b/ui/src/app/applications/components/application-status-panel/application-status-panel.tsx @@ -201,87 +201,83 @@ export const ApplicationStatusPanel = ({application, showDiff, showOperation, sh
)}
- - {sectionHeader( - { - title: 'SYNC STATUS', - helpContent: 'Whether or not the version of your app is up to date with your repo. You may wish to sync your app if it is out-of-sync.' - }, - () => showMetadataInfo(application.status.sync ? 'SYNC_STATUS_REVISION' : null) - )} -
-
- {application.status.sync.status === models.SyncStatuses.OutOfSync ? ( - showDiff && showDiff()}> - - - ) : ( - - )} -
-
{syncStatusMessage(application)}
-
-
- {application.spec.syncPolicy?.automated ? 'Auto sync is enabled.' : 'Auto sync is not enabled.'} -
- {application.status && - application.status.sync && - (hasMultipleSources - ? application.status.sync.revisions && application.status.sync.revisions[0] && application.spec.sources && !application.spec.sources[0].chart - : application.status.sync.revision && !application.spec?.source?.chart) && ( -
- -
- )} -
-
- {appOperationState && ( -
- - {sectionHeader( - { - title: 'LAST SYNC', - helpContent: - 'Whether or not your last app sync was successful. It has been ' + - daysSinceLastSynchronized + - ' days since last sync. Click for the status of that sync.' - }, - () => - showMetadataInfo( - appOperationState.syncResult && (appOperationState.syncResult.revisions || appOperationState.syncResult.revision) - ? 'OPERATION_STATE_REVISION' - : null - ) - )} -
- showOperation && showOperation()}> - {' '} + {sectionHeader( + { + title: 'SYNC STATUS', + helpContent: 'Whether or not the version of your app is up to date with your repo. You may wish to sync your app if it is out-of-sync.' + }, + () => showMetadataInfo(application.status.sync ? 'SYNC_STATUS_REVISION' : null) + )} +
+
+ {application.status.sync.status === models.SyncStatuses.OutOfSync ? ( + showDiff && showDiff()}> + - {appOperationState.syncResult && (appOperationState.syncResult.revision || appOperationState.syncResult.revisions) && ( -
- to {getAppDefaultSyncRevisionExtra(application)} -
- )} -
-
- {appOperationState.phase} -
- {(appOperationState.syncResult && operationStateRevision && ( + ) : ( + + )} +
+
{syncStatusMessage(application)}
+
+
+ {application.spec.syncPolicy?.automated ? 'Auto sync is enabled.' : 'Auto sync is not enabled.'} +
+ {application.status && + application.status.sync && + (hasMultipleSources + ? application.status.sync.revisions && application.status.sync.revisions[0] && application.spec.sources && !application.spec.sources[0].chart + : application.status.sync.revision && !application.spec?.source?.chart) && ( +
- )) ||
{appOperationState.message}
} - +
+ )} +
+ {appOperationState && ( +
+ {sectionHeader( + { + title: 'LAST SYNC', + helpContent: + 'Whether or not your last app sync was successful. It has been ' + + daysSinceLastSynchronized + + ' days since last sync. Click for the status of that sync.' + }, + () => + showMetadataInfo( + appOperationState.syncResult && (appOperationState.syncResult.revisions || appOperationState.syncResult.revision) + ? 'OPERATION_STATE_REVISION' + : null + ) + )} +
+ showOperation && showOperation()}> + {' '} + + {appOperationState.syncResult && (appOperationState.syncResult.revision || appOperationState.syncResult.revisions) && ( +
+ to {getAppDefaultSyncRevisionExtra(application)} +
+ )} +
+
+ {appOperationState.phase} +
+ {(appOperationState.syncResult && operationStateRevision && ( + + )) ||
{appOperationState.message}
}
)} {application.status.conditions && ( diff --git a/ui/src/app/applications/components/application-status-panel/revision-metadata-panel.tsx b/ui/src/app/applications/components/application-status-panel/revision-metadata-panel.tsx index b38a89ef0c4b8..4f81214e1cca4 100644 --- a/ui/src/app/applications/components/application-status-panel/revision-metadata-panel.tsx +++ b/ui/src/app/applications/components/application-status-panel/revision-metadata-panel.tsx @@ -5,7 +5,7 @@ import {services} from '../../../shared/services'; export const RevisionMetadataPanel = (props: {appName: string; appNamespace: string; type: string; revision: string; versionId: number}) => { if (props.type === 'helm' || props.type === 'oci') { - return ; + return null; } if (props.type === 'oci') { return ( 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 995f2c0a27d24..f2dd942296ef1 100644 --- a/ui/src/app/applications/components/application-summary/application-summary.tsx +++ b/ui/src/app/applications/components/application-summary/application-summary.tsx @@ -342,19 +342,17 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => { attributes.push({ title: 'URLs', view: ( - -
- {urls - .map(item => item.split('|')) - .map((parts, i) => ( - - ))} -
-
+
+ {urls + .map(item => item.split('|')) + .map((parts, i) => ( + + ))} +
) }); } @@ -493,7 +491,7 @@ export const ApplicationSummary = (props: ApplicationSummaryProps) => {
This is a multi-source app, see the Sources tab for repository URLs and source-related information. : <>} + view={hasMultipleSources ? <>This is a multi-source app, see the Sources tab for repository URLs and source-related information. : null} validate={input => ({ 'spec.project': !input.spec.project && 'Project name is required', 'spec.destination.server': !input.spec.destination.server && input.spec.destination.hasOwnProperty('server') && 'Cluster server is required', diff --git a/ui/src/app/applications/components/applications-refresh-panel/applications-refresh-panel.tsx b/ui/src/app/applications/components/applications-refresh-panel/applications-refresh-panel.tsx index 56cab7a39e982..cfdab46c618c0 100644 --- a/ui/src/app/applications/components/applications-refresh-panel/applications-refresh-panel.tsx +++ b/ui/src/app/applications/components/applications-refresh-panel/applications-refresh-panel.tsx @@ -74,30 +74,28 @@ export const ApplicationsRefreshPanel = ({show, apps, hide}: {show: boolean; app }} getApi={setForm}> {formApi => ( - -
-

Refresh app(s)

- {progress !== null && setProgress(null)} percentage={progress.percentage} title={progress.title} />} -
- -
- {RefreshTypes.map(refreshType => ( - - ))} -
+
+

Refresh app(s)

+ {progress !== null && setProgress(null)} percentage={progress.percentage} title={progress.title} />} +
+ +
+ {RefreshTypes.map(refreshType => ( + + ))}
-
- + +
)} diff --git a/ui/src/app/applications/components/applications-sync-panel/applications-sync-panel.tsx b/ui/src/app/applications/components/applications-sync-panel/applications-sync-panel.tsx index 0c97b75eb0b70..83aa01b9be9ab 100644 --- a/ui/src/app/applications/components/applications-sync-panel/applications-sync-panel.tsx +++ b/ui/src/app/applications/components/applications-sync-panel/applications-sync-panel.tsx @@ -126,30 +126,28 @@ export const ApplicationsSyncPanel = ({show, apps, hide}: {show: boolean; apps: }} getApi={setForm}> {formApi => ( - -
-

Sync app(s)

- {progress !== null && setProgress(null)} percentage={progress.percentage} title={progress.title} />} -
- -
-
- - { - formApi.setTouched('syncOptions', true); - formApi.setValue('syncOptions', opts); - }} - id='applications-sync-panel' - /> -
+
+

Sync app(s)

+ {progress !== null && setProgress(null)} percentage={progress.percentage} title={progress.title} />} +
+ +
+
+ + { + formApi.setTouched('syncOptions', true); + formApi.setValue('syncOptions', opts); + }} + id='applications-sync-panel' + /> +
- + - -
- + +
)} diff --git a/ui/src/app/applications/components/filter/filter.tsx b/ui/src/app/applications/components/filter/filter.tsx index 67e34e2c9951f..cf3b2be9e0d12 100644 --- a/ui/src/app/applications/components/filter/filter.tsx +++ b/ui/src/app/applications/components/filter/filter.tsx @@ -71,7 +71,7 @@ export const FiltersGroup = (props: {
)} - <>{props.children} + {props.children}
{props.content}
) diff --git a/ui/src/app/applications/components/pod-logs-viewer/container-selector.tsx b/ui/src/app/applications/components/pod-logs-viewer/container-selector.tsx index bcd67ead7e9ab..070e3e89ac7ee 100644 --- a/ui/src/app/applications/components/pod-logs-viewer/container-selector.tsx +++ b/ui/src/app/applications/components/pod-logs-viewer/container-selector.tsx @@ -14,7 +14,7 @@ export const ContainerSelector = ({ onClickContainer: (group: ContainerGroup, index: number, logs: string) => void; }) => { if (!containerGroups) { - return <>; + return null; } const containers = containerGroups?.reduce((acc, group) => acc.concat(group.containers), []); @@ -25,7 +25,7 @@ export const ContainerSelector = ({ const containerIndex = (n: string) => { return containerGroup(n)?.containers.findIndex(container => container.name === n); }; - if (containerNames.length <= 1) return <>; + if (containerNames.length <= 1) return null; return (