feat(tests) Add Terraform testing to support Cross-account discovery (#89)
* feat(tests) Add Terraform testing to support Cross-account discovery **Problem** * To support cross-account DHC discovery, we need to add terraform configurations and tests to test against live AWS data. * However, there was nothing in place to support any AssumeRole testing, irrespective of cross-account. **Solution** * Added a new terraform file, iam_assume_role.tf, to contain the new terraform configurations for single-account AssumeRole and cross-role * Added a second terraform file, iam_cross_account.tf, to contain the new terraform configurations for cross-account * Refactored how the tests are organized. The previous static test cases used a system where a separate function was created for each test. This was moved to a dedicated file, e2e_host_static_test.go. * For AssumeRole tests (single account, cross role, and cross account), this system wasn't ideal since there are so many test cases and they are all extremely similar. A table driven system was better that passed in a set of variables to shared test helpers. A dedicated file, e2e_host_assumerole_test.go, was created to contain the testing infrastructure for AssumeRole tests. * e2e_host_test.go remains the main test runner that then calls e2e_host_assumerole_test.go and e2e_host_static_test.go * The terraform tests work by setting environment variables for the AWS account that you want to configure the terraform for. The existing setup worked for single-account and cross-role. However, to support cross-account, support had to be added for a second set of credentials. The second set of environment variables can now be set with the TARGET_ prefix. Some configuration in testing.go had to be added to support creating/destroying multiple terraform setups. **Testing** * The single account tests pass as expected. However, a bug was discovered during this process that will be addressed later. * The cross-role and cross-account tests failed as expected because this featured has not yet been delivered. * It was noticed that some of the existing static tests were flaky. The problem and fix were identified and will be addressed later.
This commit is contained in:
1 parent
1c87d178a2
commit
13f9d0a70a
6 files changed
+1428
-375
No files matched your search
+29
-7
@@ -39,6 +39,10 @@ type TestTerraformer struct {
|
||||
// The working directory for Terraform commands.
|
||||
workDir string
|
||||
|
||||
// vars holds optional key/value pairs passed as -var flags to every
|
||||
// Terraform command that accepts them (apply, destroy, plan).
|
||||
vars map[string]string
|
||||
|
||||
// The Terraform state. Use the Output method to look up particular
|
||||
// outputs from the Terraform state.
|
||||
state *tfjson.State
|
||||
@@ -53,8 +57,9 @@ type TestTerraformer struct {
|
||||
|
||||
// NewTestTerraformer initializes a Terraform directory. It just
|
||||
// returns an initialized project, it does not perform any actions on
|
||||
// it.
|
||||
func NewTestTerraformer(workDir string) (*TestTerraformer, error) {
|
||||
// it. An optional vars map may be provided; each entry is passed as a
|
||||
// -var flag to Terraform commands.
|
||||
func NewTestTerraformer(workDir string, vars ...map[string]string) (*TestTerraformer, error) {
|
||||
tfPath, err := exec.LookPath("terraform")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("LookPath error: %w", err)
|
||||
@@ -64,10 +69,24 @@ func NewTestTerraformer(workDir string) (*TestTerraformer, error) {
|
||||
return nil, errors.New("workDir is empty")
|
||||
}
|
||||
|
||||
return &TestTerraformer{
|
||||
tf := &TestTerraformer{
|
||||
tfPath: tfPath,
|
||||
workDir: workDir,
|
||||
}, nil
|
||||
}
|
||||
if len(vars) > 0 {
|
||||
tf.vars = vars[0]
|
||||
}
|
||||
return tf, nil
|
||||
}
|
||||
|
||||
// varArgs converts the stored vars map into a slice of -var flags
|
||||
// suitable for appending to a Terraform command's argument list.
|
||||
func (t *TestTerraformer) varArgs() []string {
|
||||
args := make([]string, 0, len(t.vars)*2)
|
||||
for k, v := range t.vars {
|
||||
args = append(args, "-var", fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
// Deploy runs the following commands, in order: init, apply, plan,
|
||||
@@ -214,7 +233,8 @@ func (t *TestTerraformer) init() error {
|
||||
|
||||
// apply runs "terraform apply" in the project's working directory.
|
||||
func (t *TestTerraformer) apply() error {
|
||||
cmd := exec.Command(t.tfPath, "apply", "-input=false", "-auto-approve")
|
||||
args := append([]string{"apply", "-input=false", "-auto-approve"}, t.varArgs()...)
|
||||
cmd := exec.Command(t.tfPath, args...)
|
||||
cmd.Dir = t.workDir
|
||||
stdoutStderr, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
@@ -226,7 +246,8 @@ func (t *TestTerraformer) apply() error {
|
||||
|
||||
// destroy runs "terraform destroy" in the project's working directory.
|
||||
func (t *TestTerraformer) destroy() error {
|
||||
cmd := exec.Command(t.tfPath, "destroy", "-input=false", "-auto-approve")
|
||||
args := append([]string{"destroy", "-input=false", "-auto-approve"}, t.varArgs()...)
|
||||
cmd := exec.Command(t.tfPath, args...)
|
||||
cmd.Dir = t.workDir
|
||||
stdoutStderr, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
@@ -242,7 +263,8 @@ func (t *TestTerraformer) destroy() error {
|
||||
// it's run to get the data for for importing the state via
|
||||
// terraform-json. The apply method ignores the plan generated here.
|
||||
func (t *TestTerraformer) plan() error {
|
||||
cmd := exec.Command(t.tfPath, "plan", "-input=false", "-out=plan.tfplan")
|
||||
args := append([]string{"plan", "-input=false", "-out=plan.tfplan"}, t.varArgs()...)
|
||||
cmd := exec.Command(t.tfPath, args...)
|
||||
cmd.Dir = t.workDir
|
||||
stdoutStderr, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
|
||||
Reference in new issue
Block a user