diff --git a/internal/controller/controllers/bmh_agent_controller.go b/internal/controller/controllers/bmh_agent_controller.go index 0281eecca0e..d0652e29c26 100644 --- a/internal/controller/controllers/bmh_agent_controller.go +++ b/internal/controller/controllers/bmh_agent_controller.go @@ -1476,12 +1476,6 @@ func (r *BMACReconciler) getChecksumAndURL(ctx context.Context, spokeClient clie checksum, _ = image["checksum"].(string) url, _ = image["url"].(string) - if checksum == "" { - return "", "", errors.New("master machine ProviderSpec 'image' missing checksum"), false - } - if url == "" { - return "", "", errors.New("master machine ProviderSpec 'image' missing url"), false - } return checksum, url, nil, false } diff --git a/internal/controller/controllers/bmh_agent_controller_test.go b/internal/controller/controllers/bmh_agent_controller_test.go index c962ba66549..816c778a1bd 100644 --- a/internal/controller/controllers/bmh_agent_controller_test.go +++ b/internal/controller/controllers/bmh_agent_controller_test.go @@ -41,8 +41,10 @@ import ( fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" ) -var BASIC_KUBECONFIG = `test` -var BASIC_CERT = `test` +var ( + BASIC_KUBECONFIG = `test` + BASIC_CERT = `test` +) var _ = Describe("bmac reconcile", func() { var ( @@ -1603,6 +1605,75 @@ var _ = Describe("bmac reconcile", func() { Expect(spokeMachine.ObjectMeta.Labels[MACHINE_TYPE]).To(Equal(string(models.HostRoleWorker))) Expect(string(spokeMachine.Spec.ProviderSpec.Value.Raw)).To(ContainSubstring(imageURL)) }) + It("should create spoke BMH & Machine when master Machine uses customDeploy with empty image data (OCP 4.10+)", func() { + // Replace the master Machine with one that uses customDeploy and empty image data, + // matching the format generated by openshift-install since OCP 4.10 + spokeMachineMaster := &machinev1beta1.Machine{} + var err error + err = bmhr.spokeClient.Get(ctx, types.NamespacedName{Name: "spoke-machine-master-0", Namespace: testNamespace}, spokeMachineMaster) + Expect(err).To(BeNil()) + Expect(bmhr.spokeClient.Delete(ctx, spokeMachineMaster)).To(BeNil()) + + spokeMachineMasterCustomDeploy := &machinev1beta1.Machine{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "machine.openshift.io/v1beta1", + Kind: "Machine", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "spoke-machine-master-0", + Namespace: testNamespace, + Labels: map[string]string{ + machinev1beta1.MachineClusterIDLabel: cluster.Name, + MACHINE_ROLE: string(models.HostRoleMaster), + MACHINE_TYPE: string(models.HostRoleMaster), + }, + }, + Spec: machinev1beta1.MachineSpec{ + ProviderSpec: machinev1beta1.ProviderSpec{ + Value: &runtime.RawExtension{ + Raw: []byte(`{ + "apiVersion": "baremetal.cluster.k8s.io/v1alpha1", + "kind": "BareMetalMachineProviderSpec", + "customDeploy": {"method": "install_coreos"}, + "image": {"checksum": "", "url": ""} + }`), + }, + }, + }, + } + Expect(bmhr.spokeClient.Create(ctx, spokeMachineMasterCustomDeploy)).To(BeNil()) + + agent_day2.Status.DebugInfo.State = models.HostStatusInstalling + Expect(c.Update(ctx, agent_day2)).To(BeNil()) + + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "machine-config-server-ca", + Namespace: "openshift-machine-config-operator", + }, + Data: map[string]string{ + "ca-bundle.crt": BASIC_CERT, + }, + } + Expect(bmhr.spokeClient.Create(ctx, configMap)).ShouldNot(HaveOccurred()) + + for range [3]int{} { + var result ctrl.Result + result, err = bmhr.Reconcile(ctx, newBMHRequest(host_day2)) + Expect(err).To(BeNil()) + Expect(result).To(Equal(ctrl.Result{})) + } + + By("Checking spoke Machine was created despite empty image data") + machineName := fmt.Sprintf("%s-%s", cluster.Name, host_day2.Name) + spokeMachine := &machinev1beta1.Machine{} + spokeClient := bmhr.spokeClient + err = spokeClient.Get(ctx, types.NamespacedName{Name: machineName, Namespace: OPENSHIFT_MACHINE_API_NAMESPACE}, spokeMachine) + Expect(err).To(BeNil()) + Expect(spokeMachine.ObjectMeta.Labels).To(HaveKey(MACHINE_ROLE)) + Expect(spokeMachine.ObjectMeta.Labels[MACHINE_ROLE]).To(Equal(string(models.HostRoleWorker))) + Expect(spokeMachine.ObjectMeta.Annotations).To(HaveKey("metal3.io/BareMetalHost")) + }) It("should create spoke BMH & Machine for day 2 host with master role when it's installing - happy flow", func() { configMap := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ @@ -3773,20 +3844,22 @@ var _ = Describe("getChecksumAndURL", func() { Expect(stop).To(BeFalse()) }) - It("returns error when checksum is missing", func() { + It("returns empty strings when checksum is missing (valid for customDeploy)", func() { createMasterMachine([]byte(`{"image": {"url": "http://example.com/image"}}`)) - _, _, err, stop := bmhr.getChecksumAndURL(ctx, spokeClient) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("missing checksum")) + checksum, url, err, stop := bmhr.getChecksumAndURL(ctx, spokeClient) + Expect(err).ToNot(HaveOccurred()) Expect(stop).To(BeFalse()) + Expect(checksum).To(Equal("")) + Expect(url).To(Equal("http://example.com/image")) }) - It("returns error when url is missing", func() { + It("returns empty strings when url is missing (valid for customDeploy)", func() { createMasterMachine([]byte(`{"image": {"checksum": "abc123"}}`)) - _, _, err, stop := bmhr.getChecksumAndURL(ctx, spokeClient) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("missing url")) + checksum, url, err, stop := bmhr.getChecksumAndURL(ctx, spokeClient) + Expect(err).ToNot(HaveOccurred()) Expect(stop).To(BeFalse()) + Expect(checksum).To(Equal("abc123")) + Expect(url).To(Equal("")) }) It("returns checksum and url when both are present", func() {