From 437df132f63baa61e4a2ad2a57ea63904f2c4057 Mon Sep 17 00:00:00 2001 From: Huy Mai Date: Mon, 13 Nov 2023 13:45:05 +0000 Subject: [PATCH] Add bmo upgrade test Signed-off-by: Huy Mai --- .github/workflows/e2e-fixture-test.yml | 2 +- .gitignore | 2 +- Makefile | 4 +- config/overlays/e2e-release-0.4/ironic.env | 10 + .../e2e-release-0.4/kustomization.yaml | 45 +++ .../fixture-release-0.4/kustomization.yaml | 24 ++ hack/ci-e2e.sh | 23 ++ test/e2e/README.md | 25 +- test/e2e/common.go | 17 + test/e2e/config/fixture.yaml | 20 +- test/e2e/config/ironic.yaml | 12 +- test/e2e/upgrade_test.go | 353 ++++++++++++++++++ 12 files changed, 521 insertions(+), 16 deletions(-) create mode 100644 config/overlays/e2e-release-0.4/ironic.env create mode 100644 config/overlays/e2e-release-0.4/kustomization.yaml create mode 100644 config/overlays/fixture-release-0.4/kustomization.yaml create mode 100644 test/e2e/upgrade_test.go diff --git a/.github/workflows/e2e-fixture-test.yml b/.github/workflows/e2e-fixture-test.yml index d4f5604b87..3ea520c827 100644 --- a/.github/workflows/e2e-fixture-test.yml +++ b/.github/workflows/e2e-fixture-test.yml @@ -30,6 +30,6 @@ jobs: - name: Set Up Environment and Run BMO e2e Tests env: - E2E_CONF_FILE: ${GITHUB_WORKSPACE}/test/e2e/config/fixture.yaml + E2E_CONF_FILE: ${{ github.workspace }}/test/e2e/config/fixture.yaml USE_EXISTING_CLUSTER: "false" run: make test-e2e diff --git a/.gitignore b/.gitignore index c09ed8156a..8781fc91e7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ bin build/_output build/_test _artifacts -artifacts.tar.gz +artifacts*.tar.gz test/e2e/images # Created by https://www.gitignore.io/api/go diff --git a/Makefile b/Makefile index 4c43db2d7f..82ef5a3a67 100644 --- a/Makefile +++ b/Makefile @@ -50,8 +50,8 @@ GINKGO_NODES ?= 1 GINKGO_TIMEOUT ?= 2h GINKGO_POLL_PROGRESS_AFTER ?= 60m GINKGO_POLL_PROGRESS_INTERVAL ?= 5m -E2E_CONF_FILE ?= $(ROOT_DIR)/test/e2e/config/ironic.yaml -USE_EXISTING_CLUSTER ?= true +E2E_CONF_FILE ?= $(ROOT_DIR)/test/e2e/config/fixture.yaml +USE_EXISTING_CLUSTER ?= false SKIP_RESOURCE_CLEANUP ?= false GINKGO_NOCOLOR ?= false diff --git a/config/overlays/e2e-release-0.4/ironic.env b/config/overlays/e2e-release-0.4/ironic.env new file mode 100644 index 0000000000..786453ee78 --- /dev/null +++ b/config/overlays/e2e-release-0.4/ironic.env @@ -0,0 +1,10 @@ +HTTP_PORT=6180 +PROVISIONING_IP=192.168.222.199 +DEPLOY_KERNEL_URL=http://192.168.222.199:6180/images/ironic-python-agent.kernel +DEPLOY_RAMDISK_URL=http://192.168.222.199:6180/images/ironic-python-agent.initramfs +IRONIC_ENDPOINT=https://192.168.222.199:6385/v1/ +IRONIC_INSPECTOR_ENDPOINT=https://192.168.222.199:5050/v1/ +CACHEURL=http://192.168.222.199/images +IRONIC_FAST_TRACK=true +IRONIC_KERNEL_PARAMS=console=ttyS0 +IRONIC_INSPECTOR_VLAN_INTERFACES=all diff --git a/config/overlays/e2e-release-0.4/kustomization.yaml b/config/overlays/e2e-release-0.4/kustomization.yaml new file mode 100644 index 0000000000..3223ef5992 --- /dev/null +++ b/config/overlays/e2e-release-0.4/kustomization.yaml @@ -0,0 +1,45 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: baremetal-operator-system +resources: + - https://github.com/metal3-io/baremetal-operator/config/tls?ref=release-0.4 + +components: + - ../../components/basic-auth + +configMapGenerator: +- name: ironic + behavior: merge + envs: + - ironic.env + +patches: +- patch: | + # Don't try to pull again the pre-loaded image + - op: replace + path: /spec/template/spec/containers/0/imagePullPolicy + value: IfNotPresent + target: + kind: Deployment + name: controller-manager + +images: +- name: quay.io/metal3-io/baremetal-operator + newTag: release-0.4 + +# We cannot use suffix hashes since the kustomizations we build on +# cannot be aware of what suffixes we add. +generatorOptions: + disableNameSuffixHash: true + +# NOTE: These credentials are generated automatically in hack/ci-e2e.sh +secretGenerator: + - name: ironic-credentials + files: + - username=ironic-username + - password=ironic-password + - name: ironic-inspector-credentials + files: + - username=ironic-inspector-username + - password=ironic-inspector-password + diff --git a/config/overlays/fixture-release-0.4/kustomization.yaml b/config/overlays/fixture-release-0.4/kustomization.yaml new file mode 100644 index 0000000000..559c0097e7 --- /dev/null +++ b/config/overlays/fixture-release-0.4/kustomization.yaml @@ -0,0 +1,24 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- https://github.com/metal3-io/baremetal-operator/config/namespace?ref=release-0.4 +- https://github.com/metal3-io/baremetal-operator/config/default?ref=release-0.4 + +patches: +- patch: | + # Enable test mode (fixture provider instead of ironic) + - op: add + path: /spec/template/spec/containers/0/args/- + value: --test-mode + # Don't try to pull again the pre-loaded image + - op: replace + path: /spec/template/spec/containers/0/imagePullPolicy + value: IfNotPresent + target: + kind: Deployment + name: controller-manager + +images: +- name: quay.io/metal3-io/baremetal-operator + newTag: release-0.4 diff --git a/hack/ci-e2e.sh b/hack/ci-e2e.sh index c7d67b888e..05ef655d7f 100755 --- a/hack/ci-e2e.sh +++ b/hack/ci-e2e.sh @@ -17,6 +17,21 @@ cd "${REPO_ROOT}" || exit 1 # BMO_E2E_EMULATOR can be set to either "vbmc" or "sushy-tools" BMO_E2E_EMULATOR=${BMO_E2E_EMULATOR:-"sushy-tools"} +case "${GINKGO_FOCUS:-}" in + *upgrade*) + echo "'upgrade' found in env var GINKGO_FOCUS. Will ONLY run upgrade tests." + export GINKGO_FOCUS="upgrade" + export DEPLOY_IRONIC="false" + export DEPLOY_BMO="false" + export DEPLOY_CERT_MANAGER="false" + ;; + *) + echo "'upgrade' not found in env var GINKGO_FOCUS. Will NOT run upgrade tests." + export GINKGO_SKIP="upgrade ${GINKGO_SKIP:-}" + ;; +esac +export USE_EXISTING_CLUSTER="true" + # Ensure requirements are installed "${REPO_ROOT}/hack/e2e/ensure_go.sh" export PATH="${PATH}:/usr/local/go/bin" @@ -142,6 +157,14 @@ echo "${IRONIC_PASSWORD}" > "${BMO_OVERLAY}/ironic-password" echo "${IRONIC_INSPECTOR_USERNAME}" > "${BMO_OVERLAY}/ironic-inspector-username" echo "${IRONIC_INSPECTOR_PASSWORD}" > "${BMO_OVERLAY}/ironic-inspector-password" +if [[ "${GINKGO_FOCUS:-}" == "upgrade" ]]; then + BMO_UPGRADE_FROM_OVERLAY="${REPO_ROOT}/config/overlays/e2e-release-0.4" + echo "${IRONIC_USERNAME}" > "${BMO_UPGRADE_FROM_OVERLAY}/ironic-username" + echo "${IRONIC_PASSWORD}" > "${BMO_UPGRADE_FROM_OVERLAY}/ironic-password" + echo "${IRONIC_INSPECTOR_USERNAME}" > "${BMO_UPGRADE_FROM_OVERLAY}/ironic-inspector-username" + echo "${IRONIC_INSPECTOR_PASSWORD}" > "${BMO_UPGRADE_FROM_OVERLAY}/ironic-inspector-password" +fi + envsubst < "${REPO_ROOT}/ironic-deployment/components/basic-auth/ironic-auth-config-tpl" > \ "${IRONIC_OVERLAY}/ironic-auth-config" envsubst < "${REPO_ROOT}/ironic-deployment/components/basic-auth/ironic-inspector-auth-config-tpl" > \ diff --git a/test/e2e/README.md b/test/e2e/README.md index 0581ef5711..8b9ce0f754 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -11,15 +11,28 @@ in `config`. In the CI system we set up a pre-configured minikube cluster that is then used for the tests, as seen in [ci-e2e.sh](../../hack/ci-e2e.sh). This allows us to have control over the network and have a static configuration for Ironic and the -Baremetal Operator. The script also creates a VM and configures VBMC to be used -as BareMetalHost and BMC respectively. +Baremetal Operator. The script creates a VM to represent a BareMetalHost, +and configures either VBMC or sushy-tools to be used as BMC. This script can be +configured to run either [E2E upgrade tests](upgrade_test.go), or the "normal" +E2E tests set (all tests except the upgrade ones) by exporting the `GINKGO_FOCUS` +env var. If "upgrade" is found as a part of `GINKGO_FOCUS`, ONLY the upgrade tests +will be run, otherwise the upgrade tests are skipped (other tests in `GINKGO_FOCUS` +or `GINKGO_SKIP` will be kept as-is). + +Here is how to run the E2E upgrade tests: + +```bash +export GINKGO_FOCUS="upgrade" +./hack/ci-e2e.sh +``` It is also possible to run the tests with the fixture provider instead of -Ironic, but please note that it is quite questionable to call this configuration -"end to end". This is how to run the e2e test suite with the fixture provider: +Ironic. Without any changes, the whole suite (including upgrade tests) will be run. +Please note, however, that it is quite questionable to call this configuration +"end to end". + +Fixture provider is configured to be the default one. This is how to run the e2e test suite with it: ```bash -export E2E_CONF_FILE=${REPO_ROOT}/test/e2e/config/fixture.yaml -export USE_EXISTING_CLUSTER="false" make test-e2e ``` diff --git a/test/e2e/common.go b/test/e2e/common.go index 74a6c915cd..32ae8a248c 100644 --- a/test/e2e/common.go +++ b/test/e2e/common.go @@ -505,3 +505,20 @@ func BuildAndApplyKustomize(ctx context.Context, input *BuildAndApplyKustomizeIn } return nil } + +func DeploymentRolledOut(ctx context.Context, clusterProxy framework.ClusterProxy, name string, namespace string, desiredGeneration int64) bool { + clientSet := clusterProxy.GetClientSet() + deploy, err := clientSet.AppsV1().Deployments(namespace).Get(ctx, name, metav1.GetOptions{}) + Expect(err).To(BeNil()) + if deploy != nil { + // When the number of replicas is equal to the number of available and updated + // replicas, we know that only "new" pods are running. When we also + // have the desired number of replicas and a new enough generation, we + // know that the rollout is complete. + return (deploy.Status.UpdatedReplicas == *deploy.Spec.Replicas) && + (deploy.Status.AvailableReplicas == *deploy.Spec.Replicas) && + (deploy.Status.Replicas == *deploy.Spec.Replicas) && + (deploy.Status.ObservedGeneration >= desiredGeneration) + } + return false +} diff --git a/test/e2e/config/fixture.yaml b/test/e2e/config/fixture.yaml index afa67fef07..da489aae42 100644 --- a/test/e2e/config/fixture.yaml +++ b/test/e2e/config/fixture.yaml @@ -3,6 +3,8 @@ images: - name: quay.io/metal3-io/baremetal-operator:e2e loadBehavior: tryLoad # Save some time and network by using cached images if available +- name: quay.io/metal3-io/baremetal-operator:release-0.4 + loadBehavior: tryLoad - name: quay.io/jetstack/cert-manager-cainjector:v1.13.1 loadBehavior: tryLoad - name: quay.io/jetstack/cert-manager-webhook:v1.13.1 @@ -11,17 +13,25 @@ images: loadBehavior: tryLoad variables: + # These settings are for the "default" cluster, which is used for all tests except upgrade ones DEPLOY_IRONIC: "false" DEPLOY_BMO: "true" DEPLOY_CERT_MANAGER: "true" BMO_KUSTOMIZATION: "../../config/overlays/fixture" + + # These settings are for the separate cluster that are used for upgrade tests + UPGRADE_DEPLOY_IRONIC: "false" + UPGRADE_DEPLOY_BMO: "true" + UPGRADE_DEPLOY_CERT_MANAGER: "true" + UPGRADE_BMO_KUSTOMIZATION_FROM: "../../config/overlays/fixture-release-0.4" + + BMC_ADDRESS: ipmi://192.168.222.1:16230 + BOOT_MAC_ADDRESS: "00:60:2f:31:81:01" EXPECTED_HOST_NAME: "" # Test credentials. The tests will create a BMH with these. # For the fixture provider it does not matter much what we put here. BMC_USER: admin BMC_PASSWORD: password - BMC_ADDRESS: ipmi://192.168.222.1:16230 - BOOT_MAC_ADDRESS: "00:60:2f:31:81:01" IMAGE_URL: "http://192.168.222.1/cirros-0.6.2-x86_64-disk.img" IMAGE_CHECKSUM: "c8fc807773e5354afe61636071771906" CERT_MANAGER_VERSION: "v1.13.1" @@ -38,10 +48,10 @@ intervals: default/wait-namespace-deleted: ["20s", "1s"] ironic/wait-deployment: ["10m", "2s"] default/wait-registration: ["5s", "5ms"] - default/wait-provisioning: ["5s", "10ms"] - default/wait-provisioned: ["20s", "1s"] + default/wait-provisioning: ["30s", "10ms"] + default/wait-provisioned: ["1m", "10s"] default/wait-deprovisioning: ["5s", "10ms"] - default/wait-available: ["20s", "1s"] + default/wait-available: ["2m", "1s"] default/wait-deleting: ["5s", "10ms"] default/wait-deleted: ["5s", "10ms"] default/wait-secret-deletion: ["5s", "10ms"] diff --git a/test/e2e/config/ironic.yaml b/test/e2e/config/ironic.yaml index 9cc9e11c01..26911548b1 100644 --- a/test/e2e/config/ironic.yaml +++ b/test/e2e/config/ironic.yaml @@ -5,6 +5,8 @@ images: - name: quay.io/metal3-io/ironic:e2e loadBehavior: tryLoad # Save some time and network by using cached images if available +- name: quay.io/metal3-io/baremetal-operator:release-0.4 + loadBehavior: tryLoad - name: quay.io/jetstack/cert-manager-cainjector:v1.13.1 loadBehavior: tryLoad - name: quay.io/jetstack/cert-manager-webhook:v1.13.1 @@ -14,12 +16,18 @@ images: # These variables can be overridden with environment variables. variables: + # These settings are for the "default" cluster, which is used for all tests except upgrade ones DEPLOY_IRONIC: "true" DEPLOY_BMO: "true" DEPLOY_CERT_MANAGER: "true" BMO_KUSTOMIZATION: "../../config/overlays/e2e" IRONIC_KUSTOMIZATION: "../../ironic-deployment/overlays/e2e" - EXPECTED_HOST_NAME: "bmo-e2e-0" + # These settings are for the separate cluster that are used for upgrade tests + UPGRADE_DEPLOY_IRONIC: "true" + UPGRADE_DEPLOY_BMO: "true" + UPGRADE_DEPLOY_CERT_MANAGER: "true" + UPGRADE_BMO_KUSTOMIZATION_FROM: "../../config/overlays/e2e-release-0.4" + # Test credentials. The tests will create a BMH with these. BMC_USER: admin BMC_PASSWORD: password @@ -29,6 +37,8 @@ variables: # BMC_ADDRESS: "ipmi://192.168.222.1:16230" BMC_ADDRESS: "redfish+http://192.168.222.1:8000/redfish/v1/Systems/bmo-e2e-0" BOOT_MAC_ADDRESS: "00:60:2f:31:81:01" + EXPECTED_HOST_NAME: "bmo-e2e-0" + IMAGE_URL: "http://192.168.222.1/cirros-0.6.2-x86_64-disk.img" IMAGE_CHECKSUM: "c8fc807773e5354afe61636071771906" CERT_MANAGER_VERSION: "v1.13.1" diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go new file mode 100644 index 0000000000..6a2d94878c --- /dev/null +++ b/test/e2e/upgrade_test.go @@ -0,0 +1,353 @@ +package e2e + +import ( + "fmt" + "os" + "path/filepath" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/cluster-api/test/framework" + "sigs.k8s.io/cluster-api/test/framework/bootstrap" + "sigs.k8s.io/cluster-api/util" + "sigs.k8s.io/cluster-api/util/patch" + + metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1" +) + +const hardwareDetailsRelease04 = ` +{ + "cpu": { + "arch": "x86_64", + "count": 2, + "flags": [ + "3dnowprefetch", + "abm", + "adx", + "aes", + "apic", + "arat", + "arch_capabilities", + "avx", + "avx2", + "avx_vnni", + "bmi1", + "bmi2", + "clflush", + "clflushopt", + "clwb", + "cmov", + "constant_tsc", + "cpuid", + "cpuid_fault", + "cx16", + "cx8", + "de", + "ept", + "ept_ad", + "erms", + "f16c", + "flexpriority", + "fma", + "fpu", + "fsgsbase", + "fsrm", + "fxsr", + "gfni", + "hypervisor", + "ibpb", + "ibrs", + "ibrs_enhanced", + "invpcid", + "lahf_lm", + "lm", + "mca", + "mce", + "md_clear", + "mmx", + "movbe", + "movdir64b", + "movdiri", + "msr", + "mtrr", + "nopl", + "nx", + "ospke", + "pae", + "pat", + "pclmulqdq", + "pdpe1gb", + "pge", + "pku", + "pni", + "popcnt", + "pse", + "pse36", + "rdpid", + "rdrand", + "rdseed", + "rdtscp", + "rep_good", + "sep", + "serialize", + "sha_ni", + "smap", + "smep", + "ss", + "ssbd", + "sse", + "sse2", + "sse4_1", + "sse4_2", + "ssse3", + "stibp", + "syscall", + "tpr_shadow", + "tsc", + "tsc_adjust", + "tsc_deadline_timer", + "tsc_known_freq", + "umip", + "vaes", + "vme", + "vmx", + "vnmi", + "vpclmulqdq", + "vpid", + "waitpkg", + "x2apic", + "xgetbv1", + "xsave", + "xsavec", + "xsaveopt", + "xsaves", + "xtopology" + ], + "model": "12th Gen Intel(R) Core(TM) i9-12900H" + }, + "firmware": { + "bios": { + "date": "04/01/2014", + "vendor": "SeaBIOS", + "version": "1.15.0-1" + } + }, + "hostname": "bmo-e2e-1", + "nics": [ + { + "ip": "192.168.223.122", + "mac": "00:60:2f:31:81:02", + "model": "0x1af4 0x0001", + "name": "enp1s0", + "pxe": true + }, + { + "ip": "fe80::570a:edf2:a3a7:4eb8%enp1s0", + "mac": "00:60:2f:31:81:02", + "model": "0x1af4 0x0001", + "name": "enp1s0", + "pxe": true + } + ], + "ramMebibytes": 4096, + "storage": [ + { + "name": "/dev/disk/by-path/pci-0000:04:00.0", + "rotational": true, + "sizeBytes": 21474836480, + "type": "HDD", + "vendor": "0x1af4" + } + ], + "systemVendor": { + "manufacturer": "QEMU", + "productName": "Standard PC (Q35 + ICH9, 2009)" + } +} +` + +var _ = Describe("BMO Upgrade", func() { + var ( + specName = "upgrade" + secretName = "bmc-credentials" + namespace *corev1.Namespace + bmcUser string + bmcPassword string + bmcAddress string + bootMacAddress string + bmoIronicNamespace string + upgradeClusterProvider bootstrap.ClusterProvider + upgradeClusterProxy framework.ClusterProxy + bmh metal3api.BareMetalHost + ) + BeforeEach(func() { + bmcUser = e2eConfig.GetVariable("BMC_USER") + bmcPassword = e2eConfig.GetVariable("BMC_PASSWORD") + bmcAddress = e2eConfig.GetVariable("BMC_ADDRESS") + bootMacAddress = e2eConfig.GetVariable("BOOT_MAC_ADDRESS") + bmoIronicNamespace = "baremetal-operator-system" + var kubeconfigPath string + + if useExistingCluster { + kubeconfigPath = os.Getenv("KUBECONFIG") + if kubeconfigPath == "" { + kubeconfigPath = os.Getenv("HOME") + "/.kube/config" + } + } else { + By("Creating a separate cluster for upgrade tests") + upgradeClusterProvider = bootstrap.CreateKindBootstrapClusterAndLoadImages(ctx, bootstrap.CreateKindBootstrapClusterAndLoadImagesInput{ + Name: "bmo-e2e-upgrade", + Images: e2eConfig.Images, + }) + Expect(upgradeClusterProvider).ToNot(BeNil(), "Failed to create a cluster") + kubeconfigPath = upgradeClusterProvider.GetKubeconfigPath() + } + Expect(kubeconfigPath).To(BeAnExistingFile(), "Failed to get the kubeconfig file for the cluster") + scheme := runtime.NewScheme() + framework.TryAddDefaultSchemes(scheme) + metal3api.AddToScheme(scheme) + upgradeClusterProxy = framework.NewClusterProxy("bmo-e2e-upgrade", kubeconfigPath, scheme) + if e2eConfig.GetVariable("UPGRADE_DEPLOY_CERT_MANAGER") != "false" { + By("Installing cert-manager on the upgrade cluster") + cmVersion := e2eConfig.GetVariable("CERT_MANAGER_VERSION") + err := installCertManager(ctx, upgradeClusterProxy, cmVersion) + Expect(err).NotTo(HaveOccurred()) + By("Waiting for cert-manager webhook") + Eventually(func() error { + return checkCertManagerWebhook(ctx, upgradeClusterProxy) + }, e2eConfig.GetIntervals("default", "wait-available")...).Should(Succeed()) + err = checkCertManagerAPI(upgradeClusterProxy) + Expect(err).NotTo(HaveOccurred()) + } + + if e2eConfig.GetVariable("UPGRADE_DEPLOY_IRONIC") != "false" { + // Install Ironic + By("Installing Ironic on the upgrade cluster") + err := BuildAndApplyKustomize(ctx, &BuildAndApplyKustomizeInput{ + Kustomization: e2eConfig.GetVariable("IRONIC_KUSTOMIZATION"), + ClusterProxy: upgradeClusterProxy, + WaitForDeployment: true, + WatchDeploymentLogs: true, + DeploymentName: "ironic", + DeploymentNamespace: bmoIronicNamespace, + LogPath: filepath.Join(artifactFolder, "logs", fmt.Sprintf("%s-%s", bmoIronicNamespace, specName)), + WaitIntervals: e2eConfig.GetIntervals("default", "wait-deployment"), + }) + Expect(err).NotTo(HaveOccurred()) + } + + if e2eConfig.GetVariable("UPGRADE_DEPLOY_BMO") != "false" { + By("Installing BMO on the upgrade cluster") + err := BuildAndApplyKustomize(ctx, &BuildAndApplyKustomizeInput{ + Kustomization: e2eConfig.GetVariable("UPGRADE_BMO_KUSTOMIZATION_FROM"), + ClusterProxy: upgradeClusterProxy, + WaitForDeployment: true, + WatchDeploymentLogs: true, + DeploymentName: "baremetal-operator-controller-manager", + DeploymentNamespace: bmoIronicNamespace, + LogPath: filepath.Join(artifactFolder, "logs", fmt.Sprintf("%s-%s", bmoIronicNamespace, specName)), + WaitIntervals: e2eConfig.GetIntervals("default", "wait-deployment"), + }) + Expect(err).NotTo(HaveOccurred()) + } + + namespace, cancelWatches = framework.CreateNamespaceAndWatchEvents(ctx, framework.CreateNamespaceAndWatchEventsInput{ + Creator: upgradeClusterProxy.GetClient(), + ClientSet: upgradeClusterProxy.GetClientSet(), + Name: fmt.Sprintf("%s-%s", specName, util.RandomString(6)), + LogFolder: artifactFolder, + }) + }) + + It("Should upgrade BMO to latest version", func() { + By("Creating a secret with BMH credentials") + bmcCredentialsData := map[string]string{ + "username": bmcUser, + "password": bmcPassword, + } + CreateSecret(ctx, upgradeClusterProxy.GetClient(), namespace.Name, secretName, bmcCredentialsData) + + By("Creating a BMH with inspection disabled and hardware details added") + bmh = metal3api.BareMetalHost{ + ObjectMeta: metav1.ObjectMeta{ + Name: specName, + Namespace: namespace.Name, + Annotations: map[string]string{ + metal3api.InspectAnnotationPrefix: "disabled", + metal3api.HardwareDetailsAnnotation: hardwareDetailsRelease04, + }, + }, + Spec: metal3api.BareMetalHostSpec{ + Online: true, + BMC: metal3api.BMCDetails{ + Address: bmcAddress, + CredentialsName: secretName, + }, + BootMode: metal3api.Legacy, + BootMACAddress: bootMacAddress, + }, + } + err := upgradeClusterProxy.GetClient().Create(ctx, &bmh) + Expect(err).NotTo(HaveOccurred()) + + By("Waiting for the BMH to become available") + WaitForBmhInProvisioningState(ctx, WaitForBmhInProvisioningStateInput{ + Client: upgradeClusterProxy.GetClient(), + Bmh: bmh, + State: metal3api.StateAvailable, + }, e2eConfig.GetIntervals(specName, "wait-available")...) + + By("Upgrading BMO deployment") + clientSet := upgradeClusterProxy.GetClientSet() + bmoDeployName := "baremetal-operator-controller-manager" + deploy, err := clientSet.AppsV1().Deployments(bmoIronicNamespace).Get(ctx, bmoDeployName, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + err = BuildAndApplyKustomize(ctx, &BuildAndApplyKustomizeInput{ + Kustomization: e2eConfig.GetVariable("BMO_KUSTOMIZATION"), + ClusterProxy: upgradeClusterProxy, + }) + Expect(err).NotTo(HaveOccurred()) + By("Waiting for BMO update to rollout") + Eventually(func() bool { + return DeploymentRolledOut(ctx, upgradeClusterProxy, bmoDeployName, bmoIronicNamespace, deploy.Status.ObservedGeneration+1) + }, + e2eConfig.GetIntervals("default", "wait-deployment")..., + ).Should(BeTrue()) + + By("Patching the BMH to test provisioning") + helper, err := patch.NewHelper(&bmh, upgradeClusterProxy.GetClient()) + Expect(err).NotTo(HaveOccurred()) + bmh.Spec.Image = &metal3api.Image{ + URL: e2eConfig.GetVariable("IMAGE_URL"), + Checksum: e2eConfig.GetVariable("IMAGE_CHECKSUM"), + } + bmh.Spec.RootDeviceHints = &metal3api.RootDeviceHints{ + DeviceName: "/dev/vda", + } + Expect(helper.Patch(ctx, &bmh)).To(Succeed()) + + By("Waiting for the BMH to become provisioned") + WaitForBmhInProvisioningState(ctx, WaitForBmhInProvisioningStateInput{ + Client: upgradeClusterProxy.GetClient(), + Bmh: bmh, + State: metal3api.StateProvisioned, + }, e2eConfig.GetIntervals(specName, "wait-provisioned")...) + }) + + AfterEach(func() { + cleanup(ctx, upgradeClusterProxy, namespace, cancelWatches, e2eConfig.GetIntervals("default", "wait-namespace-deleted")...) + if !skipCleanup { + if upgradeClusterProxy != nil { + upgradeClusterProxy.Dispose(ctx) + } + if upgradeClusterProvider != nil { + upgradeClusterProvider.Dispose(ctx) + } + } + }) + +})