Compare commits

...

27 Commits

Author SHA1 Message Date
github-actions[bot]
6648d31671 Bump version to 2.9.0-rc3 (#16112)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2023-10-25 14:06:08 -04:00
gcp-cherry-pick-bot[bot]
82185106a2 fix(ui): log button behaviors (#15848) (#16098) (#16111)
* Fixed log button behaviors



* Fixed lint-ui issues



---------

Signed-off-by: Yi Cai <yicai@redhat.com>
Co-authored-by: Yi Cai <yicai@redhat.com>
2023-10-25 13:58:39 -04:00
gcp-cherry-pick-bot[bot]
b14837e58e fix(ui): Dark theme improvements (#15891) (#16096)
Signed-off-by: Rafal Pelczar <rafal@akuity.io>
Co-authored-by: Rafal <rafpelczar@gmail.com>
2023-10-24 13:44:43 -04:00
Victor Sollerhed
9c4a90af91 chore(deps): bump kustomize to v5.2.1 (cherry-pick 2.9) (#16082)
* kustomize v5.2.1 tool-versions

Signed-off-by: Victor Sollerhed <victor.sollerhed@pagero.com>

* kustomize v5.2.1 checksums

Signed-off-by: Victor Sollerhed <victor.sollerhed@pagero.com>

---------

Signed-off-by: Victor Sollerhed <victor.sollerhed@pagero.com>
2023-10-23 17:06:29 -04:00
gcp-cherry-pick-bot[bot]
3750adefa7 fix: auto-sync fails with 'another operation is already in progress' error (#15638) (#16078)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2023-10-23 09:03:53 -07:00
gcp-cherry-pick-bot[bot]
dc3d08e626 feat(cmp): Print stderr output from command even on success (#15921) (#15973) (#16075)
* feat(cmp): Print stderr output from command even on success



* docs(cmp): Document logging from cmp sidecard for development purposes



---------

Signed-off-by: Mathias Petermann <mathias.petermann@gmail.com>
Co-authored-by: Mathias Petermann <mathias.petermann@gmail.com>
2023-10-23 10:01:15 -04:00
gcp-cherry-pick-bot[bot]
eaa9af21d7 fix: ensure appset don't attempt to remove application kind in patch requests (#16056) (#16073)
Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2023-10-23 09:32:57 -04:00
gcp-cherry-pick-bot[bot]
55e5d6bf3e fix: helm set parameter to allow passing list parameters (#15978) (#15993)
Signed-off-by: kkk777-7 <kota.kimura0725@gmail.com>
Co-authored-by: Kota Kimura <86363983+kkk777-7@users.noreply.github.com>
2023-10-16 16:47:22 -04:00
gcp-cherry-pick-bot[bot]
85422bbb17 fix(appset): performProgressiveSyncs only when the applicationset is using it (#15299) (#15990)
Signed-off-by: Eric Blackburn <eblackburn@indeed.com>
Co-authored-by: ericblackburn <eblackburn@indeed.com>
2023-10-16 16:44:24 -04:00
gcp-cherry-pick-bot[bot]
79901a4e84 fix(ui): pod count tooltip (#15928) (#15959)
Signed-off-by: Smriti Prakash <smriti_prakash@intuit.com>
Co-authored-by: smriti0710 <smriti3prakash7@gmail.com>
Co-authored-by: Smriti Prakash <smriti_prakash@intuit.com>
2023-10-13 13:07:49 -04:00
gcp-cherry-pick-bot[bot]
5506e8520c chore(deps): bump library/golang in /test/container (#15894) (#15905)
Bumps library/golang from 1.21.1 to 1.21.3.

---
updated-dependencies:
- dependency-name: library/golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-11 11:47:01 -04:00
gcp-cherry-pick-bot[bot]
0a97e150d8 chore(deps): bump library/golang from 1.21.1 to 1.21.3 (#15895) (#15904)
Bumps library/golang from 1.21.1 to 1.21.3.

---
updated-dependencies:
- dependency-name: library/golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-11 11:41:34 -04:00
Michael Crenshaw
e1ac2f6071 test: bump k8s versions for e2e tests (#15766) (#15792)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-10-03 22:29:49 -04:00
gcp-cherry-pick-bot[bot]
8c3f38a97d docs: fix list format (#15798) (#15804)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-10-03 16:21:38 -04:00
gcp-cherry-pick-bot[bot]
8b9c448786 fix(ui): responsive topbar, filter button in application details page (#11188) (#15789) (#15796)
Signed-off-by: Julien Fuix <julienfuix@epitech.eu>
Co-authored-by: Julien <57724344+JulienFuix@users.noreply.github.com>
Co-authored-by: Julien Fuix <julienfuix@epitech.eu>
2023-10-03 11:59:16 -04:00
gcp-cherry-pick-bot[bot]
80baeb8a6c fix(plugin): remove git environment variables unavailable to plugin execution (#14998) (#15104) (#15793)
* remove git creds environment variables unavailable to plugin execution



* remove integration test asserting askpass is forwarded



---------

Signed-off-by: jmcshane <james.mcshane@superorbital.io>
Co-authored-by: James McShane <jmcshan1@gmail.com>
2023-10-03 11:48:44 -04:00
github-actions[bot]
72f7b14594 Bump version to 2.9.0-rc2 (#15791)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2023-10-03 10:00:04 -04:00
gcp-cherry-pick-bot[bot]
b9bf46dfb9 fix: address nil pointer when controller runs with sts and replicas > 1 (#15770) (#15778)
* fix: address nil pointer when controller runs with sts and replicas > 1



* fix: lint



* fix: better handle errors



---------

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
Co-authored-by: Leonardo Luz Almeida <leoluz@users.noreply.github.com>
2023-10-03 09:34:47 -04:00
gcp-cherry-pick-bot[bot]
d7c489b9cc fix: only enable dynamic cluster sharding feature explicitly (#15734) (#15772)
* fix: only enable dynamic cluster sharding feature explicitly



---------

Signed-off-by: Remington Breeze <remington@breeze.software>
Co-authored-by: Remington Breeze <remington@breeze.software>
2023-10-02 15:00:18 -04:00
gcp-cherry-pick-bot[bot]
38eb17a027 fix(application-controller): Fix panic error when trying to scale application controller shards (#15725) (#15732)
* Added error checking to determine if application controller deployment is found or not



* Fixed the informer to list deployments in namespace scope



* Fixed readiness check probe for application controller when running as deployment



---------

Signed-off-by: Anand Francis Joseph <anjoseph@redhat.com>
Co-authored-by: Anand Francis Joseph <anjoseph@redhat.com>
2023-09-29 13:45:34 -04:00
gcp-cherry-pick-bot[bot]
ea3402962f fix(action): populate all fields of Job from CronJob (#15259) (#15727) (#15730)
Signed-off-by: sergey.ladutko <sergey.ladutko@vizor-games.com>
Co-authored-by: SergeyLadutko <40435115+SergeyLadutko@users.noreply.github.com>
Co-authored-by: sergey.ladutko <sergey.ladutko@vizor-games.com>
2023-09-29 11:45:05 -04:00
gcp-cherry-pick-bot[bot]
b3fabc23cd fix(ci): free up disk space (#15683) (#15684)
* fix(ci): free up disk space



* Update .github/workflows/image-reuse.yaml




* Update .github/workflows/image-reuse.yaml



---------

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Justin Marquis <76892343+34fathombelow@users.noreply.github.com>
2023-09-26 19:37:56 -04:00
gcp-cherry-pick-bot[bot]
69d6d1064b [fix] sidebar style (#15652) (#15682)
Signed-off-by: ymktmk <ymktmk.tt@gmail.com>
Co-authored-by: ymktmk <73768462+ymktmk@users.noreply.github.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2023-09-26 18:13:25 -04:00
gcp-cherry-pick-bot[bot]
d09621d36b fix: add a not found check for application controller deployment (#15678) (#15679)
Signed-off-by: ishitasequeira <ishiseq29@gmail.com>
Co-authored-by: Ishita Sequeira <46771830+ishitasequeira@users.noreply.github.com>
2023-09-26 14:35:08 -04:00
gcp-cherry-pick-bot[bot]
728205618e chore(ci): free up disk space (#15674) (#15677)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2023-09-26 12:52:24 -04:00
gcp-cherry-pick-bot[bot]
912a2db05c fix(applicationset): cannot validate inherited project permissions (#9298) (#15026) (#15664)
* fix(applicationset): cannot validate inherited project permissions



* update tests to reflect behavior



---------

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>
Co-authored-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>
2023-09-25 18:58:03 -04:00
github-actions[bot]
d105196075 Bump version to 2.9.0-rc1 (#15663)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: crenshaw-dev <crenshaw-dev@users.noreply.github.com>
2023-09-25 18:54:33 -04:00
51 changed files with 337 additions and 223 deletions

View File

@@ -361,7 +361,7 @@ jobs:
runs-on: ubuntu-22.04
strategy:
matrix:
k3s-version: [v1.27.2, v1.26.0, v1.25.4, v1.24.3]
k3s-version: [v1.28.2, v1.27.6, v1.26.9, v1.25.14]
needs:
- build-go
env:

View File

@@ -135,6 +135,14 @@ jobs:
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
echo "GIT_TREE_STATE=$(if [ -z "`git status --porcelain`" ]; then echo "clean" ; else echo "dirty"; fi)" >> $GITHUB_ENV
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@4d9e71b726748f254fe64fa44d273194bd18ec91
with:
large-packages: false
docker-images: false
swap-storage: false
tool-cache: false
- name: Build and push container image
id: image
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 #v4.1.1

View File

@@ -4,7 +4,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:22.04@sha256:0bced47fffa3361afa981854fca
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
# Also used as the image in CI jobs so needs all dependencies
####################################################################################################
FROM docker.io/library/golang:1.21.1@sha256:2270a408c4cb38f8459839082d89afa4a2870773c509adf7641e9558167d0030 AS builder
FROM docker.io/library/golang:1.21.3@sha256:02d7116222536a5cf0fcf631f90b507758b669648e0f20186d2dc94a9b419a9b AS builder
RUN echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
@@ -101,7 +101,7 @@ RUN HOST_ARCH=$TARGETARCH NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OP
####################################################################################################
# Argo CD Build stage which performs the actual build of Argo CD binaries
####################################################################################################
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21.1@sha256:2270a408c4cb38f8459839082d89afa4a2870773c509adf7641e9558167d0030 AS argocd-build
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21.3@sha256:02d7116222536a5cf0fcf631f90b507758b669648e0f20186d2dc94a9b419a9b AS argocd-build
WORKDIR /go/src/github.com/argoproj/argo-cd

View File

@@ -1 +1 @@
2.9.0
2.9.0-rc3

View File

@@ -163,13 +163,15 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
if r.EnableProgressiveSyncs {
if applicationSetInfo.Spec.Strategy == nil && len(applicationSetInfo.Status.ApplicationStatus) > 0 {
// If appset used progressive sync but stopped, clean up the progressive sync application statuses
log.Infof("Removing %v unnecessary AppStatus entries from ApplicationSet %v", len(applicationSetInfo.Status.ApplicationStatus), applicationSetInfo.Name)
err := r.setAppSetApplicationStatus(ctx, &applicationSetInfo, []argov1alpha1.ApplicationSetApplicationStatus{})
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to clear previous AppSet application statuses for %v: %w", applicationSetInfo.Name, err)
}
} else {
} else if applicationSetInfo.Spec.Strategy != nil {
// appset uses progressive sync
applications, err := r.getCurrentApplications(ctx, applicationSetInfo)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get current applications for application set: %w", err)
@@ -439,8 +441,7 @@ func (r *ApplicationSetReconciler) validateGeneratedApplications(ctx context.Con
errorsByIndex[i] = fmt.Errorf("ApplicationSet %s contains applications with duplicate name: %s", applicationSetInfo.Name, app.Name)
continue
}
proj, err := r.ArgoAppClientset.ArgoprojV1alpha1().AppProjects(r.ArgoCDNamespace).Get(ctx, app.Spec.GetProject(), metav1.GetOptions{})
_, err := r.ArgoAppClientset.ArgoprojV1alpha1().AppProjects(r.ArgoCDNamespace).Get(ctx, app.Spec.GetProject(), metav1.GetOptions{})
if err != nil {
if apierr.IsNotFound(err) {
errorsByIndex[i] = fmt.Errorf("application references project %s which does not exist", app.Spec.Project)
@@ -454,15 +455,6 @@ func (r *ApplicationSetReconciler) validateGeneratedApplications(ctx context.Con
continue
}
conditions, err := argoutil.ValidatePermissions(ctx, &app.Spec, proj, r.ArgoDB)
if err != nil {
return nil, fmt.Errorf("error validating permissions: %s", err)
}
if len(conditions) > 0 {
errorsByIndex[i] = fmt.Errorf("application spec is invalid: %s", argoutil.FormatAppConditions(conditions))
continue
}
}
return errorsByIndex, nil

View File

@@ -1953,7 +1953,7 @@ func TestValidateGeneratedApplications(t *testing.T) {
}
}
func TestReconcilerValidationErrorBehaviour(t *testing.T) {
func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) {
scheme := runtime.NewScheme()
err := v1alpha1.AddToScheme(scheme)
@@ -1961,9 +1961,8 @@ func TestReconcilerValidationErrorBehaviour(t *testing.T) {
err = v1alpha1.AddToScheme(scheme)
assert.Nil(t, err)
defaultProject := v1alpha1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "default", Namespace: "argocd"},
Spec: v1alpha1.AppProjectSpec{SourceRepos: []string{"*"}, Destinations: []v1alpha1.ApplicationDestination{{Namespace: "*", Server: "https://good-cluster"}}},
project := v1alpha1.AppProject{
ObjectMeta: metav1.ObjectMeta{Name: "good-project", Namespace: "argocd"},
}
appSet := v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
@@ -1976,22 +1975,22 @@ func TestReconcilerValidationErrorBehaviour(t *testing.T) {
{
List: &v1alpha1.ListGenerator{
Elements: []apiextensionsv1.JSON{{
Raw: []byte(`{"cluster": "good-cluster","url": "https://good-cluster"}`),
Raw: []byte(`{"project": "good-project"}`),
}, {
Raw: []byte(`{"cluster": "bad-cluster","url": "https://bad-cluster"}`),
Raw: []byte(`{"project": "bad-project"}`),
}},
},
},
},
Template: v1alpha1.ApplicationSetTemplate{
ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
Name: "{{.cluster}}",
Name: "{{.project}}",
Namespace: "argocd",
},
Spec: v1alpha1.ApplicationSpec{
Source: &v1alpha1.ApplicationSource{RepoURL: "https://github.com/argoproj/argocd-example-apps", Path: "guestbook"},
Project: "default",
Destination: v1alpha1.ApplicationDestination{Server: "{{.url}}"},
Project: "{{.project}}",
Destination: v1alpha1.ApplicationDestination{Server: "https://kubernetes.default.svc"},
},
},
},
@@ -1999,17 +1998,9 @@ func TestReconcilerValidationErrorBehaviour(t *testing.T) {
kubeclientset := kubefake.NewSimpleClientset()
argoDBMock := dbmocks.ArgoDB{}
argoObjs := []runtime.Object{&defaultProject}
argoObjs := []runtime.Object{&project}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).Build()
goodCluster := v1alpha1.Cluster{Server: "https://good-cluster", Name: "good-cluster"}
badCluster := v1alpha1.Cluster{Server: "https://bad-cluster", Name: "bad-cluster"}
argoDBMock.On("GetCluster", mock.Anything, "https://good-cluster").Return(&goodCluster, nil)
argoDBMock.On("GetCluster", mock.Anything, "https://bad-cluster").Return(&badCluster, nil)
argoDBMock.On("ListClusters", mock.Anything).Return(&v1alpha1.ClusterList{Items: []v1alpha1.Cluster{
goodCluster,
}}, nil)
r := ApplicationSetReconciler{
Client: client,
Scheme: scheme,
@@ -2041,12 +2032,12 @@ func TestReconcilerValidationErrorBehaviour(t *testing.T) {
var app v1alpha1.Application
// make sure good app got created
err = r.Client.Get(context.TODO(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-cluster"}, &app)
err = r.Client.Get(context.TODO(), crtclient.ObjectKey{Namespace: "argocd", Name: "good-project"}, &app)
assert.NoError(t, err)
assert.Equal(t, app.Name, "good-cluster")
assert.Equal(t, app.Name, "good-project")
// make sure bad app was not created
err = r.Client.Get(context.TODO(), crtclient.ObjectKey{Namespace: "argocd", Name: "bad-cluster"}, &app)
err = r.Client.Get(context.TODO(), crtclient.ObjectKey{Namespace: "argocd", Name: "bad-project"}, &app)
assert.Error(t, err)
}

View File

@@ -10,6 +10,7 @@ import (
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
@@ -78,6 +79,12 @@ func CreateOrUpdate(ctx context.Context, c client.Client, obj client.Object, f c
return a.Namespace == b.Namespace && a.Name == b.Name && a.Server == b.Server
},
)
// make sure updated object has the same apiVersion & kind as original object
if objKind, ok := obj.(schema.ObjectKind); ok {
if existingKind, ok := existing.(schema.ObjectKind); ok {
existingKind.SetGroupVersionKind(objKind.GroupVersionKind())
}
}
if equality.DeepEqual(existing, obj) {
return controllerutil.OperationResultNone, nil

View File

@@ -45,28 +45,29 @@ const (
func NewCommand() *cobra.Command {
var (
clientConfig clientcmd.ClientConfig
appResyncPeriod int64
appHardResyncPeriod int64
repoServerAddress string
repoServerTimeoutSeconds int
selfHealTimeoutSeconds int
statusProcessors int
operationProcessors int
glogLevel int
metricsPort int
metricsCacheExpiration time.Duration
metricsAplicationLabels []string
kubectlParallelismLimit int64
cacheSource func() (*appstatecache.Cache, error)
redisClient *redis.Client
repoServerPlaintext bool
repoServerStrictTLS bool
otlpAddress string
otlpAttrs []string
applicationNamespaces []string
persistResourceHealth bool
shardingAlgorithm string
clientConfig clientcmd.ClientConfig
appResyncPeriod int64
appHardResyncPeriod int64
repoServerAddress string
repoServerTimeoutSeconds int
selfHealTimeoutSeconds int
statusProcessors int
operationProcessors int
glogLevel int
metricsPort int
metricsCacheExpiration time.Duration
metricsAplicationLabels []string
kubectlParallelismLimit int64
cacheSource func() (*appstatecache.Cache, error)
redisClient *redis.Client
repoServerPlaintext bool
repoServerStrictTLS bool
otlpAddress string
otlpAttrs []string
applicationNamespaces []string
persistResourceHealth bool
shardingAlgorithm string
enableDynamicClusterDistribution bool
)
var command = cobra.Command{
Use: cliName,
@@ -139,7 +140,7 @@ func NewCommand() *cobra.Command {
appController.InvalidateProjectsCache()
}))
kubectl := kubeutil.NewKubectl()
clusterFilter := getClusterFilter(kubeClient, settingsMgr, shardingAlgorithm)
clusterFilter := getClusterFilter(kubeClient, settingsMgr, shardingAlgorithm, enableDynamicClusterDistribution)
errors.CheckError(err)
appController, err = controller.NewApplicationController(
namespace,
@@ -204,21 +205,27 @@ func NewCommand() *cobra.Command {
command.Flags().StringSliceVar(&applicationNamespaces, "application-namespaces", env.StringsFromEnv("ARGOCD_APPLICATION_NAMESPACES", []string{}, ","), "List of additional namespaces that applications are allowed to be reconciled from")
command.Flags().BoolVar(&persistResourceHealth, "persist-resource-health", env.ParseBoolFromEnv("ARGOCD_APPLICATION_CONTROLLER_PERSIST_RESOURCE_HEALTH", true), "Enables storing the managed resources health in the Application CRD")
command.Flags().StringVar(&shardingAlgorithm, "sharding-method", env.StringFromEnv(common.EnvControllerShardingAlgorithm, common.DefaultShardingAlgorithm), "Enables choice of sharding method. Supported sharding methods are : [legacy, round-robin] ")
command.Flags().BoolVar(&enableDynamicClusterDistribution, "dynamic-cluster-distribution-enabled", env.ParseBoolFromEnv(common.EnvEnableDynamicClusterDistribution, false), "Enables dynamic cluster distribution.")
cacheSource = appstatecache.AddCacheFlagsToCmd(&command, func(client *redis.Client) {
redisClient = client
})
return &command
}
func getClusterFilter(kubeClient *kubernetes.Clientset, settingsMgr *settings.SettingsManager, shardingAlgorithm string) sharding.ClusterFilterFunction {
func getClusterFilter(kubeClient *kubernetes.Clientset, settingsMgr *settings.SettingsManager, shardingAlgorithm string, enableDynamicClusterDistribution bool) sharding.ClusterFilterFunction {
var replicas int
shard := env.ParseNumFromEnv(common.EnvControllerShard, -1, -math.MaxInt32, math.MaxInt32)
applicationControllerName := env.StringFromEnv(common.EnvAppControllerName, common.DefaultApplicationControllerName)
appControllerDeployment, _ := kubeClient.AppsV1().Deployments(settingsMgr.GetNamespace()).Get(context.Background(), applicationControllerName, metav1.GetOptions{})
appControllerDeployment, err := kubeClient.AppsV1().Deployments(settingsMgr.GetNamespace()).Get(context.Background(), applicationControllerName, metav1.GetOptions{})
if appControllerDeployment != nil && appControllerDeployment.Spec.Replicas != nil {
// if the application controller deployment was not found, the Get() call returns an empty Deployment object. So, set the variable to nil explicitly
if err != nil && kubeerrors.IsNotFound(err) {
appControllerDeployment = nil
}
if enableDynamicClusterDistribution && appControllerDeployment != nil && appControllerDeployment.Spec.Replicas != nil {
replicas = int(*appControllerDeployment.Spec.Replicas)
} else {
replicas = env.ParseNumFromEnv(common.EnvControllerReplicas, 0, 0, math.MaxInt32)
@@ -228,7 +235,7 @@ func getClusterFilter(kubeClient *kubernetes.Clientset, settingsMgr *settings.Se
if replicas > 1 {
// check for shard mapping using configmap if application-controller is a deployment
// else use existing logic to infer shard from pod name if application-controller is a statefulset
if appControllerDeployment != nil {
if enableDynamicClusterDistribution && appControllerDeployment != nil {
var err error
// retry 3 times if we find a conflict while updating shard mapping configMap.

View File

@@ -120,11 +120,16 @@ func runCommand(ctx context.Context, command Command, path string, env []string)
logCtx.Error(err.Error())
return strings.TrimSuffix(output, "\n"), err
}
logCtx = logCtx.WithFields(log.Fields{
"stderr": stderr.String(),
"command": command,
})
if len(output) == 0 {
log.WithFields(log.Fields{
"stderr": stderr.String(),
"command": command,
}).Warn("Plugin command returned zero output")
logCtx.Warn("Plugin command returned zero output")
} else {
// Log stderr even on successfull commands to help develop plugins
logCtx.Info("Plugin command successfull")
}
return strings.TrimSuffix(output, "\n"), nil

View File

@@ -224,6 +224,8 @@ const (
EnvControllerShard = "ARGOCD_CONTROLLER_SHARD"
// EnvControllerShardingAlgorithm is the distribution sharding algorithm to be used: legacy or round-robin
EnvControllerShardingAlgorithm = "ARGOCD_CONTROLLER_SHARDING_ALGORITHM"
//EnvEnableDynamicClusterDistribution enables dynamic sharding (ALPHA)
EnvEnableDynamicClusterDistribution = "ARGOCD_ENABLE_DYNAMIC_CLUSTER_DISTRIBUTION"
// EnvEnableGRPCTimeHistogramEnv enables gRPC metrics collection
EnvEnableGRPCTimeHistogramEnv = "ARGOCD_ENABLE_GRPC_TIME_HISTOGRAM"
// EnvGithubAppCredsExpirationDuration controls the caching of Github app credentials. This value is in minutes (default: 60)

View File

@@ -3,6 +3,7 @@ package controller
import (
"context"
"encoding/json"
goerrors "errors"
"fmt"
"math"
"net/http"
@@ -208,14 +209,18 @@ func NewApplicationController(
},
})
factory := informers.NewSharedInformerFactory(ctrl.kubeClientset, defaultDeploymentInformerResyncDuration)
factory := informers.NewSharedInformerFactoryWithOptions(ctrl.kubeClientset, defaultDeploymentInformerResyncDuration, informers.WithNamespace(settingsMgr.GetNamespace()))
deploymentInformer := factory.Apps().V1().Deployments()
readinessHealthCheck := func(r *http.Request) error {
applicationControllerName := env.StringFromEnv(common.EnvAppControllerName, common.DefaultApplicationControllerName)
appControllerDeployment, err := deploymentInformer.Lister().Deployments(settingsMgr.GetNamespace()).Get(applicationControllerName)
if !kubeerrors.IsNotFound(err) {
return fmt.Errorf("error retrieving Application Controller Deployment: %s", err)
if err != nil {
if kubeerrors.IsNotFound(err) {
appControllerDeployment = nil
} else {
return fmt.Errorf("error retrieving Application Controller Deployment: %s", err)
}
}
if appControllerDeployment != nil {
if appControllerDeployment.Spec.Replicas != nil && int(*appControllerDeployment.Spec.Replicas) <= 0 {
@@ -1783,6 +1788,13 @@ func (ctrl *ApplicationController) autoSync(app *appv1.Application, syncStatus *
_, err := argo.SetAppOperation(appIf, app.Name, &op)
setOpTime := time.Since(start)
if err != nil {
if goerrors.Is(err, argo.ErrAnotherOperationInProgress) {
// skipping auto-sync because another operation is in progress and was not noticed due to stale data in informer
// it is safe to skip auto-sync because it is already running
logCtx.Warnf("Failed to initiate auto-sync to %s: %v", desiredCommitSHA, err)
return nil, 0
}
logCtx.Errorf("Failed to initiate auto-sync to %s: %v", desiredCommitSHA, err)
return &appv1.ApplicationCondition{Type: appv1.ApplicationConditionSyncError, Message: err.Error()}, setOpTime
}

View File

@@ -44,6 +44,7 @@ spec:
args: [-c, 'echo "Initializing..."']
# The generate command runs in the Application source directory each time manifests are generated. Standard output
# must be ONLY valid Kubernetes Objects in either YAML or JSON. A non-zero exit code will fail manifest generation.
# To write log messages from the command, write them to stderr, it will always be displayed.
# Error output will be sent to the UI, so avoid printing sensitive information (such as secrets).
generate:
command: [sh, -c]
@@ -333,6 +334,7 @@ If you are actively developing a sidecar-installed CMP, keep a few things in min
3. CMP errors are cached by the repo-server in Redis. Restarting the repo-server Pod will not clear the cache. Always
do a "Hard Refresh" when actively developing a CMP so you have the latest output.
4. Verify your sidecar has started properly by viewing the Pod and seeing that two containers are running `kubectl get pod -l app.kubernetes.io/component=repo-server -n argocd`
5. Write log message to stderr and set the `--loglevel=info` flag in the sidecar. This will print everything written to stderr, even on successfull command execution.
### Other Common Errors

View File

@@ -17,6 +17,8 @@ which does not require a restart of the application controller pods.
## Enabling Dynamic Distribution of Clusters
This feature is disabled by default while it is in alpha. To enable it, you must set the environment `ARGOCD_ENABLE_DYNAMIC_CLUSTER_DISTRIBUTION` to true when running the Application Controller.
In order to utilize the feature, the manifests `manifests/ha/base/controller-deployment/` can be applied as a Kustomize
overlay. This overlay sets the StatefulSet replicas to `0` and deploys the application controller as a Deployment. The
dynamic distribution code automatically kicks in when the controller is deployed as a Deployment.

View File

@@ -15,58 +15,59 @@ argocd-application-controller [flags]
### Options
```
--app-hard-resync int Time period in seconds for application hard resync.
--app-resync int Time period in seconds for application resync. (default 180)
--app-state-cache-expiration duration Cache expiration for app state (default 1h0m0s)
--application-namespaces strings List of additional namespaces that applications are allowed to be reconciled from
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--default-cache-expiration duration Cache expiration default (default 24h0m0s)
--gloglevel int Set the glog logging level
-h, --help help for argocd-application-controller
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to a kube config. Only required if out-of-cluster
--kubectl-parallelism-limit int Number of allowed concurrent kubectl fork/execs. Any value less than 1 means no limit. (default 20)
--logformat string Set the logging format. One of: text|json (default "text")
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
--metrics-application-labels strings List of Application labels that will be added to the argocd_application_labels metric
--metrics-cache-expiration duration Prometheus metrics cache expiration (disabled by default. e.g. 24h0m0s)
--metrics-port int Start metrics server on given port (default 8082)
-n, --namespace string If present, the namespace scope for this CLI request
--operation-processors int Number of application operation processors (default 10)
--otlp-address string OpenTelemetry collector address to send traces to
--otlp-attrs strings List of OpenTelemetry collector extra attrs when send traces, each attribute is separated by a colon(e.g. key:value)
--password string Password for basic authentication to the API server
--persist-resource-health Enables storing the managed resources health in the Application CRD (default true)
--proxy-url string If provided, this URL will be used to connect via proxy
--redis string Redis server hostname and port (e.g. argocd-redis:6379).
--redis-ca-certificate string Path to Redis server CA certificate (e.g. /etc/certs/redis/ca.crt). If not specified, system trusted CAs will be used for server certificate validation.
--redis-client-certificate string Path to Redis client certificate (e.g. /etc/certs/redis/client.crt).
--redis-client-key string Path to Redis client key (e.g. /etc/certs/redis/client.crt).
--redis-compress string Enable compression for data sent to Redis with the required compression algorithm. (possible values: gzip, none) (default "gzip")
--redis-insecure-skip-tls-verify Skip Redis server certificate validation.
--redis-use-tls Use TLS when connecting to Redis.
--redisdb int Redis database.
--repo-server string Repo server address. (default "argocd-repo-server:8081")
--repo-server-plaintext Disable TLS on connections to repo server
--repo-server-strict-tls Whether to use strict validation of the TLS cert presented by the repo server
--repo-server-timeout-seconds int Repo server RPC call timeout seconds. (default 60)
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--self-heal-timeout-seconds int Specifies timeout between application self heal attempts (default 5)
--sentinel stringArray Redis sentinel hostname and port (e.g. argocd-redis-ha-announce-0:6379).
--sentinelmaster string Redis sentinel master group name. (default "master")
--server string The address and port of the Kubernetes API server
--sharding-method string Enables choice of sharding method. Supported sharding methods are : [legacy, round-robin] (default "legacy")
--status-processors int Number of application status processors (default 20)
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
--app-hard-resync int Time period in seconds for application hard resync.
--app-resync int Time period in seconds for application resync. (default 180)
--app-state-cache-expiration duration Cache expiration for app state (default 1h0m0s)
--application-namespaces strings List of additional namespaces that applications are allowed to be reconciled from
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--default-cache-expiration duration Cache expiration default (default 24h0m0s)
--dynamic-cluster-distribution-enabled Enables dynamic cluster distribution.
--gloglevel int Set the glog logging level
-h, --help help for argocd-application-controller
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to a kube config. Only required if out-of-cluster
--kubectl-parallelism-limit int Number of allowed concurrent kubectl fork/execs. Any value less than 1 means no limit. (default 20)
--logformat string Set the logging format. One of: text|json (default "text")
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
--metrics-application-labels strings List of Application labels that will be added to the argocd_application_labels metric
--metrics-cache-expiration duration Prometheus metrics cache expiration (disabled by default. e.g. 24h0m0s)
--metrics-port int Start metrics server on given port (default 8082)
-n, --namespace string If present, the namespace scope for this CLI request
--operation-processors int Number of application operation processors (default 10)
--otlp-address string OpenTelemetry collector address to send traces to
--otlp-attrs strings List of OpenTelemetry collector extra attrs when send traces, each attribute is separated by a colon(e.g. key:value)
--password string Password for basic authentication to the API server
--persist-resource-health Enables storing the managed resources health in the Application CRD (default true)
--proxy-url string If provided, this URL will be used to connect via proxy
--redis string Redis server hostname and port (e.g. argocd-redis:6379).
--redis-ca-certificate string Path to Redis server CA certificate (e.g. /etc/certs/redis/ca.crt). If not specified, system trusted CAs will be used for server certificate validation.
--redis-client-certificate string Path to Redis client certificate (e.g. /etc/certs/redis/client.crt).
--redis-client-key string Path to Redis client key (e.g. /etc/certs/redis/client.crt).
--redis-compress string Enable compression for data sent to Redis with the required compression algorithm. (possible values: gzip, none) (default "gzip")
--redis-insecure-skip-tls-verify Skip Redis server certificate validation.
--redis-use-tls Use TLS when connecting to Redis.
--redisdb int Redis database.
--repo-server string Repo server address. (default "argocd-repo-server:8081")
--repo-server-plaintext Disable TLS on connections to repo server
--repo-server-strict-tls Whether to use strict validation of the TLS cert presented by the repo server
--repo-server-timeout-seconds int Repo server RPC call timeout seconds. (default 60)
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--self-heal-timeout-seconds int Specifies timeout between application self heal attempts (default 5)
--sentinel stringArray Redis sentinel hostname and port (e.g. argocd-redis-ha-announce-0:6379).
--sentinelmaster string Redis sentinel master group name. (default "master")
--server string The address and port of the Kubernetes API server
--sharding-method string Enables choice of sharding method. Supported sharding methods are : [legacy, round-robin] (default "legacy")
--status-processors int Number of application status processors (default 20)
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
```

View File

@@ -1,6 +1,5 @@
| Argo CD version | Kubernetes versions |
|-----------------|---------------------|
| 2.9 | v1.28, v1.27, v1.26, v1.25 |
| 2.8 | v1.27, v1.26, v1.25, v1.24 |
| 2.7 | v1.26, v1.25, v1.24, v1.23 |
| 2.6 | v1.24, v1.23, v1.22 |
| 2.5 | v1.24, v1.23, v1.22 |

View File

@@ -31,6 +31,7 @@ This proposal is experimental, meaning after trying a single bounty, we will rev
#### Creating a Bounty
A bounty is a special proposal created under `docs/proposals/feature-bounties`.
* A bounty proposal may only be created by an existing Argo maintainer.
* The proposal document must be reviewed in regular maintainer meetings and an invitation for feedback will provide 7-days to comment.
* Bounty should have approval with [lazy-consensus](https://community.apache.org/committers/lazyConsensus.html)

View File

@@ -0,0 +1 @@
b7aba749da75d33e6fea49a5098747d379abc45583ff5cd16e2356127a396549 kustomize_5.2.1_darwin_amd64.tar.gz

View File

@@ -0,0 +1 @@
f6a5f3cffd45bac585a0c80b5ed855c2b72d932a1d6e8e7c87aae3be4eba5750 kustomize_5.2.1_darwin_arm64.tar.gz

View File

@@ -0,0 +1 @@
88346543206b889f9287c0b92c70708040ecd5aad54dd33019c4d6579cd24de8 kustomize_5.2.1_linux_amd64.tar.gz

View File

@@ -0,0 +1 @@
5566f7badece5a72d42075d8dffa6296a228966dd6ac2390de7afbb9675c3aaa kustomize_5.2.1_linux_arm64.tar.gz

View File

@@ -0,0 +1 @@
82d732cf624b6fa67dfabe751e9a1510e2d08605996b1b130b4c0f5b835b130e kustomize_5.2.1_linux_ppc64le.tar.gz

View File

@@ -0,0 +1 @@
d94cb97a2776b4685ab41233dfd5f0b426f399d2fce87d2b69e1ce4907f3aad2 kustomize_5.2.1_linux_s390x.tar.gz

View File

@@ -14,5 +14,5 @@
helm3_version=3.12.1
kubectl_version=1.17.8
kubectx_version=0.6.3
kustomize5_version=5.1.0
kustomize5_version=5.2.1
protoc_version=3.17.3

View File

@@ -5,7 +5,7 @@ kind: Kustomization
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: latest
newTag: v2.9.0-rc3
resources:
- ./application-controller
- ./dex

View File

@@ -20742,7 +20742,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -21042,7 +21042,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -21094,7 +21094,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -21313,7 +21313,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -12,4 +12,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: latest
newTag: v2.9.0-rc3

View File

@@ -12,7 +12,7 @@ patches:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: latest
newTag: v2.9.0-rc3
resources:
- ../../base/application-controller
- ../../base/applicationset-controller

View File

@@ -1094,7 +1094,13 @@ spec:
args:
- /readonly/haproxy_init.sh
securityContext:
null
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: config-volume
mountPath: /readonly
@@ -1106,7 +1112,13 @@ spec:
image: haproxy:2.6.14-alpine
imagePullPolicy: IfNotPresent
securityContext:
null
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
livenessProbe:
httpGet:
path: /healthz
@@ -1204,7 +1216,14 @@ spec:
args:
- /readonly-config/init.sh
securityContext:
null
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
env:
- name: SENTINEL_ID_0
value: 3c0d9c0320bb34888c2df5757c718ce6ca992ce6
@@ -1229,7 +1248,14 @@ spec:
args:
- /data/conf/redis.conf
securityContext:
null
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 15
@@ -1279,7 +1305,14 @@ spec:
args:
- /data/conf/sentinel.conf
securityContext:
null
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 15
@@ -1323,7 +1356,14 @@ spec:
args:
- /readonly-config/fix-split-brain.sh
securityContext:
null
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
env:
- name: SENTINEL_ID_0
value: 3c0d9c0320bb34888c2df5757c718ce6ca992ce6

View File

@@ -21998,7 +21998,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -22121,7 +22121,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -22191,7 +22191,7 @@ spec:
key: notificationscontroller.log.level
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -22522,7 +22522,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -22574,7 +22574,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -22863,7 +22863,7 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -23109,7 +23109,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -1654,7 +1654,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1777,7 +1777,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1847,7 +1847,7 @@ spec:
key: notificationscontroller.log.level
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2178,7 +2178,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2230,7 +2230,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2519,7 +2519,7 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2765,7 +2765,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -21093,7 +21093,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -21216,7 +21216,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -21286,7 +21286,7 @@ spec:
key: notificationscontroller.log.level
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -21568,7 +21568,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -21620,7 +21620,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -21907,7 +21907,7 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -22153,7 +22153,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -749,7 +749,7 @@ spec:
key: applicationsetcontroller.allowed.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -872,7 +872,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -942,7 +942,7 @@ spec:
key: notificationscontroller.log.level
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1224,7 +1224,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1276,7 +1276,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1563,7 +1563,7 @@ spec:
key: server.enable.proxy.extension
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -1809,7 +1809,7 @@ spec:
key: controller.kubectl.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:latest
image: quay.io/argoproj/argocd:v2.9.0-rc3
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -1381,7 +1381,7 @@ func GenerateManifests(ctx context.Context, appPath, repoRoot, revision string,
pluginName = q.ApplicationSource.Plugin.Name
}
// if pluginName is provided it has to be `<metadata.name>-<spec.version>` or just `<metadata.name>` if plugin version is empty
targetObjs, err = runConfigManagementPluginSidecars(ctx, appPath, repoRoot, pluginName, env, q, q.Repo.GetGitCreds(gitCredsStore), opt.cmpTarDoneCh, opt.cmpTarExcludedGlobs)
targetObjs, err = runConfigManagementPluginSidecars(ctx, appPath, repoRoot, pluginName, env, q, opt.cmpTarDoneCh, opt.cmpTarExcludedGlobs)
if err != nil {
err = fmt.Errorf("plugin sidecar failed. %s", err.Error())
}
@@ -1845,25 +1845,17 @@ func makeJsonnetVm(appPath string, repoRoot string, sourceJsonnet v1alpha1.Appli
return vm, nil
}
func getPluginEnvs(env *v1alpha1.Env, q *apiclient.ManifestRequest, creds git.Creds) ([]string, error) {
func getPluginEnvs(env *v1alpha1.Env, q *apiclient.ManifestRequest) ([]string, error) {
envVars := env.Environ()
envVars = append(envVars, "KUBE_VERSION="+text.SemVer(q.KubeVersion))
envVars = append(envVars, "KUBE_API_VERSIONS="+strings.Join(q.ApiVersions, ","))
return getPluginParamEnvs(envVars, q.ApplicationSource.Plugin, creds)
return getPluginParamEnvs(envVars, q.ApplicationSource.Plugin)
}
// getPluginParamEnvs gets environment variables for plugin parameter announcement generation.
func getPluginParamEnvs(envVars []string, plugin *v1alpha1.ApplicationSourcePlugin, creds git.Creds) ([]string, error) {
func getPluginParamEnvs(envVars []string, plugin *v1alpha1.ApplicationSourcePlugin) ([]string, error) {
env := envVars
if creds != nil {
closer, environ, err := creds.Environ()
if err != nil {
return nil, err
}
defer func() { _ = closer.Close() }()
env = append(env, environ...)
}
parsedEnv := make(v1alpha1.Env, len(env))
for i, v := range env {
@@ -1890,9 +1882,9 @@ func getPluginParamEnvs(envVars []string, plugin *v1alpha1.ApplicationSourcePlug
return env, nil
}
func runConfigManagementPluginSidecars(ctx context.Context, appPath, repoPath, pluginName string, envVars *v1alpha1.Env, q *apiclient.ManifestRequest, creds git.Creds, tarDoneCh chan<- bool, tarExcludedGlobs []string) ([]*unstructured.Unstructured, error) {
func runConfigManagementPluginSidecars(ctx context.Context, appPath, repoPath, pluginName string, envVars *v1alpha1.Env, q *apiclient.ManifestRequest, tarDoneCh chan<- bool, tarExcludedGlobs []string) ([]*unstructured.Unstructured, error) {
// compute variables.
env, err := getPluginEnvs(envVars, q, creds)
env, err := getPluginEnvs(envVars, q)
if err != nil {
return nil, err
}
@@ -2134,8 +2126,6 @@ func populateKustomizeAppDetails(res *apiclient.RepoAppDetailsResponse, q *apicl
func populatePluginAppDetails(ctx context.Context, res *apiclient.RepoAppDetailsResponse, appPath string, repoPath string, q *apiclient.RepoServerAppDetailsQuery, store git.CredsStore, tarExcludedGlobs []string) error {
res.Plugin = &apiclient.PluginAppSpec{}
creds := q.Repo.GetGitCreds(store)
envVars := []string{
fmt.Sprintf("ARGOCD_APP_NAME=%s", q.AppName),
fmt.Sprintf("ARGOCD_APP_SOURCE_REPO_URL=%s", q.Repo.Repo),
@@ -2143,7 +2133,7 @@ func populatePluginAppDetails(ctx context.Context, res *apiclient.RepoAppDetails
fmt.Sprintf("ARGOCD_APP_SOURCE_TARGET_REVISION=%s", q.Source.TargetRevision),
}
env, err := getPluginParamEnvs(envVars, q.Source.Plugin, creds)
env, err := getPluginParamEnvs(envVars, q.Source.Plugin)
if err != nil {
return fmt.Errorf("failed to get env vars for plugin: %w", err)
}

View File

@@ -47,11 +47,7 @@ ownerRef.uid = obj.metadata.uid
job.metadata.ownerReferences = {}
job.metadata.ownerReferences[1] = ownerRef
job.spec = {}
job.spec.suspend = false
job.spec.template = {}
job.spec.template.metadata = deepCopy(obj.spec.jobTemplate.spec.template.metadata)
job.spec.template.spec = deepCopy(obj.spec.jobTemplate.spec.template.spec)
job.spec = deepCopy(obj.spec.jobTemplate.spec)
local impactedResource = {}
impactedResource.operation = "create"

View File

@@ -13,6 +13,7 @@ spec:
annotations:
my: annotation
spec:
ttlSecondsAfterFinished: 100
template:
metadata:
labels:

View File

@@ -10,6 +10,7 @@
annotations:
my: annotation
spec:
ttlSecondsAfterFinished: 100
template:
metadata:
labels:

View File

@@ -8,7 +8,7 @@ RUN ln -s /usr/lib/$(uname -m)-linux-gnu /usr/lib/linux-gnu
# Please make sure to also check the contained yarn version and update the references below when upgrading this image's version
FROM docker.io/library/node:20.7.0@sha256:f08c20b9f9c55dd47b1841793f0ee480c5395aa165cd02edfd68b068ed64bfb5 as node
FROM docker.io/library/golang:1.21.1@sha256:2270a408c4cb38f8459839082d89afa4a2870773c509adf7641e9558167d0030 as golang
FROM docker.io/library/golang:1.21.3@sha256:02d7116222536a5cf0fcf631f90b507758b669648e0f20186d2dc94a9b419a9b as golang
FROM docker.io/library/registry:2.8@sha256:41f413c22d6156587e2a51f3e80c09808b8c70e82be149b82b5e0196a88d49b4 as registry

View File

@@ -39,12 +39,7 @@ func TestCustomToolWithGitCreds(t *testing.T) {
Then().
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(HealthIs(health.HealthStatusHealthy)).
And(func(app *Application) {
output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.GitAskpass}")
assert.NoError(t, err)
assert.Equal(t, "argocd", output)
})
Expect(HealthIs(health.HealthStatusHealthy))
}
// make sure we can echo back the Git creds
@@ -70,11 +65,6 @@ func TestCustomToolWithGitCredsTemplate(t *testing.T) {
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(HealthIs(health.HealthStatusHealthy)).
And(func(app *Application) {
output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.GitAskpass}")
assert.NoError(t, err)
assert.Equal(t, "argocd", output)
}).
And(func(app *Application) {
output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.GitUsername}")
assert.NoError(t, err)

View File

@@ -217,7 +217,9 @@ export class App extends React.Component<
</Helmet>
<PageContext.Provider value={{title: 'Argo CD'}}>
<Provider value={{history, popup: this.popupManager, notifications: this.notificationsManager, navigation: this.navigationManager, baseHref: base}}>
{this.state.popupProps && <Popup {...this.state.popupProps} />}
<DataLoader load={() => services.viewPreferences.getPreferences()}>
{pref => <div className={pref.theme ? 'theme-' + pref.theme : 'theme-light'}>{this.state.popupProps && <Popup {...this.state.popupProps} />}</div>}
</DataLoader>
<AuthSettingsCtx.Provider value={this.state.authSettings}>
<Router history={history}>
<Switch>

View File

@@ -1,5 +1,6 @@
@import 'node_modules/argo-ui/src/styles/config';
@import 'node_modules/foundation-sites/scss/util/util';
@import 'node_modules/argo-ui/src/styles/theme';
@import '../../../shared/config.scss';
$header: 120px;
@@ -154,7 +155,7 @@ $header: 120px;
}
}
@media screen and (max-width: map-get($breakpoints, xlarge)) {
@media screen and (max-width: map-get($breakpoints, xxlarge)) {
.page__content-wrapper {
min-height: calc(100vh - 3 * 50px);
}
@@ -211,9 +212,14 @@ $header: 120px;
z-index: 1;
padding: 5px;
display: inline-block;
background-color: $argo-color-gray-1;
box-shadow: 1px 1px 3px $argo-color-gray-5;
position: absolute;
@include themify($themes) {
background: themed('background-2');
}
a {
padding: 5px;
margin: 2px;
@@ -255,7 +261,9 @@ $header: 120px;
}
.separator {
border-right: 1px solid $argo-color-gray-4;
@include themify($themes) {
border-right: 1px solid themed('border');
}
padding-top: 6px;
padding-bottom: 6px;
}

View File

@@ -459,7 +459,8 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{app
<Tooltip
content={AppUtils.userMsgsList[showToolTip?.msgKey] || 'Group Nodes'}
visible={pref.groupNodes && showToolTip !== undefined && !showToolTip?.display}
duration={showToolTip?.duration}>
duration={showToolTip?.duration}
zIndex={1}>
<a
className={`group-nodes-button group-nodes-button${!pref.groupNodes ? '' : '-on'}`}
title={pref.view === 'tree' ? 'Group Nodes' : 'Collapse Pods'}

View File

@@ -79,6 +79,10 @@
border: 1px solid transparent;
cursor: pointer;
.theme-dark & {
box-shadow: 1px 1px 1px $argo-color-gray-7;
}
.icon {
font-size: 2em;
}
@@ -120,6 +124,10 @@
}
margin-top: 9px;
margin-left: 215px;
.theme-dark & {
box-shadow: 1px 1px 1px $argo-color-gray-7;
}
}
&--podgroup--expansion {
@@ -131,6 +139,10 @@
box-shadow: 1px 1px 1px $argo-color-gray-4;
background-color: white;
margin-left: 215px;
.theme-dark & {
box-shadow: 1px 1px 1px $argo-color-gray-7;
}
}
&--pod {
@@ -348,8 +360,12 @@
border-radius: 33px;
left: -20px;
top: -8px;
border: 4px solid white;
text-align: center;
@include themify($themes) {
border: 4px solid themed('background-2');
}
i {
color: $white-color;
line-height: 56px;

View File

@@ -101,7 +101,9 @@
}
&:not(:first-child) {
border-left: 1px solid $argo-color-gray-3;
@include themify($themes) {
border-left: 1px solid themed('border');
}
}
& {

View File

@@ -118,9 +118,9 @@
}
&__search {
border: 1px solid $argo-color-gray-4;
@include themify($themes) {
background-color: themed('light-argo-gray-2');
border: 1px solid themed('border');
}
border-radius: 7px;
position: relative;

View File

@@ -1,7 +1,7 @@
import {DataLoader} from 'argo-ui';
import * as classNames from 'classnames';
import * as React from 'react';
import {useEffect, useState} from 'react';
import {useEffect, useState, useRef} from 'react';
import {bufferTime, delay, retryWhen} from 'rxjs/operators';
import {LogEntry} from '../../../shared/models';
@@ -83,6 +83,7 @@ export const PodsLogsViewer = (props: PodLogsProps) => {
const [highlight, setHighlight] = useState<RegExp>(matchNothing);
const [scrollToBottom, setScrollToBottom] = useState(true);
const [logs, setLogs] = useState<LogEntry[]>([]);
const logsContainerRef = useRef(null);
useEffect(() => {
if (viewPodNames) {
@@ -102,6 +103,15 @@ export const PodsLogsViewer = (props: PodLogsProps) => {
useEffect(() => setScrollToBottom(true), [follow]);
useEffect(() => {
if (scrollToBottom) {
const element = logsContainerRef.current;
if (element) {
element.scrollTop = element.scrollHeight;
}
}
}, [logs, scrollToBottom]);
useEffect(() => {
setLogs([]);
const logsSource = services.applications
@@ -125,6 +135,10 @@ export const PodsLogsViewer = (props: PodLogsProps) => {
return () => logsSource.unsubscribe();
}, [applicationName, applicationNamespace, namespace, podName, group, kind, name, containerName, tail, follow, sinceSeconds, filter, previous]);
const handleScroll = (event: React.WheelEvent<HTMLDivElement>) => {
if (event.deltaY < 0) setScrollToBottom(false);
};
const renderLog = (log: LogEntry, lineNum: number) =>
// show the pod name if there are multiple pods, pad with spaces to align
(viewPodNames ? (lineNum === 0 || logs[lineNum - 1].podName !== log.podName ? podColor(podName) + log.podName + reset : ' '.repeat(log.podName.length)) + ' ' : '') +
@@ -133,7 +147,7 @@ export const PodsLogsViewer = (props: PodLogsProps) => {
// show the log content, highlight the filter text
log.content?.replace(highlight, (substring: string) => whiteOnYellow + substring + reset);
const logsContent = (width: number, height: number, isWrapped: boolean) => (
<div style={{width, height, overflow: 'scroll'}}>
<div ref={logsContainerRef} onScroll={handleScroll} style={{width, height, overflow: 'scroll'}}>
{logs.map((log, lineNum) => (
<pre key={lineNum} style={{whiteSpace: isWrapped ? 'normal' : 'pre'}} className='noscroll'>
<Ansi>{renderLog(log, lineNum)}</Ansi>
@@ -177,11 +191,7 @@ export const PodsLogsViewer = (props: PodLogsProps) => {
<FullscreenButton {...props} />
</span>
</div>
<div
className={classNames('pod-logs-viewer', {'pod-logs-viewer--inverted': prefs.appDetails.darkMode})}
onWheel={e => {
if (e.deltaY < 0) setScrollToBottom(false);
}}>
<div className={classNames('pod-logs-viewer', {'pod-logs-viewer--inverted': prefs.appDetails.darkMode})} onWheel={handleScroll}>
<AutoSizer>{({width, height}: {width: number; height: number}) => logsContent(width, height, prefs.appDetails.wrapLines)}</AutoSizer>
</div>
</React.Fragment>

View File

@@ -1,3 +1,5 @@
@import 'node_modules/argo-ui/src/styles/theme';
.propagation-policy-list {
display: flex;
justify-content: left;
@@ -9,9 +11,12 @@
padding-right: 2em;
label {
color: #6D7F8B;
font-size: 15px;
cursor: pointer;
@include themify($themes) {
color: themed('light-argo-gray-6');
}
}
input {

View File

@@ -15,7 +15,7 @@ $deselected-text: #818d94;
color: white;
background-color: #0f2733;
overflow: auto;
z-index: 0;
z-index: 2;
&__container {
padding: 0 5px;

View File

@@ -35,6 +35,10 @@ const (
errDestinationMissing = "Destination server missing from app spec"
)
var (
ErrAnotherOperationInProgress = status.Errorf(codes.FailedPrecondition, "another operation is already in progress")
)
// AugmentSyncMsg enrich the K8s message with user-relevant information
func AugmentSyncMsg(res common.ResourceSyncResult, apiResourceInfoGetter func() ([]kube.APIResourceInfo, error)) (string, error) {
switch res.Message {
@@ -800,7 +804,7 @@ func SetAppOperation(appIf v1alpha1.ApplicationInterface, appName string, op *ar
return nil, fmt.Errorf("error getting application %q: %w", appName, err)
}
if a.Operation != nil {
return nil, status.Errorf(codes.FailedPrecondition, "another operation is already in progress")
return nil, ErrAnotherOperationInProgress
}
a.Operation = op
a.Status.OperationState = nil

View File

@@ -6,6 +6,7 @@ import (
"strings"
v1 "k8s.io/api/core/v1"
kubeerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
@@ -13,6 +14,7 @@ import (
appv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/env"
"github.com/argoproj/argo-cd/v2/util/settings"
log "github.com/sirupsen/logrus"
)
// SecretMaperValidation determine whether the secret should be transformed(i.e. trailing CRLF characters trimmed)
@@ -152,8 +154,14 @@ func StripCRLFCharacter(input string) string {
func (db *db) GetApplicationControllerReplicas() int {
// get the replicas from application controller deployment, if the application controller deployment does not exist, check for environment variable
applicationControllerName := env.StringFromEnv(common.EnvAppControllerName, common.DefaultApplicationControllerName)
appControllerDeployment, _ := db.kubeclientset.AppsV1().Deployments(db.settingsMgr.GetNamespace()).Get(context.Background(), applicationControllerName, metav1.GetOptions{})
if appControllerDeployment != nil {
appControllerDeployment, err := db.kubeclientset.AppsV1().Deployments(db.settingsMgr.GetNamespace()).Get(context.Background(), applicationControllerName, metav1.GetOptions{})
if err != nil {
appControllerDeployment = nil
if !kubeerrors.IsNotFound(err) {
log.Warnf("error retrieveing Argo CD controller deployment: %s", err)
}
}
if appControllerDeployment != nil && appControllerDeployment.Spec.Replicas != nil {
return int(*appControllerDeployment.Spec.Replicas)
}
return env.ParseNumFromEnv(common.EnvControllerReplicas, 0, 0, math.MaxInt32)

View File

@@ -274,6 +274,10 @@ var (
)
func cleanSetParameters(val string) string {
// `{}` equal helm list parameters format, so don't escape `,`.
if strings.HasPrefix(val, `{`) && strings.HasSuffix(val, `}`) {
return val
}
return re.ReplaceAllString(val, `$1\,`)
}

View File

@@ -165,6 +165,7 @@ func TestHelmArgCleaner(t *testing.T) {
`bar`: `bar`,
`not, clean`: `not\, clean`,
`a\,b,c`: `a\,b\,c`,
`{a,b,c}`: `{a,b,c}`,
} {
cleaned := cleanSetParameters(input)
assert.Equal(t, expected, cleaned)