github.com/verrazzano/verrazzano@v1.7.1/tools/vz/cmd/install/install_test.go (about)

     1  // Copyright (c) 2022, 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  
     4  package install
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/validators"
    14  
    15  	"github.com/spf13/cobra"
    16  	"github.com/stretchr/testify/assert"
    17  	vzconstants "github.com/verrazzano/verrazzano/pkg/constants"
    18  	"github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1"
    19  	"github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1beta1"
    20  	"github.com/verrazzano/verrazzano/tools/vz/cmd/analyze"
    21  	cmdHelpers "github.com/verrazzano/verrazzano/tools/vz/cmd/helpers"
    22  	"github.com/verrazzano/verrazzano/tools/vz/pkg/constants"
    23  	"github.com/verrazzano/verrazzano/tools/vz/pkg/helpers"
    24  	testhelpers "github.com/verrazzano/verrazzano/tools/vz/test/helpers"
    25  	appsv1 "k8s.io/api/apps/v1"
    26  	corev1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/types"
    29  	"k8s.io/cli-runtime/pkg/genericclioptions"
    30  	dynfake "k8s.io/client-go/dynamic/fake"
    31  	"sigs.k8s.io/controller-runtime/pkg/client"
    32  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    33  	"sigs.k8s.io/yaml"
    34  )
    35  
    36  const (
    37  	testKubeConfig    = "kubeconfig"
    38  	testK8sContext    = "testcontext"
    39  	testFilenamePath  = "../../test/testdata/v1beta1.yaml"
    40  	BugReportNotExist = "cannot find bug report file in current directory"
    41  )
    42  
    43  // TestInstallCmdDefaultNoWait
    44  // GIVEN a CLI install command with all defaults and --wait==false
    45  //
    46  //	WHEN I call cmd.Execute for install
    47  //	THEN the CLI install command is successful
    48  func TestInstallCmdDefaultNoWait(t *testing.T) {
    49  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
    50  	cmd, rc := createNewTestCommandAndContext(t, c)
    51  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
    52  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
    53  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
    54  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
    55  	defer cmdHelpers.SetDefaultDeleteFunc()
    56  
    57  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
    58  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
    59  
    60  	SetValidateCRFunc(FakeValidateCRFunc)
    61  	defer SetDefaultValidateCRFunc()
    62  
    63  	// Run install command
    64  	err := cmd.Execute()
    65  	assert.NoError(t, err)
    66  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
    67  	assert.NoError(t, err)
    68  	assert.Equal(t, "", string(errBytes))
    69  
    70  	// Verify the vz resource is as expected
    71  	vz := v1alpha1.Verrazzano{}
    72  	err = c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "verrazzano"}, &vz)
    73  	assert.NoError(t, err)
    74  
    75  	expectedLastAppliedConfigAnnotation := "{\"apiVersion\":\"install.verrazzano.io/v1alpha1\",\"kind\":\"Verrazzano\",\"metadata\":{\"annotations\":{},\"name\":\"verrazzano\",\"namespace\":\"default\"}}\n"
    76  	testhelpers.VerifyLastAppliedConfigAnnotation(t, vz.ObjectMeta, expectedLastAppliedConfigAnnotation)
    77  }
    78  
    79  // TestInstallCmdDefaultTimeoutBugReport
    80  // GIVEN a CLI install command with all defaults and --timeout=2ms
    81  //
    82  //	WHEN I call cmd.Execute for install
    83  //	THEN the CLI install command times out and a bug report is generated
    84  func TestInstallCmdDefaultTimeoutBugReport(t *testing.T) {
    85  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
    86  	cmd, rc := createNewTestCommandAndContext(t, c)
    87  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
    88  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
    89  	cmd.PersistentFlags().Set(constants.FilenameFlag, testFilenamePath)
    90  	tempKubeConfigPath, _ := os.CreateTemp(os.TempDir(), testKubeConfig)
    91  	cmd.Flags().String(constants.GlobalFlagKubeConfig, tempKubeConfigPath.Name(), "")
    92  	cmd.Flags().String(constants.GlobalFlagContext, testK8sContext, "")
    93  	cmd.PersistentFlags().Set(constants.TimeoutFlag, "2ms")
    94  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
    95  	defer cmdHelpers.SetDefaultDeleteFunc()
    96  	defer os.RemoveAll(tempKubeConfigPath.Name())
    97  
    98  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
    99  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   100  
   101  	SetValidateCRFunc(FakeValidateCRFunc)
   102  	defer SetDefaultValidateCRFunc()
   103  
   104  	// Run install command
   105  	err := cmd.Execute()
   106  	assert.Error(t, err)
   107  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   108  	assert.NoError(t, err)
   109  	outBuf, err := os.ReadFile(rc.Out.Name())
   110  	assert.NoError(t, err)
   111  	assert.Equal(t, "Error: Timeout 2ms exceeded waiting for install to complete\n", string(errBytes))
   112  	assert.Contains(t, string(outBuf), "Installing Verrazzano version v1.3.1")
   113  	if !helpers.CheckAndRemoveBugReportAndRedactionFileExistsInDir("") {
   114  		t.Fatal(BugReportNotExist)
   115  	}
   116  }
   117  
   118  // TestInstallCmdDefaultTimeoutNoBugReport
   119  // GIVEN a CLI install command with --timeout=2ms and auto-bug-report=false
   120  //
   121  //	WHEN I call cmd.Execute for install
   122  //	THEN the CLI install command times out and a bug report is not generated
   123  func TestInstallCmdDefaultTimeoutNoBugReport(t *testing.T) {
   124  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   125  	cmd, rc := createNewTestCommandAndContext(t, c)
   126  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   127  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
   128  	cmd.PersistentFlags().Set(constants.TimeoutFlag, "2ms")
   129  	cmd.PersistentFlags().Set(constants.FilenameFlag, testFilenamePath)
   130  	tempKubeConfigPath, _ := os.CreateTemp(os.TempDir(), testKubeConfig)
   131  	cmd.Flags().String(constants.GlobalFlagKubeConfig, tempKubeConfigPath.Name(), "")
   132  	cmd.Flags().String(constants.GlobalFlagContext, testK8sContext, "")
   133  	cmd.PersistentFlags().Set(constants.AutoBugReportFlag, "false")
   134  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   135  	defer os.RemoveAll(tempKubeConfigPath.Name())
   136  	defer cmdHelpers.SetDefaultDeleteFunc()
   137  
   138  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   139  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   140  
   141  	SetValidateCRFunc(FakeValidateCRFunc)
   142  	defer SetDefaultValidateCRFunc()
   143  
   144  	// Run install command
   145  	err := cmd.Execute()
   146  	assert.Error(t, err)
   147  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   148  	assert.NoError(t, err)
   149  	outBuf, err := os.ReadFile(rc.Out.Name())
   150  	assert.NoError(t, err)
   151  	assert.Equal(t, "Error: Timeout 2ms exceeded waiting for install to complete\n", string(errBytes))
   152  	assert.Contains(t, string(outBuf), "Installing Verrazzano version v1.3.1")
   153  	// Bug report must not exist
   154  	if helpers.CheckAndRemoveBugReportAndRedactionFileExistsInDir("") {
   155  		t.Fatal("found bug report file in current directory")
   156  	}
   157  }
   158  
   159  // TestInstallCmdDefaultNoVPO
   160  // GIVEN a CLI install command with all defaults and no VPO found
   161  //
   162  //	WHEN I call cmd.Execute for install
   163  //	THEN the CLI install command fails and a bug report should be generated
   164  func TestInstallCmdDefaultNoVPO(t *testing.T) {
   165  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).Build()
   166  	cmd, rc := createNewTestCommandAndContext(t, c)
   167  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   168  
   169  	// Run install command
   170  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   171  	defer cmdHelpers.SetDefaultDeleteFunc()
   172  	cmd.PersistentFlags().Set(constants.VPOTimeoutFlag, "1s")
   173  	tempKubeConfigPath, _ := os.CreateTemp(os.TempDir(), testKubeConfig)
   174  	cmd.Flags().String(constants.GlobalFlagKubeConfig, tempKubeConfigPath.Name(), "")
   175  	cmd.Flags().String(constants.GlobalFlagContext, testK8sContext, "")
   176  	err := cmd.Execute()
   177  	assert.Error(t, err)
   178  	assert.ErrorContains(t, err, "Waiting for verrazzano-platform-operator pod in namespace verrazzano-install")
   179  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   180  	assert.NoError(t, err)
   181  	assert.Contains(t, string(errBytes), "Error: Waiting for verrazzano-platform-operator pod in namespace verrazzano-install")
   182  	if !helpers.CheckAndRemoveBugReportAndRedactionFileExistsInDir("") {
   183  		t.Fatal(BugReportNotExist)
   184  	}
   185  }
   186  
   187  // TestInstallCmdDefaultMultipleVPO
   188  // GIVEN a CLI install command with all defaults and multiple VPOs found
   189  //
   190  //	WHEN I call cmd.Execute for install
   191  //	THEN the CLI install command fails and a bug report should be generated
   192  func TestInstallCmdDefaultMultipleVPO(t *testing.T) {
   193  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(append(testhelpers.CreateTestVPOObjects(), testhelpers.CreateVPOPod(constants.VerrazzanoPlatformOperator+"-2"))...).Build()
   194  	cmd, rc := createNewTestCommandAndContext(t, c)
   195  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   196  
   197  	// Run install command
   198  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   199  	defer cmdHelpers.SetDefaultDeleteFunc()
   200  
   201  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   202  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   203  
   204  	//cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
   205  	cmd.PersistentFlags().Set(constants.VPOTimeoutFlag, "1s")
   206  	tempKubeConfigPath, _ := os.CreateTemp(os.TempDir(), testKubeConfig)
   207  	cmd.Flags().String(constants.GlobalFlagKubeConfig, tempKubeConfigPath.Name(), "")
   208  	cmd.Flags().String(constants.GlobalFlagContext, testK8sContext, "")
   209  	cmd.PersistentFlags().Set(constants.SkipConfirmationFlag, "true")
   210  	err := cmd.Execute()
   211  	assert.Error(t, err)
   212  	assert.ErrorContains(t, err, "Waiting for verrazzano-platform-operator, more than one verrazzano-platform-operator pod was found in namespace verrazzano-install")
   213  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   214  	assert.NoError(t, err)
   215  	assert.Contains(t, string(errBytes), "Error: Waiting for verrazzano-platform-operator, more than one verrazzano-platform-operator pod was found in namespace verrazzano-install")
   216  	if !helpers.CheckAndRemoveBugReportAndRedactionFileExistsInDir("") {
   217  		t.Fatal(BugReportNotExist)
   218  	}
   219  }
   220  
   221  // TestInstallCmdJsonLogFormat
   222  // GIVEN a CLI install command with defaults and --log-format=json and --wait==false
   223  //
   224  //	WHEN I call cmd.Execute for install
   225  //	THEN the CLI install command is successful
   226  func TestInstallCmdJsonLogFormat(t *testing.T) {
   227  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   228  	cmd, rc := createNewTestCommandAndContext(t, c)
   229  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   230  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
   231  	cmd.PersistentFlags().Set(constants.LogFormatFlag, "json")
   232  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   233  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   234  	defer cmdHelpers.SetDefaultDeleteFunc()
   235  
   236  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   237  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   238  
   239  	SetValidateCRFunc(FakeValidateCRFunc)
   240  	defer SetDefaultValidateCRFunc()
   241  
   242  	// Run install command
   243  	err := cmd.Execute()
   244  	assert.NoError(t, err)
   245  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   246  	assert.NoError(t, err)
   247  	assert.Equal(t, "", string(errBytes))
   248  
   249  	// Verify the vz resource is as expected
   250  	vz := v1alpha1.Verrazzano{}
   251  	err = c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "verrazzano"}, &vz)
   252  	assert.NoError(t, err)
   253  }
   254  
   255  // TestInstallCmdMultipleGroupVersions
   256  // GIVEN a CLI install command with defaults and --wait=false and --filename specified and multiple group versions in the filenames
   257  //
   258  //	WHEN I call cmd.Execute for install
   259  //	THEN the CLI install command is unsuccessful but a bug report should not be generated
   260  func TestInstallCmdMultipleGroupVersions(t *testing.T) {
   261  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   262  	cmd, rc := createNewTestCommandAndContext(t, c)
   263  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   264  	cmd.PersistentFlags().Set(constants.FilenameFlag, "../../test/testdata/dev-profile.yaml")
   265  	cmd.PersistentFlags().Set(constants.FilenameFlag, testFilenamePath)
   266  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   267  	tempKubeConfigPath, _ := os.CreateTemp(os.TempDir(), testKubeConfig)
   268  	cmd.Flags().String(constants.GlobalFlagKubeConfig, tempKubeConfigPath.Name(), "")
   269  	cmd.Flags().String(constants.GlobalFlagContext, testK8sContext, "")
   270  
   271  	// Run install command
   272  	err := cmd.Execute()
   273  	assert.Error(t, err)
   274  	assert.Contains(t, err.Error(), "cannot merge objects with different group versions")
   275  	if helpers.CheckAndRemoveBugReportAndRedactionFileExistsInDir("") {
   276  		t.Fatal(BugReportNotExist)
   277  	}
   278  }
   279  
   280  func TestInstallCmdFilenamesV1Beta1(t *testing.T) {
   281  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   282  	cmd, rc := createNewTestCommandAndContext(t, c)
   283  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   284  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
   285  	cmd.PersistentFlags().Set(constants.FilenameFlag, testFilenamePath)
   286  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   287  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   288  	defer cmdHelpers.SetDefaultDeleteFunc()
   289  
   290  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   291  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   292  
   293  	SetValidateCRFunc(FakeValidateCRFunc)
   294  	defer SetDefaultValidateCRFunc()
   295  	// Run install command
   296  	err := cmd.Execute()
   297  	assert.NoError(t, err)
   298  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   299  	assert.NoError(t, err)
   300  	assert.Equal(t, "", string(errBytes))
   301  
   302  	// Verify the vz resource is as expected
   303  	vz := v1beta1.Verrazzano{}
   304  	err = c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "my-verrazzano"}, &vz)
   305  	assert.NoError(t, err)
   306  	assert.Equal(t, v1beta1.Dev, vz.Spec.Profile)
   307  	assert.NotNil(t, vz.Spec.Components.IngressNGINX)
   308  	assert.NotNil(t, vz.Spec.Components.Fluentd)
   309  	assert.Equal(t, vz.Spec.Components.Fluentd.OpenSearchURL, "https://opensearch.com:9200/")
   310  	assert.Equal(t, vz.Spec.Components.Fluentd.OpenSearchSecret, "foo")
   311  }
   312  
   313  // TestInstallCmdFilenames
   314  // GIVEN a CLI install command with defaults and --wait=false and --filename specified
   315  //
   316  //	WHEN I call cmd.Execute for install
   317  //	THEN the CLI install command is successful
   318  func TestInstallCmdFilenames(t *testing.T) {
   319  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   320  	cmd, rc := createNewTestCommandAndContext(t, c)
   321  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   322  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
   323  	cmd.PersistentFlags().Set(constants.FilenameFlag, "../../test/testdata/dev-profile.yaml")
   324  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   325  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   326  	defer cmdHelpers.SetDefaultDeleteFunc()
   327  
   328  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   329  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   330  	SetValidateCRFunc(FakeValidateCRFunc)
   331  	defer SetDefaultValidateCRFunc()
   332  
   333  	// Run install command
   334  	err := cmd.Execute()
   335  	assert.NoError(t, err)
   336  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   337  	assert.NoError(t, err)
   338  	assert.Equal(t, "", string(errBytes))
   339  
   340  	// Verify the vz resource is as expected
   341  	vz := v1alpha1.Verrazzano{}
   342  	err = c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "my-verrazzano"}, &vz)
   343  	assert.NoError(t, err)
   344  	assert.Equal(t, v1alpha1.Dev, vz.Spec.Profile)
   345  }
   346  
   347  // TestInstallCmdFilenamesCsv
   348  // GIVEN a CLI install command with defaults and --wait=false and --filename specified as a comma separated list
   349  //
   350  //	WHEN I call cmd.Execute for install
   351  //	THEN the CLI install command is successful
   352  func TestInstallCmdFilenamesCsv(t *testing.T) {
   353  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   354  	cmd, rc := createNewTestCommandAndContext(t, c)
   355  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   356  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
   357  	cmd.PersistentFlags().Set(constants.FilenameFlag, "../../test/testdata/dev-profile.yaml,../../test/testdata/override-components.yaml")
   358  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   359  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   360  	defer cmdHelpers.SetDefaultDeleteFunc()
   361  
   362  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   363  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   364  
   365  	SetValidateCRFunc(FakeValidateCRFunc)
   366  	defer SetDefaultValidateCRFunc()
   367  
   368  	// Run install command
   369  	err := cmd.Execute()
   370  	assert.NoError(t, err)
   371  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   372  	assert.NoError(t, err)
   373  	assert.Equal(t, "", string(errBytes))
   374  
   375  	// Verify the vz resource is as expected
   376  	vz := v1alpha1.Verrazzano{}
   377  	err = c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "my-verrazzano"}, &vz)
   378  	assert.NoError(t, err)
   379  	assert.Equal(t, v1alpha1.Dev, vz.Spec.Profile)
   380  	assert.False(t, *vz.Spec.Components.Rancher.Enabled)
   381  }
   382  
   383  // TestInstallCmdSets
   384  // GIVEN a CLI install command with defaults and --wait=false and --set specified
   385  //
   386  //	WHEN I call cmd.Execute for install
   387  //	THEN the CLI install command is successful
   388  func TestInstallCmdSets(t *testing.T) {
   389  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   390  	cmd, rc := createNewTestCommandAndContext(t, c)
   391  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   392  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
   393  	cmd.PersistentFlags().Set(constants.SetFlag, "profile=dev")
   394  	cmd.PersistentFlags().Set(constants.SetFlag, "environmentName=test")
   395  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   396  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   397  	defer cmdHelpers.SetDefaultDeleteFunc()
   398  
   399  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   400  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   401  
   402  	SetValidateCRFunc(FakeValidateCRFunc)
   403  	defer SetDefaultValidateCRFunc()
   404  
   405  	// Run install command
   406  	err := cmd.Execute()
   407  	assert.NoError(t, err)
   408  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   409  	assert.NoError(t, err)
   410  	assert.Equal(t, "", string(errBytes))
   411  
   412  	// Verify the vz resource is as expected
   413  	vz := v1alpha1.Verrazzano{}
   414  	err = c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "verrazzano"}, &vz)
   415  	assert.NoError(t, err)
   416  	assert.Equal(t, v1alpha1.Dev, vz.Spec.Profile)
   417  	assert.Equal(t, "test", vz.Spec.EnvironmentName)
   418  }
   419  
   420  // TestInstallCmdFilenamesAndSets
   421  // GIVEN a CLI install command with defaults and --wait=false and --filename and --set specified
   422  //
   423  //	WHEN I call cmd.Execute for install
   424  //	THEN the CLI install command is successful
   425  func TestInstallCmdFilenamesAndSets(t *testing.T) {
   426  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   427  	cmd, rc := createNewTestCommandAndContext(t, c)
   428  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   429  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
   430  	cmd.PersistentFlags().Set(constants.FilenameFlag, "../../test/testdata/dev-profile.yaml")
   431  	cmd.PersistentFlags().Set(constants.SetFlag, "profile=prod")
   432  	cmd.PersistentFlags().Set(constants.SetFlag, "environmentName=test")
   433  	cmd.PersistentFlags().Set(constants.SetFlag, "components.ingress.overrides[0].values.controller.podLabels.override=\"true\"")
   434  	cmd.PersistentFlags().Set(constants.SetFlag, "components.ingress.overrides[1].values.controller.service.annotations.\"service\\.beta\\.kubernetes\\.io/oci-load-balancer-shape\"=flexible")
   435  	cmd.PersistentFlags().Set(constants.SetFlag, "components.ingress.enabled=true")
   436  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   437  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   438  	defer cmdHelpers.SetDefaultDeleteFunc()
   439  
   440  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   441  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   442  
   443  	SetValidateCRFunc(FakeValidateCRFunc)
   444  	defer SetDefaultValidateCRFunc()
   445  
   446  	// Run install command
   447  	err := cmd.Execute()
   448  	assert.NoError(t, err)
   449  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   450  	assert.NoError(t, err)
   451  	assert.Equal(t, "", string(errBytes))
   452  
   453  	// Verify the vz resource is as expected
   454  	vz := v1alpha1.Verrazzano{}
   455  	err = c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "my-verrazzano"}, &vz)
   456  	assert.NoError(t, err)
   457  	assert.Equal(t, v1alpha1.Prod, vz.Spec.Profile)
   458  	assert.Equal(t, "test", vz.Spec.EnvironmentName)
   459  	assert.Equal(t, true, *vz.Spec.Components.Ingress.Enabled)
   460  	json, err := vz.Spec.Components.Ingress.InstallOverrides.ValueOverrides[0].Values.MarshalJSON()
   461  	assert.NoError(t, err)
   462  	outyaml, err := yaml.JSONToYAML(json)
   463  	assert.NoError(t, err)
   464  	assert.Equal(t, "controller:\n  podLabels:\n    override: \"true\"\n", string(outyaml))
   465  	json, err = vz.Spec.Components.Ingress.InstallOverrides.ValueOverrides[1].Values.MarshalJSON()
   466  	assert.NoError(t, err)
   467  	outyaml, err = yaml.JSONToYAML(json)
   468  	assert.NoError(t, err)
   469  	assert.Equal(t, "controller:\n  service:\n    annotations:\n      service.beta.kubernetes.io/oci-load-balancer-shape: flexible\n", string(outyaml))
   470  }
   471  
   472  // TestInstallCmdOperatorFile
   473  // GIVEN a CLI install command with defaults and --wait=false and --manifests OR the deprecated --operator-file is specified
   474  //
   475  //	WHEN I call cmd.Execute for install
   476  //	THEN the CLI install command is successful
   477  func TestInstallCmdManifestsFile(t *testing.T) {
   478  	tests := []struct {
   479  		testName          string
   480  		manifestsFlagName string
   481  	}{
   482  		{"Use manifests flag", constants.ManifestsFlag},
   483  		{"Use deprecated operator-file flag", constants.OperatorFileFlag},
   484  	}
   485  	for _, tt := range tests {
   486  		t.Run(tt.testName, func(t *testing.T) {
   487  			c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   488  			cmd, rc := createNewTestCommandAndContext(t, c)
   489  			defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   490  			cmd.PersistentFlags().Set(tt.manifestsFlagName, "../../test/testdata/operator-file-fake.yaml")
   491  			cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   492  			cmd.PersistentFlags().Set(constants.SkipConfirmationFlag, "true")
   493  			cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   494  			defer cmdHelpers.SetDefaultDeleteFunc()
   495  			cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   496  			defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   497  			SetValidateCRFunc(FakeValidateCRFunc)
   498  			defer SetDefaultValidateCRFunc()
   499  
   500  			// Run install command
   501  			err := cmd.Execute()
   502  			assert.NoError(t, err)
   503  			errBytes, err := os.ReadFile(rc.ErrOut.Name())
   504  			assert.NoError(t, err)
   505  			outBuf, err := os.ReadFile(rc.Out.Name())
   506  			assert.NoError(t, err)
   507  			assert.Equal(t, "", string(errBytes))
   508  			assert.Contains(t, string(outBuf), "Applying the file ../../test/testdata/operator-file-fake.yaml")
   509  			assert.Contains(t, string(outBuf), "namespace/verrazzano-install created")
   510  			assert.Contains(t, string(outBuf), "serviceaccount/verrazzano-platform-operator created")
   511  			assert.Contains(t, string(outBuf), "service/verrazzano-platform-operator created\n")
   512  
   513  			// Verify the objects in the operator-file got added
   514  			sa := corev1.ServiceAccount{}
   515  			err = c.Get(context.TODO(), types.NamespacedName{Namespace: vzconstants.VerrazzanoInstallNamespace, Name: constants.VerrazzanoPlatformOperator}, &sa)
   516  			assert.NoError(t, err)
   517  
   518  			ns := corev1.Namespace{}
   519  			err = c.Get(context.TODO(), types.NamespacedName{Name: vzconstants.VerrazzanoInstallNamespace}, &ns)
   520  			assert.NoError(t, err)
   521  
   522  			svc := corev1.Service{}
   523  			err = c.Get(context.TODO(), types.NamespacedName{Namespace: vzconstants.VerrazzanoInstallNamespace, Name: constants.VerrazzanoPlatformOperator}, &svc)
   524  			assert.NoError(t, err)
   525  
   526  			// Verify the vz resource is as expected
   527  			vz := v1beta1.Verrazzano{}
   528  			err = c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "verrazzano"}, &vz)
   529  			assert.NoError(t, err)
   530  		})
   531  	}
   532  }
   533  
   534  // TestInstallValidations
   535  // GIVEN an install command
   536  //
   537  //	WHEN invalid command options exist
   538  //	THEN expect an error but a bug report should not be generated
   539  func TestInstallValidations(t *testing.T) {
   540  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   541  	cmd, rc := createNewTestCommandAndContext(t, c)
   542  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   543  	cmd.PersistentFlags().Set(constants.ManifestsFlag, "test")
   544  	cmd.PersistentFlags().Set(constants.VersionFlag, "test")
   545  	tempKubeConfigPath, _ := os.CreateTemp(os.TempDir(), testKubeConfig)
   546  	cmd.Flags().String(constants.GlobalFlagKubeConfig, tempKubeConfigPath.Name(), "")
   547  	cmd.Flags().String(constants.GlobalFlagContext, testK8sContext, "")
   548  	err := cmd.Execute()
   549  	assert.Error(t, err)
   550  	assert.Contains(t, err.Error(), fmt.Sprintf("--%s and --%s cannot both be specified", constants.VersionFlag, constants.ManifestsFlag))
   551  	if helpers.CheckAndRemoveBugReportAndRedactionFileExistsInDir("") {
   552  		t.Fatal(BugReportNotExist)
   553  	}
   554  
   555  	// test validation for deprecated operator-file flag and version being set
   556  	cmd, rc = createNewTestCommandAndContext(t, c)
   557  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   558  	cmd.PersistentFlags().Set(constants.OperatorFileFlag, "test")
   559  	cmd.PersistentFlags().Set(constants.VersionFlag, "test")
   560  	err = cmd.Execute()
   561  	assert.Error(t, err)
   562  	assert.Contains(t, err.Error(), fmt.Sprintf("--%s and --%s cannot both be specified", constants.VersionFlag, constants.ManifestsFlag))
   563  }
   564  
   565  // TestGetWaitTimeoutDefault
   566  // GIVEN no wait and timeout arguments specified
   567  //
   568  //	WHEN I call GetWaitTimeout
   569  //	THEN the default timeout duration is returned
   570  func TestGetWaitTimeoutDefault(t *testing.T) {
   571  	cmd, rc := createNewTestCommandAndContext(t, nil)
   572  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   573  	duration, err := cmdHelpers.GetWaitTimeout(cmd, constants.TimeoutFlag)
   574  	assert.NoError(t, err)
   575  	assert.Equal(t, "30m0s", duration.String())
   576  }
   577  
   578  // TestGetWaitTimeoutNoWait
   579  // GIVEN wait is specified as false
   580  //
   581  //	WHEN I call GetWaitTimeout
   582  //	THEN the duration returned is zero
   583  func TestGetWaitTimeoutNoWait(t *testing.T) {
   584  	cmd, rc := createNewTestCommandAndContext(t, nil)
   585  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   586  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   587  	duration, err := cmdHelpers.GetWaitTimeout(cmd, constants.TimeoutFlag)
   588  	assert.NoError(t, err)
   589  	assert.Equal(t, "0s", duration.String())
   590  }
   591  
   592  // TestGetWaitTimeoutSpecified
   593  // GIVEN wait the timeout is specified as 10m
   594  //
   595  //	WHEN I call GetWaitTimeout
   596  //	THEN the duration returned is 10m0s
   597  func TestGetWaitTimeoutSpecified(t *testing.T) {
   598  	cmd, rc := createNewTestCommandAndContext(t, nil)
   599  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   600  	cmd.PersistentFlags().Set(constants.TimeoutFlag, "10m")
   601  	duration, err := cmdHelpers.GetWaitTimeout(cmd, constants.TimeoutFlag)
   602  	assert.NoError(t, err)
   603  	assert.Equal(t, "10m0s", duration.String())
   604  }
   605  
   606  // TestGetLogFormatSimple
   607  // GIVEN simple log format argument specified
   608  //
   609  //	WHEN I call GetLogFormat
   610  //	THEN the simple log format is returned
   611  func TestGetLogFormatSimple(t *testing.T) {
   612  	cmd, rc := createNewTestCommandAndContext(t, nil)
   613  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   614  	cmd.PersistentFlags().Set(constants.LogFormatFlag, "simple")
   615  	logFormat, err := cmdHelpers.GetLogFormat(cmd)
   616  	assert.NoError(t, err)
   617  	assert.Equal(t, "simple", logFormat.String())
   618  }
   619  
   620  // TestGetLogFormatJson
   621  // GIVEN json log format is specified
   622  //
   623  //	WHEN I call GetLogFormat
   624  //	THEN json log format is returned
   625  func TestGetLogFormatJson(t *testing.T) {
   626  	cmd, rc := createNewTestCommandAndContext(t, nil)
   627  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   628  	cmd.PersistentFlags().Set(constants.LogFormatFlag, "json")
   629  	logFormat, err := cmdHelpers.GetLogFormat(cmd)
   630  	assert.NoError(t, err)
   631  	assert.Equal(t, "json", logFormat.String())
   632  }
   633  
   634  // TestSetCommandInvalidFormat
   635  // GIVEN a set command is specified with the invalid format
   636  //
   637  //	WHEN I call getSetArguments
   638  //	THEN an error is returned
   639  func TestSetCommandInvalidFormat(t *testing.T) {
   640  	cmd, rc := createNewTestCommandAndContext(t, nil)
   641  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   642  	cmd.PersistentFlags().Set(constants.SetFlag, "badflag")
   643  	propValues, err := cmdHelpers.GetSetArguments(cmd, rc)
   644  	assert.Nil(t, propValues)
   645  	assert.Error(t, err)
   646  	assert.Equal(t, err.Error(), "Invalid set flag(s) specified")
   647  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   648  	assert.NoError(t, err)
   649  	assert.Equal(t, "Invalid set flag \"badflag\" specified. Flag must be specified in the format path=value\n", string(errBytes))
   650  }
   651  
   652  // TestSetCommandSingle
   653  // GIVEN a single set command
   654  //
   655  //	WHEN I call getSetArguments
   656  //	THEN the expected property value is returned
   657  func TestSetCommandSingle(t *testing.T) {
   658  	cmd, rc := createNewTestCommandAndContext(t, nil)
   659  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   660  	cmd.PersistentFlags().Set(constants.SetFlag, "profile=dev")
   661  	propValues, err := cmdHelpers.GetSetArguments(cmd, rc)
   662  	assert.NoError(t, err)
   663  	assert.Len(t, propValues, 1)
   664  	assert.Contains(t, propValues["spec.profile"], "dev")
   665  }
   666  
   667  // TestSetCommandMultiple
   668  // GIVEN multiple set commands
   669  //
   670  //	WHEN I call getSetArguments
   671  //	THEN the expected property values are returned
   672  func TestSetCommandMultiple(t *testing.T) {
   673  	cmd, rc := createNewTestCommandAndContext(t, nil)
   674  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   675  	cmd.PersistentFlags().Set(constants.SetFlag, "profile=dev")
   676  	cmd.PersistentFlags().Set(constants.SetFlag, "spec.environmentName=default")
   677  	propValues, err := cmdHelpers.GetSetArguments(cmd, rc)
   678  	assert.NoError(t, err)
   679  	assert.Len(t, propValues, 2)
   680  	assert.Contains(t, propValues["spec.profile"], "dev")
   681  	assert.Contains(t, propValues["spec.environmentName"], "default")
   682  }
   683  
   684  // TestSetCommandOverride
   685  // GIVEN multiple set commands overriding the same property
   686  //
   687  //	WHEN I call getSetArguments
   688  //	THEN the expected property values are returned
   689  func TestSetCommandOverride(t *testing.T) {
   690  	cmd, rc := createNewTestCommandAndContext(t, nil)
   691  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   692  	cmd.PersistentFlags().Set(constants.SetFlag, "profile=dev")
   693  	cmd.PersistentFlags().Set(constants.SetFlag, "profile=prod")
   694  	propValues, err := cmdHelpers.GetSetArguments(cmd, rc)
   695  	assert.NoError(t, err)
   696  	assert.Len(t, propValues, 1)
   697  	assert.Contains(t, propValues["spec.profile"], "prod")
   698  }
   699  
   700  // TestInstallCmdInProgress
   701  // GIVEN a CLI install command when an install was in progress
   702  //
   703  //	WHEN I call cmd.Execute for install
   704  //	THEN the CLI install command is successful
   705  func TestInstallCmdInProgress(t *testing.T) {
   706  	vz := &v1beta1.Verrazzano{
   707  		TypeMeta: metav1.TypeMeta{},
   708  		ObjectMeta: metav1.ObjectMeta{
   709  			Namespace: "default",
   710  			Name:      "verrazzano",
   711  		},
   712  		Status: v1beta1.VerrazzanoStatus{
   713  			State:   v1beta1.VzStateReconciling,
   714  			Version: "v1.3.1",
   715  		},
   716  	}
   717  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(append(testhelpers.CreateTestVPOObjects(), vz)...).Build()
   718  	cmd, rc := createNewTestCommandAndContext(t, c)
   719  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   720  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   721  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   722  	defer cmdHelpers.SetDefaultDeleteFunc()
   723  
   724  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   725  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   726  	defer ensureResourcesDeleted(t, c)
   727  
   728  	// Run install command
   729  	err := cmd.Execute()
   730  	assert.NoError(t, err)
   731  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   732  	assert.NoError(t, err)
   733  	assert.Equal(t, "", string(errBytes))
   734  }
   735  
   736  // TestInstallCmdAlreadyInstalled
   737  // GIVEN a CLI install command when an install already happened
   738  //
   739  //	WHEN I call cmd.Execute for install
   740  //	THEN the CLI install command is unsuccessful but a bug report is not generated
   741  func TestInstallCmdAlreadyInstalled(t *testing.T) {
   742  	vz := &v1beta1.Verrazzano{
   743  		TypeMeta: metav1.TypeMeta{},
   744  		ObjectMeta: metav1.ObjectMeta{
   745  			Namespace: "default",
   746  			Name:      "verrazzano",
   747  		},
   748  		Status: v1beta1.VerrazzanoStatus{
   749  			State:   v1beta1.VzStateReady,
   750  			Version: "v1.3.1",
   751  		},
   752  	}
   753  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(append(testhelpers.CreateTestVPOObjects(), vz)...).Build()
   754  	cmd, rc := createNewTestCommandAndContext(t, c)
   755  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   756  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   757  	tempKubeConfigPath, _ := os.CreateTemp(os.TempDir(), testKubeConfig)
   758  	cmd.Flags().String(constants.GlobalFlagKubeConfig, tempKubeConfigPath.Name(), "")
   759  	cmd.Flags().String(constants.GlobalFlagContext, testK8sContext, "")
   760  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   761  	defer cmdHelpers.SetDefaultDeleteFunc()
   762  
   763  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   764  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   765  
   766  	// Run install command
   767  	err := cmd.Execute()
   768  	assert.Error(t, err)
   769  	assert.Contains(t, err.Error(), "Only one install of Verrazzano is allowed")
   770  	if helpers.CheckAndRemoveBugReportAndRedactionFileExistsInDir("") {
   771  		t.Fatal(BugReportNotExist)
   772  	}
   773  }
   774  
   775  // TestInstallCmdDifferentVersion
   776  // GIVEN a CLI install command when an install is in progress for a different version
   777  //
   778  //	WHEN I call cmd.Execute for install
   779  //	THEN the CLI install command is unsuccessful but a bug report is not generated
   780  func TestInstallCmdDifferentVersion(t *testing.T) {
   781  	vz := &v1beta1.Verrazzano{
   782  		TypeMeta: metav1.TypeMeta{},
   783  		ObjectMeta: metav1.ObjectMeta{
   784  			Namespace: "default",
   785  			Name:      "verrazzano",
   786  		},
   787  		Status: v1beta1.VerrazzanoStatus{
   788  			State:   v1beta1.VzStateReconciling,
   789  			Version: "v1.3.2",
   790  		},
   791  	}
   792  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(append(testhelpers.CreateTestVPOObjects(), vz)...).Build()
   793  	cmd, rc := createNewTestCommandAndContext(t, c)
   794  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   795  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   796  	tempKubeConfigPath, _ := os.CreateTemp(os.TempDir(), testKubeConfig)
   797  	cmd.Flags().String(constants.GlobalFlagKubeConfig, tempKubeConfigPath.Name(), "")
   798  	cmd.Flags().String(constants.GlobalFlagContext, testK8sContext, "")
   799  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   800  	defer cmdHelpers.SetDefaultDeleteFunc()
   801  
   802  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   803  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   804  
   805  	// Run install command
   806  	err := cmd.Execute()
   807  	assert.Error(t, err)
   808  	assert.Contains(t, err.Error(), "Unable to install version v1.3.1, install of version v1.3.2 is in progress")
   809  	if helpers.CheckAndRemoveBugReportAndRedactionFileExistsInDir("") {
   810  		t.Fatal(BugReportNotExist)
   811  	}
   812  }
   813  
   814  func createNewTestCommandAndContext(t *testing.T, c client.Client) (*cobra.Command, *testhelpers.FakeRootCmdContextWithFiles) {
   815  	rc := testhelpers.NewFakeRootCmdContextWithFiles(t)
   816  	if c != nil {
   817  		rc.SetClient(c)
   818  	}
   819  	rc.SetDynamicClient(dynfake.NewSimpleDynamicClient(helpers.GetScheme()))
   820  
   821  	cmd := NewCmdInstall(rc)
   822  	assert.NotNil(t, cmd)
   823  	return cmd, rc
   824  }
   825  
   826  // installVZ installs Verrazzano using the given client
   827  func installVZ(t *testing.T, c client.WithWatch) {
   828  	stdoutFile, stderrFile := createStdTempFiles(t)
   829  	defer func() {
   830  		os.Remove(stdoutFile.Name())
   831  		os.Remove(stderrFile.Name())
   832  	}()
   833  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   834  	rc.SetClient(c)
   835  	cmd := NewCmdInstall(rc)
   836  	assert.NotNil(t, cmd)
   837  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   838  	cmd.PersistentFlags().Set(constants.VersionFlag, "v1.4.0")
   839  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   840  	defer cmdHelpers.SetDefaultDeleteFunc()
   841  
   842  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   843  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   844  
   845  	// Run install command
   846  	err := cmd.Execute()
   847  	assert.NoError(t, err)
   848  	buf, err := os.ReadFile(stderrFile.Name())
   849  	assert.NoError(t, err)
   850  	assert.Equal(t, "", string(buf))
   851  }
   852  
   853  // createStdTempFiles creates temporary files for stdout and stderr.
   854  func createStdTempFiles(t *testing.T) (*os.File, *os.File) {
   855  	stdoutFile, err := os.CreateTemp("", "tmpstdout")
   856  	assert.NoError(t, err)
   857  
   858  	stderrFile, err := os.CreateTemp("", "tmpstderr")
   859  	assert.NoError(t, err)
   860  
   861  	return stdoutFile, stderrFile
   862  }
   863  
   864  // TestAnalyzeCommandDefault
   865  // GIVEN a CLI analyze command
   866  // WHEN I call cmd.Execute without specifying flag capture-dir
   867  // THEN expect the command to analyze the live cluster
   868  func TestAnalyzeCommandDefault(t *testing.T) {
   869  	c := getClientWithWatch()
   870  	SetValidateCRFunc(FakeValidateCRFunc)
   871  	defer SetDefaultValidateCRFunc()
   872  	installVZ(t, c)
   873  
   874  	// Verify the vz resource is as expected
   875  	vz := v1beta1.Verrazzano{}
   876  	err := c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "verrazzano"}, &vz)
   877  	assert.NoError(t, err)
   878  
   879  	stdoutFile, stderrFile := createStdTempFiles(t)
   880  	defer func() {
   881  		os.Remove(stdoutFile.Name())
   882  		os.Remove(stderrFile.Name())
   883  	}()
   884  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: stdoutFile, ErrOut: stderrFile})
   885  	rc.SetClient(c)
   886  	rc.SetDynamicClient(dynfake.NewSimpleDynamicClient(helpers.GetScheme()))
   887  
   888  	cmd := analyze.NewCmdAnalyze(rc)
   889  	cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
   890  	assert.NotNil(t, cmd)
   891  	err = cmd.Execute()
   892  	assert.Nil(t, err)
   893  	buf, err := os.ReadFile(stdoutFile.Name())
   894  	assert.NoError(t, err)
   895  	// This should generate a stdout from the live cluster
   896  	assert.Contains(t, string(buf), "Verrazzano analysis CLI did not detect any issue in")
   897  	// Clean analysis should not generate a report file
   898  	fileMatched, _ := filepath.Glob(constants.VzAnalysisReportTmpFile)
   899  	assert.Len(t, fileMatched, 0)
   900  }
   901  
   902  // getClientWithWatch returns a client for installing Verrazzano
   903  func getClientWithWatch() client.WithWatch {
   904  	vpo := &corev1.Pod{
   905  		ObjectMeta: metav1.ObjectMeta{
   906  			Namespace: vzconstants.VerrazzanoInstallNamespace,
   907  			Name:      constants.VerrazzanoPlatformOperator,
   908  			Labels: map[string]string{
   909  				"app":               constants.VerrazzanoPlatformOperator,
   910  				"pod-template-hash": "45f78ffddd",
   911  			},
   912  		},
   913  	}
   914  	deployment := &appsv1.Deployment{
   915  		ObjectMeta: metav1.ObjectMeta{
   916  			Namespace: vzconstants.VerrazzanoInstallNamespace,
   917  			Name:      constants.VerrazzanoPlatformOperator,
   918  		},
   919  		Spec: appsv1.DeploymentSpec{
   920  			Selector: &metav1.LabelSelector{
   921  				MatchLabels: map[string]string{"app": constants.VerrazzanoPlatformOperator},
   922  			},
   923  		},
   924  		Status: appsv1.DeploymentStatus{
   925  			AvailableReplicas: 1,
   926  			UpdatedReplicas:   1,
   927  		},
   928  	}
   929  	replicaset := &appsv1.ReplicaSet{
   930  		ObjectMeta: metav1.ObjectMeta{
   931  			Namespace: vzconstants.VerrazzanoInstallNamespace,
   932  			Name:      fmt.Sprintf("%s-45f78ffddd", constants.VerrazzanoPlatformOperator),
   933  			Annotations: map[string]string{
   934  				"deployment.kubernetes.io/revision": "1",
   935  			},
   936  		},
   937  	}
   938  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(vpo, deployment, replicaset).Build()
   939  	return c
   940  }
   941  
   942  // TestInstallFromPrivateRegistry tests installing from a private registry.
   943  //
   944  // GIVEN a CLI install command with private registry flags set
   945  //
   946  //	WHEN I call cmd.Execute for install
   947  //	THEN the CLI install command is successful and the VPO and VPO webhook deployments have the expected private registry configuration
   948  func TestInstallFromPrivateRegistry(t *testing.T) {
   949  	const imageRegistry = "testreg.io"
   950  	const imagePrefix = "testrepo"
   951  
   952  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
   953  	cmd, rc := createNewTestCommandAndContext(t, c)
   954  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
   955  	cmd.PersistentFlags().Set(constants.WaitFlag, "false")
   956  	cmd.PersistentFlags().Set(constants.ImageRegistryFlag, imageRegistry)
   957  	cmd.PersistentFlags().Set(constants.ImagePrefixFlag, imagePrefix)
   958  	cmd.PersistentFlags().Set(constants.SkipConfirmationFlag, "true")
   959  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
   960  	defer cmdHelpers.SetDefaultDeleteFunc()
   961  
   962  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
   963  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
   964  
   965  	SetValidateCRFunc(FakeValidateCRFunc)
   966  	defer SetDefaultValidateCRFunc()
   967  
   968  	// Run install command
   969  	err := cmd.Execute()
   970  	assert.NoError(t, err)
   971  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
   972  	assert.NoError(t, err)
   973  	assert.Equal(t, "", string(errBytes))
   974  
   975  	// Verify that the VPO deployment has the expected environment variables to enable pulling images from a private registry
   976  	deployment, err := cmdHelpers.GetExistingVPODeployment(c)
   977  	assert.NoError(t, err)
   978  	assert.NotNil(t, deployment)
   979  	testhelpers.AssertPrivateRegistryEnvVars(t, c, deployment, imageRegistry, imagePrefix)
   980  
   981  	// Verify that the VPO image has been updated
   982  	testhelpers.AssertPrivateRegistryImage(t, c, deployment, imageRegistry, imagePrefix)
   983  
   984  	// Verify that the VPO webhook image has been updated
   985  	deployment, err = cmdHelpers.GetExistingVPOWebhookDeployment(c)
   986  	assert.NoError(t, err)
   987  	assert.NotNil(t, deployment)
   988  
   989  	testhelpers.AssertPrivateRegistryImage(t, c, deployment, imageRegistry, imagePrefix)
   990  }
   991  
   992  // TestInstallFromFilename tests installing from a filename.
   993  //
   994  // GIVEN a filename after install command with filename flags set
   995  //
   996  //	WHEN I call cmd.Execute for install
   997  //	THEN the CLI install command fails and should catch the missing filename flag or the missing file
   998  func TestInstallFromFilename(t *testing.T) {
   999  	c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).Build()
  1000  	cmd, rc := createNewTestCommandAndContext(t, c)
  1001  	defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
  1002  
  1003  	cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
  1004  	defer cmdHelpers.SetDefaultDeleteFunc()
  1005  
  1006  	cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
  1007  	defer cmdHelpers.SetDefaultVPOIsReadyFunc()
  1008  
  1009  	SetValidateCRFunc(FakeValidateCRFunc)
  1010  	defer SetDefaultValidateCRFunc()
  1011  
  1012  	// Send stdout stderr to a byte bufferF
  1013  	rc.SetClient(c)
  1014  
  1015  	os.Args = append(os.Args, testFilenamePath)
  1016  	err := cmd.Execute()
  1017  	if err != nil {
  1018  		return
  1019  	}
  1020  	errBytes, err := os.ReadFile(rc.ErrOut.Name())
  1021  	assert.NoError(t, err)
  1022  	assert.Contains(t, string(errBytes), "Error: invalid arguments specified:")
  1023  	//Clean the resource args for further test cases.
  1024  	s := len(os.Args)
  1025  	os.Args = append(os.Args[:s-1])
  1026  }
  1027  
  1028  // TestInstallSkipOperatorInstall tests installing Verrazzano and skipping the install of the operator.
  1029  //
  1030  // GIVEN a CLI install command with skip-operator-install flags set
  1031  //
  1032  //	WHEN I call cmd.Execute for install
  1033  //	THEN the CLI install command is successful and the VPO and VPO webhook deployments do not get reinstalled
  1034  func TestInstallSkipOperatorInstall(t *testing.T) {
  1035  	tests := []struct {
  1036  		name         string
  1037  		skipInstall  bool
  1038  		vpoExists    bool
  1039  		cmdLineInput string
  1040  	}{
  1041  		{name: "VPO is already running, skip-platform-operator enabled", skipInstall: true, vpoExists: true},
  1042  		{name: "VPO is already running, skip-platform-operator disabled, reInstallVPO-y", skipInstall: false, vpoExists: true, cmdLineInput: "y"},
  1043  		{name: "VPO is already running, skip-platform-operator disabled, reInstallVPO-n", skipInstall: false, vpoExists: true, cmdLineInput: "n"},
  1044  		{name: "VPO is already running, reinstall", skipInstall: false, vpoExists: true, cmdLineInput: "y"},
  1045  		{name: "Clean install, no VPO is running", skipInstall: false, vpoExists: false},
  1046  	}
  1047  	for _, tt := range tests {
  1048  		t.Run(tt.name, func(t *testing.T) {
  1049  			c := fake.NewClientBuilder().WithScheme(helpers.NewScheme()).WithObjects(testhelpers.CreateTestVPOObjects()...).Build()
  1050  			cmd, rc := createNewTestCommandAndContext(t, c)
  1051  			defer testhelpers.CleanUpNewFakeRootCmdContextWithFiles(rc)
  1052  			cmd.PersistentFlags().Set(constants.WaitFlag, "false")
  1053  			if tt.skipInstall {
  1054  				cmd.PersistentFlags().Set(constants.SkipPlatformOperatorFlag, "true")
  1055  			}
  1056  
  1057  			if tt.cmdLineInput != "" {
  1058  				content := []byte(tt.cmdLineInput)
  1059  				tempfile, err := os.CreateTemp("", "test-input.txt")
  1060  				if err != nil {
  1061  					assert.Error(t, err)
  1062  				}
  1063  				// clean up tempfile
  1064  				defer os.Remove(tempfile.Name())
  1065  				if _, err := tempfile.Write(content); err != nil {
  1066  					assert.Error(t, err)
  1067  				}
  1068  				if _, err := tempfile.Seek(0, 0); err != nil {
  1069  					assert.Error(t, err)
  1070  				}
  1071  				oldStdin := os.Stdin
  1072  				// Restore original Stdin
  1073  				defer func() { os.Stdin = oldStdin }()
  1074  				os.Stdin = tempfile
  1075  			}
  1076  
  1077  			cmdHelpers.SetDeleteFunc(cmdHelpers.FakeDeleteFunc)
  1078  			defer cmdHelpers.SetDefaultDeleteFunc()
  1079  
  1080  			cmdHelpers.SetVPOIsReadyFunc(func(_ client.Client) (bool, error) { return true, nil })
  1081  			defer cmdHelpers.SetDefaultVPOIsReadyFunc()
  1082  
  1083  			SetValidateCRFunc(FakeValidateCRFunc)
  1084  			defer SetDefaultValidateCRFunc()
  1085  
  1086  			// Run install command
  1087  			err := cmd.Execute()
  1088  
  1089  			if tt.vpoExists {
  1090  				existingVPOPodList, _ := validators.GetPlatformOperatorPodList(c)
  1091  				assert.NotNil(t, existingVPOPodList)
  1092  				assert.Greater(t, len(existingVPOPodList.Items), 0)
  1093  			}
  1094  			assert.NoError(t, err)
  1095  			vz := v1alpha1.Verrazzano{}
  1096  			err = c.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "verrazzano"}, &vz)
  1097  			assert.NoError(t, err)
  1098  
  1099  			expectedLastAppliedConfigAnnotation := "{\"apiVersion\":\"install.verrazzano.io/v1alpha1\",\"kind\":\"Verrazzano\",\"metadata\":{\"annotations\":{},\"name\":\"verrazzano\",\"namespace\":\"default\"}}\n"
  1100  			testhelpers.VerifyLastAppliedConfigAnnotation(t, vz.ObjectMeta, expectedLastAppliedConfigAnnotation)
  1101  		})
  1102  	}
  1103  }