diff options
| author | jannfis <jann@mistrust.net> | 2020-08-19 09:41:14 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-19 09:41:14 +0200 |
| commit | e848d6f558d87e2150767be87f4cf0cb18a28954 (patch) | |
| tree | 7d3921b9d7ff6b843057cd0a935189157d7accbd | |
| parent | 1fb6cbab5e5c3bb8dfee71f3cb48caa2e802d751 (diff) | |
feat: Allow filtering by application name (#66)
* feat: Allow filtering by application name
* include allowed word otherapp
| -rw-r--r-- | .github/actions/spelling/expect.txt | 1 | ||||
| -rw-r--r-- | cmd/main.go | 4 | ||||
| -rw-r--r-- | pkg/argocd/argocd.go | 29 | ||||
| -rw-r--r-- | pkg/argocd/argocd_test.go | 58 |
4 files changed, 88 insertions, 4 deletions
diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index edee088..3f8c49a 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -1,3 +1,4 @@ wohoo myuser mypass +otherapp diff --git a/cmd/main.go b/cmd/main.go index b0d2ab9..ff951c4 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -41,6 +41,7 @@ type ImageUpdaterConfig struct { MaxConcurrency int HealthPort int RegistriesConf string + AppNamePatterns []string } // Main loop for argocd-image-controller @@ -66,7 +67,7 @@ func runImageUpdater(cfg *ImageUpdaterConfig) (argocd.ImageUpdaterResult, error) // Get the list of applications that are allowed for updates, that is, those // applications which have correct annotation. - appList, err := argocd.FilterApplicationsForUpdate(apps) + appList, err := argocd.FilterApplicationsForUpdate(apps, cfg.AppNamePatterns) if err != nil { return result, err } @@ -305,6 +306,7 @@ func newRunCommand() *cobra.Command { runCmd.Flags().BoolVar(&disableKubernetes, "disable-kubernetes", false, "do not create and use a Kubernetes client") runCmd.Flags().IntVar(&cfg.MaxConcurrency, "max-concurrency", 10, "maximum number of update threads to run concurrently") runCmd.Flags().StringVar(&cfg.ArgocdNamespace, "argocd-namespace", "argocd", "namespace where ArgoCD runs in") + runCmd.Flags().StringSliceVar(&cfg.AppNamePatterns, "match-application-name", nil, "patterns to match application name against") return runCmd } diff --git a/pkg/argocd/argocd.go b/pkg/argocd/argocd.go index 159c7ca..1696123 100644 --- a/pkg/argocd/argocd.go +++ b/pkg/argocd/argocd.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "path/filepath" "strings" "github.com/argoproj-labs/argocd-image-updater/pkg/common" @@ -81,17 +82,43 @@ type ApplicationImages struct { // update. type ImageList map[string]ApplicationImages +// Match a name against a list of patterns +func nameMatchesPattern(name string, patterns []string) bool { + if len(patterns) == 0 { + return true + } + for _, p := range patterns { + log.Tracef("Matching application name %s against pattern %s", name, p) + if m, err := filepath.Match(p, name); err != nil { + log.Warnf("Invalid application name pattern '%s': %v", p, err) + } else if m { + return true + } + } + return false +} + // Retrieve a list of applications from ArgoCD that qualify for image updates // Application needs either to be of type Kustomize or Helm and must have the // correct annotation in order to be considered. -func FilterApplicationsForUpdate(apps []v1alpha1.Application) (map[string]ApplicationImages, error) { +func FilterApplicationsForUpdate(apps []v1alpha1.Application, patterns []string) (map[string]ApplicationImages, error) { var appsForUpdate = make(map[string]ApplicationImages) for _, app := range apps { + + // Check for valid application type if !IsValidApplicationType(&app) { log.Tracef("skipping app '%s' of type '%s' because it's not of supported source type", app.GetName(), app.Status.SourceType) continue } + + // Check if application name matches requested patterns + if !nameMatchesPattern(app.GetName(), patterns) { + log.Tracef("Skipping app '%s' because it does not match requested patterns", app.GetName()) + continue + } + + // Check whether application has our annotation set annotations := app.GetAnnotations() if updateImage, ok := annotations[common.ImageUpdaterAnnotation]; !ok { log.Tracef("skipping app '%s' of type '%s' because required annotation is missing", app.GetName(), app.Status.SourceType) diff --git a/pkg/argocd/argocd_test.go b/pkg/argocd/argocd_test.go index 05d3979..fb562c9 100644 --- a/pkg/argocd/argocd_test.go +++ b/pkg/argocd/argocd_test.go @@ -113,7 +113,7 @@ func Test_GetApplicationType(t *testing.T) { } func Test_FilterApplicationsForUpdate(t *testing.T) { - t.Run("Filter for applications", func(t *testing.T) { + t.Run("Filter for applications without patterns", func(t *testing.T) { applicationList := []v1alpha1.Application{ // Annotated and correct type { @@ -155,12 +155,66 @@ func Test_FilterApplicationsForUpdate(t *testing.T) { }, }, } - filtered, err := FilterApplicationsForUpdate(applicationList) + filtered, err := FilterApplicationsForUpdate(applicationList, []string{}) require.NoError(t, err) require.Len(t, filtered, 1) require.Contains(t, filtered, "app1") assert.Len(t, filtered["app1"].Images, 2) }) + + t.Run("Filter for applications with patterns", func(t *testing.T) { + applicationList := []v1alpha1.Application{ + // Annotated and correct type + { + ObjectMeta: v1.ObjectMeta{ + Name: "app1", + Namespace: "argocd", + Annotations: map[string]string{ + common.ImageUpdaterAnnotation: "nginx, quay.io/dexidp/dex:v1.23.0", + }, + }, + Spec: v1alpha1.ApplicationSpec{}, + Status: v1alpha1.ApplicationStatus{ + SourceType: v1alpha1.ApplicationSourceTypeKustomize, + }, + }, + // Annotated, but invalid type + { + ObjectMeta: v1.ObjectMeta{ + Name: "app2", + Namespace: "argocd", + Annotations: map[string]string{ + common.ImageUpdaterAnnotation: "nginx, quay.io/dexidp/dex:v1.23.0", + }, + }, + Spec: v1alpha1.ApplicationSpec{}, + Status: v1alpha1.ApplicationStatus{ + SourceType: v1alpha1.ApplicationSourceTypeKustomize, + }, + }, + // Valid type, but not annotated + { + ObjectMeta: v1.ObjectMeta{ + Name: "otherapp3", + Namespace: "argocd", + Annotations: map[string]string{ + common.ImageUpdaterAnnotation: "nginx, quay.io/dexidp/dex:v1.23.0", + }, + }, + Spec: v1alpha1.ApplicationSpec{}, + Status: v1alpha1.ApplicationStatus{ + SourceType: v1alpha1.ApplicationSourceTypeHelm, + }, + }, + } + filtered, err := FilterApplicationsForUpdate(applicationList, []string{"app*"}) + require.NoError(t, err) + require.Len(t, filtered, 2) + require.Contains(t, filtered, "app1") + require.Contains(t, filtered, "app2") + assert.Len(t, filtered["app1"].Images, 2) + }) + } func Test_GetHelmParamAnnotations(t *testing.T) { |
