github.com/verrazzano/verrazzano@v1.7.1/tools/vz/pkg/analysis/main_test.go (about)

     1  // Copyright (c) 2021, 2024, 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  package analysis
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/verrazzano/verrazzano/tools/vz/pkg/internal/util/log"
    12  	"github.com/verrazzano/verrazzano/tools/vz/pkg/internal/util/report"
    13  	vzhelper "github.com/verrazzano/verrazzano/tools/vz/test/helpers"
    14  	"k8s.io/cli-runtime/pkg/genericclioptions"
    15  )
    16  
    17  // TestHandleMain Tests the handleMain function
    18  // GIVEN a call to handleMain
    19  // WHEN with valid/invalid inputs
    20  // THEN exit codes returned are as expected
    21  func TestHandleMain(_ *testing.T) {
    22  	// This is setting up the main.logger, do NOT set it as a var here (or you will get a nil reference running
    23  	// the test)
    24  	logger = log.GetDebugEnabledLogger()
    25  	analyzerType = "cluster"
    26  }
    27  
    28  // TestAnalyzeBad Tests the main Analyze function
    29  // GIVEN a call to Analyze
    30  // WHEN with invalid inputs
    31  // THEN errors are generated as expected
    32  func TestExecuteAnalysisBadArgs(t *testing.T) {
    33  	logger := log.GetDebugEnabledLogger()
    34  	stdoutFile, stderrFile := createStdTempFiles(t)
    35  	defer func() {
    36  		os.Remove(stdoutFile.Name())
    37  		os.Remove(stderrFile.Name())
    38  	}()
    39  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
    40  	// Call the analyzer with an unknown type, give it a good cluster dump directory
    41  	err := Analyze(rc, logger, "badnamehere", "../test/cluster/image-pull-case1")
    42  	assert.NotNil(t, err)
    43  	// TODO: Check error message is what we expected here
    44  
    45  }
    46  func TestProblemPodsInCattleSystem(t *testing.T) {
    47  	logger := log.GetDebugEnabledLogger()
    48  	stdoutFile, stderrFile := createStdTempFiles(t)
    49  	defer func() {
    50  		os.Remove(stdoutFile.Name())
    51  		os.Remove(stderrFile.Name())
    52  	}()
    53  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
    54  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/testCattleSystempods")
    55  	assert.Nil(t, err)
    56  
    57  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
    58  	assert.Nil(t, reportedIssues)
    59  	assert.False(t, len(reportedIssues) > 0)
    60  	problemPodsFound := 0
    61  	for _, issue := range reportedIssues {
    62  		if issue.Type == report.PodProblemsNotReported {
    63  			problemPodsFound++
    64  		}
    65  
    66  	}
    67  	assert.True(t, problemPodsFound == 0)
    68  }
    69  
    70  // TestImagePullCase1 Tests that analysis of a cluster dump with image pull issues is handled
    71  // GIVEN a call to analyze a cluster-snapshot
    72  // WHEN the cluster-snapshot shows image pull issues
    73  // THEN a report is generated with image pull issues identified
    74  func TestImagePull(t *testing.T) {
    75  	logger := log.GetDebugEnabledLogger()
    76  	stdoutFile, stderrFile := createStdTempFiles(t)
    77  	defer func() {
    78  		os.Remove(stdoutFile.Name())
    79  		os.Remove(stderrFile.Name())
    80  	}()
    81  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
    82  	report.ClearReports()
    83  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/image-pull-case1")
    84  	assert.Nil(t, err)
    85  
    86  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
    87  	assert.NotNil(t, reportedIssues)
    88  	assert.True(t, len(reportedIssues) > 0)
    89  	imagePullsFound := 0
    90  	for _, issue := range reportedIssues {
    91  		if issue.Type == report.ImagePullNotFound {
    92  			imagePullsFound++
    93  		}
    94  	}
    95  	assert.True(t, imagePullsFound > 0)
    96  }
    97  
    98  // TestInsufficientMemory Tests that analysis of a cluster dump with pods that failed due to insufficient memory
    99  // GIVEN a call to analyze a cluster-snapshot
   100  // WHEN the cluster-snapshot shows pods with insufficient memory problems
   101  // THEN a report is generated with issues identified
   102  func TestInsufficientMemory(t *testing.T) {
   103  	logger := log.GetDebugEnabledLogger()
   104  	stdoutFile, stderrFile := createStdTempFiles(t)
   105  	defer func() {
   106  		os.Remove(stdoutFile.Name())
   107  		os.Remove(stderrFile.Name())
   108  	}()
   109  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   110  	report.ClearReports()
   111  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/insufficient-mem")
   112  	assert.Nil(t, err)
   113  
   114  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   115  	assert.NotNil(t, reportedIssues)
   116  	assert.True(t, len(reportedIssues) > 0)
   117  	issuesFound := 0
   118  	for _, issue := range reportedIssues {
   119  		if issue.Type == report.InsufficientMemory {
   120  			issuesFound++
   121  		}
   122  	}
   123  	assert.True(t, issuesFound > 0)
   124  }
   125  
   126  // TestProblemPodsNotReportedUninstall Tests that analysis of a cluster dump with pods that have unknown issues during
   127  // uninstall, is handled
   128  // GIVEN a call to analyze a cluster-snapshot
   129  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   130  // THEN a report is generated with problem pod issues identified
   131  func TestProblemPodsNotReportedUninstall(t *testing.T) {
   132  	logger := log.GetDebugEnabledLogger()
   133  	stdoutFile, stderrFile := createStdTempFiles(t)
   134  	defer func() {
   135  		os.Remove(stdoutFile.Name())
   136  		os.Remove(stderrFile.Name())
   137  	}()
   138  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   139  	report.ClearReports()
   140  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/problem-pods")
   141  	assert.Nil(t, err)
   142  
   143  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   144  	assert.NotNil(t, reportedIssues)
   145  	assert.True(t, len(reportedIssues) > 0)
   146  	problemPodsFound := 0
   147  	for _, issue := range reportedIssues {
   148  		if issue.Type == report.PodProblemsNotReported {
   149  			problemPodsFound++
   150  		}
   151  	}
   152  	assert.True(t, problemPodsFound > 0)
   153  }
   154  
   155  // TestProblemPodsNotReportedInstall Tests that analysis of a cluster dump with pods that have unknown issues during
   156  // install, is handled
   157  // GIVEN a call to analyze a cluster-snapshot
   158  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   159  // THEN a report is generated with problem pod issues identified
   160  func TestProblemPodsNotReportedInstall(t *testing.T) {
   161  	logger := log.GetDebugEnabledLogger()
   162  	stdoutFile, stderrFile := createStdTempFiles(t)
   163  	defer func() {
   164  		os.Remove(stdoutFile.Name())
   165  		os.Remove(stderrFile.Name())
   166  	}()
   167  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   168  	report.ClearReports()
   169  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/problem-pods-install")
   170  	assert.Nil(t, err)
   171  
   172  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   173  	assert.NotNil(t, reportedIssues)
   174  	assert.True(t, len(reportedIssues) > 0)
   175  
   176  	exceededLBLimit := 0
   177  	for _, issue := range reportedIssues {
   178  		if issue.Type == report.IngressLBLimitExceeded {
   179  			exceededLBLimit++
   180  		}
   181  
   182  	}
   183  	assert.True(t, exceededLBLimit > 0)
   184  }
   185  
   186  // TestLBIpNotSet Tests that analysis of a cluster dump where LB issue occurred with no IP set is handled
   187  // GIVEN a call to analyze a cluster-snapshot
   188  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   189  // THEN a report is generated with problem pod issues identified
   190  // Note: With the latest changes to platform operator and analysis tool, the issue is reported differently.
   191  // Commenting the test for now, and added a new test TestLBIpNotFound
   192  //func TestLBIpNotSet(t *testing.T) {
   193  //	logger := log.GetDebugEnabledLogger()
   194  
   195  //	err := Analyze(logger, "cluster", "../internal/test/cluster/lb-ipnotset")
   196  //	assert.Nil(t, err)
   197  
   198  //	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   199  //	assert.NotNil(t, reportedIssues)
   200  //	assert.True(t, len(reportedIssues) > 0)
   201  //	problemsFound := 0
   202  //	for _, issue := range reportedIssues {
   203  //		if issue.Type == report.IngressNoLoadBalancerIP {
   204  //			problemsFound++
   205  //		}
   206  //	}
   207  //	assert.True(t, problemsFound > 0)
   208  //}
   209  
   210  // TestLBIpNotFound Tests that analysis of a cluster dump where no IP was found for load balancer
   211  // GIVEN a call to analyze a cluster-snapshot
   212  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   213  // THEN a report is generated with problem pod issues identified
   214  func TestLBIpNotFound(t *testing.T) {
   215  	logger := log.GetDebugEnabledLogger()
   216  	stdoutFile, stderrFile := createStdTempFiles(t)
   217  	defer func() {
   218  		os.Remove(stdoutFile.Name())
   219  		os.Remove(stderrFile.Name())
   220  	}()
   221  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   222  	report.ClearReports()
   223  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/ingress-ip-not-found")
   224  	assert.Nil(t, err)
   225  
   226  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   227  	assert.NotNil(t, reportedIssues)
   228  	assert.True(t, len(reportedIssues) > 0)
   229  	problemsFound := 0
   230  	for _, issue := range reportedIssues {
   231  		if issue.Type == report.IngressNoIPFound {
   232  			problemsFound++
   233  		}
   234  	}
   235  	assert.True(t, problemsFound > 0)
   236  }
   237  
   238  // TestIstioLBIpNotFound Tests that analysis of a cluster dump where no Istio Gateway IP was found
   239  // GIVEN a call to analyze a cluster-snapshot
   240  // WHEN the cluster-snapshot shows services with external IP problems
   241  // THEN a report is generated with issues identified
   242  func TestIstioLBIpNotFound(t *testing.T) {
   243  	logger := log.GetDebugEnabledLogger()
   244  	stdoutFile, stderrFile := createStdTempFiles(t)
   245  	defer func() {
   246  		os.Remove(stdoutFile.Name())
   247  		os.Remove(stderrFile.Name())
   248  	}()
   249  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   250  	report.ClearReports()
   251  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/istio-ingress-ip-not-found")
   252  	assert.Nil(t, err)
   253  
   254  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   255  	assert.NotNil(t, reportedIssues)
   256  	assert.True(t, len(reportedIssues) > 0)
   257  	problemsFound := 0
   258  	for _, issue := range reportedIssues {
   259  		if issue.Type == report.IstioIngressNoIP {
   260  			problemsFound++
   261  		}
   262  	}
   263  	assert.True(t, problemsFound > 0)
   264  }
   265  
   266  // TODO: Enable this test once there is a cluster dump for this use case
   267  // TestIngressInstall Tests that analysis of a cluster dump where Ingress install failed without more info handled
   268  // GIVEN a call to analyze a cluster-snapshot
   269  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   270  // THEN a report is generated with problem pod issues identified
   271  // func TestIngressInstall(t *testing.T) {
   272  //	logger := log.GetDebugEnabledLogger()
   273  
   274  //	err := Analyze(logger, "cluster", "../internal/test/cluster/ingress-install-unknown")
   275  //	assert.Nil(t, err)
   276  
   277  //	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   278  //	assert.NotNil(t, reportedIssues)
   279  //	assert.True(t, len(reportedIssues) > 0)
   280  //	problemsFound := 0
   281  //	for _, issue := range reportedIssues {
   282  //		if issue.Type == report.IngressInstallFailure {
   283  //			problemsFound++
   284  //		}
   285  //	}
   286  //	assert.True(t, problemsFound > 0)
   287  //}
   288  
   289  // TestLBLimitExceeded Test that analysis of a cluster dump where Ingress install failed due to LoadBalancer service limit handled
   290  // GIVEN a call to analyze a cluster-snapshot
   291  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   292  // THEN a report is generated with problem pod issues identified
   293  func TestLBLimitExceeded(t *testing.T) {
   294  	logger := log.GetDebugEnabledLogger()
   295  	stdoutFile, stderrFile := createStdTempFiles(t)
   296  	defer func() {
   297  		os.Remove(stdoutFile.Name())
   298  		os.Remove(stderrFile.Name())
   299  	}()
   300  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   301  	report.ClearReports()
   302  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/ingress-lb-limit")
   303  	assert.Nil(t, err)
   304  
   305  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   306  	assert.NotNil(t, reportedIssues)
   307  	assert.True(t, len(reportedIssues) > 0)
   308  	problemsFound := 0
   309  	for _, issue := range reportedIssues {
   310  		if issue.Type == report.IngressLBLimitExceeded {
   311  			problemsFound++
   312  		}
   313  	}
   314  	assert.True(t, problemsFound > 0)
   315  }
   316  
   317  // TestOciIPLimitExceeded Tests that analysis of a cluster dump where Ingress install failed due to OCI limit handled
   318  // GIVEN a call to analyze a cluster-snapshot
   319  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   320  // THEN a report is generated with problem pod issues identified
   321  func TestOciIPLimitExceeded(t *testing.T) {
   322  	logger := log.GetDebugEnabledLogger()
   323  	stdoutFile, stderrFile := createStdTempFiles(t)
   324  	defer func() {
   325  		os.Remove(stdoutFile.Name())
   326  		os.Remove(stderrFile.Name())
   327  	}()
   328  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   329  	report.ClearReports()
   330  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/ingress-oci-limit")
   331  	assert.Nil(t, err)
   332  
   333  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   334  	assert.NotNil(t, reportedIssues)
   335  	assert.True(t, len(reportedIssues) > 0)
   336  	problemsFound := 0
   337  	for _, issue := range reportedIssues {
   338  		if issue.Type == report.IngressOciIPLimitExceeded {
   339  			problemsFound++
   340  		}
   341  	}
   342  	assert.True(t, problemsFound > 0)
   343  }
   344  
   345  // TestOciLBInvalidShape Tests that analysis of a cluster dump where an invalid shape specified for OCI load balancer
   346  // GIVEN a call to analyze a cluster-snapshot
   347  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   348  // THEN a report is generated with problem pod issues identified
   349  func TestOciLBInvalidShape(t *testing.T) {
   350  	logger := log.GetDebugEnabledLogger()
   351  	stdoutFile, stderrFile := createStdTempFiles(t)
   352  	defer func() {
   353  		os.Remove(stdoutFile.Name())
   354  		os.Remove(stderrFile.Name())
   355  	}()
   356  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   357  	report.ClearReports()
   358  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/ingress-invalid-shape")
   359  	assert.Nil(t, err)
   360  
   361  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   362  	assert.NotNil(t, reportedIssues)
   363  	assert.True(t, len(reportedIssues) > 0)
   364  	problemsFound := 0
   365  	for _, issue := range reportedIssues {
   366  		if issue.Type == report.IngressShapeInvalid {
   367  			problemsFound++
   368  		}
   369  	}
   370  	assert.True(t, problemsFound > 0)
   371  }
   372  
   373  // TestPendingPods that analysis of a cluster dump where pending pods only is handled
   374  // GIVEN a call to analyze a cluster-snapshot
   375  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   376  // THEN a report is generated with problem pod issues identified
   377  func TestPendingPods(t *testing.T) {
   378  	logger := log.GetDebugEnabledLogger()
   379  	stdoutFile, stderrFile := createStdTempFiles(t)
   380  	defer func() {
   381  		os.Remove(stdoutFile.Name())
   382  		os.Remove(stderrFile.Name())
   383  	}()
   384  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   385  	report.ClearReports()
   386  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/pending-pods")
   387  	assert.Nil(t, err)
   388  
   389  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   390  	assert.NotNil(t, reportedIssues)
   391  	assert.True(t, len(reportedIssues) > 0)
   392  	problemsFound := 0
   393  	for _, issue := range reportedIssues {
   394  		if issue.Type == report.PendingPods {
   395  			problemsFound++
   396  		}
   397  	}
   398  	assert.True(t, problemsFound > 0)
   399  }
   400  
   401  // TestUnknownInstall Tests that analysis of a cluster dump where install failed without more info handled
   402  // GIVEN a call to analyze a cluster-snapshot
   403  // WHEN the cluster-snapshot shows pods with problems that are not known issues
   404  // THEN a report is generated with problem pod issues identified
   405  // Commenting this test as there might not be an install issue like this now.
   406  //func TestUnknownInstall(t *testing.T) {
   407  //	logger := log.GetDebugEnabledLogger()
   408  
   409  //	err := Analyze(logger, "cluster", "../internal/test/cluster/install-unknown")
   410  //	assert.Nil(t, err)
   411  
   412  //	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   413  //	assert.NotNil(t, reportedIssues)
   414  //	assert.True(t, len(reportedIssues) > 0)
   415  //	problemsFound := 0
   416  //	for _, issue := range reportedIssues {
   417  //		if issue.Type == report.InstallFailure {
   418  //			problemsFound++
   419  //		}
   420  //	}
   421  //	assert.True(t, problemsFound > 0)
   422  //}
   423  
   424  // TestIstioIngressInstallFailure Tests that analysis of a cluster dump when IstioIngressLoadBalancer was not created
   425  // GIVEN a call to analyze a cluster-snapshot
   426  // WHEN the cluster-snapshot shows private subnet not allowed in public LB.
   427  // THEN a report is generated with issues identified
   428  func TestIstioIngressInstallFailure(t *testing.T) {
   429  	logger := log.GetDebugEnabledLogger()
   430  	stdoutFile, stderrFile := createStdTempFiles(t)
   431  	defer func() {
   432  		os.Remove(stdoutFile.Name())
   433  		os.Remove(stderrFile.Name())
   434  	}()
   435  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   436  	report.ClearReports()
   437  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/istio-loadbalancer-creation-issue")
   438  	assert.Nil(t, err)
   439  
   440  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   441  	assert.NotNil(t, reportedIssues)
   442  	assert.True(t, len(reportedIssues) > 0)
   443  	problemsFound := 0
   444  	for _, issue := range reportedIssues {
   445  		if issue.Type == report.IstioIngressPrivateSubnet {
   446  			problemsFound++
   447  		}
   448  	}
   449  	assert.True(t, problemsFound > 0)
   450  }
   451  
   452  // TestComponentsNotReadyNoErrorMsg Tests that analysis of a cluster dump where there are failed components with no error message in the VPO logs
   453  // GIVEN a call to analyze a cluster-snapshot
   454  // WHEN the cluster-snapshot shows that there is install failure with no known root cause
   455  // THEN a report is generated with supporting messages from the events related to those failed components' pods
   456  func TestComponentsNotReadyNoErrorMsg(t *testing.T) {
   457  	logger := log.GetDebugEnabledLogger()
   458  	stdoutFile, stderrFile := createStdTempFiles(t)
   459  	defer func() {
   460  		os.Remove(stdoutFile.Name())
   461  		os.Remove(stderrFile.Name())
   462  	}()
   463  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   464  	report.ClearReports()
   465  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/components-not-ready")
   466  	assert.Nil(t, err)
   467  
   468  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   469  	assert.NotNil(t, reportedIssues)
   470  	assert.True(t, len(reportedIssues) > 0)
   471  
   472  	problemsFound := 0
   473  	for _, issue := range reportedIssues {
   474  		if issue.Type == report.InstallFailure {
   475  			problemsFound++
   476  			// Two supporting messages are always included. Rest should come from events related to failed components
   477  			assert.True(t, len(issue.SupportingData[0].Messages) > 2)
   478  		}
   479  	}
   480  	assert.True(t, problemsFound > 0)
   481  }
   482  
   483  // TestExternalDNSConfigurationIssue Tests that analysis of a cluster dump when dns(oci,custom dns) was not configured
   484  // GIVEN a call to analyze a cluster-snapshot
   485  // WHEN the cluster-snapshot shows private subnet not allowed in public LB.
   486  // THEN a report is generated with issues identified
   487  func TestExternalDNSConfigurationIssue(t *testing.T) {
   488  	logger := log.GetDebugEnabledLogger()
   489  	stdoutFile, stderrFile := createStdTempFiles(t)
   490  	defer func() {
   491  		os.Remove(stdoutFile.Name())
   492  		os.Remove(stderrFile.Name())
   493  	}()
   494  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   495  	report.ClearReports()
   496  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/external-dns-issue")
   497  	assert.Nil(t, err)
   498  
   499  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   500  	assert.NotNil(t, reportedIssues)
   501  	assert.True(t, len(reportedIssues) > 0)
   502  	problemsFound := 0
   503  	for _, issue := range reportedIssues {
   504  		if issue.Type == report.ExternalDNSConfigureIssue {
   505  			problemsFound++
   506  		}
   507  	}
   508  	assert.True(t, problemsFound > 0)
   509  }
   510  
   511  // TestResourceJSONWithVerrazzanoFormat Tests that analysis of a cluster dump
   512  // when there is an install failure and the verrazzano-resource.json contains Verrazzano type instead of VerrazzanoList type
   513  // GIVEN a call to analyze a cluster-snapshot
   514  // WHEN the cluster-snapshot shows components not in ready state
   515  // THEN a report is generated with install failure
   516  func TestResourceJSONWithVerrazzanoFormat(t *testing.T) {
   517  	logger := log.GetDebugEnabledLogger()
   518  	stdoutFile, stderrFile := createStdTempFiles(t)
   519  	defer func() {
   520  		os.Remove(stdoutFile.Name())
   521  		os.Remove(stderrFile.Name())
   522  	}()
   523  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   524  	report.ClearReports()
   525  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/install-failure-verrazzano-format-json")
   526  	assert.Nil(t, err)
   527  
   528  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   529  	assert.NotNil(t, reportedIssues)
   530  	assert.True(t, len(reportedIssues) > 0)
   531  	problemsFound := 0
   532  	for _, issue := range reportedIssues {
   533  		fmt.Println(issue)
   534  		if issue.Type == report.InstallFailure {
   535  			problemsFound++
   536  		}
   537  	}
   538  	assert.True(t, problemsFound > 0)
   539  }
   540  
   541  // TestKeycloakDataMigrationFailure tests that analysis of a cluster dump when keycloak data migration during upgrade has failed
   542  // GIVEN a call to analyze a cluster-snapshot
   543  // WHEN the cluster-snapshot data load job failure
   544  // THEN a report is generated with issues identified
   545  func TestKeycloakDataMigrationFailure(t *testing.T) {
   546  	logger := log.GetDebugEnabledLogger()
   547  	stdoutFile, stderrFile := createStdTempFiles(t)
   548  	defer func() {
   549  		os.Remove(stdoutFile.Name())
   550  		os.Remove(stderrFile.Name())
   551  	}()
   552  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   553  	report.ClearReports()
   554  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/keycloak-data-migration-failure")
   555  	assert.Nil(t, err)
   556  
   557  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   558  	assert.NotNil(t, reportedIssues)
   559  	assert.True(t, len(reportedIssues) > 0)
   560  	problemsFound := 0
   561  	for _, issue := range reportedIssues {
   562  		if issue.Type == report.KeycloakDataMigrationFailure {
   563  			problemsFound++
   564  		}
   565  	}
   566  	assert.True(t, problemsFound > 0)
   567  }
   568  
   569  // TestCertificateVZClientHangingIssue tests analysis of a cluster dump when the VZ Client is hanging
   570  // GIVEN a call to analyze a cluster-snapshot
   571  // WHEN the VZ Client is hanging on a certificate, but the certificate is not expired
   572  // THEN a report is generated with issues identified
   573  // This test also tests for detecting a separate expired certificate in the certificates.json
   574  func TestCertificateVZClientHangingIssue(t *testing.T) {
   575  	logger := log.GetDebugEnabledLogger()
   576  	stdoutFile, stderrFile := createStdTempFiles(t)
   577  	defer func() {
   578  		os.Remove(stdoutFile.Name())
   579  		os.Remove(stderrFile.Name())
   580  	}()
   581  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   582  	report.ClearReports()
   583  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/testCLIHangingIssue")
   584  	assert.Nil(t, err)
   585  
   586  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   587  	assert.NotNil(t, reportedIssues)
   588  	assert.True(t, len(reportedIssues) > 0)
   589  	problemsFound := 0
   590  	for _, issue := range reportedIssues {
   591  		if issue.Type == report.VZClientHangingIssueDueToLongCertificateApproval {
   592  			problemsFound++
   593  		}
   594  		if issue.Type == report.CertificateExpired {
   595  			problemsFound++
   596  		}
   597  	}
   598  	assert.True(t, problemsFound == 2)
   599  }
   600  
   601  // TestBlockStorageFailure Tests that analysis of a cluster dump when Block Storage limit is exceeded
   602  // GIVEN a call to analyze a cluster-snapshot
   603  // WHEN the cluster-snapshot shows private subnet not allowed in public LB.
   604  // THEN a report is generated with issues identified
   605  func TestBlockStorageFailure(t *testing.T) {
   606  	logger := log.GetDebugEnabledLogger()
   607  	stdoutFile, stderrFile := createStdTempFiles(t)
   608  	defer func() {
   609  		os.Remove(stdoutFile.Name())
   610  		os.Remove(stderrFile.Name())
   611  	}()
   612  	rc := vzhelper.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   613  	report.ClearReports()
   614  	err := Analyze(rc, logger, "cluster", "../internal/test/cluster/blockstorage-limitexceeded")
   615  	assert.Nil(t, err)
   616  
   617  	reportedIssues := report.GetAllSourcesFilteredIssues(logger, true, 0, 0)
   618  	assert.NotNil(t, reportedIssues)
   619  	assert.True(t, len(reportedIssues) > 0)
   620  	problemsFound := 0
   621  	for _, issue := range reportedIssues {
   622  		if issue.Type == report.BlockStorageLimitExceeded {
   623  			problemsFound++
   624  		}
   625  	}
   626  	assert.True(t, problemsFound > 0)
   627  }
   628  
   629  // createStdTempFiles creates temporary files for stdout and stderr.
   630  func createStdTempFiles(t *testing.T) (*os.File, *os.File) {
   631  	stdoutFile, err := os.CreateTemp("", "tmpstdout")
   632  	assert.NoError(t, err)
   633  
   634  	stderrFile, err := os.CreateTemp("", "tmpstderr")
   635  	assert.NoError(t, err)
   636  
   637  	return stdoutFile, stderrFile
   638  }