github.com/DelineaXPM/dsv-cli@v1.40.6/tests/e2e/cmd_init_test.go (about)

     1  //go:build endtoend
     2  // +build endtoend
     3  
     4  package e2e
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"path/filepath"
    10  	"runtime"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  func TestInitWithNoConfig(t *testing.T) {
    16  	if runtime.GOOS == "windows" {
    17  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
    18  	}
    19  	e := newEnv()
    20  
    21  	var (
    22  		config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
    23  	)
    24  
    25  	defer func() { deleteFile(t, config) }()
    26  
    27  	cmd := []string{
    28  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
    29  	}
    30  
    31  	runFlow(t, cmd, func(c console) {
    32  		c.ExpectString("Please enter tenant name")
    33  		c.SendLine(e.tenant)
    34  
    35  		c.ExpectString("Please select store type")
    36  		c.SendKeyEnter()
    37  
    38  		c.ExpectString("Please enter directory for file store")
    39  		c.SendKeyEnter()
    40  
    41  		c.ExpectString("Please enter cache strategy for secrets")
    42  		c.SendKeyEnter()
    43  
    44  		c.ExpectString("Please enter auth type")
    45  		c.SendKeyEnter()
    46  
    47  		c.ExpectString("Please enter username")
    48  		c.SendLine(e.username)
    49  
    50  		c.ExpectString("Please enter password")
    51  		c.SendLine(e.password)
    52  
    53  		c.ExpectEOF()
    54  	})
    55  
    56  	got := readFile(t, config)
    57  	requireLine(t, got, "default:")
    58  	requireLine(t, got, "auth:")
    59  	requireLine(t, got, "type: password")
    60  	requireLine(t, got, fmt.Sprintf("username: %s", e.username))
    61  	requireLine(t, got, "cache:")
    62  	requireLine(t, got, "strategy: server")
    63  	requireLine(t, got, fmt.Sprintf("domain: %s", e.domain))
    64  	requireLine(t, got, "store:")
    65  	requireLine(t, got, "type: file")
    66  	requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant))
    67  }
    68  
    69  func TestInitWithExistingConfig(t *testing.T) {
    70  	if runtime.GOOS == "windows" {
    71  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
    72  	}
    73  	e := newEnv()
    74  
    75  	const (
    76  		profileName = "automation"
    77  		cacheAge    = "5"
    78  	)
    79  	var (
    80  		config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
    81  	)
    82  
    83  	createFile(t, config)
    84  	defer func() { deleteFile(t, config) }()
    85  
    86  	cmd := []string{
    87  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
    88  	}
    89  
    90  	runFlow(t, cmd, func(c console) {
    91  		c.ExpectString("Found an existing cli-config located at")
    92  		c.ExpectString("Select an option")
    93  		c.SendKeyArrowDown()
    94  		c.SendKeyArrowDown()
    95  		c.SendKeyEnter()
    96  
    97  		c.ExpectString("Please enter profile name")
    98  		c.SendLine(profileName)
    99  
   100  		c.ExpectString("Please enter tenant name")
   101  		c.SendLine(e.tenant)
   102  
   103  		c.ExpectString("Please select store type")
   104  		c.SendKeyEnter()
   105  
   106  		c.ExpectString("Please enter directory for file store")
   107  		c.SendKeyEnter()
   108  
   109  		c.ExpectString("Please enter cache strategy for secrets")
   110  		c.SendKeyArrowDown()
   111  		c.SendKeyArrowDown()
   112  		c.SendKeyEnter()
   113  
   114  		c.ExpectString("Please enter cache age (minutes until expiration)")
   115  		c.SendLine("a")
   116  
   117  		c.ExpectString("Sorry, your reply was invalid: Unable to parse age.")
   118  		c.SendLine("-2")
   119  
   120  		c.ExpectString("Sorry, your reply was invalid: Unable to parse age.")
   121  		c.SendLine("0")
   122  
   123  		c.ExpectString("Sorry, your reply was invalid: Unable to parse age.")
   124  		c.SendLine(cacheAge)
   125  
   126  		c.ExpectString("Please enter auth type")
   127  		c.SendKeyEnter()
   128  
   129  		c.ExpectString("Please enter username")
   130  		c.SendLine(e.username)
   131  
   132  		c.ExpectString("Please enter password")
   133  		c.SendLine(e.password)
   134  
   135  		c.ExpectEOF()
   136  	})
   137  
   138  	got := readFile(t, config)
   139  	requireLine(t, got, fmt.Sprintf("%s:", profileName))
   140  	requireLine(t, got, "auth:")
   141  	requireLine(t, got, "type: password")
   142  	requireLine(t, got, fmt.Sprintf("username: %s", e.username))
   143  	requireLine(t, got, "cache:")
   144  	requireLine(t, got, fmt.Sprintf("age: %s", cacheAge))
   145  	requireLine(t, got, "strategy: cache.server")
   146  	requireLine(t, got, fmt.Sprintf("domain: %s", e.domain))
   147  	requireLine(t, got, "store:")
   148  	requireLine(t, got, "type: file")
   149  	requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant))
   150  }
   151  
   152  func TestInitOverwriteExistingConfig(t *testing.T) {
   153  	if runtime.GOOS == "windows" {
   154  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
   155  	}
   156  	e := newEnv()
   157  
   158  	var (
   159  		config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
   160  	)
   161  
   162  	createFile(t, config)
   163  	defer func() { deleteFile(t, config) }()
   164  
   165  	cmd := []string{
   166  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
   167  	}
   168  
   169  	runFlow(t, cmd, func(c console) {
   170  		c.ExpectString("Found an existing cli-config located at")
   171  		c.ExpectString("Select an option")
   172  		c.SendKeyArrowDown()
   173  		c.SendKeyEnter()
   174  
   175  		c.ExpectString("Please enter profile name")
   176  		c.SendKeyEnter()
   177  
   178  		c.ExpectString("Please enter tenant name")
   179  		c.SendLine(e.tenant)
   180  
   181  		c.ExpectString("Please select store type")
   182  		c.SendKeyEnter()
   183  
   184  		c.ExpectString("Please enter directory for file store")
   185  		c.SendKeyEnter()
   186  
   187  		c.ExpectString("Please enter cache strategy for secrets")
   188  		c.SendKeyEnter()
   189  
   190  		c.ExpectString("Please enter auth type")
   191  		c.SendKeyEnter()
   192  
   193  		c.ExpectString("Please enter username")
   194  		c.SendLine(e.username)
   195  
   196  		c.ExpectString("Please enter password")
   197  		c.SendLine(e.password)
   198  
   199  		c.ExpectEOF()
   200  	})
   201  
   202  	got := readFile(t, config)
   203  	requireLine(t, got, "default:")
   204  	requireLine(t, got, "auth:")
   205  	requireLine(t, got, "type: password")
   206  	requireLine(t, got, fmt.Sprintf("username: %s", e.username))
   207  	requireLine(t, got, "cache:")
   208  	requireLine(t, got, "strategy: server")
   209  	requireLine(t, got, fmt.Sprintf("domain: %s", e.domain))
   210  	requireLine(t, got, "store:")
   211  	requireLine(t, got, "type: file")
   212  	requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant))
   213  }
   214  
   215  func TestInitAuthFails(t *testing.T) {
   216  	if runtime.GOOS == "windows" {
   217  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
   218  	}
   219  	e := newEnv()
   220  
   221  	var (
   222  		config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
   223  	)
   224  
   225  	createFile(t, config)
   226  	defer func() { deleteFile(t, config) }()
   227  
   228  	cmd := []string{
   229  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
   230  	}
   231  
   232  	runFlow(t, cmd, func(c console) {
   233  		c.ExpectString("Found an existing cli-config located at")
   234  		c.ExpectString("Select an option")
   235  		c.SendKeyArrowDown()
   236  		c.SendKeyArrowDown()
   237  		c.SendKeyEnter()
   238  
   239  		c.ExpectString("Please enter profile name")
   240  		c.SendLine("automation")
   241  
   242  		c.ExpectString("Please enter tenant name")
   243  		c.SendLine(e.tenant)
   244  
   245  		c.ExpectString("Please select store type")
   246  		c.SendKeyEnter()
   247  
   248  		c.ExpectString("Please enter directory for file store")
   249  		c.SendKeyEnter()
   250  
   251  		c.ExpectString("Please enter cache strategy for secrets")
   252  		c.SendKeyEnter()
   253  
   254  		c.ExpectString("Please enter auth type")
   255  		c.SendKeyEnter()
   256  
   257  		c.ExpectString("Please enter username")
   258  		c.SendLine("random-username-that-definitely-does-not-exist")
   259  
   260  		c.ExpectString("Please enter password")
   261  		c.SendLine("n0t-a-Stronges-P@assWord")
   262  
   263  		c.ExpectString("Failed to authenticate, restoring previous config.")
   264  		c.ExpectEOF()
   265  	})
   266  }
   267  
   268  func TestInitAWSInvalid(t *testing.T) {
   269  	if runtime.GOOS == "windows" {
   270  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
   271  	}
   272  	e := newEnv()
   273  
   274  	var (
   275  		config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
   276  	)
   277  
   278  	createFile(t, config)
   279  	defer func() { deleteFile(t, config) }()
   280  
   281  	cmd := []string{
   282  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
   283  	}
   284  
   285  	runFlow(t, cmd, func(c console) {
   286  		c.ExpectString("Found an existing cli-config located at")
   287  		c.ExpectString("Select an option")
   288  		c.SendKeyArrowDown()
   289  		c.SendKeyEnter()
   290  
   291  		c.ExpectString("Please enter profile name")
   292  		c.SendKeyEnter()
   293  
   294  		c.ExpectString("Please enter tenant name")
   295  		c.SendLine(e.tenant)
   296  
   297  		c.ExpectString("Please select store type")
   298  		c.SendKeyEnter()
   299  
   300  		c.ExpectString("Please enter directory for file store")
   301  		c.SendKeyEnter()
   302  
   303  		c.ExpectString("Please enter cache strategy for secrets")
   304  		c.SendKeyEnter()
   305  
   306  		c.ExpectString("Please enter auth type")
   307  		c.SendKeyArrowDown()
   308  		c.SendKeyArrowDown()
   309  		c.SendKeyArrowDown()
   310  		c.SendKeyEnter()
   311  
   312  		c.ExpectString("Please enter aws profile for federated aws auth")
   313  		c.SendLine("not-a-real-profile")
   314  
   315  		c.ExpectString("Failed to authenticate, restoring previous config.")
   316  		c.ExpectEOF()
   317  	})
   318  }
   319  
   320  func TestInitClientCredsInvalid(t *testing.T) {
   321  	if runtime.GOOS == "windows" {
   322  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
   323  	}
   324  	e := newEnv()
   325  
   326  	var (
   327  		config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
   328  	)
   329  
   330  	createFile(t, config)
   331  	defer func() { deleteFile(t, config) }()
   332  
   333  	cmd := []string{
   334  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
   335  	}
   336  
   337  	runFlow(t, cmd, func(c console) {
   338  		c.ExpectString("Found an existing cli-config located at")
   339  		c.ExpectString("Select an option")
   340  		c.SendKeyArrowDown()
   341  		c.SendKeyEnter()
   342  
   343  		c.ExpectString("Please enter profile name")
   344  		c.SendKeyEnter()
   345  
   346  		c.ExpectString("Please enter tenant name")
   347  		c.SendLine(e.tenant)
   348  
   349  		c.ExpectString("Please select store type")
   350  		c.SendKeyEnter()
   351  
   352  		c.ExpectString("Please enter directory for file store")
   353  		c.SendKeyEnter()
   354  
   355  		c.ExpectString("Please enter cache strategy for secrets")
   356  		c.SendKeyEnter()
   357  
   358  		c.ExpectString("Please enter auth type")
   359  		c.SendKeyArrowDown()
   360  		c.SendKeyEnter()
   361  
   362  		c.ExpectString("Please enter client id for client auth")
   363  		c.SendLine("not-a-real-client-id")
   364  
   365  		c.ExpectString("Please enter client secret for client auth")
   366  		c.SendLine("not-a-real-client-secret")
   367  
   368  		c.ExpectString("Failed to authenticate, restoring previous config.")
   369  		c.ExpectEOF()
   370  	})
   371  }
   372  
   373  func TestInitProfileExists(t *testing.T) {
   374  	if runtime.GOOS == "windows" {
   375  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
   376  	}
   377  	e := newEnv()
   378  
   379  	var (
   380  		config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
   381  	)
   382  
   383  	defer func() { deleteFile(t, config) }()
   384  
   385  	cmd := []string{
   386  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
   387  	}
   388  
   389  	runFlow(t, cmd, func(c console) {
   390  		c.ExpectString("Please enter tenant name")
   391  		c.SendLine(e.tenant)
   392  
   393  		c.ExpectString("Please select store type")
   394  		c.SendKeyEnter()
   395  
   396  		c.ExpectString("Please enter directory for file store")
   397  		c.SendKeyEnter()
   398  
   399  		c.ExpectString("Please enter cache strategy for secrets")
   400  		c.SendKeyEnter()
   401  
   402  		c.ExpectString("Please enter auth type")
   403  		c.SendKeyEnter()
   404  
   405  		c.ExpectString("Please enter username")
   406  		c.SendLine(e.username)
   407  
   408  		c.ExpectString("Please enter password")
   409  		c.SendLine(e.password)
   410  
   411  		c.ExpectEOF()
   412  	})
   413  
   414  	cmd = []string{
   415  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config), "--profile=default",
   416  	}
   417  
   418  	runFlow(t, cmd, func(c console) {
   419  		c.ExpectString("Profile \"default\" already exists in the config.")
   420  		c.ExpectEOF()
   421  	})
   422  }
   423  
   424  func TestInitWrongStoreType(t *testing.T) {
   425  	if runtime.GOOS == "windows" {
   426  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
   427  	}
   428  	e := newEnv()
   429  
   430  	var (
   431  		config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
   432  	)
   433  
   434  	cmd := []string{
   435  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
   436  	}
   437  
   438  	runFlow(t, cmd, func(c console) {
   439  		c.ExpectString("Please enter tenant name")
   440  		c.SendLine(e.tenant)
   441  
   442  		c.ExpectString("Please select store type")
   443  		c.SendKeyArrowDown()
   444  		c.SendKeyArrowDown()
   445  		c.SendKeyArrowDown()
   446  		c.SendKeyEnter()
   447  
   448  		c.ExpectString("Failed to get store: 'wincred' option for store.type is supported on windows only.")
   449  		c.ExpectEOF()
   450  	})
   451  }
   452  
   453  func TestInitWithNoStore(t *testing.T) {
   454  	if runtime.GOOS == "windows" {
   455  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
   456  	}
   457  	e := newEnv()
   458  
   459  	var (
   460  		config = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
   461  	)
   462  
   463  	defer func() { deleteFile(t, config) }()
   464  
   465  	cmd := []string{
   466  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
   467  	}
   468  
   469  	runFlow(t, cmd, func(c console) {
   470  		c.ExpectString("Please enter tenant name")
   471  		c.SendLine(e.tenant)
   472  
   473  		c.ExpectString("Please select store type")
   474  		c.SendKeyArrowDown()
   475  		c.SendKeyEnter()
   476  
   477  		c.ExpectString("Please enter auth type")
   478  		c.SendKeyEnter()
   479  
   480  		c.ExpectString("CLI configuration file successfully saved.")
   481  		c.ExpectEOF()
   482  	})
   483  
   484  	got := readFile(t, config)
   485  	requireLine(t, got, "default:")
   486  	requireLine(t, got, "auth:")
   487  	requireLine(t, got, "type: password")
   488  	requireLine(t, got, fmt.Sprintf("domain: %s", e.domain))
   489  	requireLine(t, got, "store:")
   490  	requireLine(t, got, "type: none")
   491  	requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant))
   492  }
   493  
   494  func TestInitUsingCertificateFileData(t *testing.T) {
   495  	if runtime.GOOS == "windows" {
   496  		t.Skip("Sorry, interactive End-to-End tests cannot be executed on Windows.")
   497  	}
   498  	e := newEnv()
   499  
   500  	const (
   501  		profileName = "file-cert-data"
   502  		cacheAge    = "5"
   503  	)
   504  	var (
   505  		config   = filepath.Join(e.tmpDirPath, "e2e-configuration.yml")
   506  		certPath = filepath.Join(e.tmpDirPath, "e2e-cert-data.json")
   507  	)
   508  
   509  	certData, err := json.Marshal(&struct {
   510  		Certificate  string `json:"certificate"`
   511  		PrivateKey   string `json:"privateKey"`
   512  		SshPublicKey string `json:"sshPublicKey"`
   513  	}{
   514  		Certificate:  e.certificate,
   515  		PrivateKey:   e.privateKey,
   516  		SshPublicKey: "ssh-key",
   517  	})
   518  	if err != nil {
   519  		t.Fatalf("json.Marshal(%q) = %v", certData, err)
   520  	}
   521  
   522  	createFile(t, config)
   523  	defer func() { deleteFile(t, config) }()
   524  
   525  	writeFile(t, certData, certPath)
   526  	defer func() { deleteFile(t, certPath) }()
   527  
   528  	cmd := []string{
   529  		"init", fmt.Sprintf("--dev=%s", e.domain), fmt.Sprintf("--config=%s", config),
   530  	}
   531  
   532  	runFlow(t, cmd, func(c console) {
   533  		c.ExpectString("Found an existing cli-config located at")
   534  		c.ExpectString("Select an option")
   535  		c.SendKeyArrowDown()
   536  		c.SendKeyArrowDown()
   537  		c.SendKeyEnter()
   538  
   539  		c.ExpectString("Please enter profile name")
   540  		c.SendLine(profileName)
   541  
   542  		c.ExpectString("Please enter tenant name")
   543  		c.SendLine(e.tenant)
   544  
   545  		c.ExpectString("Please select store type")
   546  		c.SendKeyEnter()
   547  
   548  		c.ExpectString("Please enter directory for file store")
   549  		c.SendKeyEnter()
   550  
   551  		c.ExpectString("Please enter cache strategy for secrets")
   552  		c.SendKeyArrowDown()
   553  		c.SendKeyArrowDown()
   554  		c.SendKeyEnter()
   555  
   556  		c.ExpectString("Please enter cache age (minutes until expiration)")
   557  		c.SendLine(cacheAge)
   558  
   559  		c.ExpectString("Please enter auth type")
   560  		c.SendKeyArrowDown()
   561  		c.SendKeyArrowDown()
   562  		c.SendKeyArrowDown()
   563  		c.SendKeyArrowDown()
   564  		c.SendKeyArrowDown()
   565  		c.SendKeyArrowDown()
   566  		c.SendKeyArrowDown()
   567  		c.SendKeyEnter()
   568  
   569  		c.ExpectString("Raw certificate")
   570  		c.SendKeyArrowDown()
   571  		c.SendKeyEnter()
   572  
   573  		c.ExpectString("Certificate file path:")
   574  		time.Sleep(time.Millisecond * 10)
   575  		c.SendLine(certPath)
   576  
   577  		c.ExpectString("Raw private key")
   578  		c.SendKeyArrowDown()
   579  		c.SendKeyEnter()
   580  
   581  		c.ExpectString("Private key file path:")
   582  		time.Sleep(time.Millisecond * 10)
   583  		c.SendLine(certPath)
   584  
   585  		c.ExpectEOF()
   586  	})
   587  
   588  	got := readFile(t, config)
   589  	requireLine(t, got, fmt.Sprintf("%s:", profileName))
   590  	requireLine(t, got, "auth:")
   591  	requireLine(t, got, "type: cert")
   592  	requireLine(t, got, fmt.Sprintf("certificate: %s", e.certificate))
   593  	requireLine(t, got, fmt.Sprintf("privateKey: %s", e.privateKey))
   594  	requireLine(t, got, "cache:")
   595  	requireLine(t, got, fmt.Sprintf("age: %s", cacheAge))
   596  	requireLine(t, got, "strategy: cache.server")
   597  	requireLine(t, got, fmt.Sprintf("domain: %s", e.domain))
   598  	requireLine(t, got, "store:")
   599  	requireLine(t, got, "type: file")
   600  	requireLine(t, got, fmt.Sprintf("tenant: %s", e.tenant))
   601  }