constellation/cli/internal/cloudcmd/tfupgrade_test.go
Moritz Sanft 95cf4bdf21
cli: perform upgrades in-place in Terraform workspace (#2317)
* perform upgrades in-place in terraform workspace

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* update buildfiles

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* add iam upgrade apply test

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* update buildfiles

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix linter

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* make config fetcher stubbable

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* change workspace restoring behaviour

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* allow overwriting existing Terraform files

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* allow overwrites of TF variables

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix iam upgrade apply

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix embed directive

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* make loader test less brittle

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* pass upgrade ID to user

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* naming nit

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* use upgradeDir

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* tidy

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

---------

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>
2023-09-14 11:51:20 +02:00

222 lines
5.2 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package cloudcmd
import (
"context"
"io"
"testing"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/file"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestPlanUpgrade(t *testing.T) {
testCases := map[string]struct {
prepareFs func(require *require.Assertions) file.Handler
tf *stubUpgradePlanner
wantDiff bool
wantErr bool
}{
"success no diff": {
prepareFs: func(require *require.Assertions) file.Handler {
return file.NewHandler(afero.NewMemMapFs())
},
tf: &stubUpgradePlanner{},
},
"success diff": {
prepareFs: func(require *require.Assertions) file.Handler {
return file.NewHandler(afero.NewMemMapFs())
},
tf: &stubUpgradePlanner{
planDiff: true,
},
wantDiff: true,
},
"workspace not clean": {
prepareFs: func(require *require.Assertions) file.Handler {
fs := file.NewHandler(afero.NewMemMapFs())
require.NoError(fs.MkdirAll("backup"))
return fs
},
tf: &stubUpgradePlanner{},
wantErr: true,
},
"prepare workspace error": {
prepareFs: func(require *require.Assertions) file.Handler {
return file.NewHandler(afero.NewMemMapFs())
},
tf: &stubUpgradePlanner{
prepareWorkspaceErr: assert.AnError,
},
wantErr: true,
},
"plan error": {
prepareFs: func(require *require.Assertions) file.Handler {
return file.NewHandler(afero.NewMemMapFs())
},
tf: &stubUpgradePlanner{
planErr: assert.AnError,
},
wantErr: true,
},
"show plan error": {
prepareFs: func(require *require.Assertions) file.Handler {
return file.NewHandler(afero.NewMemMapFs())
},
tf: &stubUpgradePlanner{
planDiff: true,
showPlanErr: assert.AnError,
},
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
fs := tc.prepareFs(require.New(t))
hasDiff, err := planUpgrade(
context.Background(), tc.tf, fs, io.Discard, terraform.LogLevelDebug,
&terraform.QEMUVariables{},
"test", "backup",
)
if tc.wantErr {
assert.Error(err)
return
}
assert.NoError(err)
assert.Equal(tc.wantDiff, hasDiff)
})
}
}
func TestRestoreBackup(t *testing.T) {
existingWorkspace := "foo"
backupDir := "bar"
testCases := map[string]struct {
prepareFs func(require *require.Assertions) file.Handler
wantErr bool
}{
"success": {
prepareFs: func(require *require.Assertions) file.Handler {
fs := file.NewHandler(afero.NewMemMapFs())
require.NoError(fs.MkdirAll(existingWorkspace))
require.NoError(fs.MkdirAll(backupDir))
return fs
},
},
"existing workspace does not exist": {
prepareFs: func(require *require.Assertions) file.Handler {
fs := file.NewHandler(afero.NewMemMapFs())
require.NoError(fs.MkdirAll(backupDir))
return fs
},
},
"backup dir does not exist": {
prepareFs: func(require *require.Assertions) file.Handler {
fs := file.NewHandler(afero.NewMemMapFs())
require.NoError(fs.MkdirAll(existingWorkspace))
return fs
},
wantErr: true,
},
"read only file system": {
prepareFs: func(require *require.Assertions) file.Handler {
memFS := afero.NewMemMapFs()
fs := file.NewHandler(memFS)
require.NoError(fs.MkdirAll(existingWorkspace))
require.NoError(fs.MkdirAll(backupDir))
return file.NewHandler(afero.NewReadOnlyFs(memFS))
},
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
fs := tc.prepareFs(require.New(t))
err := restoreBackup(fs, existingWorkspace, backupDir)
if tc.wantErr {
assert.Error(err)
return
}
assert.NoError(err)
})
}
}
func TestEnsureFileNotExist(t *testing.T) {
testCases := map[string]struct {
fs file.Handler
fileName string
wantErr bool
}{
"file does not exist": {
fs: file.NewHandler(afero.NewMemMapFs()),
fileName: "foo",
},
"file exists": {
fs: func() file.Handler {
fs := file.NewHandler(afero.NewMemMapFs())
err := fs.Write("foo", []byte{})
require.NoError(t, err)
return fs
}(),
fileName: "foo",
wantErr: true,
},
"directory exists": {
fs: func() file.Handler {
fs := file.NewHandler(afero.NewMemMapFs())
err := fs.MkdirAll("foo/bar")
require.NoError(t, err)
return fs
}(),
fileName: "foo/bar",
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
err := ensureFileNotExist(tc.fs, tc.fileName)
if tc.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
type stubUpgradePlanner struct {
prepareWorkspaceErr error
planDiff bool
planErr error
showPlanErr error
}
func (s *stubUpgradePlanner) PrepareUpgradeWorkspace(_, _ string, _ terraform.Variables) error {
return s.prepareWorkspaceErr
}
func (s *stubUpgradePlanner) Plan(_ context.Context, _ terraform.LogLevel) (bool, error) {
return s.planDiff, s.planErr
}
func (s *stubUpgradePlanner) ShowPlan(_ context.Context, _ terraform.LogLevel, _ io.Writer) error {
return s.showPlanErr
}