github.com/argoproj/argo-cd/v2@v2.10.5/test/e2e/custom_tool_test.go (about) 1 package e2e 2 3 import ( 4 "os" 5 "path/filepath" 6 "sort" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/argoproj/gitops-engine/pkg/health" 12 . "github.com/argoproj/gitops-engine/pkg/sync/common" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 16 . "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" 17 . "github.com/argoproj/argo-cd/v2/test/e2e/fixture" 18 . "github.com/argoproj/argo-cd/v2/test/e2e/fixture/app" 19 . "github.com/argoproj/argo-cd/v2/util/errors" 20 ) 21 22 // make sure we can echo back the Git creds 23 func TestCustomToolWithGitCreds(t *testing.T) { 24 ctx := Given(t) 25 ctx. 26 And(func() { 27 go startCMPServer(t, "./testdata/cmp-gitcreds") 28 time.Sleep(1 * time.Second) 29 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 30 }). 31 CustomCACertAdded(). 32 // add the private repo with credentials 33 HTTPSRepoURLAdded(true). 34 RepoURLType(RepoURLTypeHTTPS). 35 Path("cmp-gitcreds"). 36 When(). 37 CreateApp(). 38 Sync(). 39 Then(). 40 Expect(OperationPhaseIs(OperationSucceeded)). 41 Expect(SyncStatusIs(SyncStatusCodeSynced)). 42 Expect(HealthIs(health.HealthStatusHealthy)) 43 } 44 45 // make sure we can echo back the Git creds 46 func TestCustomToolWithGitCredsTemplate(t *testing.T) { 47 ctx := Given(t) 48 ctx. 49 And(func() { 50 go startCMPServer(t, "./testdata/cmp-gitcredstemplate") 51 time.Sleep(1 * time.Second) 52 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 53 }). 54 CustomCACertAdded(). 55 // add the git creds template 56 HTTPSCredentialsUserPassAdded(). 57 // add the private repo without credentials 58 HTTPSRepoURLAdded(false). 59 RepoURLType(RepoURLTypeHTTPS). 60 Path("cmp-gitcredstemplate"). 61 When(). 62 CreateApp(). 63 Sync(). 64 Then(). 65 Expect(OperationPhaseIs(OperationSucceeded)). 66 Expect(SyncStatusIs(SyncStatusCodeSynced)). 67 Expect(HealthIs(health.HealthStatusHealthy)). 68 And(func(app *Application) { 69 output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.GitUsername}") 70 assert.NoError(t, err) 71 assert.Empty(t, output) 72 }). 73 And(func(app *Application) { 74 output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.GitPassword}") 75 assert.NoError(t, err) 76 assert.Empty(t, output) 77 }) 78 } 79 80 // make sure we can echo back the env 81 func TestCustomToolWithEnv(t *testing.T) { 82 ctx := Given(t) 83 ctx. 84 And(func() { 85 go startCMPServer(t, "./testdata/cmp-fileName") 86 time.Sleep(1 * time.Second) 87 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 88 }). 89 // does not matter what the path is 90 Path("cmp-fileName"). 91 When(). 92 CreateFromFile(func(app *Application) { 93 app.Spec.Source.Plugin = &ApplicationSourcePlugin{ 94 Env: Env{{ 95 Name: "FOO", 96 Value: "bar", 97 }}, 98 } 99 }). 100 Sync(). 101 Then(). 102 Expect(OperationPhaseIs(OperationSucceeded)). 103 Expect(SyncStatusIs(SyncStatusCodeSynced)). 104 Expect(HealthIs(health.HealthStatusHealthy)). 105 And(func(app *Application) { 106 time.Sleep(1 * time.Second) 107 }). 108 And(func(app *Application) { 109 output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.Bar}") 110 assert.NoError(t, err) 111 assert.Equal(t, "baz", output) 112 }). 113 And(func(app *Application) { 114 output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.Foo}") 115 assert.NoError(t, err) 116 assert.Equal(t, "bar", output) 117 }). 118 And(func(app *Application) { 119 expectedKubeVersion := GetVersions().ServerVersion.Format("%s.%s") 120 output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.KubeVersion}") 121 assert.NoError(t, err) 122 assert.Equal(t, expectedKubeVersion, output) 123 }). 124 And(func(app *Application) { 125 expectedApiVersion := GetApiResources() 126 expectedApiVersionSlice := strings.Split(expectedApiVersion, ",") 127 sort.Strings(expectedApiVersionSlice) 128 129 output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.KubeApiVersion}") 130 assert.NoError(t, err) 131 outputSlice := strings.Split(output, ",") 132 sort.Strings(outputSlice) 133 134 assert.EqualValues(t, expectedApiVersionSlice, outputSlice) 135 }) 136 } 137 138 // make sure we can sync and diff with --local 139 func TestCustomToolSyncAndDiffLocal(t *testing.T) { 140 testdataPath, err := filepath.Abs("testdata") 141 require.NoError(t, err) 142 ctx := Given(t) 143 appPath := filepath.Join(testdataPath, "guestbook") 144 ctx. 145 And(func() { 146 go startCMPServer(t, "./testdata/cmp-kustomize") 147 time.Sleep(1 * time.Second) 148 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 149 }). 150 // does not matter what the path is 151 Path("guestbook"). 152 When(). 153 CreateApp("--config-management-plugin", "cmp-kustomize-v1.0"). 154 Sync("--local", appPath, "--local-repo-root", testdataPath). 155 Then(). 156 Expect(OperationPhaseIs(OperationSucceeded)). 157 Expect(SyncStatusIs(SyncStatusCodeSynced)). 158 Expect(HealthIs(health.HealthStatusHealthy)). 159 And(func(app *Application) { 160 time.Sleep(1 * time.Second) 161 }). 162 And(func(app *Application) { 163 FailOnErr(RunCli("app", "sync", ctx.AppName(), "--local", appPath, "--local-repo-root", testdataPath)) 164 }). 165 And(func(app *Application) { 166 FailOnErr(RunCli("app", "diff", ctx.AppName(), "--local", appPath, "--local-repo-root", testdataPath)) 167 }) 168 } 169 170 func startCMPServer(t *testing.T, configFile string) { 171 pluginSockFilePath := TmpDir + PluginSockFilePath 172 t.Setenv("ARGOCD_BINARY_NAME", "argocd-cmp-server") 173 // ARGOCD_PLUGINSOCKFILEPATH should be set as the same value as repo server env var 174 t.Setenv("ARGOCD_PLUGINSOCKFILEPATH", pluginSockFilePath) 175 if _, err := os.Stat(pluginSockFilePath); os.IsNotExist(err) { 176 // path/to/whatever does not exist 177 err := os.Mkdir(pluginSockFilePath, 0700) 178 require.NoError(t, err) 179 } 180 FailOnErr(RunWithStdin("", "", "../../dist/argocd", "--config-dir-path", configFile)) 181 } 182 183 // Discover by fileName 184 func TestCMPDiscoverWithFileName(t *testing.T) { 185 pluginName := "cmp-fileName" 186 Given(t). 187 And(func() { 188 go startCMPServer(t, "./testdata/cmp-fileName") 189 time.Sleep(1 * time.Second) 190 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 191 }). 192 Path(pluginName + "/subdir"). 193 When(). 194 CreateApp(). 195 Sync(). 196 Then(). 197 Expect(OperationPhaseIs(OperationSucceeded)). 198 Expect(SyncStatusIs(SyncStatusCodeSynced)). 199 Expect(HealthIs(health.HealthStatusHealthy)) 200 } 201 202 // Discover by Find glob 203 func TestCMPDiscoverWithFindGlob(t *testing.T) { 204 Given(t). 205 And(func() { 206 go startCMPServer(t, "./testdata/cmp-find-glob") 207 time.Sleep(1 * time.Second) 208 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 209 }). 210 Path("guestbook"). 211 When(). 212 CreateApp(). 213 Sync(). 214 Then(). 215 Expect(OperationPhaseIs(OperationSucceeded)). 216 Expect(SyncStatusIs(SyncStatusCodeSynced)). 217 Expect(HealthIs(health.HealthStatusHealthy)) 218 } 219 220 // Discover by Plugin Name 221 func TestCMPDiscoverWithPluginName(t *testing.T) { 222 Given(t). 223 And(func() { 224 go startCMPServer(t, "./testdata/cmp-find-glob") 225 time.Sleep(1 * time.Second) 226 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 227 }). 228 Path("guestbook"). 229 When(). 230 CreateFromFile(func(app *Application) { 231 // specifically mention the plugin to use (name is based on <plugin name>-<version> 232 app.Spec.Source.Plugin = &ApplicationSourcePlugin{Name: "cmp-find-glob-v1.0"} 233 }). 234 Sync(). 235 Then(). 236 Expect(OperationPhaseIs(OperationSucceeded)). 237 Expect(SyncStatusIs(SyncStatusCodeSynced)). 238 Expect(HealthIs(health.HealthStatusHealthy)) 239 } 240 241 // Discover by Find command 242 func TestCMPDiscoverWithFindCommandWithEnv(t *testing.T) { 243 pluginName := "cmp-find-command" 244 ctx := Given(t) 245 ctx. 246 And(func() { 247 go startCMPServer(t, "./testdata/cmp-find-command") 248 time.Sleep(1 * time.Second) 249 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 250 }). 251 Path(pluginName). 252 When(). 253 CreateApp(). 254 Sync(). 255 Then(). 256 Expect(OperationPhaseIs(OperationSucceeded)). 257 Expect(SyncStatusIs(SyncStatusCodeSynced)). 258 Expect(HealthIs(health.HealthStatusHealthy)). 259 And(func(app *Application) { 260 time.Sleep(1 * time.Second) 261 }). 262 And(func(app *Application) { 263 output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.Bar}") 264 assert.NoError(t, err) 265 assert.Equal(t, "baz", output) 266 }). 267 And(func(app *Application) { 268 expectedKubeVersion := GetVersions().ServerVersion.Format("%s.%s") 269 output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.KubeVersion}") 270 assert.NoError(t, err) 271 assert.Equal(t, expectedKubeVersion, output) 272 }). 273 And(func(app *Application) { 274 expectedApiVersion := GetApiResources() 275 expectedApiVersionSlice := strings.Split(expectedApiVersion, ",") 276 sort.Strings(expectedApiVersionSlice) 277 278 output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.KubeApiVersion}") 279 assert.NoError(t, err) 280 outputSlice := strings.Split(output, ",") 281 sort.Strings(outputSlice) 282 283 assert.EqualValues(t, expectedApiVersionSlice, outputSlice) 284 }) 285 } 286 287 func TestPruneResourceFromCMP(t *testing.T) { 288 Given(t). 289 And(func() { 290 go startCMPServer(t, "./testdata/cmp-find-glob") 291 time.Sleep(1 * time.Second) 292 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 293 }). 294 Path("guestbook"). 295 When(). 296 CreateApp(). 297 Sync(). 298 Then(). 299 Expect(SyncStatusIs(SyncStatusCodeSynced)). 300 When(). 301 Delete(true). 302 Then(). 303 Expect(DoesNotExist()). 304 AndAction(func() { 305 _, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "deployment", "guestbook-ui") 306 assert.Error(t, err) 307 }) 308 } 309 310 func TestPreserveFileModeForCMP(t *testing.T) { 311 Given(t). 312 And(func() { 313 go startCMPServer(t, "./testdata/cmp-preserve-file-mode") 314 time.Sleep(1 * time.Second) 315 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 316 }). 317 Path("cmp-preserve-file-mode"). 318 When(). 319 CreateFromFile(func(app *Application) { 320 app.Spec.Source.Plugin = &ApplicationSourcePlugin{Name: "cmp-preserve-file-mode-v1.0"} 321 }). 322 Refresh(RefreshTypeNormal). 323 Then(). 324 And(func(app *Application) { 325 require.Len(t, app.Status.Resources, 1) 326 assert.Equal(t, "ConfigMap", app.Status.Resources[0].Kind) 327 }) 328 } 329 330 func TestCMPWithSymlinkPartialFiles(t *testing.T) { 331 Given(t, WithTestData("testdata2")). 332 And(func() { 333 go startCMPServer(t, "./testdata2/cmp-symlink") 334 time.Sleep(1 * time.Second) 335 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 336 }). 337 Path("guestbook-partial-symlink-files"). 338 When(). 339 CreateApp(). 340 Sync(). 341 Then(). 342 Expect(OperationPhaseIs(OperationSucceeded)). 343 Expect(SyncStatusIs(SyncStatusCodeSynced)). 344 Expect(HealthIs(health.HealthStatusHealthy)) 345 } 346 347 func TestCMPWithSymlinkFiles(t *testing.T) { 348 Given(t, WithTestData("testdata2")). 349 And(func() { 350 go startCMPServer(t, "./testdata2/cmp-symlink") 351 time.Sleep(1 * time.Second) 352 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 353 }). 354 Path("guestbook-symlink-files"). 355 When(). 356 CreateApp(). 357 Sync(). 358 Then(). 359 Expect(OperationPhaseIs(OperationSucceeded)). 360 Expect(SyncStatusIs(SyncStatusCodeSynced)). 361 Expect(HealthIs(health.HealthStatusHealthy)) 362 } 363 364 func TestCMPWithSymlinkFolder(t *testing.T) { 365 Given(t, WithTestData("testdata2")). 366 And(func() { 367 go startCMPServer(t, "./testdata2/cmp-symlink") 368 time.Sleep(1 * time.Second) 369 t.Setenv("ARGOCD_BINARY_NAME", "argocd") 370 }). 371 Path("guestbook-symlink-folder"). 372 When(). 373 CreateApp(). 374 Sync(). 375 Then(). 376 Expect(OperationPhaseIs(OperationSucceeded)). 377 Expect(SyncStatusIs(SyncStatusCodeSynced)). 378 Expect(HealthIs(health.HealthStatusHealthy)) 379 }