github.com/argoproj/argo-cd/v2@v2.10.5/test/e2e/fixture/app/actions.go (about)

     1  package app
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  
     8  	log "github.com/sirupsen/logrus"
     9  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  
    11  	client "github.com/argoproj/argo-cd/v2/pkg/apiclient/application"
    12  	. "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
    13  	"github.com/argoproj/argo-cd/v2/test/e2e/fixture"
    14  	"github.com/argoproj/argo-cd/v2/util/errors"
    15  	"github.com/argoproj/argo-cd/v2/util/grpc"
    16  )
    17  
    18  // this implements the "when" part of given/when/then
    19  //
    20  // none of the func implement error checks, and that is complete intended, you should check for errors
    21  // using the Then()
    22  type Actions struct {
    23  	context      *Context
    24  	lastOutput   string
    25  	lastError    error
    26  	ignoreErrors bool
    27  }
    28  
    29  func (a *Actions) IgnoreErrors() *Actions {
    30  	a.ignoreErrors = true
    31  	return a
    32  }
    33  
    34  func (a *Actions) DoNotIgnoreErrors() *Actions {
    35  	a.ignoreErrors = false
    36  	return a
    37  }
    38  
    39  func (a *Actions) PatchFile(file string, jsonPath string) *Actions {
    40  	a.context.t.Helper()
    41  	fixture.Patch(a.context.path+"/"+file, jsonPath)
    42  	return a
    43  }
    44  
    45  func (a *Actions) DeleteFile(file string) *Actions {
    46  	a.context.t.Helper()
    47  	fixture.Delete(a.context.path + "/" + file)
    48  	return a
    49  }
    50  
    51  func (a *Actions) WriteFile(fileName, fileContents string) *Actions {
    52  	a.context.t.Helper()
    53  	fixture.WriteFile(a.context.path+"/"+fileName, fileContents)
    54  	return a
    55  }
    56  
    57  func (a *Actions) AddFile(fileName, fileContents string) *Actions {
    58  	a.context.t.Helper()
    59  	fixture.AddFile(a.context.path+"/"+fileName, fileContents)
    60  	return a
    61  }
    62  
    63  func (a *Actions) AddSignedFile(fileName, fileContents string) *Actions {
    64  	a.context.t.Helper()
    65  	fixture.AddSignedFile(a.context.path+"/"+fileName, fileContents)
    66  	return a
    67  }
    68  
    69  func (a *Actions) AddSignedTag(name string) *Actions {
    70  	a.context.t.Helper()
    71  	fixture.AddSignedTag(name)
    72  	return a
    73  }
    74  
    75  func (a *Actions) AddTag(name string) *Actions {
    76  	a.context.t.Helper()
    77  	fixture.AddTag(name)
    78  	return a
    79  }
    80  
    81  func (a *Actions) RemoveSubmodule() *Actions {
    82  	a.context.t.Helper()
    83  	fixture.RemoveSubmodule()
    84  	return a
    85  }
    86  
    87  func (a *Actions) CreateFromPartialFile(data string, flags ...string) *Actions {
    88  	a.context.t.Helper()
    89  	tmpFile, err := os.CreateTemp("", "")
    90  	errors.CheckError(err)
    91  	_, err = tmpFile.Write([]byte(data))
    92  	errors.CheckError(err)
    93  
    94  	args := append([]string{
    95  		"app", "create",
    96  		"-f", tmpFile.Name(),
    97  		"--name", a.context.AppName(),
    98  		"--repo", fixture.RepoURL(a.context.repoURLType),
    99  		"--dest-server", a.context.destServer,
   100  		"--dest-namespace", fixture.DeploymentNamespace(),
   101  	}, flags...)
   102  	if a.context.appNamespace != "" {
   103  		args = append(args, "--app-namespace", a.context.appNamespace)
   104  	}
   105  	defer tmpFile.Close()
   106  	a.runCli(args...)
   107  	return a
   108  }
   109  func (a *Actions) CreateFromFile(handler func(app *Application), flags ...string) *Actions {
   110  	a.context.t.Helper()
   111  	app := &Application{
   112  		ObjectMeta: v1.ObjectMeta{
   113  			Name:      a.context.AppName(),
   114  			Namespace: a.context.AppNamespace(),
   115  		},
   116  		Spec: ApplicationSpec{
   117  			Project: a.context.project,
   118  			Source: &ApplicationSource{
   119  				RepoURL: fixture.RepoURL(a.context.repoURLType),
   120  				Path:    a.context.path,
   121  			},
   122  			Destination: ApplicationDestination{
   123  				Server:    a.context.destServer,
   124  				Namespace: fixture.DeploymentNamespace(),
   125  			},
   126  		},
   127  	}
   128  	source := app.Spec.GetSource()
   129  	if a.context.namePrefix != "" || a.context.nameSuffix != "" {
   130  		source.Kustomize = &ApplicationSourceKustomize{
   131  			NamePrefix: a.context.namePrefix,
   132  			NameSuffix: a.context.nameSuffix,
   133  		}
   134  	}
   135  	if a.context.configManagementPlugin != "" {
   136  		source.Plugin = &ApplicationSourcePlugin{
   137  			Name: a.context.configManagementPlugin,
   138  		}
   139  	}
   140  
   141  	if len(a.context.parameters) > 0 {
   142  		log.Fatal("Application parameters or json tlas are not supported")
   143  	}
   144  
   145  	if a.context.directoryRecurse {
   146  		source.Directory = &ApplicationSourceDirectory{Recurse: true}
   147  	}
   148  	app.Spec.Source = &source
   149  
   150  	handler(app)
   151  	data := grpc.MustMarshal(app)
   152  	tmpFile, err := os.CreateTemp("", "")
   153  	errors.CheckError(err)
   154  	_, err = tmpFile.Write(data)
   155  	errors.CheckError(err)
   156  
   157  	args := append([]string{
   158  		"app", "create",
   159  		"-f", tmpFile.Name(),
   160  	}, flags...)
   161  	defer tmpFile.Close()
   162  	a.runCli(args...)
   163  	return a
   164  }
   165  
   166  func (a *Actions) CreateMultiSourceAppFromFile(flags ...string) *Actions {
   167  	a.context.t.Helper()
   168  	app := &Application{
   169  		ObjectMeta: v1.ObjectMeta{
   170  			Name:      a.context.AppName(),
   171  			Namespace: a.context.AppNamespace(),
   172  		},
   173  		Spec: ApplicationSpec{
   174  			Project: a.context.project,
   175  			Sources: a.context.sources,
   176  			Destination: ApplicationDestination{
   177  				Server:    a.context.destServer,
   178  				Namespace: fixture.DeploymentNamespace(),
   179  			},
   180  			SyncPolicy: &SyncPolicy{
   181  				Automated: &SyncPolicyAutomated{
   182  					SelfHeal: true,
   183  				},
   184  			},
   185  		},
   186  	}
   187  
   188  	data := grpc.MustMarshal(app)
   189  	tmpFile, err := os.CreateTemp("", "")
   190  	errors.CheckError(err)
   191  	_, err = tmpFile.Write(data)
   192  	errors.CheckError(err)
   193  
   194  	args := append([]string{
   195  		"app", "create",
   196  		"-f", tmpFile.Name(),
   197  	}, flags...)
   198  	defer tmpFile.Close()
   199  	a.runCli(args...)
   200  	return a
   201  }
   202  
   203  func (a *Actions) CreateWithNoNameSpace(args ...string) *Actions {
   204  	args = a.prepareCreateAppArgs(args)
   205  	//  are you adding new context values? if you only use them for this func, then use args instead
   206  	a.runCli(args...)
   207  	return a
   208  }
   209  
   210  func (a *Actions) CreateApp(args ...string) *Actions {
   211  	args = a.prepareCreateAppArgs(args)
   212  	args = append(args, "--dest-namespace", fixture.DeploymentNamespace())
   213  
   214  	//  are you adding new context values? if you only use them for this func, then use args instead
   215  	a.runCli(args...)
   216  
   217  	return a
   218  }
   219  
   220  func (a *Actions) prepareCreateAppArgs(args []string) []string {
   221  	a.context.t.Helper()
   222  	args = append([]string{
   223  		"app", "create", a.context.AppQualifiedName(),
   224  		"--repo", fixture.RepoURL(a.context.repoURLType),
   225  	}, args...)
   226  
   227  	if a.context.destName != "" {
   228  		args = append(args, "--dest-name", a.context.destName)
   229  	} else {
   230  		args = append(args, "--dest-server", a.context.destServer)
   231  	}
   232  	if a.context.path != "" {
   233  		args = append(args, "--path", a.context.path)
   234  	}
   235  
   236  	if a.context.chart != "" {
   237  		args = append(args, "--helm-chart", a.context.chart)
   238  	}
   239  
   240  	if a.context.env != "" {
   241  		args = append(args, "--env", a.context.env)
   242  	}
   243  
   244  	for _, parameter := range a.context.parameters {
   245  		args = append(args, "--parameter", parameter)
   246  	}
   247  
   248  	args = append(args, "--project", a.context.project)
   249  
   250  	if a.context.namePrefix != "" {
   251  		args = append(args, "--nameprefix", a.context.namePrefix)
   252  	}
   253  
   254  	if a.context.nameSuffix != "" {
   255  		args = append(args, "--namesuffix", a.context.nameSuffix)
   256  	}
   257  
   258  	if a.context.configManagementPlugin != "" {
   259  		args = append(args, "--config-management-plugin", a.context.configManagementPlugin)
   260  	}
   261  
   262  	if a.context.revision != "" {
   263  		args = append(args, "--revision", a.context.revision)
   264  	}
   265  	if a.context.helmPassCredentials {
   266  		args = append(args, "--helm-pass-credentials")
   267  	}
   268  	if a.context.helmSkipCrds {
   269  		args = append(args, "--helm-skip-crds")
   270  	}
   271  	return args
   272  }
   273  
   274  func (a *Actions) Declarative(filename string) *Actions {
   275  	a.context.t.Helper()
   276  	return a.DeclarativeWithCustomRepo(filename, fixture.RepoURL(a.context.repoURLType))
   277  }
   278  
   279  func (a *Actions) DeclarativeWithCustomRepo(filename string, repoURL string) *Actions {
   280  	a.context.t.Helper()
   281  	values := map[string]interface{}{
   282  		"ArgoCDNamespace":     fixture.TestNamespace(),
   283  		"DeploymentNamespace": fixture.DeploymentNamespace(),
   284  		"Name":                a.context.AppName(),
   285  		"Path":                a.context.path,
   286  		"Project":             a.context.project,
   287  		"RepoURL":             repoURL,
   288  	}
   289  	a.lastOutput, a.lastError = fixture.Declarative(filename, values)
   290  	a.verifyAction()
   291  	return a
   292  }
   293  
   294  func (a *Actions) PatchApp(patch string) *Actions {
   295  	a.context.t.Helper()
   296  	a.runCli("app", "patch", a.context.AppQualifiedName(), "--patch", patch)
   297  	return a
   298  }
   299  
   300  func (a *Actions) PatchAppHttp(patch string) *Actions {
   301  	a.context.t.Helper()
   302  	var application Application
   303  	var patchType = "merge"
   304  	var appName = a.context.AppQualifiedName()
   305  	var appNamespace = a.context.AppNamespace()
   306  	patchRequest := &client.ApplicationPatchRequest{
   307  		Name:         &appName,
   308  		PatchType:    &patchType,
   309  		Patch:        &patch,
   310  		AppNamespace: &appNamespace,
   311  	}
   312  	jsonBytes, err := json.MarshalIndent(patchRequest, "", "  ")
   313  	errors.CheckError(err)
   314  	err = fixture.DoHttpJsonRequest("PATCH",
   315  		fmt.Sprintf("/api/v1/applications/%v", appName),
   316  		&application,
   317  		jsonBytes...)
   318  	errors.CheckError(err)
   319  	return a
   320  }
   321  
   322  func (a *Actions) AppSet(flags ...string) *Actions {
   323  	a.context.t.Helper()
   324  	args := []string{"app", "set", a.context.AppQualifiedName()}
   325  	args = append(args, flags...)
   326  	a.runCli(args...)
   327  	return a
   328  }
   329  
   330  func (a *Actions) AppUnSet(flags ...string) *Actions {
   331  	a.context.t.Helper()
   332  	args := []string{"app", "unset", a.context.AppQualifiedName()}
   333  	args = append(args, flags...)
   334  	a.runCli(args...)
   335  	return a
   336  }
   337  
   338  func (a *Actions) Sync(args ...string) *Actions {
   339  	a.context.t.Helper()
   340  	args = append([]string{"app", "sync"}, args...)
   341  	if a.context.name != "" {
   342  		args = append(args, a.context.AppQualifiedName())
   343  	}
   344  	args = append(args, "--timeout", fmt.Sprintf("%v", a.context.timeout))
   345  
   346  	if a.context.async {
   347  		args = append(args, "--async")
   348  	}
   349  
   350  	if a.context.prune {
   351  		args = append(args, "--prune")
   352  	}
   353  
   354  	if a.context.resource != "" {
   355  		// Waiting for the app to be successfully created.
   356  		// Else the sync would fail to retrieve the app resources.
   357  		a.context.Sleep(5)
   358  		args = append(args, "--resource", a.context.resource)
   359  	}
   360  
   361  	if a.context.localPath != "" {
   362  		args = append(args, "--local", a.context.localPath)
   363  	}
   364  
   365  	if a.context.force {
   366  		args = append(args, "--force")
   367  	}
   368  
   369  	if a.context.applyOutOfSyncOnly {
   370  		args = append(args, "--apply-out-of-sync-only")
   371  	}
   372  
   373  	if a.context.replace {
   374  		args = append(args, "--replace")
   375  	}
   376  
   377  	//  are you adding new context values? if you only use them for this func, then use args instead
   378  
   379  	a.runCli(args...)
   380  
   381  	return a
   382  }
   383  
   384  func (a *Actions) TerminateOp() *Actions {
   385  	a.context.t.Helper()
   386  	a.runCli("app", "terminate-op", a.context.AppQualifiedName())
   387  	return a
   388  }
   389  
   390  func (a *Actions) Refresh(refreshType RefreshType) *Actions {
   391  	a.context.t.Helper()
   392  	flag := map[RefreshType]string{
   393  		RefreshTypeNormal: "--refresh",
   394  		RefreshTypeHard:   "--hard-refresh",
   395  	}[refreshType]
   396  
   397  	a.runCli("app", "get", a.context.AppQualifiedName(), flag)
   398  
   399  	return a
   400  }
   401  
   402  func (a *Actions) Get() *Actions {
   403  	a.context.t.Helper()
   404  	a.runCli("app", "get", a.context.AppQualifiedName())
   405  	return a
   406  }
   407  
   408  func (a *Actions) Delete(cascade bool) *Actions {
   409  	a.context.t.Helper()
   410  	a.runCli("app", "delete", a.context.AppQualifiedName(), fmt.Sprintf("--cascade=%v", cascade), "--yes")
   411  	return a
   412  }
   413  
   414  func (a *Actions) DeleteBySelector(selector string) *Actions {
   415  	a.context.t.Helper()
   416  	a.runCli("app", "delete", fmt.Sprintf("--selector=%s", selector), "--yes")
   417  	return a
   418  }
   419  
   420  func (a *Actions) Wait(args ...string) *Actions {
   421  	a.context.t.Helper()
   422  	args = append([]string{"app", "wait"}, args...)
   423  	if a.context.name != "" {
   424  		args = append(args, a.context.AppQualifiedName())
   425  	}
   426  	args = append(args, "--timeout", fmt.Sprintf("%v", a.context.timeout))
   427  	a.runCli(args...)
   428  	return a
   429  }
   430  
   431  func (a *Actions) SetParamInSettingConfigMap(key, value string) *Actions {
   432  	fixture.SetParamInSettingConfigMap(key, value)
   433  	return a
   434  }
   435  
   436  func (a *Actions) And(block func()) *Actions {
   437  	a.context.t.Helper()
   438  	block()
   439  	return a
   440  }
   441  
   442  func (a *Actions) Then() *Consequences {
   443  	a.context.t.Helper()
   444  	return &Consequences{a.context, a, 15}
   445  }
   446  
   447  func (a *Actions) runCli(args ...string) {
   448  	a.context.t.Helper()
   449  	a.lastOutput, a.lastError = fixture.RunCli(args...)
   450  	a.verifyAction()
   451  }
   452  
   453  func (a *Actions) verifyAction() {
   454  	a.context.t.Helper()
   455  	if !a.ignoreErrors {
   456  		a.Then().Expect(Success(""))
   457  	}
   458  }
   459  
   460  func (a *Actions) SetTrackingMethod(trackingMethod string) *Actions {
   461  	fixture.SetTrackingMethod(trackingMethod)
   462  	return a
   463  }
   464  
   465  func (a *Actions) SetTrackingLabel(trackingLabel string) *Actions {
   466  	fixture.SetTrackingLabel(trackingLabel)
   467  	return a
   468  }