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 }