Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ linters:
text: 'SA1019: "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions" is deprecated: This package is deprecated and is going to be removed when support for v1beta1 will be dropped. Please see https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more details.'
- linters:
- staticcheck
text: 'SA1019: .*.Status.Ready is deprecated: This field is deprecated and will be removed in a future API version. Use status.conditions to determine the ready state of the cluster.'
text: 'SA1019: .*.Status.Ready is deprecated: This field is deprecated and will be removed in a future API version. Use status.conditions to determine the ready state of the *'
- linters:
- staticcheck
text: 'SA1019: .*.Status.FailureReason is deprecated: This field is deprecated and will be removed in a future API version. Use status.conditions to report failures.'
Expand Down
28 changes: 28 additions & 0 deletions api/v1beta1/openstackmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,27 @@ type ServerMetadata struct {
Value string `json:"value"`
}

// MachineInitialization contains information about the initialization status of the machine.
type MachineInitialization struct {
// Provisioned is set to true when the initial provisioning of the machine infrastructure is completed.
// The value of this field is never updated after provisioning is completed.
// +optional
Provisioned bool `json:"provisioned,omitempty"`
}

// OpenStackMachineStatus defines the observed state of OpenStackMachine.
type OpenStackMachineStatus struct {
// Ready is true when the provider resource is ready.
//
// Deprecated: This field is deprecated and will be removed in a future API version.
// Use status.conditions to determine the ready state of the machine.
// +optional
Ready bool `json:"ready"`

// Initialization contains information about the initialization status of the machine.
// +optional
Initialization *MachineInitialization `json:"initialization,omitempty"`

// InstanceID is the OpenStack instance ID for this machine.
// +optional
InstanceID optional.String `json:"instanceID,omitempty"`
Expand All @@ -213,6 +228,11 @@ type OpenStackMachineStatus struct {
// +optional
Resources *MachineResources `json:"resources,omitempty"`

// FailureReason explains the reson behind a failure.
//
// Deprecated: This field is deprecated and will be removed in a future API version.
// Use status.conditions to report failures.
// +optional
FailureReason *capoerrors.DeprecatedCAPIMachineStatusError `json:"failureReason,omitempty"`

// FailureMessage will be set in the event that there is a terminal problem
Expand All @@ -231,9 +251,17 @@ type OpenStackMachineStatus struct {
// Any transient errors that occur during the reconciliation of Machines
// can be added as events to the Machine object and/or logged in the
// controller's output.
//
// Deprecated: This field is deprecated and will be removed in a future API version.
// Use status.conditions to report failures.
// +optional
FailureMessage *string `json:"failureMessage,omitempty"`

// Conditions defines current service state of the OpenStackMachine.
// This field surfaces into Machine's status.conditions[InfrastructureReady] condition.
// The Ready condition must surface issues during the entire lifecycle of the OpenStackMachine
// (both during initial provisioning and after the initial provisioning is completed).
// +optional
Conditions clusterv1beta1.Conditions `json:"conditions,omitempty"`
}

Expand Down
20 changes: 20 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 35 additions & 6 deletions cmd/models-schema/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions controllers/openstackmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ func (r *OpenStackMachineReconciler) reconcileNormal(ctx context.Context, scope

if instanceStatus == nil {
v1beta1conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceDeletedReason, clusterv1beta1.ConditionSeverityError, infrav1.ServerUnexpectedDeletedMessage)
v1beta1conditions.MarkFalse(openStackMachine, clusterv1beta1.ReadyCondition, infrav1.InstanceDeletedReason, clusterv1beta1.ConditionSeverityError, infrav1.ServerUnexpectedDeletedMessage)
openStackMachine.SetFailure(capoerrors.DeprecatedCAPIUpdateMachineError, errors.New(infrav1.ServerUnexpectedDeletedMessage)) //nolint:staticcheck // This error is not used as an error
return ctrl.Result{}, nil
}
Expand Down Expand Up @@ -437,6 +438,22 @@ func (r *OpenStackMachineReconciler) reconcileMachineState(scope *scope.WithLogg
openStackMachine.Spec.ProviderID = ptr.To(fmt.Sprintf("openstack://%s/%s", region, *openStackServer.Status.InstanceID))
openStackMachine.Status.InstanceID = openStackServer.Status.InstanceID
openStackMachine.Status.Ready = true

// Set initialization.provisioned to true when initial infrastructure provisioning is complete.
// This field should only be set once and never changed afterward, as per CAPI v1beta2 contract.
// We set it here when the machine becomes ACTIVE for the first time.
if openStackMachine.Status.Initialization == nil {
openStackMachine.Status.Initialization = &infrav1.MachineInitialization{}
}
if !openStackMachine.Status.Initialization.Provisioned {
openStackMachine.Status.Initialization.Provisioned = true
scope.Logger().Info("Initial machine infrastructure provisioning completed")
}

// Set the Ready condition to True when infrastructure is ready.
// This condition surfaces into Machine's status.conditions[InfrastructureReady].
// It reflects the current operational state of the machine infrastructure.
v1beta1conditions.MarkTrue(openStackMachine, clusterv1beta1.ReadyCondition)
case infrav1.InstanceStateError:
// If the machine has a NodeRef then it must have been working at some point,
// so the error could be something temporary.
Expand All @@ -447,20 +464,24 @@ func (r *OpenStackMachineReconciler) reconcileMachineState(scope *scope.WithLogg
openStackMachine.SetFailure(capoerrors.DeprecatedCAPIUpdateMachineError, err)
}
v1beta1conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceStateErrorReason, clusterv1beta1.ConditionSeverityError, "")
v1beta1conditions.MarkFalse(openStackMachine, clusterv1beta1.ReadyCondition, infrav1.InstanceStateErrorReason, clusterv1beta1.ConditionSeverityError, "Instance is in ERROR state")
return &ctrl.Result{}
case infrav1.InstanceStateDeleted:
// we should avoid further actions for DELETED VM
scope.Logger().Info("Machine instance state is DELETED, no actions")
v1beta1conditions.MarkFalse(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceDeletedReason, clusterv1beta1.ConditionSeverityError, "")
v1beta1conditions.MarkFalse(openStackMachine, clusterv1beta1.ReadyCondition, infrav1.InstanceDeletedReason, clusterv1beta1.ConditionSeverityError, "Instance has been deleted")
return &ctrl.Result{}
case infrav1.InstanceStateBuild, infrav1.InstanceStateUndefined:
scope.Logger().Info("Waiting for instance to become ACTIVE", "id", openStackServer.Status.InstanceID, "status", openStackServer.Status.InstanceState)
v1beta1conditions.MarkFalse(openStackMachine, clusterv1beta1.ReadyCondition, infrav1.InstanceNotReadyReason, clusterv1beta1.ConditionSeverityInfo, "Instance is building")
return &ctrl.Result{RequeueAfter: waitForBuildingInstanceToReconcile}
default:
// The other state is normal (for example, migrating, shutoff) but we don't want to proceed until it's ACTIVE
// due to potential conflict or unexpected actions
scope.Logger().Info("Waiting for instance to become ACTIVE", "id", openStackServer.Status.InstanceID, "status", openStackServer.Status.InstanceState)
v1beta1conditions.MarkUnknown(openStackMachine, infrav1.InstanceReadyCondition, infrav1.InstanceNotReadyReason, "Instance state is not handled: %v", ptr.Deref(openStackServer.Status.InstanceState, infrav1.InstanceStateUndefined))
v1beta1conditions.MarkUnknown(openStackMachine, clusterv1beta1.ReadyCondition, infrav1.InstanceNotReadyReason, "Instance state is: %v", ptr.Deref(openStackServer.Status.InstanceState, infrav1.InstanceStateUndefined))

return &ctrl.Result{RequeueAfter: waitForInstanceBecomeActiveToReconcile}
}
Expand Down
Loading