github.com/verrazzano/verrazzano@v1.7.0/tools/vz/cmd/analyze/analyze_test.go (about) 1 // Copyright (c) 2022, 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package analyze 5 6 import ( 7 "github.com/stretchr/testify/assert" 8 "github.com/verrazzano/verrazzano/tools/vz/pkg/constants" 9 "github.com/verrazzano/verrazzano/tools/vz/test/helpers" 10 "k8s.io/cli-runtime/pkg/genericclioptions" 11 "os" 12 "path/filepath" 13 "testing" 14 ) 15 16 const imagePullCase1 = "../../pkg/analysis/test/cluster/image-pull-case1/" 17 const ingressIPNotFound = "../../pkg/analysis/test/cluster/ingress-ip-not-found" 18 19 const loadBalancerErr = "Error syncing load balancer: failed to ensure load balancer: awaiting load balancer: context deadline exceeded" 20 const noIPFoundErr = "Verrazzano install failed as no IP found for service ingress-controller-ingress-nginx-controller with type LoadBalancer" 21 22 // TestAnalyzeDefaultFromReadOnlyDir 23 // GIVEN a CLI analyze command 24 // WHEN I call cmd.Execute from read only dir with a valid capture-dir and report-format set to "summary" 25 // THEN expect the command to do the analysis and generate report file into tmp dir 26 func TestAnalyzeDefaultFromReadOnlyDir(t *testing.T) { 27 stdoutFile, stderrFile := createStdTempFiles(t) 28 defer func() { 29 os.Remove(stdoutFile.Name()) 30 os.Remove(stderrFile.Name()) 31 }() 32 rc := helpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile}) 33 cmd := NewCmdAnalyze(rc) 34 assert.NotNil(t, cmd) 35 pwd, err := os.Getwd() 36 assert.Nil(t, err) 37 cmd.PersistentFlags().Set(constants.DirectoryFlagName, pwd+"/"+ingressIPNotFound) 38 cmd.PersistentFlags().Set(constants.ReportFormatFlagName, constants.SummaryReport) 39 assert.Nil(t, os.Chdir("/")) 40 defer os.Chdir(pwd) 41 err = cmd.Execute() 42 assert.Nil(t, err) 43 if fileMatched, _ := filepath.Glob(os.TempDir() + "/" + constants.VzAnalysisReportTmpFile); len(fileMatched) == 1 { 44 os.Remove(fileMatched[0]) 45 assert.NoFileExists(t, fileMatched[0]) 46 } 47 } 48 49 // TestAnalyzeCommandDetailedReport 50 // GIVEN a CLI analyze command 51 // WHEN I call cmd.Execute with a valid capture-dir and report-format set to "detailed" 52 // THEN expect the command to provide the report containing all the details for one or more issues reported 53 func TestAnalyzeCommandDetailedReport(t *testing.T) { 54 stdoutFile, stderrFile := createStdTempFiles(t) 55 defer func() { 56 os.Remove(stdoutFile.Name()) 57 os.Remove(stderrFile.Name()) 58 }() 59 rc := helpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile}) 60 cmd := NewCmdAnalyze(rc) 61 assert.NotNil(t, cmd) 62 cmd.PersistentFlags().Set(constants.DirectoryFlagName, ingressIPNotFound) 63 cmd.PersistentFlags().Set(constants.ReportFormatFlagName, constants.DetailedReport) 64 err := cmd.Execute() 65 assert.Nil(t, err) 66 buf, err := os.ReadFile(stdoutFile.Name()) 67 assert.NoError(t, err) 68 assert.Contains(t, string(buf), noIPFoundErr, 69 loadBalancerErr) 70 // Failures must be reported underreport file details-XXXXXX.out 71 if fileMatched, _ := filepath.Glob(constants.VzAnalysisReportTmpFile); len(fileMatched) == 1 { 72 os.Remove(fileMatched[0]) 73 assert.NoFileExists(t, fileMatched[0]) 74 } 75 } 76 77 // TestAnalyzeCommandSummaryReport 78 // GIVEN a CLI analyze command 79 // WHEN I call cmd.Execute with a valid capture-dir and report-format set to "summary" 80 // THEN expect the command to provide the report containing only summary for one or more issues reported 81 func TestAnalyzeCommandSummaryReport(t *testing.T) { 82 stdoutFile, stderrFile := createStdTempFiles(t) 83 defer func() { 84 os.Remove(stdoutFile.Name()) 85 os.Remove(stderrFile.Name()) 86 }() 87 rc := helpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile}) 88 cmd := NewCmdAnalyze(rc) 89 assert.NotNil(t, cmd) 90 cmd.PersistentFlags().Set(constants.DirectoryFlagName, ingressIPNotFound) 91 cmd.PersistentFlags().Set(constants.ReportFormatFlagName, constants.SummaryReport) 92 err := cmd.Execute() 93 assert.Nil(t, err) 94 buf, err := os.ReadFile(stdoutFile.Name()) 95 assert.NoError(t, err) 96 assert.NotContains(t, string(buf), loadBalancerErr) 97 assert.Contains(t, string(buf), noIPFoundErr) 98 // Failures must be reported underreport file details-XXXXXX.out 99 if fileMatched, _ := filepath.Glob(constants.VzAnalysisReportTmpFile); len(fileMatched) == 1 { 100 os.Remove(fileMatched[0]) 101 assert.NoFileExists(t, fileMatched[0]) 102 } 103 } 104 105 // TestAnalyzeCommandInvalidReportFormat 106 // GIVEN a CLI analyze command 107 // WHEN I call cmd.Execute with an invalid value for report-format 108 // THEN expect the command to fail with an appropriate error message to indicate the issue 109 func TestAnalyzeCommandInvalidReportFormat(t *testing.T) { 110 stdoutFile, stderrFile := createStdTempFiles(t) 111 defer func() { 112 os.Remove(stdoutFile.Name()) 113 os.Remove(stderrFile.Name()) 114 }() 115 rc := helpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile}) 116 cmd := NewCmdAnalyze(rc) 117 assert.NotNil(t, cmd) 118 cmd.PersistentFlags().Set(constants.DirectoryFlagName, imagePullCase1) 119 cmd.PersistentFlags().Set(constants.ReportFormatFlagName, "invalid-report-format") 120 err := cmd.Execute() 121 assert.NotNil(t, err) 122 buf, err := os.ReadFile(stderrFile.Name()) 123 assert.NoError(t, err) 124 assert.Contains(t, string(buf), "\"invalid-report-format\" is not valid for flag report-format, only \"summary\" and \"detailed\" are valid") 125 } 126 127 // TestAnalyzeWithDefaultReportFormat 128 // GIVEN a CLI analyze command 129 // WHEN I call cmd.Execute without report-format 130 // THEN expect the command to take the default value of summary for report-format and perform the analysis 131 func TestAnalyzeWithDefaultReportFormat(t *testing.T) { 132 stdoutFile, stderrFile := createStdTempFiles(t) 133 defer func() { 134 os.Remove(stdoutFile.Name()) 135 os.Remove(stderrFile.Name()) 136 if fileMatched, _ := filepath.Glob(constants.VzAnalysisReportTmpFile); len(fileMatched) == 1 { 137 os.Remove(fileMatched[0]) 138 assert.NoFileExists(t, fileMatched[0]) 139 } 140 }() 141 rc := helpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile}) 142 cmd := NewCmdAnalyze(rc) 143 assert.NotNil(t, cmd) 144 cmd.PersistentFlags().Set(constants.DirectoryFlagName, ingressIPNotFound) 145 err := cmd.Execute() 146 assert.Nil(t, err) 147 buf, err := os.ReadFile(stdoutFile.Name()) 148 assert.NoError(t, err) 149 assert.NotContains(t, string(buf), loadBalancerErr) 150 assert.Contains(t, string(buf), noIPFoundErr) 151 } 152 153 // TestAnalyzeWithNonPermissiveReportFile 154 // GIVEN a CLI analyze command 155 // WHEN I call cmd.Execute with report-file in read only file location 156 // THEN expect the command to fail the analysis and do not create report file 157 func TestAnalyzeWithNonPermissiveReportFile(t *testing.T) { 158 stdoutFile, stderrFile := createStdTempFiles(t) 159 defer func() { 160 os.Remove(stdoutFile.Name()) 161 os.Remove(stderrFile.Name()) 162 }() 163 rc := helpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile}) 164 cmd := NewCmdAnalyze(rc) 165 assert.NotNil(t, cmd) 166 cmd.PersistentFlags().Set(constants.DirectoryFlagName, imagePullCase1) 167 cmd.PersistentFlags().Set(constants.ReportFormatFlagName, constants.DetailedReport) 168 cmd.PersistentFlags().Set(constants.ReportFileFlagName, "/TestAnalyzeCommandReportFileOutput") 169 err := cmd.Execute() 170 // Failures must not be reported as report file only has read permissions 171 assert.NotNil(t, err) 172 assert.NoFileExists(t, "/TestAnalyzeCommandReportFileOutput") 173 } 174 175 // TestAnalyzeCommandWithReportFile 176 // GIVEN a CLI analyze command 177 // WHEN I call cmd.Execute with a valid report-file 178 // THEN expect the command to create the report file, containing the analysis report 179 func TestAnalyzeCommandWithReportFile(t *testing.T) { 180 stdoutFile, stderrFile := createStdTempFiles(t) 181 defer func() { 182 os.Remove(stdoutFile.Name()) 183 os.Remove(stderrFile.Name()) 184 os.Remove("TestAnalyzeCommandReportFileOutput") 185 }() 186 rc := helpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile}) 187 cmd := NewCmdAnalyze(rc) 188 assert.NotNil(t, cmd) 189 cmd.PersistentFlags().Set(constants.DirectoryFlagName, imagePullCase1) 190 cmd.PersistentFlags().Set(constants.ReportFormatFlagName, constants.DetailedReport) 191 cmd.PersistentFlags().Set(constants.ReportFileFlagName, "TestAnalyzeCommandReportFileOutput") 192 err := cmd.Execute() 193 assert.Nil(t, err) 194 assert.FileExists(t, "TestAnalyzeCommandReportFileOutput") 195 } 196 197 // TestAnalyzeCommandInvalidCapturedDir 198 // GIVEN a CLI analyze command 199 // WHEN I call cmd.Execute with capture-dir not containing the cluster snapshot 200 // THEN expect the command to fail with an appropriate error message 201 func TestAnalyzeCommandInvalidCapturedDir(t *testing.T) { 202 stdoutFile, stderrFile := createStdTempFiles(t) 203 defer func() { 204 os.Remove(stdoutFile.Name()) 205 os.Remove(stderrFile.Name()) 206 }() 207 rc := helpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile}) 208 cmd := NewCmdAnalyze(rc) 209 assert.NotNil(t, cmd) 210 cmd.PersistentFlags().Set(constants.DirectoryFlagName, "../") 211 err := cmd.Execute() 212 assert.NotNil(t, err) 213 buf, err := os.ReadFile(stderrFile.Name()) 214 assert.NoError(t, err) 215 assert.Contains(t, string(buf), "Cluster Analyzer runAnalysis didn't find any clusters") 216 } 217 218 // createStdTempFiles creates temporary files for stdout and stderr. 219 func createStdTempFiles(t *testing.T) (*os.File, *os.File) { 220 stdoutFile, err := os.CreateTemp("", "tmpstdout") 221 assert.NoError(t, err) 222 223 stderrFile, err := os.CreateTemp("", "tmpstderr") 224 assert.NoError(t, err) 225 226 return stdoutFile, stderrFile 227 }