diff --git a/pkg/argocd/argocd.go b/pkg/argocd/argocd.go index 4584dbe0..e43398b2 100644 --- a/pkg/argocd/argocd.go +++ b/pkg/argocd/argocd.go @@ -481,19 +481,32 @@ func SetKustomizeImage(app *v1alpha1.Application, newImage *image.ContainerImage return nil } +// ImageIsAllowed checks whether img is declared in image-list annotation +func ImageIsAllowed(img *image.ContainerImage, list *image.ContainerImageList) bool { + for _, i := range *list { + if i.ImageName == img.ImageName { + return true + } + } + return false +} + // GetImagesFromApplication returns the list of known images for the given application func GetImagesFromApplication(app *v1alpha1.Application) image.ContainerImageList { images := make(image.ContainerImageList, 0) + annotations := app.Annotations + imagesFromAnnotations := parseImageList(annotations) for _, imageStr := range app.Status.Summary.Images { - image := image.NewFromIdentifier(imageStr) - images = append(images, image) + img := image.NewFromIdentifier(imageStr) + if ImageIsAllowed(img, imagesFromAnnotations) { + images = append(images, img) + } } // The Application may wish to update images that don't create a container we can detect. // Check the image list for images with a force-update annotation, and add them if they are not already present. - annotations := app.Annotations - for _, img := range *parseImageList(annotations) { + for _, img := range *imagesFromAnnotations { if img.HasForceUpdateOptionAnnotation(annotations) { img.ImageTag = nil // the tag from the image list will be a version constraint, which isn't a valid tag images = append(images, img) diff --git a/pkg/argocd/argocd_test.go b/pkg/argocd/argocd_test.go index 95553570..bfedb126 100644 --- a/pkg/argocd/argocd_test.go +++ b/pkg/argocd/argocd_test.go @@ -27,6 +27,9 @@ func Test_GetImagesFromApplication(t *testing.T) { ObjectMeta: v1.ObjectMeta{ Name: "test-app", Namespace: "argocd", + Annotations: map[string]string{ + common.ImageUpdaterAnnotation: "nginx:1.12.2,that/image,quay.io/dexidp/dex:v1.23.0", + }, }, Spec: v1alpha1.ApplicationSpec{}, Status: v1alpha1.ApplicationStatus{ diff --git a/pkg/argocd/update_test.go b/pkg/argocd/update_test.go index 1d1246fa..0197aa23 100644 --- a/pkg/argocd/update_test.go +++ b/pkg/argocd/update_test.go @@ -109,11 +109,15 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "jannfis/foobar:1.0.0", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -167,11 +171,15 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "jannfis/foobar:1.0.0,jannfis/barbar:1.0.0", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -354,11 +362,15 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "jannfis/foobar:1.0.x", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -412,14 +424,16 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeClientsetWithResources(fixture.NewSecret("foo", "bar", map[string][]byte{"creds": []byte("myuser:mypass")})), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "jannfis/foobar:1.0.0", + fmt.Sprintf(common.PullSecretAnnotation, "dummy"): "secret:foo/bar#creds", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", - Annotations: map[string]string{ - fmt.Sprintf(common.PullSecretAnnotation, "dummy"): "secret:foo/bar#creds", - }, + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -526,11 +540,15 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "jannfis/foobar:1.0.1", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -716,15 +734,17 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "dummy=jannfis/foobar", + fmt.Sprintf(common.AllowTagsOptionAnnotation, "dummy"): "regexp:^foobar$", + fmt.Sprintf(common.UpdateStrategyAnnotation, "dummy"): "name", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", - Annotations: map[string]string{ - fmt.Sprintf(common.AllowTagsOptionAnnotation, "dummy"): "regexp:^foobar$", - fmt.Sprintf(common.UpdateStrategyAnnotation, "dummy"): "name", - }, + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -792,15 +812,17 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "dummy=jannfis/foobar", + fmt.Sprintf(common.IgnoreTagsOptionAnnotation, "dummy"): "*", + fmt.Sprintf(common.UpdateStrategyAnnotation, "dummy"): "name", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", - Annotations: map[string]string{ - fmt.Sprintf(common.IgnoreTagsOptionAnnotation, "dummy"): "*", - fmt.Sprintf(common.UpdateStrategyAnnotation, "dummy"): "name", - }, + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -852,11 +874,15 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "example.io/jannfis/example:1.0.x", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -905,11 +931,15 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "jannfis/foobar:1.0.0", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -961,11 +991,15 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "jannfis/foobar:1.0.0", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{ @@ -1017,11 +1051,15 @@ func Test_UpdateApplication(t *testing.T) { kubeClient := kube.KubernetesClient{ Clientset: fake.NewFakeKubeClient(), } + annotations := map[string]string{ + common.ImageUpdaterAnnotation: "jannfis/foobar:stable", + } appImages := &ApplicationImages{ Application: v1alpha1.Application{ ObjectMeta: v1.ObjectMeta{ - Name: "guestbook", - Namespace: "guestbook", + Name: "guestbook", + Namespace: "guestbook", + Annotations: annotations, }, Spec: v1alpha1.ApplicationSpec{ Source: &v1alpha1.ApplicationSource{