github.com/argoproj/argo-cd/v3@v3.2.1/test/e2e/app_multiple_sources_test.go (about) 1 package e2e 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 10 . "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1" 11 . "github.com/argoproj/argo-cd/v3/test/e2e/fixture" 12 . "github.com/argoproj/argo-cd/v3/test/e2e/fixture/app" 13 . "github.com/argoproj/argo-cd/v3/util/argo" 14 ) 15 16 func TestMultiSourceAppCreation(t *testing.T) { 17 sources := []ApplicationSource{{ 18 RepoURL: RepoURL(RepoURLTypeFile), 19 Path: guestbookPath, 20 }, { 21 RepoURL: RepoURL(RepoURLTypeFile), 22 Path: "two-nice-pods", 23 }} 24 ctx := Given(t) 25 ctx. 26 Sources(sources). 27 When(). 28 CreateMultiSourceAppFromFile(). 29 Then(). 30 And(func(app *Application) { 31 assert.Equal(t, Name(), app.Name) 32 for i, source := range app.Spec.GetSources() { 33 assert.Equal(t, sources[i].RepoURL, source.RepoURL) 34 assert.Equal(t, sources[i].Path, source.Path) 35 } 36 assert.Equal(t, DeploymentNamespace(), app.Spec.Destination.Namespace) 37 assert.Equal(t, KubernetesInternalAPIServerAddr, app.Spec.Destination.Server) 38 }). 39 Expect(Event(EventReasonResourceCreated, "create")). 40 And(func(_ *Application) { 41 // app should be listed 42 output, err := RunCli("app", "list") 43 require.NoError(t, err) 44 assert.Contains(t, output, Name()) 45 }). 46 Expect(Success("")). 47 Given().Timeout(60). 48 When().Wait().Then(). 49 Expect(Success("")). 50 And(func(app *Application) { 51 statusByName := map[string]SyncStatusCode{} 52 for _, r := range app.Status.Resources { 53 statusByName[r.Name] = r.Status 54 } 55 // check if the app has 3 resources, guestbook and 2 pods 56 assert.Len(t, statusByName, 3) 57 assert.Equal(t, SyncStatusCodeSynced, statusByName["pod-1"]) 58 assert.Equal(t, SyncStatusCodeSynced, statusByName["pod-2"]) 59 assert.Equal(t, SyncStatusCodeSynced, statusByName["guestbook-ui"]) 60 }) 61 } 62 63 func TestMultiSourceAppWithHelmExternalValueFiles(t *testing.T) { 64 sources := []ApplicationSource{{ 65 RepoURL: RepoURL(RepoURLTypeFile), 66 Ref: "values", 67 }, { 68 RepoURL: RepoURL(RepoURLTypeFile), 69 TargetRevision: "HEAD", 70 Path: "helm-guestbook", 71 Helm: &ApplicationSourceHelm{ 72 ReleaseName: "helm-guestbook", 73 ValueFiles: []string{ 74 "$values/multiple-source-values/values.yaml", 75 }, 76 }, 77 }} 78 fmt.Printf("sources: %v\n", sources) 79 ctx := Given(t) 80 ctx. 81 Sources(sources). 82 When(). 83 CreateMultiSourceAppFromFile(). 84 Then(). 85 And(func(app *Application) { 86 assert.Equal(t, Name(), app.Name) 87 for i, source := range app.Spec.GetSources() { 88 assert.Equal(t, sources[i].RepoURL, source.RepoURL) 89 assert.Equal(t, sources[i].Path, source.Path) 90 } 91 assert.Equal(t, DeploymentNamespace(), app.Spec.Destination.Namespace) 92 assert.Equal(t, KubernetesInternalAPIServerAddr, app.Spec.Destination.Server) 93 }). 94 Expect(Event(EventReasonResourceCreated, "create")). 95 And(func(_ *Application) { 96 // app should be listed 97 output, err := RunCli("app", "list") 98 require.NoError(t, err) 99 assert.Contains(t, output, Name()) 100 }). 101 Expect(Success("")). 102 Given().Timeout(60). 103 When().Wait().Then(). 104 Expect(Success("")). 105 And(func(app *Application) { 106 statusByName := map[string]SyncStatusCode{} 107 for _, r := range app.Status.Resources { 108 statusByName[r.Name] = r.Status 109 } 110 assert.Len(t, statusByName, 1) 111 assert.Equal(t, SyncStatusCodeSynced, statusByName["guestbook-ui"]) 112 113 // Confirm that the deployment has 3 replicas. 114 output, err := Run("", "kubectl", "get", "deployment", "guestbook-ui", "-n", DeploymentNamespace(), "-o", "jsonpath={.spec.replicas}") 115 require.NoError(t, err) 116 assert.Equal(t, "3", output, "Expected 3 replicas for the helm-guestbook deployment") 117 }) 118 } 119 120 func TestMultiSourceAppWithSourceOverride(t *testing.T) { 121 sources := []ApplicationSource{{ 122 RepoURL: RepoURL(RepoURLTypeFile), 123 Path: guestbookPath, 124 }, { 125 RepoURL: RepoURL(RepoURLTypeFile), 126 Path: "two-nice-pods", 127 }, { 128 RepoURL: RepoURL(RepoURLTypeFile), 129 Path: "multiple-source-values", 130 }} 131 ctx := Given(t) 132 ctx. 133 Sources(sources). 134 When(). 135 CreateMultiSourceAppFromFile(). 136 Then(). 137 And(func(app *Application) { 138 assert.Equal(t, Name(), app.Name) 139 for i, source := range app.Spec.GetSources() { 140 assert.Equal(t, sources[i].RepoURL, source.RepoURL) 141 assert.Equal(t, sources[i].Path, source.Path) 142 } 143 assert.Equal(t, DeploymentNamespace(), app.Spec.Destination.Namespace) 144 assert.Equal(t, KubernetesInternalAPIServerAddr, app.Spec.Destination.Server) 145 }). 146 Expect(Event(EventReasonResourceCreated, "create")). 147 And(func(_ *Application) { 148 // app should be listed 149 output, err := RunCli("app", "list") 150 require.NoError(t, err) 151 assert.Contains(t, output, Name()) 152 }). 153 Expect(Success("")). 154 Given().Timeout(60). 155 When().Wait().Then(). 156 Expect(Success("")). 157 And(func(app *Application) { 158 statusByName := map[string]SyncStatusCode{} 159 for _, r := range app.Status.Resources { 160 statusByName[r.Name] = r.Status 161 } 162 // check if the app has 3 resources, guestbook and 2 pods 163 assert.Len(t, statusByName, 3) 164 assert.Equal(t, SyncStatusCodeSynced, statusByName["pod-1"]) 165 assert.Equal(t, SyncStatusCodeSynced, statusByName["pod-2"]) 166 assert.Equal(t, SyncStatusCodeSynced, statusByName["guestbook-ui"]) 167 168 // check if label was added to the pod to make sure resource was taken from the later source 169 output, err := Run("", "kubectl", "describe", "pods", "pod-1", "-n", DeploymentNamespace()) 170 require.NoError(t, err) 171 assert.Contains(t, output, "foo=bar") 172 }) 173 } 174 175 func TestMultiSourceAppWithSourceName(t *testing.T) { 176 sources := []ApplicationSource{{ 177 RepoURL: RepoURL(RepoURLTypeFile), 178 Path: guestbookPath, 179 Name: "guestbook", 180 }, { 181 RepoURL: RepoURL(RepoURLTypeFile), 182 Path: "two-nice-pods", 183 Name: "dynamic duo", 184 }} 185 ctx := Given(t) 186 ctx. 187 Sources(sources). 188 When(). 189 CreateMultiSourceAppFromFile(). 190 Then(). 191 And(func(app *Application) { 192 assert.Equal(t, Name(), app.Name) 193 for i, source := range app.Spec.GetSources() { 194 assert.Equal(t, sources[i].RepoURL, source.RepoURL) 195 assert.Equal(t, sources[i].Path, source.Path) 196 assert.Equal(t, sources[i].Name, source.Name) 197 } 198 assert.Equal(t, DeploymentNamespace(), app.Spec.Destination.Namespace) 199 assert.Equal(t, KubernetesInternalAPIServerAddr, app.Spec.Destination.Server) 200 }). 201 Expect(Event(EventReasonResourceCreated, "create")). 202 And(func(_ *Application) { 203 // we remove the first source 204 output, err := RunCli("app", "remove-source", Name(), "--source-name", sources[0].Name) 205 require.NoError(t, err) 206 assert.Contains(t, output, "updated successfully") 207 }). 208 Expect(Success("")). 209 And(func(app *Application) { 210 assert.Len(t, app.Spec.GetSources(), 1) 211 // we add a source 212 output, err := RunCli("app", "add-source", Name(), "--source-name", sources[0].Name, "--repo", RepoURL(RepoURLTypeFile), "--path", guestbookPath) 213 require.NoError(t, err) 214 assert.Contains(t, output, "updated successfully") 215 }). 216 Expect(Success("")). 217 Given().Timeout(60). 218 When().Wait().Then(). 219 Expect(Success("")). 220 And(func(app *Application) { 221 assert.Len(t, app.Spec.GetSources(), 2) 222 // sources order has been inverted 223 assert.Equal(t, sources[1].Name, app.Spec.GetSources()[0].Name) 224 assert.Equal(t, sources[0].Name, app.Spec.GetSources()[1].Name) 225 statusByName := map[string]SyncStatusCode{} 226 for _, r := range app.Status.Resources { 227 statusByName[r.Name] = r.Status 228 } 229 // check if the app has 3 resources, guestbook and 2 pods 230 assert.Len(t, statusByName, 3) 231 assert.Equal(t, SyncStatusCodeSynced, statusByName["pod-1"]) 232 assert.Equal(t, SyncStatusCodeSynced, statusByName["pod-2"]) 233 assert.Equal(t, SyncStatusCodeSynced, statusByName["guestbook-ui"]) 234 }) 235 } 236 237 func TestMultiSourceAppSetWithSourceName(t *testing.T) { 238 sources := []ApplicationSource{{ 239 RepoURL: RepoURL(RepoURLTypeFile), 240 Path: guestbookPath, 241 Name: "guestbook", 242 }, { 243 RepoURL: RepoURL(RepoURLTypeFile), 244 Path: "two-nice-pods", 245 Name: "dynamic duo", 246 }} 247 ctx := Given(t) 248 ctx. 249 Sources(sources). 250 When(). 251 CreateMultiSourceAppFromFile(). 252 Then(). 253 And(func(app *Application) { 254 assert.Equal(t, Name(), app.Name) 255 for i, source := range app.Spec.GetSources() { 256 assert.Equal(t, sources[i].RepoURL, source.RepoURL) 257 assert.Equal(t, sources[i].Path, source.Path) 258 assert.Equal(t, sources[i].Name, source.Name) 259 } 260 assert.Equal(t, DeploymentNamespace(), app.Spec.Destination.Namespace) 261 assert.Equal(t, KubernetesInternalAPIServerAddr, app.Spec.Destination.Server) 262 }). 263 Expect(Event(EventReasonResourceCreated, "create")). 264 And(func(_ *Application) { 265 _, err := RunCli("app", "set", Name(), "--source-name", sources[1].Name, "--path", "deployment") 266 require.NoError(t, err) 267 }). 268 Expect(Success("")). 269 And(func(app *Application) { 270 assert.Equal(t, "deployment", app.Spec.GetSources()[1].Path) 271 }) 272 } 273 274 func TestMultiSourceApptErrorWhenSourceNameAndSourcePosition(t *testing.T) { 275 sources := []ApplicationSource{{ 276 RepoURL: RepoURL(RepoURLTypeFile), 277 Path: guestbookPath, 278 Name: "guestbook", 279 }, { 280 RepoURL: RepoURL(RepoURLTypeFile), 281 Path: "two-nice-pods", 282 Name: "dynamic duo", 283 }} 284 ctx := Given(t) 285 ctx. 286 Sources(sources). 287 When(). 288 CreateMultiSourceAppFromFile(). 289 Then(). 290 Expect(Event(EventReasonResourceCreated, "create")). 291 And(func(_ *Application) { 292 _, err := RunCli("app", "get", Name(), "--source-name", sources[1].Name, "--source-position", "1") 293 assert.ErrorContains(t, err, "Only one of source-position and source-name can be specified.") 294 }). 295 And(func(_ *Application) { 296 _, err := RunCli("app", "manifests", Name(), "--revisions", "0.0.2", "--source-names", sources[0].Name, "--revisions", "0.0.2", "--source-positions", "1") 297 assert.ErrorContains(t, err, "Only one of source-positions and source-names can be specified.") 298 }) 299 }