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 }