github.com/argoproj/argo-cd/v3@v3.2.1/test/e2e/sync_waves_test.go (about) 1 package e2e 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/argoproj/gitops-engine/pkg/health" 8 . "github.com/argoproj/gitops-engine/pkg/sync/common" 9 "github.com/stretchr/testify/require" 10 corev1 "k8s.io/api/core/v1" 11 12 . "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1" 13 . "github.com/argoproj/argo-cd/v3/test/e2e/fixture" 14 . "github.com/argoproj/argo-cd/v3/test/e2e/fixture/app" 15 ) 16 17 func TestFixingDegradedApp(t *testing.T) { 18 var lastTransitionTime string 19 Given(t). 20 Path("sync-waves"). 21 When(). 22 IgnoreErrors(). 23 CreateApp(). 24 And(func() { 25 require.NoError(t, SetResourceOverrides(map[string]ResourceOverride{ 26 "ConfigMap": { 27 HealthLua: `return { status = obj.metadata.annotations and obj.metadata.annotations['health'] or 'Degraded' }`, 28 }, 29 })) 30 }). 31 Sync(). 32 Then(). 33 Expect(OperationPhaseIs(OperationFailed)). 34 Expect(SyncStatusIs(SyncStatusCodeOutOfSync)). 35 Expect(HealthIs(health.HealthStatusDegraded)). 36 Expect(ResourceResultNumbering(1)). 37 Expect(ResourceSyncStatusIs("ConfigMap", "cm-1", SyncStatusCodeSynced)). 38 Expect(ResourceHealthIs("ConfigMap", "cm-1", health.HealthStatusDegraded)). 39 Expect(ResourceSyncStatusIs("ConfigMap", "cm-2", SyncStatusCodeOutOfSync)). 40 Expect(ResourceHealthIs("ConfigMap", "cm-2", health.HealthStatusMissing)). 41 When(). 42 Then(). 43 And(func(app *Application) { 44 lastTransitionTime = app.Status.Health.LastTransitionTime.UTC().Format(time.RFC3339) 45 }). 46 When(). 47 PatchFile("cm-1.yaml", `[{"op": "replace", "path": "/metadata/annotations/health", "value": "Healthy"}]`). 48 PatchFile("cm-2.yaml", `[{"op": "replace", "path": "/metadata/annotations/health", "value": "Healthy"}]`). 49 // need to force a refresh here 50 Refresh(RefreshTypeNormal). 51 Then(). 52 Expect(ResourceSyncStatusIs("ConfigMap", "cm-1", SyncStatusCodeOutOfSync)). 53 When(). 54 Sync(). 55 Then(). 56 Expect(OperationPhaseIs(OperationSucceeded)). 57 Expect(SyncStatusIs(SyncStatusCodeSynced)). 58 Expect(HealthIs(health.HealthStatusHealthy)). 59 Expect(ResourceResultNumbering(2)). 60 Expect(ResourceSyncStatusIs("ConfigMap", "cm-1", SyncStatusCodeSynced)). 61 Expect(ResourceHealthIs("ConfigMap", "cm-1", health.HealthStatusHealthy)). 62 Expect(ResourceSyncStatusIs("ConfigMap", "cm-2", SyncStatusCodeSynced)). 63 Expect(ResourceHealthIs("ConfigMap", "cm-2", health.HealthStatusHealthy)). 64 When(). 65 Then(). 66 And(func(app *Application) { 67 // check that the last transition time is updated 68 require.NotEqual(t, lastTransitionTime, app.Status.Health.LastTransitionTime.UTC().Format(time.RFC3339)) 69 }) 70 } 71 72 func TestOneProgressingDeploymentIsSucceededAndSynced(t *testing.T) { 73 Given(t). 74 Path("one-deployment"). 75 When(). 76 // make this deployment get stuck in progressing due to "invalidimagename" 77 PatchFile("deployment.yaml", `[ 78 { 79 "op": "replace", 80 "path": "/spec/template/spec/containers/0/image", 81 "value": "alpine:ops!" 82 } 83 ]`). 84 CreateApp(). 85 Sync(). 86 Then(). 87 Expect(OperationPhaseIs(OperationSucceeded)). 88 Expect(HealthIs(health.HealthStatusProgressing)). 89 Expect(SyncStatusIs(SyncStatusCodeSynced)). 90 Expect(ResourceResultNumbering(1)) 91 } 92 93 func TestDegradedDeploymentIsSucceededAndSynced(t *testing.T) { 94 Given(t). 95 Path("one-deployment"). 96 When(). 97 // make this deployment get stuck in progressing due to "invalidimagename" 98 PatchFile("deployment.yaml", `[ 99 { 100 "op": "replace", 101 "path": "/spec/progressDeadlineSeconds", 102 "value": 1 103 }, 104 { 105 "op": "replace", 106 "path": "/spec/template/spec/containers/0/image", 107 "value": "alpine:ops!" 108 } 109 ]`). 110 CreateApp(). 111 Sync(). 112 Then(). 113 Expect(OperationPhaseIs(OperationSucceeded)). 114 Expect(HealthIs(health.HealthStatusDegraded)). 115 Expect(SyncStatusIs(SyncStatusCodeSynced)). 116 Expect(ResourceResultNumbering(1)) 117 } 118 119 // resources should be pruned in reverse of creation order(syncwaves order) 120 func TestSyncPruneOrderWithSyncWaves(t *testing.T) { 121 ctx := Given(t).Timeout(60) 122 123 // remove finalizer to ensure proper cleanup if test fails at early stage 124 defer func() { 125 _, _ = RunCli("app", "patch-resource", ctx.AppQualifiedName(), 126 "--kind", "Pod", 127 "--resource-name", "pod-with-finalizers", 128 "--patch", `[{"op": "remove", "path": "/metadata/finalizers"}]`, 129 "--patch-type", "application/json-patch+json", "--all", 130 ) 131 }() 132 133 ctx.Path("syncwaves-prune-order"). 134 When(). 135 CreateApp(). 136 // creation order: sa & role -> rolebinding -> pod 137 Sync(). 138 Wait(). 139 Then(). 140 Expect(SyncStatusIs(SyncStatusCodeSynced)). 141 Expect(HealthIs(health.HealthStatusHealthy)). 142 When(). 143 // delete files to remove resources 144 DeleteFile("pod.yaml"). 145 DeleteFile("rbac.yaml"). 146 Refresh(RefreshTypeHard). 147 IgnoreErrors(). 148 Then(). 149 Expect(SyncStatusIs(SyncStatusCodeOutOfSync)). 150 When(). 151 // prune order: pod -> rolebinding -> sa & role 152 Sync("--prune"). 153 Wait(). 154 Then(). 155 Expect(OperationPhaseIs(OperationSucceeded)). 156 Expect(SyncStatusIs(SyncStatusCodeSynced)). 157 Expect(HealthIs(health.HealthStatusHealthy)). 158 Expect(NotPod(func(p corev1.Pod) bool { return p.Name == "pod-with-finalizers" })). 159 Expect(ResourceResultNumbering(4)) 160 }