Skip to content

Commit 460cab3

Browse files
committed
Merge branch 'master' of https://github.com/argoproj/argo-cd into bb-bearer-token
2 parents 5659e07 + d183d9c commit 460cab3

File tree

15 files changed

+125
-69
lines changed

15 files changed

+125
-69
lines changed

.golangci.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ linters-settings:
6666
pkg: k8s.io/api/rbac/v1
6767
- alias: apierrors
6868
pkg: k8s.io/apimachinery/pkg/api/errors
69+
- alias: apiextensionsv1
70+
pkg: k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
6971
- alias: metav1
7072
pkg: k8s.io/apimachinery/pkg/apis/meta/v1
7173
- alias: informersv1

applicationset/controllers/applicationset_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ func (r *ApplicationSetReconciler) deleteInCluster(ctx context.Context, logCtx *
768768
}
769769

770770
// removeFinalizerOnInvalidDestination removes the Argo CD resources finalizer if the application contains an invalid target (eg missing cluster)
771-
func (r *ApplicationSetReconciler) removeFinalizerOnInvalidDestination(ctx context.Context, applicationSet argov1alpha1.ApplicationSet, app *argov1alpha1.Application, clusterList *argov1alpha1.ClusterList, appLog *log.Entry) error {
771+
func (r *ApplicationSetReconciler) removeFinalizerOnInvalidDestination(ctx context.Context, applicationSet argov1alpha1.ApplicationSet, app *argov1alpha1.Application, clusterList []utils.ClusterSpecifier, appLog *log.Entry) error {
772772
// Only check if the finalizers need to be removed IF there are finalizers to remove
773773
if len(app.Finalizers) == 0 {
774774
return nil
@@ -783,7 +783,7 @@ func (r *ApplicationSetReconciler) removeFinalizerOnInvalidDestination(ctx conte
783783
} else {
784784
// Detect if the destination's server field does not match an existing cluster
785785
matchingCluster := false
786-
for _, cluster := range clusterList.Items {
786+
for _, cluster := range clusterList {
787787
if destCluster.Server != cluster.Server {
788788
continue
789789
}

applicationset/generators/cluster.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
7070
// - Since local clusters do not have secrets, they do not have labels to match against
7171
ignoreLocalClusters := len(appSetGenerator.Clusters.Selector.MatchExpressions) > 0 || len(appSetGenerator.Clusters.Selector.MatchLabels) > 0
7272

73-
// ListCluster from Argo CD's util/db package will include the local cluster in the list of clusters
73+
// ListCluster will include the local cluster in the list of clusters
7474
clustersFromArgoCD, err := utils.ListClusters(g.ctx, g.clientset, g.namespace)
7575
if err != nil {
7676
return nil, fmt.Errorf("error listing clusters: %w", err)
@@ -93,7 +93,7 @@ func (g *ClusterGenerator) GenerateParams(appSetGenerator *argoappsetv1alpha1.Ap
9393
logCtx.Debugf("Using flat mode = %t for cluster generator", isFlatMode)
9494
clustersParams := make([]map[string]any, 0)
9595

96-
for _, cluster := range clustersFromArgoCD.Items {
96+
for _, cluster := range clustersFromArgoCD {
9797
// If there is a secret for this cluster, then it's a non-local cluster, so it will be
9898
// handled by the next step.
9999
if secretForCluster, exists := clusterSecrets[cluster.Name]; exists {

applicationset/generators/duck_type.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,6 @@ func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.A
165165
}
166166
log.Infof("Number of decisions found: %v", len(clusterDecisions))
167167

168-
// Read this outside the loop to improve performance
169-
argoClusters := clustersFromArgoCD.Items
170-
171168
if len(clusterDecisions) == 0 {
172169
log.Warningf("clusterDecisionResource status.%s missing", statusListKey)
173170
return nil, nil
@@ -188,7 +185,7 @@ func (g *DuckTypeGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.A
188185

189186
found := false
190187

191-
for _, argoCluster := range argoClusters {
188+
for _, argoCluster := range clustersFromArgoCD {
192189
if argoCluster.Name == strMatchValue {
193190
log.WithField(matchKey, argoCluster.Name).Info("matched cluster in ArgoCD")
194191
params["name"] = argoCluster.Name

applicationset/utils/clusterUtils.go

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package utils
33
import (
44
"context"
55
"fmt"
6-
"sync"
76

87
"github.com/argoproj/argo-cd/v3/common"
98
appv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
@@ -13,16 +12,14 @@ import (
1312
"k8s.io/client-go/kubernetes"
1413
)
1514

16-
var (
17-
localCluster = appv1.Cluster{
18-
Name: "in-cluster",
19-
Server: appv1.KubernetesInternalAPIServerAddr,
20-
ConnectionState: appv1.ConnectionState{Status: appv1.ConnectionStatusSuccessful},
21-
}
22-
initLocalCluster sync.Once
23-
)
15+
// ClusterSpecifier contains only the name and server URL of a cluster. We use this struct to avoid partially-populating
16+
// the full Cluster struct, which would be misleading.
17+
type ClusterSpecifier struct {
18+
Name string
19+
Server string
20+
}
2421

25-
func ListClusters(ctx context.Context, clientset kubernetes.Interface, namespace string) (*appv1.ClusterList, error) {
22+
func ListClusters(ctx context.Context, clientset kubernetes.Interface, namespace string) ([]ClusterSpecifier, error) {
2623
clusterSecretsList, err := clientset.CoreV1().Secrets(namespace).List(ctx,
2724
metav1.ListOptions{LabelSelector: common.LabelKeySecretType + "=" + common.LabelValueSecretTypeCluster})
2825
if err != nil {
@@ -35,54 +32,29 @@ func ListClusters(ctx context.Context, clientset kubernetes.Interface, namespace
3532

3633
clusterSecrets := clusterSecretsList.Items
3734

38-
clusterList := appv1.ClusterList{
39-
Items: make([]appv1.Cluster, len(clusterSecrets)),
40-
}
35+
clusterList := make([]ClusterSpecifier, len(clusterSecrets))
36+
4137
hasInClusterCredentials := false
4238
for i, clusterSecret := range clusterSecrets {
43-
// This line has changed from the original Argo CD code: now receives an error, and handles it
4439
cluster, err := db.SecretToCluster(&clusterSecret)
4540
if err != nil || cluster == nil {
4641
return nil, fmt.Errorf("unable to convert cluster secret to cluster object '%s': %w", clusterSecret.Name, err)
4742
}
48-
49-
// db.SecretToCluster populates these, but they're not meant to be available to the caller.
50-
cluster.Labels = nil
51-
cluster.Annotations = nil
52-
53-
clusterList.Items[i] = *cluster
43+
clusterList[i] = ClusterSpecifier{
44+
Name: cluster.Name,
45+
Server: cluster.Server,
46+
}
5447
if cluster.Server == appv1.KubernetesInternalAPIServerAddr {
5548
hasInClusterCredentials = true
5649
}
5750
}
5851
if !hasInClusterCredentials {
59-
localCluster := getLocalCluster(clientset)
60-
if localCluster != nil {
61-
clusterList.Items = append(clusterList.Items, *localCluster)
62-
}
52+
// There was no secret for the in-cluster config, so we add it here. We don't fully-populate the Cluster struct,
53+
// since only the name and server fields are used by the generator.
54+
clusterList = append(clusterList, ClusterSpecifier{
55+
Name: "in-cluster",
56+
Server: appv1.KubernetesInternalAPIServerAddr,
57+
})
6358
}
64-
return &clusterList, nil
65-
}
66-
67-
func getLocalCluster(clientset kubernetes.Interface) *appv1.Cluster {
68-
initLocalCluster.Do(func() {
69-
info, err := clientset.Discovery().ServerVersion()
70-
if err == nil {
71-
//nolint:staticcheck
72-
localCluster.ServerVersion = fmt.Sprintf("%s.%s", info.Major, info.Minor)
73-
//nolint:staticcheck
74-
localCluster.ConnectionState = appv1.ConnectionState{Status: appv1.ConnectionStatusSuccessful}
75-
} else {
76-
//nolint:staticcheck
77-
localCluster.ConnectionState = appv1.ConnectionState{
78-
Status: appv1.ConnectionStatusFailed,
79-
Message: err.Error(),
80-
}
81-
}
82-
})
83-
cluster := localCluster.DeepCopy()
84-
now := metav1.Now()
85-
//nolint:staticcheck
86-
cluster.ConnectionState.ModifiedAt = &now
87-
return cluster
59+
return clusterList, nil
8860
}

controller/appcontroller.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,32 @@ func NewApplicationController(
288288
return fmt.Errorf("application controller deployment replicas is not set or is less than 0, replicas: %d", appControllerDeployment.Spec.Replicas)
289289
}
290290
shard := env.ParseNumFromEnv(common.EnvControllerShard, -1, -math.MaxInt32, math.MaxInt32)
291-
if _, err := sharding.GetOrUpdateShardFromConfigMap(kubeClientset.(*kubernetes.Clientset), settingsMgr, int(*appControllerDeployment.Spec.Replicas), shard); err != nil {
291+
shard, err := sharding.GetOrUpdateShardFromConfigMap(kubeClientset.(*kubernetes.Clientset), settingsMgr, int(*appControllerDeployment.Spec.Replicas), shard)
292+
if err != nil {
292293
return fmt.Errorf("error while updating the heartbeat for to the Shard Mapping ConfigMap: %w", err)
293294
}
295+
296+
// update the shard number in the clusterSharding, and resync all applications if the shard number is updated
297+
if ctrl.clusterSharding.UpdateShard(shard) {
298+
// update shard number in stateCache
299+
ctrl.stateCache.UpdateShard(shard)
300+
301+
// resync all applications
302+
apps, err := ctrl.appLister.List(labels.Everything())
303+
if err != nil {
304+
return err
305+
}
306+
for _, app := range apps {
307+
if !ctrl.canProcessApp(app) {
308+
continue
309+
}
310+
key, err := cache.MetaNamespaceKeyFunc(app)
311+
if err == nil {
312+
ctrl.appRefreshQueue.AddRateLimited(key)
313+
ctrl.clusterSharding.AddApp(app)
314+
}
315+
}
316+
}
294317
}
295318
}
296319
return nil

controller/cache/cache.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ type LiveStateCache interface {
153153
GetClustersInfo() []clustercache.ClusterInfo
154154
// Init must be executed before cache can be used
155155
Init() error
156+
// UpdateShard will update the shard of ClusterSharding when the shard has changed.
157+
UpdateShard(shard int) bool
156158
}
157159

158160
type ObjectUpdatedHandler = func(managedByApp map[string]bool, ref corev1.ObjectReference)
@@ -906,3 +908,8 @@ func (c *liveStateCache) GetClustersInfo() []clustercache.ClusterInfo {
906908
func (c *liveStateCache) GetClusterCache(server *appv1.Cluster) (clustercache.ClusterCache, error) {
907909
return c.getSyncedCluster(server)
908910
}
911+
912+
// UpdateShard will update the shard of ClusterSharding when the shard has changed.
913+
func (c *liveStateCache) UpdateShard(shard int) bool {
914+
return c.clusterSharding.UpdateShard(shard)
915+
}

controller/cache/mocks/LiveStateCache.go

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

controller/sharding/cache.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ type ClusterShardingCache interface {
1919
UpdateApp(a *v1alpha1.Application)
2020
IsManagedCluster(c *v1alpha1.Cluster) bool
2121
GetDistribution() map[string]int
22+
GetAppDistribution() map[string]int
23+
UpdateShard(shard int) bool
2224
}
2325

2426
type ClusterSharding struct {
@@ -244,3 +246,33 @@ func (sharding *ClusterSharding) UpdateApp(a *v1alpha1.Application) {
244246
log.Debugf("Skipping sharding distribution update. No relevant changes")
245247
}
246248
}
249+
250+
// GetAppDistribution should be not be called from a DestributionFunction because
251+
// it could cause a deadlock when updateDistribution is called.
252+
func (sharding *ClusterSharding) GetAppDistribution() map[string]int {
253+
sharding.lock.RLock()
254+
clusters := sharding.Clusters
255+
apps := sharding.Apps
256+
sharding.lock.RUnlock()
257+
258+
appDistribution := make(map[string]int, len(clusters))
259+
260+
for _, a := range apps {
261+
if _, ok := appDistribution[a.Spec.Destination.Server]; !ok {
262+
appDistribution[a.Spec.Destination.Server] = 0
263+
}
264+
appDistribution[a.Spec.Destination.Server]++
265+
}
266+
return appDistribution
267+
}
268+
269+
// UpdateShard will update the shard of ClusterSharding when the shard has changed.
270+
func (sharding *ClusterSharding) UpdateShard(shard int) bool {
271+
if shard != sharding.Shard {
272+
sharding.lock.RLock()
273+
sharding.Shard = shard
274+
sharding.lock.RUnlock()
275+
return true
276+
}
277+
return false
278+
}

controller/sharding/sharding.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,10 @@ func GetClusterSharding(kubeClient kubernetes.Interface, settingsMgr *settings.S
485485
err = fmt.Errorf("unable to get shard due to error updating the sharding config map: %w", err)
486486
break
487487
}
488-
log.Warnf("conflict when getting shard from shard mapping configMap. Retrying (%d/3)", i)
488+
// if `err == nil`, should not log the following warning message
489+
if err != nil {
490+
log.Warnf("conflict when getting shard from shard mapping configMap. Retrying (%d/3)", i)
491+
}
489492
}
490493
errors.CheckError(err)
491494
} else {

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ require (
9494
golang.org/x/time v0.10.0
9595
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a
9696
google.golang.org/grpc v1.70.0
97-
google.golang.org/protobuf v1.36.4
97+
google.golang.org/protobuf v1.36.5
9898
gopkg.in/yaml.v2 v2.4.0
9999
gopkg.in/yaml.v3 v3.0.1
100100
k8s.io/api v0.31.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,8 +1382,8 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
13821382
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
13831383
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
13841384
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
1385-
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
1386-
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
1385+
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
1386+
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
13871387
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
13881388
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
13891389
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=

hack/gen-crd-spec/main.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/argoproj/argo-cd/v3/pkg/apis/application"
1212

1313
"github.com/argoproj/gitops-engine/pkg/utils/kube"
14-
extensionsobj "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
14+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1515
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1616
"sigs.k8s.io/yaml"
1717
)
@@ -22,7 +22,7 @@ var kindToCRDPath = map[string]string{
2222
application.ApplicationSetFullName: "manifests/crds/applicationset-crd.yaml",
2323
}
2424

25-
func getCustomResourceDefinitions() map[string]*extensionsobj.CustomResourceDefinition {
25+
func getCustomResourceDefinitions() map[string]*apiextensionsv1.CustomResourceDefinition {
2626
crdYamlBytes, err := exec.Command(
2727
"controller-gen",
2828
"paths=./pkg/apis/application/...",
@@ -41,7 +41,7 @@ func getCustomResourceDefinitions() map[string]*extensionsobj.CustomResourceDefi
4141

4242
objs, err := kube.SplitYAML(crdYamlBytes)
4343
checkErr(err)
44-
crds := make(map[string]*extensionsobj.CustomResourceDefinition)
44+
crds := make(map[string]*apiextensionsv1.CustomResourceDefinition)
4545
for i := range objs {
4646
un := objs[i]
4747

@@ -80,14 +80,14 @@ func removeValidation(un *unstructured.Unstructured, path string) {
8080
unstructured.RemoveNestedField(un.Object, schemaPath...)
8181
}
8282

83-
func toCRD(un *unstructured.Unstructured, removeDesc bool) *extensionsobj.CustomResourceDefinition {
83+
func toCRD(un *unstructured.Unstructured, removeDesc bool) *apiextensionsv1.CustomResourceDefinition {
8484
if removeDesc {
8585
removeDescription(un.Object)
8686
}
8787
unBytes, err := json.Marshal(un)
8888
checkErr(err)
8989

90-
var crd extensionsobj.CustomResourceDefinition
90+
var crd apiextensionsv1.CustomResourceDefinition
9191
err = json.Unmarshal(unBytes, &crd)
9292
checkErr(err)
9393

@@ -134,7 +134,7 @@ func main() {
134134
}
135135
}
136136

137-
func writeCRDintoFile(crd *extensionsobj.CustomResourceDefinition, path string) {
137+
func writeCRDintoFile(crd *apiextensionsv1.CustomResourceDefinition, path string) {
138138
jsonBytes, err := json.Marshal(crd)
139139
checkErr(err)
140140

test/container/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,15 @@ RUN userdel -r ubuntu && \
104104
HOME=/home/user git config --global user.name "ArgoCD Test User" && \
105105
HOME=/home/user git config --global user.email "[email protected]" && \
106106
HOME=/home/user git config --global --add safe.directory '*' && \
107+
mkdir -p /go/src && \
107108
mkdir -p /go/pkg && \
109+
chown -R user:user /go && \
108110
mkdir -p /var/run/sshd && \
109111
mkdir -p /root/.ssh && \
110-
mkdir -p /go && \
111112
chown root /etc/ssh/ssh_host_*_key* && \
112113
chmod 0600 /etc/ssh/ssh_host_*_key && \
113114
mkdir -p /tmp/go-build-cache && \
115+
chown -R user:user /tmp/go-build-cache && \
114116
ln -s /usr/local/bin/node /usr/local/bin/nodejs && \
115117
ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
116118
ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx && \

test/remote/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:80dd3c3b9c6cecb9f1667e9290b3bc61b78c2678c02cbdae5f0fea92cc6734ab
22

3-
FROM docker.io/library/golang:1.23.5@sha256:51a6466e8dbf3e00e422eb0f7a97ac450b2d57b33617bbe8d2ee0bddcd9d0d37 AS go
3+
FROM docker.io/library/golang:1.23.6@sha256:927112936d6b496ed95f55f362cc09da6e3e624ef868814c56d55bd7323e0959 AS go
44

55
RUN go install github.com/mattn/goreman@latest && \
66
go install github.com/kisielk/godepgraph@latest

0 commit comments

Comments
 (0)