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  }