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  }