github.com/mponton/terratest@v0.44.0/modules/terraform/workspace.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"strings"
     7  
     8  	"github.com/mponton/terratest/modules/testing"
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  // WorkspaceSelectOrNew runs terraform workspace with the given options and the workspace name
    13  // and returns a name of the current workspace. It tries to select a workspace with the given
    14  // name, or it creates a new one if it doesn't exist.
    15  func WorkspaceSelectOrNew(t testing.TestingT, options *Options, name string) string {
    16  	out, err := WorkspaceSelectOrNewE(t, options, name)
    17  	if err != nil {
    18  		t.Fatal(err)
    19  	}
    20  	return out
    21  }
    22  
    23  // WorkspaceSelectOrNewE runs terraform workspace with the given options and the workspace name
    24  // and returns a name of the current workspace. It tries to select a workspace with the given
    25  // name, or it creates a new one if it doesn't exist.
    26  func WorkspaceSelectOrNewE(t testing.TestingT, options *Options, name string) (string, error) {
    27  	out, err := RunTerraformCommandE(t, options, "workspace", "list")
    28  	if err != nil {
    29  		return "", err
    30  	}
    31  
    32  	if isExistingWorkspace(out, name) {
    33  		_, err = RunTerraformCommandE(t, options, "workspace", "select", name)
    34  	} else {
    35  		_, err = RunTerraformCommandE(t, options, "workspace", "new", name)
    36  	}
    37  	if err != nil {
    38  		return "", err
    39  	}
    40  
    41  	return RunTerraformCommandE(t, options, "workspace", "show")
    42  }
    43  
    44  func isExistingWorkspace(out string, name string) bool {
    45  	workspaces := strings.Split(out, "\n")
    46  	for _, ws := range workspaces {
    47  		if nameMatchesWorkspace(name, ws) {
    48  			return true
    49  		}
    50  	}
    51  	return false
    52  }
    53  
    54  func nameMatchesWorkspace(name string, workspace string) bool {
    55  	// Regex for matching workspace should match for strings with optional leading asterisk "*"
    56  	// following optional white spaces following the workspace name.
    57  	// E.g. for the given name "terratest", following strings will match:
    58  	//
    59  	//    "* terratest"
    60  	//    "  terratest"
    61  	match, _ := regexp.MatchString(fmt.Sprintf("^\\*?\\s*%s$", name), workspace)
    62  	return match
    63  }
    64  
    65  // WorkspaceDelete removes the specified terraform workspace with the given options.
    66  // It returns the name of the current workspace AFTER deletion, and the returned error (that can be nil).
    67  // If the workspace to delete is the current one, then it tries to switch to the "default" workspace.
    68  // Deleting the workspace "default" is not supported.
    69  func WorkspaceDeleteE(t testing.TestingT, options *Options, name string) (string, error) {
    70  	currentWorkspace, err := RunTerraformCommandE(t, options, "workspace", "show")
    71  	if err != nil {
    72  		return currentWorkspace, err
    73  	}
    74  
    75  	if name == "default" {
    76  		return currentWorkspace, &UnsupportedDefaultWorkspaceDeletion{}
    77  	}
    78  
    79  	out, err := RunTerraformCommandE(t, options, "workspace", "list")
    80  	if err != nil {
    81  		return currentWorkspace, err
    82  	}
    83  	if !isExistingWorkspace(out, name) {
    84  		return currentWorkspace, WorkspaceDoesNotExist(name)
    85  	}
    86  
    87  	// Switch workspace before deleting if it is the current
    88  	if currentWorkspace == name {
    89  		currentWorkspace, err = WorkspaceSelectOrNewE(t, options, "default")
    90  		if err != nil {
    91  			return currentWorkspace, err
    92  		}
    93  	}
    94  
    95  	// delete workspace
    96  	_, err = RunTerraformCommandE(t, options, "workspace", "delete", name)
    97  
    98  	return currentWorkspace, err
    99  }
   100  
   101  // WorkspaceDelete removes the specified terraform workspace with the given options.
   102  // It returns the name of the current workspace AFTER deletion.
   103  // If the workspace to delete is the current one, then it tries to switch to the "default" workspace.
   104  // Deleting the workspace "default" is not supported and only return an empty string (to avoid a fatal error).
   105  func WorkspaceDelete(t testing.TestingT, options *Options, name string) string {
   106  	out, err := WorkspaceDeleteE(t, options, name)
   107  	require.NoError(t, err)
   108  	return out
   109  }