Skip to content

Commit 7c655c3

Browse files
grahamalamadkarpele
authored andcommitted
feat: Add configuration option to scope application listing / getting to particular namespace (argoproj-labs#1112)
Signed-off-by: Graham Beckley <gbeckley@mozilla.com>
1 parent 1774073 commit 7c655c3

File tree

5 files changed

+45
-15
lines changed

5 files changed

+45
-15
lines changed

cmd/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ type ImageUpdaterConfig struct {
6060
ApplicationsAPIKind string
6161
ClientOpts argocd.ClientOptions
6262
ArgocdNamespace string
63+
AppNamespace string
6364
DryRun bool
6465
CheckInterval time.Duration
6566
ArgoClient argocd.ArgoCD

cmd/run.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
"github.com/spf13/cobra"
2525

2626
"golang.org/x/sync/semaphore"
27+
28+
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2729
)
2830

2931
// newRunCommand implements "run" command
@@ -235,6 +237,7 @@ func newRunCommand() *cobra.Command {
235237
runCmd.Flags().BoolVar(&disableKubernetes, "disable-kubernetes", false, "do not create and use a Kubernetes client")
236238
runCmd.Flags().IntVar(&cfg.MaxConcurrency, "max-concurrency", 10, "maximum number of update threads to run concurrently")
237239
runCmd.Flags().StringVar(&cfg.ArgocdNamespace, "argocd-namespace", "", "namespace where ArgoCD runs in (current namespace by default)")
240+
runCmd.Flags().StringVar(&cfg.AppNamespace, "application-namespace", v1.NamespaceAll, "namespace where Argo Image Updater will manage applications (all namespaces by default)")
238241
runCmd.Flags().StringSliceVar(&cfg.AppNamePatterns, "match-application-name", nil, "patterns to match application name against")
239242
runCmd.Flags().StringVar(&cfg.AppLabel, "match-application-label", "", "label selector to match application labels against")
240243
runCmd.Flags().BoolVar(&warmUpCache, "warmup-cache", true, "whether to perform a cache warm-up on startup")
@@ -256,7 +259,7 @@ func runImageUpdater(cfg *ImageUpdaterConfig, warmUp bool) (argocd.ImageUpdaterR
256259
var argoClient argocd.ArgoCD
257260
switch cfg.ApplicationsAPIKind {
258261
case applicationsAPIKindK8S:
259-
argoClient, err = argocd.NewK8SClient(cfg.KubeClient)
262+
argoClient, err = argocd.NewK8SClient(cfg.KubeClient, &argocd.K8SClientOptions{AppNamespace: cfg.AppNamespace})
260263
case applicationsAPIKindArgoCD:
261264
argoClient, err = argocd.NewAPIClient(&cfg.ClientOpts)
262265
default:

docs/install/reference.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ Runs the Argo CD Image Updater, possibly in an endless loop.
2626

2727
### Flags
2828

29+
**--application-namespace *namespace***
30+
31+
Specifies the Kubernetes namespace in which Argo CD Image Updater will manage Argo CD Applications when using the Kubernetes-based Application API. By default, applications in all namespaces are considered. This flag can be used to limit scope to a single namespace for performance, security, or organizational reasons.
32+
2933
**--argocd-auth-token *token***
3034

3135
Use *token* for authenticating to the Argo CD API. This token must be a base64

pkg/argocd/argocd.go

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,21 @@ import (
2525

2626
// Kubernetes based client
2727
type k8sClient struct {
28-
kubeClient *kube.ImageUpdaterKubernetesClient
28+
kubeClient *kube.ImageUpdaterKubernetesClient
29+
appNamespace *string
2930
}
3031

31-
// GetApplication retrieves an application by name across all namespaces.
32+
// GetApplication retrieves an application by name, either in a specific namespace or all namespaces depending on client configuration.
3233
func (client *k8sClient) GetApplication(ctx context.Context, appName string) (*v1alpha1.Application, error) {
33-
// List all applications across all namespaces (using empty labelSelector)
34-
appList, err := client.ListApplications(v1.NamespaceAll)
34+
// List all applications across configured namespace or all namespaces (using empty labelSelector)
35+
if *client.appNamespace != v1.NamespaceAll {
36+
return client.kubeClient.ApplicationsClientset.ArgoprojV1alpha1().Applications(*client.appNamespace).Get(ctx, appName, v1.GetOptions{})
37+
}
38+
return client.getApplicationInAllNamespaces(appName)
39+
}
40+
41+
func (client *k8sClient) getApplicationInAllNamespaces(appName string) (*v1alpha1.Application, error) {
42+
appList, err := client.ListApplications("")
3543
if err != nil {
3644
return nil, fmt.Errorf("error listing applications: %w", err)
3745
}
@@ -61,7 +69,7 @@ func (client *k8sClient) GetApplication(ctx context.Context, appName string) (*v
6169

6270
// ListApplications lists all applications across all namespaces.
6371
func (client *k8sClient) ListApplications(labelSelector string) ([]v1alpha1.Application, error) {
64-
list, err := client.kubeClient.ApplicationsClientset.ArgoprojV1alpha1().Applications(v1.NamespaceAll).List(context.TODO(), v1.ListOptions{LabelSelector: labelSelector})
72+
list, err := client.kubeClient.ApplicationsClientset.ArgoprojV1alpha1().Applications(*client.appNamespace).List(context.TODO(), v1.ListOptions{LabelSelector: labelSelector})
6573
if err != nil {
6674
return nil, fmt.Errorf("error listing applications: %w", err)
6775
}
@@ -99,9 +107,23 @@ func (client *k8sClient) UpdateSpec(ctx context.Context, spec *application.Appli
99107
return nil, fmt.Errorf("max retries(%d) reached while updating application: %s", maxRetries, spec.GetName())
100108
}
101109

110+
type K8SClientOptions struct {
111+
AppNamespace string
112+
}
113+
102114
// NewK8SClient creates a new kubernetes client to interact with kubernetes api-server.
103-
func NewK8SClient(kubeClient *kube.ImageUpdaterKubernetesClient) (ArgoCD, error) {
104-
return &k8sClient{kubeClient: kubeClient}, nil
115+
func NewK8SClient(kubeClient *kube.ImageUpdaterKubernetesClient, opts *K8SClientOptions) (ArgoCD, error) {
116+
// Provide default options if nil
117+
if opts == nil {
118+
opts = &K8SClientOptions{
119+
AppNamespace: v1.NamespaceAll,
120+
}
121+
}
122+
123+
return &k8sClient{
124+
kubeClient: kubeClient,
125+
appNamespace: &opts.AppNamespace,
126+
}, nil
105127
}
106128

107129
// Native

pkg/argocd/argocd_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ func TestKubernetesClient(t *testing.T) {
10231023
Namespace: "testns1",
10241024
},
10251025
ApplicationsClientset: fake.NewSimpleClientset(app1, app2),
1026-
})
1026+
}, nil)
10271027

10281028
require.NoError(t, err)
10291029

@@ -1064,7 +1064,7 @@ func TestKubernetesClient(t *testing.T) {
10641064
// Create the Kubernetes client
10651065
client, err := NewK8SClient(&kube.ImageUpdaterKubernetesClient{
10661066
ApplicationsClientset: clientset,
1067-
})
1067+
}, nil)
10681068
require.NoError(t, err)
10691069

10701070
// Test ListApplications error handling
@@ -1094,7 +1094,7 @@ func TestKubernetesClient(t *testing.T) {
10941094
// Create the Kubernetes client
10951095
client, err := NewK8SClient(&kube.ImageUpdaterKubernetesClient{
10961096
ApplicationsClientset: clientset,
1097-
})
1097+
}, nil)
10981098
require.NoError(t, err)
10991099

11001100
// Test GetApplication with multiple matching applications
@@ -1124,7 +1124,7 @@ func TestKubernetesClientUpdateSpec(t *testing.T) {
11241124

11251125
client, err := NewK8SClient(&kube.ImageUpdaterKubernetesClient{
11261126
ApplicationsClientset: clientset,
1127-
})
1127+
}, nil)
11281128
require.NoError(t, err)
11291129

11301130
appName := "test-app"
@@ -1145,7 +1145,7 @@ func TestKubernetesClientUpdateSpec(t *testing.T) {
11451145

11461146
client, err := NewK8SClient(&kube.ImageUpdaterKubernetesClient{
11471147
ApplicationsClientset: clientset,
1148-
})
1148+
}, nil)
11491149
require.NoError(t, err)
11501150

11511151
appName := "test-app"
@@ -1169,7 +1169,7 @@ func TestKubernetesClientUpdateSpec(t *testing.T) {
11691169

11701170
client, err := NewK8SClient(&kube.ImageUpdaterKubernetesClient{
11711171
ApplicationsClientset: clientset,
1172-
})
1172+
}, nil)
11731173
require.NoError(t, err)
11741174

11751175
clientset.PrependReactor("update", "applications", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) {
@@ -1198,7 +1198,7 @@ func TestKubernetesClientUpdateSpec(t *testing.T) {
11981198

11991199
client, err := NewK8SClient(&kube.ImageUpdaterKubernetesClient{
12001200
ApplicationsClientset: clientset,
1201-
})
1201+
}, nil)
12021202
require.NoError(t, err)
12031203

12041204
clientset.PrependReactor("update", "applications", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) {

0 commit comments

Comments
 (0)