get.porter.sh/porter@v1.3.0/pkg/exec/exec_test.go (about)

     1  package exec
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"os"
     8  	"sort"
     9  	"testing"
    10  
    11  	"get.porter.sh/porter/pkg/exec/builder"
    12  	"get.porter.sh/porter/pkg/test"
    13  	"get.porter.sh/porter/pkg/yaml"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestAction_UnmarshalYAML(t *testing.T) {
    19  	b, err := os.ReadFile("testdata/install-input.yaml")
    20  	require.NoError(t, err)
    21  
    22  	action := Action{}
    23  	err = yaml.Unmarshal(b, &action)
    24  	require.NoError(t, err)
    25  
    26  	require.Len(t, action.Steps, 1)
    27  	step := action.Steps[0]
    28  	assert.Equal(t, "gcloud", step.Command)
    29  	assert.Equal(t, "Install a VM and collect its ID", step.Description)
    30  	require.Len(t, step.Arguments, 3)
    31  	assert.Len(t, step.Flags, 3)
    32  	sort.Sort(step.Flags) // This returns the flags in ascending order
    33  	assert.Equal(t, builder.NewFlag("machine-type", "f1-micro"), step.Flags[0])
    34  	assert.Equal(t, builder.NewFlag("project", "porterci"), step.Flags[1])
    35  	assert.Equal(t, builder.NewFlag("zone", "us-central1-a"), step.Flags[2])
    36  	assert.Equal(t, step.EnvironmentVars, map[string]string{"SECRET": "super-secret"})
    37  	require.Len(t, step.Outputs, 1)
    38  	assert.Equal(t, Output{Name: "vms", JsonPath: "$[*].id"}, step.Outputs[0])
    39  }
    40  
    41  func TestMixin_ExecuteCommand(t *testing.T) {
    42  	ctx := context.Background()
    43  
    44  	step := Step{
    45  		Instruction: Instruction{
    46  			Command:   "bash",
    47  			Arguments: []string{"-c", "echo Hello World"},
    48  		},
    49  	}
    50  	action := Action{
    51  		Name:  "install",
    52  		Steps: []Step{step},
    53  	}
    54  	b, _ := yaml.Marshal(action)
    55  
    56  	fmt.Println(string(b))
    57  	m := NewTestMixin(t)
    58  	m.Config.In = bytes.NewReader(b)
    59  
    60  	m.Config.Setenv(test.ExpectedCommandEnv, `bash -c echo Hello World`)
    61  
    62  	err := m.Execute(ctx, ExecuteOptions{})
    63  
    64  	require.NoError(t, err)
    65  }
    66  
    67  func TestMixin_ErrorHandling(t *testing.T) {
    68  	testcases := []struct {
    69  		name      string
    70  		handler   builder.IgnoreErrorHandler
    71  		wantError string
    72  	}{
    73  		{name: "legit error", handler: builder.IgnoreErrorHandler{}, wantError: "error running command"},
    74  		{name: "all", handler: builder.IgnoreErrorHandler{All: true}},
    75  		{name: "exit code", handler: builder.IgnoreErrorHandler{ExitCodes: []int{1}}},
    76  		{name: "contains", handler: builder.IgnoreErrorHandler{Output: builder.IgnoreErrorWithOutput{Contains: []string{"already exists"}}}},
    77  		{name: "regex", handler: builder.IgnoreErrorHandler{Output: builder.IgnoreErrorWithOutput{Regex: []string{".* exists"}}}},
    78  	}
    79  
    80  	for _, tc := range testcases {
    81  		t.Run(tc.name, func(t *testing.T) {
    82  			ctx := context.Background()
    83  			step := Step{
    84  				Instruction: Instruction{
    85  					Command:            "bash",
    86  					Arguments:          []string{"-c", "echo Hello World"},
    87  					IgnoreErrorHandler: tc.handler,
    88  				},
    89  			}
    90  			action := Action{
    91  				Name:  "install",
    92  				Steps: []Step{step},
    93  			}
    94  			b, _ := yaml.Marshal(action)
    95  
    96  			m := NewTestMixin(t)
    97  			m.Config.In = bytes.NewReader(b)
    98  
    99  			m.Config.Setenv(test.ExpectedCommandEnv, `bash -c echo Hello World`)
   100  			m.Config.Setenv(test.ExpectedCommandExitCodeEnv, "1")
   101  			m.Config.Setenv(test.ExpectedCommandErrorEnv, "thing already exists")
   102  
   103  			err := m.Execute(ctx, ExecuteOptions{})
   104  			if tc.wantError == "" {
   105  				require.NoError(t, err)
   106  			} else {
   107  				require.Error(t, err)
   108  				assert.Contains(t, err.Error(), tc.wantError)
   109  			}
   110  		})
   111  	}
   112  }
   113  
   114  func TestMixin_Install(t *testing.T) {
   115  	ctx := context.Background()
   116  	h := NewTestMixin(t)
   117  	h.TestConfig.TestContext.AddTestDirectory("testdata", "testdata")
   118  
   119  	action, err := h.loadAction(ctx, "testdata/install-input.yaml")
   120  	require.NoError(t, err)
   121  
   122  	assert.Len(t, action.Steps, 1)
   123  	step := action.Steps[0]
   124  	assert.Equal(t, "gcloud", step.Instruction.Command)
   125  	require.Len(t, step.Outputs, 1)
   126  	assert.Equal(t, "$[*].id", step.Outputs[0].JsonPath)
   127  }
   128  
   129  func TestMixin_Upgrade(t *testing.T) {
   130  	ctx := context.Background()
   131  	h := NewTestMixin(t)
   132  	h.TestConfig.TestContext.AddTestDirectory("testdata", "testdata")
   133  
   134  	action, err := h.loadAction(ctx, "testdata/upgrade-input.yaml")
   135  	require.NoError(t, err)
   136  
   137  	assert.Len(t, action.Steps, 1)
   138  	step := action.Steps[0]
   139  	assert.Equal(t, "bash", step.Instruction.Command)
   140  	require.Len(t, step.Outputs, 1)
   141  	assert.Equal(t, "config/kube.yaml", step.Outputs[0].FilePath)
   142  }
   143  
   144  func TestMixin_CustomAction(t *testing.T) {
   145  	ctx := context.Background()
   146  	h := NewTestMixin(t)
   147  	h.TestConfig.TestContext.AddTestDirectory("testdata", "testdata")
   148  
   149  	action, err := h.loadAction(ctx, "testdata/invoke-input.yaml")
   150  	require.NoError(t, err)
   151  
   152  	assert.Len(t, action.Steps, 1)
   153  	step := action.Steps[0]
   154  	assert.Equal(t, "bash", step.Instruction.Command)
   155  	require.Len(t, step.Outputs, 1)
   156  	assert.Equal(t, "Hello (.*)", step.Outputs[0].Regex)
   157  }
   158  
   159  func TestMixin_Uninstall(t *testing.T) {
   160  	ctx := context.Background()
   161  	h := NewTestMixin(t)
   162  	h.TestConfig.TestContext.AddTestDirectory("testdata", "testdata")
   163  
   164  	action, err := h.loadAction(ctx, "testdata/uninstall-input.yaml")
   165  	require.NoError(t, err)
   166  
   167  	assert.Len(t, action.Steps, 1)
   168  	step := action.Steps[0]
   169  	assert.Equal(t, "bash", step.Instruction.Command)
   170  }
   171  
   172  func TestMixin_SuffixArgs(t *testing.T) {
   173  	ctx := context.Background()
   174  	b, err := os.ReadFile("testdata/suffix-args-input.yaml")
   175  	require.NoError(t, err, "ReadFile failed")
   176  
   177  	var action Action
   178  	err = yaml.Unmarshal(b, &action)
   179  	require.NoError(t, err, "Unmarshal failed")
   180  
   181  	m := NewTestMixin(t)
   182  	m.Config.In = bytes.NewReader(b)
   183  
   184  	m.Config.Setenv(test.ExpectedCommandEnv, `docker build --tag getporter/porter-hello:latest .`)
   185  
   186  	err = m.Execute(ctx, ExecuteOptions{})
   187  	require.NoError(t, err)
   188  }