Skip to content

Commit e64efdd

Browse files
authored
Restrict containsInvalidImage to a specific namespace (#1670)
Signed-off-by: Jonathan West <jonwest@redhat.com>
1 parent e53e06f commit e64efdd

File tree

2 files changed

+61
-14
lines changed

2 files changed

+61
-14
lines changed

controllers/argocd/statefulset.go

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -787,8 +787,10 @@ func (r *ReconcileArgoCD) reconcileApplicationControllerStatefulSet(cr *argoproj
787787
podSpec.Volumes = getArgoImportVolumes(export)
788788
}
789789

790-
invalidImagePod := containsInvalidImage(cr, r)
791-
if invalidImagePod {
790+
invalidImagePod, err := containsInvalidImage(*cr, *r)
791+
if err != nil {
792+
return err
793+
} else if invalidImagePod {
792794
argoutil.LogResourceDeletion(log, ss, "one or more pods has an invalid image")
793795
if err := r.Client.Delete(context.TODO(), ss); err != nil {
794796
return err
@@ -1002,22 +1004,52 @@ func updateNodePlacementStateful(existing *appsv1.StatefulSet, ss *appsv1.Statef
10021004

10031005
// Returns true if a StatefulSet has pods in ErrImagePull or ImagePullBackoff state.
10041006
// These pods cannot be restarted automatially due to known kubernetes issue https://github.com/kubernetes/kubernetes/issues/67250
1005-
func containsInvalidImage(cr *argoproj.ArgoCD, r *ReconcileArgoCD) bool {
1006-
1007-
brokenPod := false
1007+
func containsInvalidImage(cr argoproj.ArgoCD, r ReconcileArgoCD) (bool, error) {
10081008

10091009
podList := &corev1.PodList{}
1010-
listOption := client.MatchingLabels{common.ArgoCDKeyName: fmt.Sprintf("%s-%s", cr.Name, "application-controller")}
1010+
applicationControllerListOption := client.MatchingLabels{common.ArgoCDKeyName: fmt.Sprintf("%s-%s", cr.Name, "application-controller")}
10111011

1012-
if err := r.Client.List(context.TODO(), podList, listOption); err != nil {
1012+
if err := r.Client.List(context.TODO(), podList, applicationControllerListOption, client.InNamespace(cr.Namespace)); err != nil {
10131013
log.Error(err, "Failed to list Pods")
1014+
return false, err
1015+
}
1016+
1017+
if len(podList.Items) == 0 {
1018+
// No pods, no work to do
1019+
return false, nil
1020+
}
1021+
1022+
if len(podList.Items) != 1 {
1023+
// There should only be 0 or 1. If this message is printed, it suggests a problem.
1024+
log.Info("Unexpected number of pods in 'containsInvalidImage' pod list", "podListItems", fmt.Sprintf("%d", len(podList.Items)), "namespace", cr.Namespace)
1025+
return false, nil
1026+
}
1027+
1028+
appControllerPod := podList.Items[0]
1029+
1030+
if len(appControllerPod.Status.ContainerStatuses) == 0 {
1031+
// No container statuses for application-controller, no work to do.
1032+
return false, nil
10141033
}
1015-
if len(podList.Items) > 0 {
1016-
if len(podList.Items[0].Status.ContainerStatuses) > 0 {
1017-
if podList.Items[0].Status.ContainerStatuses[0].State.Waiting != nil && (podList.Items[0].Status.ContainerStatuses[0].State.Waiting.Reason == "ImagePullBackOff" || podList.Items[0].Status.ContainerStatuses[0].State.Waiting.Reason == "ErrImagePull") {
1018-
brokenPod = true
1034+
1035+
brokenPod := false
1036+
1037+
waitingState := appControllerPod.Status.ContainerStatuses[0].State.Waiting
1038+
if waitingState != nil {
1039+
1040+
waitingReason := waitingState.Reason
1041+
if waitingReason == "ImagePullBackOff" || waitingReason == "ErrImagePull" {
1042+
1043+
var containerImage string
1044+
if len(appControllerPod.Spec.Containers) > 0 {
1045+
containerImage = appControllerPod.Spec.Containers[0].Image
10191046
}
1047+
1048+
log.Info("A broken pod was detected", "waitingReason", waitingReason, "containerImage", containerImage)
1049+
brokenPod = true
10201050
}
1051+
10211052
}
1022-
return brokenPod
1053+
1054+
return brokenPod, nil
10231055
}

controllers/argocd/statefulset_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,11 +638,13 @@ func Test_UpdateNodePlacementStateful(t *testing.T) {
638638
}
639639
}
640640

641-
func Test_ContainsValidImage(t *testing.T) {
641+
func Test_ContainsInvalidImage(t *testing.T) {
642642

643643
a := makeTestArgoCD()
644644
po := &corev1.Pod{
645645
ObjectMeta: metav1.ObjectMeta{
646+
Name: "argo-cd-application-controller",
647+
Namespace: a.Namespace,
646648
Labels: map[string]string{
647649
common.ArgoCDKeyName: fmt.Sprintf("%s-%s", a.Name, "application-controller"),
648650
},
@@ -658,10 +660,23 @@ func Test_ContainsValidImage(t *testing.T) {
658660
cl := makeTestReconcilerClient(sch, objs, objs, runtimeObjs)
659661
r := makeTestReconciler(cl, sch)
660662

661-
if containsInvalidImage(a, r) {
663+
// Test that containsInvalidImage returns false if there is nothing wrong with the Pod
664+
containsInvalidImageRes, err := containsInvalidImage(*a, *r)
665+
assert.NoError(t, err)
666+
if containsInvalidImageRes {
662667
t.Fatalf("containsInvalidImage failed, got true, expected false")
663668
}
664669

670+
// Test that containsInvalidImage returns true if the Pod is in ErrImagePull
671+
po.Status.ContainerStatuses = []corev1.ContainerStatus{
672+
{State: corev1.ContainerState{Waiting: &corev1.ContainerStateWaiting{Reason: "ErrImagePull"}}}}
673+
err = cl.Status().Update(context.Background(), po)
674+
assert.NoError(t, err)
675+
676+
containsInvalidImageRes, err = containsInvalidImage(*a, *r)
677+
assert.NoError(t, err)
678+
assert.True(t, containsInvalidImageRes)
679+
665680
}
666681

667682
func TestReconcileArgoCD_reconcileApplicationController_withDynamicSharding(t *testing.T) {

0 commit comments

Comments
 (0)