mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-02-23 00:10:06 -05:00
cli: fix iam rollback (#1148)
* AB#2897 rename DestroyCluster * #AB2897 error if terraform dir exists * AB#2897 reword DestroyResources
This commit is contained in:
parent
94245416ca
commit
7410cf8038
@ -19,7 +19,7 @@ type terraformClient interface {
|
||||
PrepareWorkspace(path string, input terraform.Variables) error
|
||||
CreateCluster(ctx context.Context) (terraform.CreateOutput, error)
|
||||
CreateIAMConfig(ctx context.Context, provider cloudprovider.Provider) (terraform.IAMOutput, error)
|
||||
DestroyCluster(ctx context.Context) error
|
||||
Destroy(ctx context.Context) error
|
||||
CleanUpWorkspace() error
|
||||
RemoveInstaller()
|
||||
}
|
||||
|
@ -32,9 +32,9 @@ type stubTerraformClient struct {
|
||||
uid string
|
||||
cleanUpWorkspaceCalled bool
|
||||
removeInstallerCalled bool
|
||||
destroyClusterCalled bool
|
||||
destroyCalled bool
|
||||
createClusterErr error
|
||||
destroyClusterErr error
|
||||
destroyErr error
|
||||
prepareWorkspaceErr error
|
||||
cleanUpWorkspaceErr error
|
||||
iamOutputErr error
|
||||
@ -56,9 +56,9 @@ func (c *stubTerraformClient) PrepareWorkspace(path string, input terraform.Vari
|
||||
return c.prepareWorkspaceErr
|
||||
}
|
||||
|
||||
func (c *stubTerraformClient) DestroyCluster(ctx context.Context) error {
|
||||
c.destroyClusterCalled = true
|
||||
return c.destroyClusterErr
|
||||
func (c *stubTerraformClient) Destroy(ctx context.Context) error {
|
||||
c.destroyCalled = true
|
||||
return c.destroyErr
|
||||
}
|
||||
|
||||
func (c *stubTerraformClient) CleanUpWorkspace() error {
|
||||
|
@ -121,7 +121,7 @@ func TestCreator(t *testing.T) {
|
||||
if tc.wantRollback {
|
||||
cl := tc.tfClient.(*stubTerraformClient)
|
||||
if tc.wantTerraformRollback {
|
||||
assert.True(cl.destroyClusterCalled)
|
||||
assert.True(cl.destroyCalled)
|
||||
}
|
||||
assert.True(cl.cleanUpWorkspaceCalled)
|
||||
if tc.provider == cloudprovider.QEMU {
|
||||
|
@ -40,7 +40,7 @@ type rollbackerTerraform struct {
|
||||
|
||||
func (r *rollbackerTerraform) rollback(ctx context.Context) error {
|
||||
var err error
|
||||
err = multierr.Append(err, r.client.DestroyCluster(ctx))
|
||||
err = multierr.Append(err, r.client.Destroy(ctx))
|
||||
if err == nil {
|
||||
err = multierr.Append(err, r.client.CleanUpWorkspace())
|
||||
}
|
||||
@ -56,7 +56,7 @@ type rollbackerQEMU struct {
|
||||
func (r *rollbackerQEMU) rollback(ctx context.Context) error {
|
||||
var err error
|
||||
if r.createdWorkspace {
|
||||
err = multierr.Append(err, r.client.DestroyCluster(ctx))
|
||||
err = multierr.Append(err, r.client.Destroy(ctx))
|
||||
}
|
||||
err = multierr.Append(err, r.libvirt.Stop(ctx))
|
||||
if err == nil {
|
||||
|
@ -25,7 +25,7 @@ func TestRollbackTerraform(t *testing.T) {
|
||||
tfClient: &stubTerraformClient{},
|
||||
},
|
||||
"destroy cluster error": {
|
||||
tfClient: &stubTerraformClient{destroyClusterErr: someErr},
|
||||
tfClient: &stubTerraformClient{destroyErr: someErr},
|
||||
wantErr: true,
|
||||
},
|
||||
"clean up workspace error": {
|
||||
@ -51,7 +51,7 @@ func TestRollbackTerraform(t *testing.T) {
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.True(tc.tfClient.destroyClusterCalled)
|
||||
assert.True(tc.tfClient.destroyCalled)
|
||||
assert.True(tc.tfClient.cleanUpWorkspaceCalled)
|
||||
})
|
||||
}
|
||||
@ -78,7 +78,7 @@ func TestRollbackQEMU(t *testing.T) {
|
||||
},
|
||||
"destroy cluster error": {
|
||||
libvirt: &stubLibvirtRunner{stopErr: someErr},
|
||||
tfClient: &stubTerraformClient{destroyClusterErr: someErr},
|
||||
tfClient: &stubTerraformClient{destroyErr: someErr},
|
||||
wantErr: true,
|
||||
},
|
||||
"clean up workspace error": {
|
||||
@ -109,9 +109,9 @@ func TestRollbackQEMU(t *testing.T) {
|
||||
assert.NoError(err)
|
||||
assert.True(tc.libvirt.stopCalled)
|
||||
if tc.createdWorkspace {
|
||||
assert.True(tc.tfClient.destroyClusterCalled)
|
||||
assert.True(tc.tfClient.destroyCalled)
|
||||
} else {
|
||||
assert.False(tc.tfClient.destroyClusterCalled)
|
||||
assert.False(tc.tfClient.destroyCalled)
|
||||
}
|
||||
assert.True(tc.tfClient.cleanUpWorkspaceCalled)
|
||||
})
|
||||
|
@ -50,7 +50,7 @@ func (t *Terminator) Terminate(ctx context.Context) (retErr error) {
|
||||
}
|
||||
|
||||
func (t *Terminator) terminateTerraform(ctx context.Context, cl terraformClient) error {
|
||||
if err := cl.DestroyCluster(ctx); err != nil {
|
||||
if err := cl.Destroy(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return cl.CleanUpWorkspace()
|
||||
|
@ -33,7 +33,7 @@ func TestTerminator(t *testing.T) {
|
||||
wantErr: true,
|
||||
},
|
||||
"destroy cluster error": {
|
||||
tfClient: &stubTerraformClient{destroyClusterErr: someErr},
|
||||
tfClient: &stubTerraformClient{destroyErr: someErr},
|
||||
libvirt: &stubLibvirtRunner{},
|
||||
wantErr: true,
|
||||
},
|
||||
@ -70,7 +70,7 @@ func TestTerminator(t *testing.T) {
|
||||
}
|
||||
assert.NoError(err)
|
||||
cl := tc.tfClient.(*stubTerraformClient)
|
||||
assert.True(cl.destroyClusterCalled)
|
||||
assert.True(cl.destroyCalled)
|
||||
assert.True(cl.removeInstallerCalled)
|
||||
assert.True(tc.libvirt.stopCalled)
|
||||
})
|
||||
|
@ -197,6 +197,10 @@ func (c *iamCreator) create(ctx context.Context) error {
|
||||
}
|
||||
c.log.Debugf("Using flags: %+v", flags)
|
||||
|
||||
if err := c.checkWorkingDir(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !flags.yesFlag {
|
||||
c.cmd.Printf("The following IAM configuration will be created:\n\n")
|
||||
c.providerCreator.printConfirmValues(c.cmd, flags)
|
||||
@ -275,6 +279,17 @@ func (c *iamCreator) parseFlagsAndSetupConfig() (iamFlags, error) {
|
||||
return flags, nil
|
||||
}
|
||||
|
||||
// checkWorkingDir checks if the current working directory already contains a Terraform dir or a Constellation config file.
|
||||
func (c *iamCreator) checkWorkingDir() error {
|
||||
if _, err := c.fileHandler.Stat(constants.TerraformIAMWorkingDir); err == nil {
|
||||
return fmt.Errorf("the current working directory already contains the %s directory. Please run the command in a different directory", constants.TerraformIAMWorkingDir)
|
||||
}
|
||||
if _, err := c.fileHandler.Stat(constants.ConfigFilename); err == nil {
|
||||
return fmt.Errorf("the current working directory already contains the %s file. Please run the command in a different directory", constants.ConfigFilename)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// iamFlags contains the parsed flags of the iam create command, including the parsed flags of the selected cloud provider.
|
||||
type iamFlags struct {
|
||||
aws awsFlags
|
||||
|
@ -67,15 +67,18 @@ func TestParseIDFile(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIAMCreateAWS(t *testing.T) {
|
||||
defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string) afero.Fs {
|
||||
defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs {
|
||||
fs := afero.NewMemMapFs()
|
||||
fileHandler := file.NewHandler(fs)
|
||||
for _, f := range existingFiles {
|
||||
require.NoError(fileHandler.Write(f, []byte{1, 2, 3}, file.OptNone))
|
||||
}
|
||||
for _, d := range existingDirs {
|
||||
require.NoError(fs.MkdirAll(d, 0o755))
|
||||
}
|
||||
return fs
|
||||
}
|
||||
readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string) afero.Fs {
|
||||
readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs {
|
||||
fs := afero.NewReadOnlyFs(afero.NewMemMapFs())
|
||||
return fs
|
||||
}
|
||||
@ -88,7 +91,7 @@ func TestIAMCreateAWS(t *testing.T) {
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string) afero.Fs
|
||||
setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs
|
||||
creator *stubIAMCreator
|
||||
provider cloudprovider.Provider
|
||||
zoneFlag string
|
||||
@ -97,6 +100,7 @@ func TestIAMCreateAWS(t *testing.T) {
|
||||
generateConfigFlag bool
|
||||
configFlag string
|
||||
existingFiles []string
|
||||
existingDirs []string
|
||||
stdin string
|
||||
wantAbort bool
|
||||
wantErr bool
|
||||
@ -153,6 +157,16 @@ func TestIAMCreateAWS(t *testing.T) {
|
||||
configFlag: "custom-config.yaml",
|
||||
existingFiles: []string{"custom-config.yaml"},
|
||||
},
|
||||
"iam create aws existing terraform dir": {
|
||||
setupFs: defaultFs,
|
||||
creator: &stubIAMCreator{id: validIAMIDFile},
|
||||
provider: cloudprovider.AWS,
|
||||
zoneFlag: "us-east-2a",
|
||||
prefixFlag: "test",
|
||||
yesFlag: true,
|
||||
wantErr: true,
|
||||
existingDirs: []string{constants.TerraformIAMWorkingDir},
|
||||
},
|
||||
"interactive": {
|
||||
setupFs: defaultFs,
|
||||
creator: &stubIAMCreator{id: validIAMIDFile},
|
||||
@ -244,7 +258,7 @@ func TestIAMCreateAWS(t *testing.T) {
|
||||
require.NoError(cmd.Flags().Set("config", tc.configFlag))
|
||||
}
|
||||
|
||||
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingFiles))
|
||||
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingFiles, tc.existingDirs))
|
||||
|
||||
iamCreator := &iamCreator{
|
||||
cmd: cmd,
|
||||
@ -285,15 +299,18 @@ func TestIAMCreateAWS(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIAMCreateAzure(t *testing.T) {
|
||||
defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string) afero.Fs {
|
||||
defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs {
|
||||
fs := afero.NewMemMapFs()
|
||||
fileHandler := file.NewHandler(fs)
|
||||
for _, f := range existingFiles {
|
||||
require.NoError(fileHandler.Write(f, []byte{1, 2, 3}, file.OptNone))
|
||||
}
|
||||
for _, d := range existingDirs {
|
||||
require.NoError(fs.MkdirAll(d, 0o755))
|
||||
}
|
||||
return fs
|
||||
}
|
||||
readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string) afero.Fs {
|
||||
readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs {
|
||||
fs := afero.NewReadOnlyFs(afero.NewMemMapFs())
|
||||
return fs
|
||||
}
|
||||
@ -309,7 +326,7 @@ func TestIAMCreateAzure(t *testing.T) {
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string) afero.Fs
|
||||
setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs
|
||||
creator *stubIAMCreator
|
||||
provider cloudprovider.Provider
|
||||
regionFlag string
|
||||
@ -319,6 +336,7 @@ func TestIAMCreateAzure(t *testing.T) {
|
||||
generateConfigFlag bool
|
||||
configFlag string
|
||||
existingFiles []string
|
||||
existingDirs []string
|
||||
stdin string
|
||||
wantAbort bool
|
||||
wantErr bool
|
||||
@ -380,6 +398,17 @@ func TestIAMCreateAzure(t *testing.T) {
|
||||
yesFlag: true,
|
||||
wantErr: true,
|
||||
},
|
||||
"iam create azure existing terraform dir": {
|
||||
setupFs: defaultFs,
|
||||
creator: &stubIAMCreator{id: validIAMIDFile},
|
||||
provider: cloudprovider.Azure,
|
||||
regionFlag: "westus",
|
||||
servicePrincipalFlag: "constell-test-sp",
|
||||
resourceGroupFlag: "constell-test-rg",
|
||||
yesFlag: true,
|
||||
wantErr: true,
|
||||
existingDirs: []string{constants.TerraformIAMWorkingDir},
|
||||
},
|
||||
"interactive": {
|
||||
setupFs: defaultFs,
|
||||
creator: &stubIAMCreator{id: validIAMIDFile},
|
||||
@ -469,7 +498,7 @@ func TestIAMCreateAzure(t *testing.T) {
|
||||
require.NoError(cmd.Flags().Set("config", tc.configFlag))
|
||||
}
|
||||
|
||||
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingFiles))
|
||||
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingFiles, tc.existingDirs))
|
||||
|
||||
iamCreator := &iamCreator{
|
||||
cmd: cmd,
|
||||
@ -513,15 +542,18 @@ func TestIAMCreateAzure(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIAMCreateGCP(t *testing.T) {
|
||||
defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string) afero.Fs {
|
||||
defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs {
|
||||
fs := afero.NewMemMapFs()
|
||||
fileHandler := file.NewHandler(fs)
|
||||
for _, f := range existingFiles {
|
||||
require.NoError(fileHandler.Write(f, []byte{1, 2, 3}, file.OptNone))
|
||||
}
|
||||
for _, d := range existingDirs {
|
||||
require.NoError(fs.MkdirAll(d, 0o755))
|
||||
}
|
||||
return fs
|
||||
}
|
||||
readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string) afero.Fs {
|
||||
readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs {
|
||||
fs := afero.NewReadOnlyFs(afero.NewMemMapFs())
|
||||
return fs
|
||||
}
|
||||
@ -539,7 +571,7 @@ func TestIAMCreateGCP(t *testing.T) {
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string) afero.Fs
|
||||
setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs
|
||||
creator *stubIAMCreator
|
||||
provider cloudprovider.Provider
|
||||
zoneFlag string
|
||||
@ -549,6 +581,7 @@ func TestIAMCreateGCP(t *testing.T) {
|
||||
generateConfigFlag bool
|
||||
configFlag string
|
||||
existingFiles []string
|
||||
existingDirs []string
|
||||
stdin string
|
||||
wantAbort bool
|
||||
wantErr bool
|
||||
@ -610,6 +643,18 @@ func TestIAMCreateGCP(t *testing.T) {
|
||||
yesFlag: true,
|
||||
wantErr: true,
|
||||
},
|
||||
"iam create gcp existing terraform dir": {
|
||||
setupFs: defaultFs,
|
||||
creator: &stubIAMCreator{id: validIAMIDFile},
|
||||
provider: cloudprovider.GCP,
|
||||
zoneFlag: "europe-west1-a",
|
||||
serviceAccountIDFlag: "constell-test",
|
||||
projectIDFlag: "constell-1234",
|
||||
|
||||
existingDirs: []string{constants.TerraformIAMWorkingDir},
|
||||
yesFlag: true,
|
||||
wantErr: true,
|
||||
},
|
||||
"iam create gcp invalid flags": {
|
||||
setupFs: defaultFs,
|
||||
creator: &stubIAMCreator{id: validIAMIDFile},
|
||||
@ -718,7 +763,7 @@ func TestIAMCreateGCP(t *testing.T) {
|
||||
require.NoError(cmd.Flags().Set("config", tc.configFlag))
|
||||
}
|
||||
|
||||
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingFiles))
|
||||
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingFiles, tc.existingDirs))
|
||||
|
||||
iamCreator := &iamCreator{
|
||||
cmd: cmd,
|
||||
|
@ -272,8 +272,8 @@ func (c *Client) CreateIAMConfig(ctx context.Context, provider cloudprovider.Pro
|
||||
}
|
||||
}
|
||||
|
||||
// DestroyCluster destroys a Constellation cluster using Terraform.
|
||||
func (c *Client) DestroyCluster(ctx context.Context) error {
|
||||
// Destroy destroys Terraform-created cloud resources.
|
||||
func (c *Client) Destroy(ctx context.Context) error {
|
||||
if err := c.tf.Init(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -660,7 +660,7 @@ func TestDestroyInstances(t *testing.T) {
|
||||
tf: tc.tf,
|
||||
}
|
||||
|
||||
err := c.DestroyCluster(context.Background())
|
||||
err := c.Destroy(context.Background())
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
|
Loading…
x
Reference in New Issue
Block a user