github.com/GoogleContainerTools/skaffold/v2@v2.13.2/integration/exec_test.go (about) 1 /* 2 Copyright 2023 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package integration 18 19 import ( 20 "os" 21 "path/filepath" 22 "testing" 23 24 "github.com/google/uuid" 25 26 "github.com/GoogleContainerTools/skaffold/v2/integration/skaffold" 27 "github.com/GoogleContainerTools/skaffold/v2/testutil" 28 ) 29 30 func TestExec_LocalActions(t *testing.T) { 31 tests := []struct { 32 description string 33 action string 34 shouldErr bool 35 envFile string 36 expectedMsgs []string 37 }{ 38 39 { 40 description: "fail due to action timeout", 41 action: "action-fail-timeout", 42 shouldErr: true, 43 expectedMsgs: []string{"context deadline exceeded"}, 44 }, 45 { 46 description: "fail with fail fast", 47 action: "action-fail-fast", 48 shouldErr: true, 49 expectedMsgs: []string{`"task4" running container image "alpine:3.15.4" errored during run with status code: 1`}, 50 }, 51 { 52 description: "fail with fail safe", 53 action: "action-fail-safe", 54 shouldErr: true, 55 expectedMsgs: []string{ 56 "[task5] hello-from-task5", 57 "[task5] bye-from-task5", 58 `* "task6" running container image "alpine:3.15.4" errored during run with status code: 1`, 59 }, 60 }, 61 { 62 description: "action succeeded", 63 action: "action-succeeded", 64 envFile: "exec.env", 65 expectedMsgs: []string{ 66 "[task7] hello-from-env-file", 67 "[task7] bye-from-env-file", 68 }, 69 }, 70 } 71 72 for _, test := range tests { 73 testutil.Run(t, test.description, func(t *testutil.T) { 74 MarkIntegrationTest(t.T, CanRunWithoutGcp) 75 args := []string{test.action} 76 77 if test.envFile != "" { 78 args = append(args, "--env-file", test.envFile) 79 } 80 81 out, err := skaffold.Exec(args...).InDir("testdata/custom-actions-local").RunWithCombinedOutput(t.T) 82 t.CheckError(test.shouldErr, err) 83 84 for _, expectedMsg := range test.expectedMsgs { 85 t.CheckContains(expectedMsg, string(out)) 86 } 87 }) 88 } 89 } 90 91 func TestExec_LocalActionWithLocalArtifact(t *testing.T) { 92 tests := []struct { 93 description string 94 action string 95 shouldErr bool 96 shouldBuild bool 97 expectedMsgs []string 98 }{ 99 { 100 description: "fail due not found image", 101 action: "action-with-local-built-img", 102 shouldErr: true, 103 expectedMsgs: []string{ 104 "Error response from daemon: pull access denied for localtaks", 105 }, 106 }, 107 { 108 description: "build and run task", 109 action: "action-with-local-built-img", 110 shouldBuild: true, 111 expectedMsgs: []string{ 112 "[local-img-task1] Hello world from-local-img! 4", 113 }, 114 }, 115 } 116 117 for _, test := range tests { 118 testutil.Run(t, test.description, func(t *testutil.T) { 119 MarkIntegrationTest(t.T, CanRunWithoutGcp) 120 dir := "testdata/custom-actions-local" 121 args := []string{test.action} 122 123 if test.shouldBuild { 124 tmpfile := testutil.TempFile(t.T, "", []byte{}) 125 skaffold.Build("--file-output", tmpfile).InDir(dir).RunOrFail(t.T) 126 args = append(args, "--build-artifacts", tmpfile) 127 } 128 129 out, err := skaffold.Exec(args...).InDir(dir).RunWithCombinedOutput(t.T) 130 t.CheckError(test.shouldErr, err) 131 132 for _, expectedMsg := range test.expectedMsgs { 133 t.CheckContains(expectedMsg, string(out)) 134 } 135 }) 136 } 137 } 138 139 func TestExec_ActionsEvents(t *testing.T) { 140 tests := []struct { 141 description string 142 action string 143 shouldErr bool 144 expectedLogs []string 145 }{ 146 { 147 description: "events for succeeded action", 148 action: "action-succeeded", 149 expectedLogs: []string{ 150 `"taskEvent":{"id":"Exec-0","task":"Exec","description":"Executing custom action action-succeeded","status":"InProgress"}}`, 151 `"execEvent":{"id":"task7","taskId":"Exec-0","status":"InProgress"}}`, 152 `"execEvent":{"id":"task8","taskId":"Exec-0","status":"InProgress"}}`, 153 `"execEvent":{"id":"task7","taskId":"Exec-0","status":"Succeeded"}}`, 154 `"execEvent":{"id":"task8","taskId":"Exec-0","status":"Succeeded"}}`, 155 // TODO(#8728): Uncomment this expected log line when the flaky behaviour is solved. 156 // `"taskEvent":{"id":"Exec-0","task":"Exec","status":"Succeeded"}}`, 157 }, 158 }, 159 { 160 description: "events for fail action - fail fast", 161 action: "action-fail-fast", 162 shouldErr: true, 163 expectedLogs: []string{ 164 `"taskEvent":{"id":"Exec-0","task":"Exec","description":"Executing custom action action-fail-fast","status":"InProgress"}}`, 165 `"execEvent":{"id":"task3","taskId":"Exec-0","status":"InProgress"}}`, 166 `"execEvent":{"id":"task4","taskId":"Exec-0","status":"InProgress"}}`, 167 `"execEvent":{"id":"task4","taskId":"Exec-0","status":"Failed","actionableErr":{"errCode":"UNKNOWN_ERROR","message":"\"task4\" running container image \"alpine:3.15.4\" errored during run with status code: 1"`, 168 `"execEvent":{"id":"task3","taskId":"Exec-0","status":"Failed","actionableErr":{"errCode":"UNKNOWN_ERROR","message":"context canceled"`, 169 `"taskEvent":{"id":"Exec-0","task":"Exec","status":"Failed","actionableErr":{"errCode":"UNKNOWN_ERROR","message":"\"task4\" running container image \"alpine:3.15.4\" errored during run with status code: 1"`, 170 }, 171 }, 172 { 173 description: "events for fail action - fail safe", 174 action: "action-fail-safe", 175 shouldErr: true, 176 expectedLogs: []string{ 177 `"taskEvent":{"id":"Exec-0","task":"Exec","description":"Executing custom action action-fail-safe","status":"InProgress"}}`, 178 `"execEvent":{"id":"task5","taskId":"Exec-0","status":"InProgress"}}`, 179 `"execEvent":{"id":"task6","taskId":"Exec-0","status":"InProgress"}}`, 180 `"execEvent":{"id":"task6","taskId":"Exec-0","status":"Failed","actionableErr":{"errCode":"UNKNOWN_ERROR","message":"\"task6\" running container image \"alpine:3.15.4\" errored during run with status code: 1"`, 181 `"execEvent":{"id":"task5","taskId":"Exec-0","status":"Succeeded"}}`, 182 `"taskEvent":{"id":"Exec-0","task":"Exec","status":"Failed","actionableErr":{"errCode":"UNKNOWN_ERROR","message":"1 error(s) occurred:\n* \"task6\" running container image \"alpine:3.15.4\" errored during run with status code: 1"`, 183 }, 184 }, 185 } 186 187 for _, test := range tests { 188 testutil.Run(t, test.description, func(t *testutil.T) { 189 MarkIntegrationTest(t.T, CanRunWithoutGcp) 190 rpcAddr := randomPort() 191 tmp := t.TempDir() 192 logFile := filepath.Join(tmp, uuid.New().String()+"logs.json") 193 194 args := []string{test.action, "--rpc-port", rpcAddr, "--event-log-file", logFile} 195 196 _, err := skaffold.Exec(args...).InDir("testdata/custom-actions-local").RunWithCombinedOutput(t.T) 197 198 t.CheckError(test.shouldErr, err) 199 200 b, err := os.ReadFile(logFile + ".v2") 201 if err != nil { 202 t.Fatalf("error reading %s", logFile+".v2") 203 } 204 v2EventLogs := string(b) 205 for _, expectedLog := range test.expectedLogs { 206 t.CheckContains(expectedLog, v2EventLogs) 207 } 208 }) 209 } 210 }