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  }