github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/deploy/util/logfile_test.go (about) 1 /* 2 Copyright 2020 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 util 18 19 import ( 20 "bytes" 21 "context" 22 "errors" 23 "fmt" 24 "io" 25 "os" 26 "path/filepath" 27 "strings" 28 "testing" 29 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/graph" 31 "github.com/GoogleContainerTools/skaffold/testutil" 32 ) 33 34 func TestWithLogFile(t *testing.T) { 35 logDeploySucceeded := " - fake/deployment created" 36 logDeployFailed := " - failed to deploy" 37 logFilename := "- writing logs to " + filepath.Join(os.TempDir(), "skaffold", "deploy", "deploy.log") 38 39 tests := []struct { 40 description string 41 muted Muted 42 shouldErr bool 43 expectedNamespaces []string 44 logsFound []string 45 logsNotFound []string 46 }{ 47 { 48 description: "all logs", 49 muted: mutedDeploy(false), 50 shouldErr: false, 51 expectedNamespaces: []string{"ns"}, 52 logsFound: []string{logDeploySucceeded}, 53 logsNotFound: []string{logFilename}, 54 }, 55 { 56 description: "mute deploy logs", 57 muted: mutedDeploy(true), 58 shouldErr: false, 59 expectedNamespaces: []string{"ns"}, 60 logsFound: []string{logFilename}, 61 logsNotFound: []string{logDeploySucceeded}, 62 }, 63 { 64 description: "failed deploy - all logs", 65 muted: mutedDeploy(false), 66 shouldErr: true, 67 expectedNamespaces: nil, 68 logsFound: []string{logDeployFailed}, 69 logsNotFound: []string{logFilename}, 70 }, 71 { 72 description: "failed deploy - mutedDeploy logs", 73 muted: mutedDeploy(true), 74 shouldErr: true, 75 expectedNamespaces: nil, 76 logsFound: []string{logFilename}, 77 logsNotFound: []string{logDeployFailed}, 78 }, 79 } 80 for _, test := range tests { 81 testutil.Run(t, test.description, func(t *testutil.T) { 82 var mockOut bytes.Buffer 83 84 var deployer = mockDeployer{ 85 muted: test.muted, 86 shouldErr: test.shouldErr, 87 } 88 89 deployOut, postDeployFn, _ := WithLogFile("deploy.log", &mockOut, test.muted) 90 namespaces, err := deployer.Deploy(context.Background(), deployOut, nil) 91 postDeployFn() 92 93 t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expectedNamespaces, namespaces) 94 for _, found := range test.logsFound { 95 t.CheckContains(found, mockOut.String()) 96 } 97 for _, notFound := range test.logsNotFound { 98 t.CheckFalse(strings.Contains(mockOut.String(), notFound)) 99 } 100 }) 101 } 102 } 103 104 func TestWithStatusCheckLogFile(t *testing.T) { 105 logDeploySucceeded := " - deployment/leeroy-app is ready. [1/2 deployment(s) still pending]" 106 logDeployFailed := " - deployment/leeroy-app failed. could not pull image" 107 logFilename := "- writing logs to " + filepath.Join(os.TempDir(), "skaffold", "status-check", "status-check.log") 108 109 tests := []struct { 110 description string 111 muted Muted 112 shouldErr bool 113 expectedNamespaces []string 114 logsFound []string 115 logsNotFound []string 116 }{ 117 { 118 description: "all logs", 119 muted: mutedStatusCheck(false), 120 shouldErr: false, 121 expectedNamespaces: []string{"ns"}, 122 logsFound: []string{logDeploySucceeded}, 123 logsNotFound: []string{logFilename}, 124 }, 125 { 126 description: "mute status check logs", 127 muted: mutedStatusCheck(true), 128 shouldErr: false, 129 expectedNamespaces: []string{"ns"}, 130 logsFound: []string{logFilename}, 131 logsNotFound: []string{logDeploySucceeded}, 132 }, 133 { 134 description: "failed status-check - all logs", 135 muted: mutedStatusCheck(false), 136 shouldErr: true, 137 expectedNamespaces: nil, 138 logsFound: []string{logDeployFailed}, 139 logsNotFound: []string{logFilename}, 140 }, 141 { 142 description: "failed status-check - mutedDeploy logs", 143 muted: mutedStatusCheck(true), 144 shouldErr: true, 145 expectedNamespaces: nil, 146 logsFound: []string{logFilename}, 147 logsNotFound: []string{logDeployFailed}, 148 }, 149 } 150 for _, test := range tests { 151 testutil.Run(t, test.description, func(t *testutil.T) { 152 var mockOut bytes.Buffer 153 154 var deployer = mockStatusMonitor{ 155 muted: test.muted, 156 shouldErr: test.shouldErr, 157 } 158 159 deployOut, postDeployFn, _ := WithStatusCheckLogFile("status-check.log", &mockOut, test.muted) 160 namespaces, err := deployer.Deploy(context.Background(), deployOut, nil) 161 postDeployFn() 162 163 t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expectedNamespaces, namespaces) 164 for _, found := range test.logsFound { 165 t.CheckContains(found, mockOut.String()) 166 } 167 for _, notFound := range test.logsNotFound { 168 t.CheckFalse(strings.Contains(mockOut.String(), notFound)) 169 } 170 }) 171 } 172 } 173 174 // Used just to show how output gets routed to different writers with the log file 175 type mockDeployer struct { 176 muted Muted 177 shouldErr bool 178 } 179 180 func (fd *mockDeployer) Deploy(ctx context.Context, out io.Writer, _ []graph.Artifact) ([]string, error) { 181 if fd.shouldErr { 182 fmt.Fprintln(out, " - failed to deploy") 183 return nil, errors.New("failed to deploy") 184 } 185 186 fmt.Fprintln(out, " - fake/deployment created") 187 return []string{"ns"}, nil 188 } 189 190 // Used just to show how output gets routed to different writers with the log file 191 type mockStatusMonitor struct { 192 muted Muted 193 shouldErr bool 194 } 195 196 func (fd *mockStatusMonitor) Deploy(ctx context.Context, out io.Writer, _ []graph.Artifact) ([]string, error) { 197 if fd.shouldErr { 198 fmt.Fprintln(out, " - deployment/leeroy-app failed. could not pull image") 199 return nil, errors.New("- deployment/leeroy-app failed. could not pull image") 200 } 201 202 fmt.Fprintln(out, " - deployment/leeroy-app is ready. [1/2 deployment(s) still pending]") 203 return []string{"ns"}, nil 204 } 205 206 type mutedDeploy bool 207 208 func (m mutedDeploy) MuteDeploy() bool { 209 return bool(m) 210 } 211 212 func (m mutedDeploy) MuteStatusCheck() bool { 213 return false 214 } 215 216 type mutedStatusCheck bool 217 218 func (m mutedStatusCheck) MuteDeploy() bool { 219 return false 220 } 221 222 func (m mutedStatusCheck) MuteStatusCheck() bool { 223 return bool(m) 224 }