diff --git a/controller/linodemachine_controller.go b/controller/linodemachine_controller.go index c045aac8c..3241fd9ae 100644 --- a/controller/linodemachine_controller.go +++ b/controller/linodemachine_controller.go @@ -41,7 +41,6 @@ import ( crcontroller "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/reconcile" infrav1alpha1 "github.com/linode/cluster-api-provider-linode/api/v1alpha1" infrav1alpha2 "github.com/linode/cluster-api-provider-linode/api/v1alpha2" @@ -64,6 +63,9 @@ const ( ConditionPreflightConfigured clusterv1.ConditionType = "PreflightConfigured" ConditionPreflightBootTriggered clusterv1.ConditionType = "PreflightBootTriggered" ConditionPreflightReady clusterv1.ConditionType = "PreflightReady" + + // WaitingForBootstrapDataReason used when machine is waiting for bootstrap data to be ready before proceeding. + WaitingForBootstrapDataReason = "WaitingForBootstrapData" ) // statuses to keep requeueing on while an instance is booting @@ -111,10 +113,10 @@ func (r *LinodeMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques linodeMachine := &infrav1alpha2.LinodeMachine{} if err := r.TracedClient().Get(ctx, req.NamespacedName, linodeMachine); err != nil { - if err = client.IgnoreNotFound(err); err != nil { - log.Error(err, "Failed to fetch LinodeMachine") + if apierrors.IsNotFound(err) { + return ctrl.Result{}, nil } - + log.Error(err, "Failed to fetch LinodeMachine") return ctrl.Result{}, err } @@ -139,7 +141,6 @@ func (r *LinodeMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, fmt.Errorf("get linodecluster %q: %w", linodeClusterKey, err) } } - log = log.WithValues("LinodeCluster", linodeCluster.Name) machineScope, err := scope.NewMachineScope( @@ -155,33 +156,20 @@ func (r *LinodeMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques ) if err != nil { log.Error(err, "Failed to create machine scope") - return ctrl.Result{}, fmt.Errorf("failed to create machine scope: %w", err) } return r.reconcile(ctx, log, machineScope) } -func (r *LinodeMachineReconciler) reconcile( - ctx context.Context, - logger logr.Logger, - machineScope *scope.MachineScope, -) (res ctrl.Result, err error) { - res = ctrl.Result{} - - machineScope.LinodeMachine.Status.Ready = false - machineScope.LinodeMachine.Status.FailureReason = nil - machineScope.LinodeMachine.Status.FailureMessage = util.Pointer("") - +func (r *LinodeMachineReconciler) reconcile(ctx context.Context, logger logr.Logger, machineScope *scope.MachineScope) (res ctrl.Result, err error) { failureReason := cerrs.MachineStatusError("UnknownError") //nolint:dupl // Code duplication is simplicity in this case. defer func() { if err != nil { machineScope.LinodeMachine.Status.FailureReason = util.Pointer(failureReason) machineScope.LinodeMachine.Status.FailureMessage = util.Pointer(err.Error()) - conditions.MarkFalse(machineScope.LinodeMachine, clusterv1.ReadyCondition, string(failureReason), clusterv1.ConditionSeverityError, err.Error()) - r.Recorder.Event(machineScope.LinodeMachine, corev1.EventTypeWarning, string(failureReason), err.Error()) } @@ -189,17 +177,14 @@ func (r *LinodeMachineReconciler) reconcile( // This ignores any resource not found errors when reconciling deletions. if patchErr := machineScope.Close(ctx); patchErr != nil && utilerrors.FilterOut(util.UnwrapError(patchErr), apierrors.IsNotFound) != nil { logger.Error(patchErr, "failed to patch LinodeMachine and LinodeCluster") - err = errors.Join(err, patchErr) } }() // Add the finalizer if not already there - err = machineScope.AddFinalizer(ctx) - if err != nil { + if err = machineScope.AddFinalizer(ctx); err != nil { logger.Error(err, "Failed to add finalizer") - - return + return ctrl.Result{}, err } // Delete @@ -208,37 +193,22 @@ func (r *LinodeMachineReconciler) reconcile( return r.reconcileDelete(ctx, logger, machineScope) } + // Make sure bootstrap data is available and populated. + if machineScope.Machine.Spec.Bootstrap.DataSecretName == nil { + logger.Info("Bootstrap data secret is not yet available") + conditions.MarkFalse(machineScope.LinodeMachine, ConditionPreflightCreated, WaitingForBootstrapDataReason, clusterv1.ConditionSeverityInfo, "") + return ctrl.Result{}, nil + } + // Update if machineScope.LinodeMachine.Status.InstanceState != nil { - var linodeInstance *linodego.Instance - defer func() { - if linodeInstance != nil { - machineScope.LinodeMachine.Status.InstanceState = &linodeInstance.Status - } - }() - failureReason = cerrs.UpdateMachineError - - res, linodeInstance, err = r.reconcileUpdate(ctx, logger, machineScope) - // If an instance exists, then we dont need to continue to create - // If there were no errors in updating, we dont need to continue to create - if linodeInstance != nil || err == nil { - return - } + return r.reconcileUpdate(ctx, logger, machineScope) } // Create failureReason = cerrs.CreateMachineError - // Make sure bootstrap data is available and populated. - if machineScope.Machine.Spec.Bootstrap.DataSecretName == nil { - logger.Info("Bootstrap data secret is not yet available") - res = ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerWaitForBootstrapDelay} - - return - } - res, err = r.reconcileCreate(ctx, logger, machineScope) - - return + return r.reconcileCreate(ctx, logger, machineScope) } func (r *LinodeMachineReconciler) reconcileCreate( @@ -253,141 +223,87 @@ func (r *LinodeMachineReconciler) reconcileCreate( return ctrl.Result{}, err } - tags := []string{machineScope.LinodeCluster.Name} - var instanceID *int - if machineScope.LinodeMachine.Spec.ProviderID != nil { - instID, err := util.GetInstanceID(machineScope.LinodeMachine.Spec.ProviderID) - if err != nil { - logger.Error(err, "Failed to parse instance ID from provider ID") - return ctrl.Result{}, err - } - instanceID = util.Pointer(instID) - } - - listFilter := util.Filter{ - ID: instanceID, - Label: machineScope.LinodeMachine.Name, - Tags: tags, - } - filter, err := listFilter.String() - if err != nil { - return ctrl.Result{}, err - } - linodeInstances, err := machineScope.LinodeClient.ListInstances(ctx, linodego.NewListOptions(1, filter)) - if err != nil { - logger.Error(err, "Failed to list Linode machine instances") - - return ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerWaitForRunningDelay}, nil - } - - var linodeInstance *linodego.Instance - switch len(linodeInstances) { - case 1: - logger.Info("Linode instance already exists") - linodeInstance = &linodeInstances[0] - case 0: + // create instance if it doesn't exist judging by the condition + if !reconciler.ConditionTrue(machineScope.LinodeMachine, ConditionPreflightCreated) && machineScope.LinodeMachine.Spec.ProviderID == nil { // get the bootstrap data for the Linode instance and set it for create config - createOpts, err := newCreateConfig(ctx, machineScope, tags, logger) + createOpts, err := newCreateConfig(ctx, machineScope, logger) if err != nil { logger.Error(err, "Failed to create Linode machine InstanceCreateOptions") return retryIfTransient(err) } - linodeInstance, err = machineScope.LinodeClient.CreateInstance(ctx, *createOpts) + linodeInstance, err := machineScope.LinodeClient.CreateInstance(ctx, *createOpts) if err != nil { - if util.IsRetryableError(err) { - logger.Error(err, "Failed to create Linode instance due to API error, requeing") - if linodego.ErrHasStatus(err, http.StatusTooManyRequests) { - return ctrl.Result{RequeueAfter: reconciler.DefaultLinodeTooManyRequestsErrorRetryDelay}, nil - } - return ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerRetryDelay}, nil - } logger.Error(err, "Failed to create Linode machine instance") - if reconciler.RecordDecayingCondition(machineScope.LinodeMachine, ConditionPreflightCreated, string(cerrs.CreateMachineError), err.Error(), reconciler.DefaultTimeout(r.ReconcileTimeout, reconciler.DefaultMachineControllerWaitForPreflightTimeout)) { return ctrl.Result{}, err } - - return ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerWaitForRunningDelay}, nil + return retryIfTransient(err) } - default: - err = errors.New("multiple instances") - logger.Error(err, "multiple instances found", "tags", tags) - - return ctrl.Result{}, err + conditions.MarkTrue(machineScope.LinodeMachine, ConditionPreflightCreated) + // Set the provider ID since the instance is successfully created + machineScope.LinodeMachine.Spec.ProviderID = util.Pointer(fmt.Sprintf("linode://%d", linodeInstance.ID)) } - - conditions.MarkTrue(machineScope.LinodeMachine, ConditionPreflightCreated) - machineScope.LinodeMachine.Spec.ProviderID = util.Pointer(fmt.Sprintf("linode://%d", linodeInstance.ID)) - - return r.reconcileInstanceCreate(ctx, logger, machineScope, linodeInstance) + return r.reconcileNewInstance(ctx, logger, machineScope) } -func (r *LinodeMachineReconciler) reconcileInstanceCreate( - ctx context.Context, - logger logr.Logger, - machineScope *scope.MachineScope, - linodeInstance *linodego.Instance, -) (ctrl.Result, error) { +func (r *LinodeMachineReconciler) reconcileNewInstance(ctx context.Context, logger logr.Logger, machineScope *scope.MachineScope) (ctrl.Result, error) { + instanceID, err := util.GetInstanceID(machineScope.LinodeMachine.Spec.ProviderID) + if err != nil { + logger.Error(err, "Failed to parse instance ID from provider ID") + return ctrl.Result{}, err + } if !reconciler.ConditionTrue(machineScope.LinodeMachine, ConditionPreflightConfigured) { - if err := configureDisks(ctx, logger, machineScope, linodeInstance.ID); err != nil { + if err := configureDisks(ctx, logger, machineScope, instanceID); err != nil { if reconciler.RecordDecayingCondition(machineScope.LinodeMachine, ConditionPreflightConfigured, string(cerrs.CreateMachineError), err.Error(), reconciler.DefaultTimeout(r.ReconcileTimeout, reconciler.DefaultMachineControllerWaitForPreflightTimeout)) { return ctrl.Result{}, err } - return ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerWaitForRunningDelay}, nil } - conditions.MarkTrue(machineScope.LinodeMachine, ConditionPreflightConfigured) - } - - if machineScope.LinodeMachine.Spec.Configuration != nil && machineScope.LinodeMachine.Spec.Configuration.Kernel != "" { - instanceConfig, err := getDefaultInstanceConfig(ctx, machineScope, linodeInstance.ID) - if err != nil { - logger.Error(err, "Failed to get default instance configuration") - return retryIfTransient(err) - } + if machineScope.LinodeMachine.Spec.Configuration != nil && machineScope.LinodeMachine.Spec.Configuration.Kernel != "" { + instanceConfig, err := getDefaultInstanceConfig(ctx, machineScope, instanceID) + if err != nil { + logger.Error(err, "Failed to get default instance configuration") + return retryIfTransient(err) + } - if _, err := machineScope.LinodeClient.UpdateInstanceConfig(ctx, linodeInstance.ID, instanceConfig.ID, linodego.InstanceConfigUpdateOptions{Kernel: machineScope.LinodeMachine.Spec.Configuration.Kernel}); err != nil { - logger.Error(err, "Failed to update default instance configuration") - return retryIfTransient(err) + if _, err := machineScope.LinodeClient.UpdateInstanceConfig(ctx, instanceID, instanceConfig.ID, linodego.InstanceConfigUpdateOptions{Kernel: machineScope.LinodeMachine.Spec.Configuration.Kernel}); err != nil { + logger.Error(err, "Failed to update default instance configuration") + return retryIfTransient(err) + } } + conditions.MarkTrue(machineScope.LinodeMachine, ConditionPreflightConfigured) } if !reconciler.ConditionTrue(machineScope.LinodeMachine, ConditionPreflightBootTriggered) { - if err := machineScope.LinodeClient.BootInstance(ctx, linodeInstance.ID, 0); err != nil && !strings.HasSuffix(err.Error(), "already booted.") { + if err := machineScope.LinodeClient.BootInstance(ctx, instanceID, 0); err != nil && !strings.HasSuffix(err.Error(), "already booted.") { logger.Error(err, "Failed to boot instance") - if reconciler.RecordDecayingCondition(machineScope.LinodeMachine, ConditionPreflightBootTriggered, string(cerrs.CreateMachineError), err.Error(), reconciler.DefaultTimeout(r.ReconcileTimeout, reconciler.DefaultMachineControllerWaitForPreflightTimeout)) { return ctrl.Result{}, err } - return ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerWaitForRunningDelay}, nil } - conditions.MarkTrue(machineScope.LinodeMachine, ConditionPreflightBootTriggered) } if !reconciler.ConditionTrue(machineScope.LinodeMachine, ConditionPreflightReady) { - addrs, err := buildInstanceAddrs(ctx, machineScope, linodeInstance.ID) + addrs, err := buildInstanceAddrs(ctx, machineScope, instanceID) if err != nil { logger.Error(err, "Failed to get instance ip addresses") - if reconciler.RecordDecayingCondition(machineScope.LinodeMachine, ConditionPreflightReady, string(cerrs.CreateMachineError), err.Error(), reconciler.DefaultTimeout(r.ReconcileTimeout, reconciler.DefaultMachineControllerWaitForPreflightTimeout)) { return ctrl.Result{}, err } - return ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerWaitForRunningDelay}, nil } machineScope.LinodeMachine.Status.Addresses = addrs - conditions.MarkTrue(machineScope.LinodeMachine, ConditionPreflightReady) } @@ -397,63 +313,34 @@ func (r *LinodeMachineReconciler) reconcileInstanceCreate( return ctrl.Result{}, nil } -func (r *LinodeMachineReconciler) reconcileUpdate( - ctx context.Context, - logger logr.Logger, - machineScope *scope.MachineScope, -) (res reconcile.Result, linodeInstance *linodego.Instance, err error) { +func (r *LinodeMachineReconciler) reconcileUpdate(ctx context.Context, logger logr.Logger, machineScope *scope.MachineScope) (ctrl.Result, error) { logger.Info("updating machine") - - res = ctrl.Result{} - instanceID, err := util.GetInstanceID(machineScope.LinodeMachine.Spec.ProviderID) if err != nil { logger.Error(err, "Failed to parse instance ID from provider ID") - return ctrl.Result{}, nil, err + return ctrl.Result{}, err } + var linodeInstance *linodego.Instance if linodeInstance, err = machineScope.LinodeClient.GetInstance(ctx, instanceID); err != nil { - if util.IgnoreLinodeAPIError(err, http.StatusNotFound) != nil { - logger.Error(err, "Failed to get Linode machine instance") - - return ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerRetryDelay}, nil, err - } else { - logger.Info("Instance not found, let's create a new one") - - // Create new machine - machineScope.LinodeMachine.Spec.ProviderID = nil - machineScope.LinodeMachine.Status.InstanceState = nil - machineScope.LinodeMachine.Status.Conditions = nil - - conditions.MarkFalse(machineScope.LinodeMachine, clusterv1.ReadyCondition, "missing", clusterv1.ConditionSeverityWarning, "instance not found") - } - return res, nil, err + return retryIfTransient(err) } if _, ok := requeueInstanceStatuses[linodeInstance.Status]; ok { if linodeInstance.Updated.Add(reconciler.DefaultMachineControllerWaitForRunningTimeout).After(time.Now()) { - logger.Info("Instance has one operation running, re-queuing reconciliation", "status", linodeInstance.Status) - - return ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerWaitForRunningDelay}, linodeInstance, nil + logger.Info("Instance not yet ready", "status", linodeInstance.Status) + return ctrl.Result{RequeueAfter: reconciler.DefaultMachineControllerWaitForRunningDelay}, nil + } else { + logger.Info("Instance not ready in time, skipping reconciliation", "status", linodeInstance.Status) + conditions.MarkFalse(machineScope.LinodeMachine, clusterv1.ReadyCondition, string(linodeInstance.Status), clusterv1.ConditionSeverityInfo, "skipped due to long running operation") } - - logger.Info("Instance has one operation long running, skipping reconciliation", "status", linodeInstance.Status) - - conditions.MarkFalse(machineScope.LinodeMachine, clusterv1.ReadyCondition, string(linodeInstance.Status), clusterv1.ConditionSeverityInfo, "skipped due to long running operation") - - return res, linodeInstance, nil } else if linodeInstance.Status != linodego.InstanceRunning { logger.Info("Instance has incompatible status, skipping reconciliation", "status", linodeInstance.Status) - conditions.MarkFalse(machineScope.LinodeMachine, clusterv1.ReadyCondition, string(linodeInstance.Status), clusterv1.ConditionSeverityInfo, "incompatible status") - - return res, linodeInstance, nil + } else { + machineScope.LinodeMachine.Status.Ready = true + conditions.MarkTrue(machineScope.LinodeMachine, clusterv1.ReadyCondition) } - - machineScope.LinodeMachine.Status.Ready = true - - conditions.MarkTrue(machineScope.LinodeMachine, clusterv1.ReadyCondition) - - return res, linodeInstance, nil + return ctrl.Result{}, nil } func (r *LinodeMachineReconciler) reconcileDelete( diff --git a/controller/linodemachine_controller_helpers.go b/controller/linodemachine_controller_helpers.go index 83bf3b604..9fe0a295c 100644 --- a/controller/linodemachine_controller_helpers.go +++ b/controller/linodemachine_controller_helpers.go @@ -69,7 +69,7 @@ func retryIfTransient(err error) (ctrl.Result, error) { return ctrl.Result{}, err } -func newCreateConfig(ctx context.Context, machineScope *scope.MachineScope, tags []string, logger logr.Logger) (*linodego.InstanceCreateOptions, error) { +func newCreateConfig(ctx context.Context, machineScope *scope.MachineScope, logger logr.Logger) (*linodego.InstanceCreateOptions, error) { var err error createConfig := linodeMachineSpecToInstanceCreateConfig(machineScope.LinodeMachine.Spec) @@ -96,7 +96,7 @@ func newCreateConfig(ctx context.Context, machineScope *scope.MachineScope, tags if createConfig.Tags == nil { createConfig.Tags = []string{} } - createConfig.Tags = append(createConfig.Tags, tags...) + createConfig.Tags = append(createConfig.Tags, machineScope.LinodeCluster.Name) if createConfig.Label == "" { createConfig.Label = machineScope.LinodeMachine.Name diff --git a/controller/linodemachine_controller_test.go b/controller/linodemachine_controller_test.go index 99a8ed811..b0e6d48d6 100644 --- a/controller/linodemachine_controller_test.go +++ b/controller/linodemachine_controller_test.go @@ -113,7 +113,6 @@ var _ = Describe("create", Label("machine", "create"), func() { UID: "12345", }, Spec: infrav1alpha2.LinodeMachineSpec{ - ProviderID: ptr.To("linode://123"), Type: "g6-nanode-1", Image: rutil.DefaultMachineControllerLinodeImage, DiskEncryption: string(linodego.InstanceDiskEncryptionEnabled), @@ -142,12 +141,8 @@ var _ = Describe("create", Label("machine", "create"), func() { It("creates a worker instance", func(ctx SpecContext) { mockLinodeClient := mock.NewMockLinodeClient(mockCtrl) - listInst := mockLinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). - Return([]linodego.Instance{}, nil) getRegion := mockLinodeClient.EXPECT(). GetRegion(ctx, gomock.Any()). - After(listInst). Return(&linodego.Region{Capabilities: []string{linodego.CapabilityMetadata, linodego.CapabilityDiskEncryption}}, nil) getImage := mockLinodeClient.EXPECT(). GetImage(ctx, gomock.Any()). @@ -231,12 +226,8 @@ var _ = Describe("create", Label("machine", "create"), func() { Context("fails when a preflight condition is stale", func() { It("can't create an instance in time", func(ctx SpecContext) { mockLinodeClient := mock.NewMockLinodeClient(mockCtrl) - listInst := mockLinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). - Return([]linodego.Instance{}, nil) getRegion := mockLinodeClient.EXPECT(). GetRegion(ctx, gomock.Any()). - After(listInst). Return(&linodego.Region{Capabilities: []string{linodego.CapabilityMetadata, linodego.CapabilityDiskEncryption}}, nil) getImage := mockLinodeClient.EXPECT(). GetImage(ctx, gomock.Any()). @@ -279,12 +270,8 @@ var _ = Describe("create", Label("machine", "create"), func() { Context("when a known error occurs", func() { It("requeues due to context deadline exceeded error", func(ctx SpecContext) { mockLinodeClient := mock.NewMockLinodeClient(mockCtrl) - listInst := mockLinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). - Return([]linodego.Instance{}, nil) getRegion := mockLinodeClient.EXPECT(). GetRegion(ctx, gomock.Any()). - After(listInst). Return(&linodego.Region{Capabilities: []string{"Metadata"}}, nil) getImage := mockLinodeClient.EXPECT(). GetImage(ctx, gomock.Any()). @@ -321,12 +308,8 @@ var _ = Describe("create", Label("machine", "create"), func() { linodeMachine.Spec.DataDisks = map[string]*infrav1alpha2.InstanceDisk{"sdb": ptr.To(infrav1alpha2.InstanceDisk{Label: "etcd-data", Size: resource.MustParse("10Gi")})} mockLinodeClient := mock.NewMockLinodeClient(mockCtrl) - listInst := mockLinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). - Return([]linodego.Instance{}, nil) getRegion := mockLinodeClient.EXPECT(). GetRegion(ctx, gomock.Any()). - After(listInst). Return(&linodego.Region{Capabilities: []string{linodego.CapabilityMetadata, linodego.CapabilityDiskEncryption}}, nil) getImage := mockLinodeClient.EXPECT(). GetImage(ctx, gomock.Any()). @@ -476,12 +459,8 @@ var _ = Describe("create", Label("machine", "create"), func() { linodeMachine.Spec.DataDisks = map[string]*infrav1alpha2.InstanceDisk{"sdb": ptr.To(infrav1alpha2.InstanceDisk{Label: "etcd-data", Size: resource.MustParse("10Gi")})} mockLinodeClient := mock.NewMockLinodeClient(mockCtrl) - listInst := mockLinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). - Return([]linodego.Instance{}, nil) getRegion := mockLinodeClient.EXPECT(). GetRegion(ctx, gomock.Any()). - After(listInst). Return(&linodego.Region{Capabilities: []string{linodego.CapabilityMetadata, linodego.CapabilityDiskEncryption}}, nil) getImage := mockLinodeClient.EXPECT(). GetImage(ctx, gomock.Any()). @@ -520,7 +499,7 @@ var _ = Describe("create", Label("machine", "create"), func() { Filesystem: string(linodego.FilesystemExt4), }). After(resizeInstDisk). - Return(nil, linodego.Error{Code: 400}) + Return(nil, &linodego.Error{Code: 400}) mScope := scope.MachineScope{ Client: k8sClient, @@ -542,22 +521,22 @@ var _ = Describe("create", Label("machine", "create"), func() { Expect(rutil.ConditionTrue(&linodeMachine, ConditionPreflightCreated)).To(BeTrue()) Expect(rutil.ConditionTrue(&linodeMachine, ConditionPreflightConfigured)).To(BeFalse()) - listInst = mockLinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). + getInst := mockLinodeClient.EXPECT(). + GetInstance(ctx, 123). After(createFailedEtcdDisk). - Return([]linodego.Instance{{ + Return(&linodego.Instance{ ID: 123, IPv4: []*net.IP{ptr.To(net.IPv4(192, 168, 0, 2))}, IPv6: "fd00::", Status: linodego.InstanceOffline, - }}, nil) + }, nil) createEtcdDisk := mockLinodeClient.EXPECT(). CreateInstanceDisk(ctx, 123, linodego.InstanceDiskCreateOptions{ Label: "etcd-data", Size: 10738, Filesystem: string(linodego.FilesystemExt4), }). - After(listInst). + After(getInst). Return(&linodego.InstanceDisk{ID: 101}, nil) listInstConfsForProfile := mockLinodeClient.EXPECT(). ListInstanceConfigs(ctx, 123, gomock.Any()). @@ -710,9 +689,8 @@ var _ = Describe("createDNS", Label("machine", "createDNS"), func() { UID: "12345", }, Spec: infrav1alpha2.LinodeMachineSpec{ - ProviderID: ptr.To("linode://0"), - Type: "g6-nanode-1", - Image: rutil.DefaultMachineControllerLinodeImage, + Type: "g6-nanode-1", + Image: rutil.DefaultMachineControllerLinodeImage, }, } reconciler = &LinodeMachineReconciler{ @@ -738,12 +716,8 @@ var _ = Describe("createDNS", Label("machine", "createDNS"), func() { It("creates a worker instance", func(ctx SpecContext) { mockLinodeClient := mock.NewMockLinodeClient(mockCtrl) - listInst := mockLinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). - Return([]linodego.Instance{}, nil) getRegion := mockLinodeClient.EXPECT(). GetRegion(ctx, gomock.Any()). - After(listInst). Return(&linodego.Region{Capabilities: []string{"Metadata"}}, nil) getImage := mockLinodeClient.EXPECT(). GetImage(ctx, gomock.Any()). @@ -934,12 +908,8 @@ var _ = Describe("machine-lifecycle", Ordered, Label("machine", "machine-lifecyc })), Path(Result("create requeues", func(ctx context.Context, mck Mock) { linodeMachine.Spec.ProviderID = util.Pointer("linode://123") - listInst := mck.LinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). - Return([]linodego.Instance{}, nil) getRegion := mck.LinodeClient.EXPECT(). GetRegion(ctx, gomock.Any()). - After(listInst). Return(&linodego.Region{Capabilities: []string{"Metadata"}}, nil) getImage := mck.LinodeClient.EXPECT(). GetImage(ctx, gomock.Any()). @@ -957,12 +927,8 @@ var _ = Describe("machine-lifecycle", Ordered, Label("machine", "machine-lifecyc ), Path( Call("machine is not created because there were too many requests", func(ctx context.Context, mck Mock) { - listInst := mck.LinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). - Return([]linodego.Instance{}, nil) mck.LinodeClient.EXPECT(). GetRegion(ctx, gomock.Any()). - After(listInst). Return(&linodego.Region{Capabilities: []string{"Metadata"}}, nil) }), OneOf( @@ -1065,12 +1031,8 @@ var _ = Describe("machine-lifecycle", Ordered, Label("machine", "machine-lifecyc }), OneOf( Path(Result("creates a worker machine without disks", func(ctx context.Context, mck Mock) { - listInst := mck.LinodeClient.EXPECT(). - ListInstances(ctx, gomock.Any()). - Return([]linodego.Instance{}, nil) getRegion := mck.LinodeClient.EXPECT(). GetRegion(ctx, gomock.Any()). - After(listInst). Return(&linodego.Region{Capabilities: []string{"Metadata"}}, nil) getImage := mck.LinodeClient.EXPECT(). GetImage(ctx, gomock.Any()). @@ -1217,7 +1179,7 @@ var _ = Describe("machine-delete", Ordered, Label("machine", "machine-delete"), })), Path(Result("delete requeues", func(ctx context.Context, mck Mock) { mck.LinodeClient.EXPECT().DeleteInstance(gomock.Any(), gomock.Any()). - Return(errors.New("failed to delete instance")) + Return(&linodego.Error{Code: http.StatusInternalServerError}) res, err := reconciler.reconcileDelete(ctx, mck.Logger(), mScope) Expect(err).NotTo(HaveOccurred()) Expect(res.RequeueAfter).To(Equal(rutil.DefaultMachineControllerRetryDelay)) @@ -1408,7 +1370,7 @@ var _ = Describe("machine in PlacementGroup", Label("machine", "placementGroup") Expect(err).NotTo(HaveOccurred()) mScope.PatchHelper = patchHelper - createOpts, err := newCreateConfig(ctx, &mScope, []string{}, logger) + createOpts, err := newCreateConfig(ctx, &mScope, logger) Expect(err).NotTo(HaveOccurred()) Expect(createOpts).NotTo(BeNil()) Expect(createOpts.PlacementGroup.ID).To(Equal(1))