Skip to content

Commit 43f4315

Browse files
authored
Merge pull request #893 from Nordix/add_failure_fileds
Add failure fields in OpestackCluster status section
2 parents c73f022 + ed64cb8 commit 43f4315

File tree

6 files changed

+125
-10
lines changed

6 files changed

+125
-10
lines changed

api/v1alpha3/conversion.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ func Convert_v1alpha4_OpenStackMachineSpec_To_v1alpha3_OpenStackMachineSpec(in *
131131
return autoConvert_v1alpha4_OpenStackMachineSpec_To_v1alpha3_OpenStackMachineSpec(in, out, s)
132132
}
133133

134+
// Convert_v1alpha4_OpenStackClusterStatus_To_v1alpha3_OpenStackClusterStatus has to be added
135+
// in order to drop the FailureReason and FailureMessage fields that are not present in v1alpha3.
136+
func Convert_v1alpha4_OpenStackClusterStatus_To_v1alpha3_OpenStackClusterStatus(in *v1alpha4.OpenStackClusterStatus, out *OpenStackClusterStatus, s conversion.Scope) error {
137+
return autoConvert_v1alpha4_OpenStackClusterStatus_To_v1alpha3_OpenStackClusterStatus(in, out, s)
138+
}
139+
134140
func Convert_Slice_v1alpha4_Network_To_Slice_v1alpha3_Network(in *[]v1alpha4.Network, out *[]Network, s conversion.Scope) error {
135141
for i := range *in {
136142
inNet := &(*in)[i]

api/v1alpha3/zz_generated.conversion.go

Lines changed: 7 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1alpha4/openstackcluster_types.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
corev1 "k8s.io/api/core/v1"
2121
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2222
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4"
23+
capierrors "sigs.k8s.io/cluster-api/errors"
2324
)
2425

2526
const (
@@ -133,6 +134,44 @@ type OpenStackClusterStatus struct {
133134
BastionSecurityGroup *SecurityGroup `json:"bastionSecurityGroup,omitempty"`
134135

135136
Bastion *Instance `json:"bastion,omitempty"`
137+
138+
// FailureReason will be set in the event that there is a terminal problem
139+
// reconciling the OpenStackCluster and will contain a succinct value suitable
140+
// for machine interpretation.
141+
//
142+
// This field should not be set for transitive errors that a controller
143+
// faces that are expected to be fixed automatically over
144+
// time (like service outages), but instead indicate that something is
145+
// fundamentally wrong with the OpenStackCluster's spec or the configuration of
146+
// the controller, and that manual intervention is required. Examples
147+
// of terminal errors would be invalid combinations of settings in the
148+
// spec, values that are unsupported by the controller, or the
149+
// responsible controller itself being critically misconfigured.
150+
//
151+
// Any transient errors that occur during the reconciliation of
152+
// OpenStackClusters can be added as events to the OpenStackCluster object
153+
// and/or logged in the controller's output.
154+
// +optional
155+
FailureReason *capierrors.ClusterStatusError `json:"failureReason,omitempty"`
156+
157+
// FailureMessage will be set in the event that there is a terminal problem
158+
// reconciling the OpenStackCluster and will contain a more verbose string suitable
159+
// for logging and human consumption.
160+
//
161+
// This field should not be set for transitive errors that a controller
162+
// faces that are expected to be fixed automatically over
163+
// time (like service outages), but instead indicate that something is
164+
// fundamentally wrong with the OpenStackCluster's spec or the configuration of
165+
// the controller, and that manual intervention is required. Examples
166+
// of terminal errors would be invalid combinations of settings in the
167+
// spec, values that are unsupported by the controller, or the
168+
// responsible controller itself being critically misconfigured.
169+
//
170+
// Any transient errors that occur during the reconciliation of
171+
// OpenStackClusters can be added as events to the OpenStackCluster object
172+
// and/or logged in the controller's output.
173+
// +optional
174+
FailureMessage *string `json:"failureMessage,omitempty"`
136175
}
137176

138177
// +kubebuilder:object:root=true

api/v1alpha4/zz_generated.deepcopy.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,6 +2061,38 @@ spec:
20612061
type: object
20622062
description: FailureDomains represent OpenStack availability zones
20632063
type: object
2064+
failureMessage:
2065+
description: "FailureMessage will be set in the event that there is
2066+
a terminal problem reconciling the OpenStackCluster and will contain
2067+
a more verbose string suitable for logging and human consumption.
2068+
\n This field should not be set for transitive errors that a controller
2069+
faces that are expected to be fixed automatically over time (like
2070+
service outages), but instead indicate that something is fundamentally
2071+
wrong with the OpenStackCluster's spec or the configuration of the
2072+
controller, and that manual intervention is required. Examples of
2073+
terminal errors would be invalid combinations of settings in the
2074+
spec, values that are unsupported by the controller, or the responsible
2075+
controller itself being critically misconfigured. \n Any transient
2076+
errors that occur during the reconciliation of OpenStackClusters
2077+
can be added as events to the OpenStackCluster object and/or logged
2078+
in the controller's output."
2079+
type: string
2080+
failureReason:
2081+
description: "FailureReason will be set in the event that there is
2082+
a terminal problem reconciling the OpenStackCluster and will contain
2083+
a succinct value suitable for machine interpretation. \n This field
2084+
should not be set for transitive errors that a controller faces
2085+
that are expected to be fixed automatically over time (like service
2086+
outages), but instead indicate that something is fundamentally wrong
2087+
with the OpenStackCluster's spec or the configuration of the controller,
2088+
and that manual intervention is required. Examples of terminal errors
2089+
would be invalid combinations of settings in the spec, values that
2090+
are unsupported by the controller, or the responsible controller
2091+
itself being critically misconfigured. \n Any transient errors that
2092+
occur during the reconciliation of OpenStackClusters can be added
2093+
as events to the OpenStackCluster object and/or logged in the controller's
2094+
output."
2095+
type: string
20642096
network:
20652097
description: Network contains all information about the created OpenStack
20662098
Network. It includes Subnets and Router.

controllers/openstackcluster_controller.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ import (
2929
"github.com/pkg/errors"
3030
apierrors "k8s.io/apimachinery/pkg/api/errors"
3131
"k8s.io/client-go/tools/record"
32+
"k8s.io/utils/pointer"
3233
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4"
34+
capierrors "sigs.k8s.io/cluster-api/errors"
3335
"sigs.k8s.io/cluster-api/util"
3436
"sigs.k8s.io/cluster-api/util/annotations"
3537
"sigs.k8s.io/cluster-api/util/patch"
@@ -143,21 +145,25 @@ func reconcileDelete(ctx context.Context, log logr.Logger, client client.Client,
143145

144146
if openStackCluster.Spec.ManagedAPIServerLoadBalancer {
145147
if err = loadBalancerService.DeleteLoadBalancer(openStackCluster, clusterName); err != nil {
148+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to delete load balancer: %v", err))
146149
return reconcile.Result{}, errors.Errorf("failed to delete load balancer: %v", err)
147150
}
148151
}
149152

150153
if err = networkingService.DeleteSecurityGroups(openStackCluster, clusterName); err != nil {
154+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to delete security groups: %v", err))
151155
return reconcile.Result{}, errors.Errorf("failed to delete security groups: %v", err)
152156
}
153157

154158
// if NodeCIDR was not set, no network was created.
155159
if openStackCluster.Spec.NodeCIDR != "" {
156160
if err = networkingService.DeleteRouter(openStackCluster, clusterName); err != nil {
161+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to delete router: %v", err))
157162
return ctrl.Result{}, errors.Errorf("failed to delete router: %v", err)
158163
}
159164

160165
if err = networkingService.DeleteNetwork(openStackCluster, clusterName); err != nil {
166+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to delete network: %v", err))
161167
return ctrl.Result{}, errors.Errorf("failed to delete network: %v", err)
162168
}
163169
}
@@ -197,22 +203,26 @@ func deleteBastion(log logr.Logger, osProviderClient *gophercloud.ProviderClient
197203

198204
if instance != nil && instance.FloatingIP != "" {
199205
if err = networkingService.DisassociateFloatingIP(openStackCluster, instance.FloatingIP); err != nil {
206+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to disassociate floating IP: %v", err))
200207
return errors.Errorf("failed to disassociate floating IP: %v", err)
201208
}
202209
if err = networkingService.DeleteFloatingIP(openStackCluster, instance.FloatingIP); err != nil {
210+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to delete floating IP: %v", err))
203211
return errors.Errorf("failed to delete floating IP: %v", err)
204212
}
205213
}
206214

207215
if instance != nil && instance.Name != "" {
208216
if err = computeService.DeleteInstance(openStackCluster, instance.Name); err != nil {
217+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to delete bastion: %v", err))
209218
return errors.Errorf("failed to delete bastion: %v", err)
210219
}
211220
}
212221

213222
openStackCluster.Status.Bastion = nil
214223

215224
if err = networkingService.DeleteBastionSecurityGroup(openStackCluster, fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)); err != nil {
225+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to delete bastion security group: %v", err))
216226
return errors.Errorf("failed to delete bastion security group: %v", err)
217227
}
218228
openStackCluster.Status.BastionSecurityGroup = nil
@@ -307,6 +317,7 @@ func reconcileBastion(log logr.Logger, osProviderClient *gophercloud.ProviderCli
307317

308318
instance, err = computeService.CreateBastion(openStackCluster, cluster.Name)
309319
if err != nil {
320+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to reconcile bastion: %v", err))
310321
return errors.Errorf("failed to reconcile bastion: %v", err)
311322
}
312323

@@ -317,10 +328,12 @@ func reconcileBastion(log logr.Logger, osProviderClient *gophercloud.ProviderCli
317328
clusterName := fmt.Sprintf("%s-%s", cluster.Namespace, cluster.Name)
318329
fp, err := networkingService.GetOrCreateFloatingIP(openStackCluster, clusterName, openStackCluster.Spec.Bastion.Instance.FloatingIP)
319330
if err != nil {
331+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to get or create floating IP for bastion: %v", err))
320332
return errors.Errorf("failed to get or create floating IP for bastion: %v", err)
321333
}
322334
err = computeService.AssociateFloatingIP(instance.ID, fp.FloatingIP)
323335
if err != nil {
336+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to associate floating IP with bastion: %v", err))
324337
return errors.Errorf("failed to associate floating IP with bastion: %v", err)
325338
}
326339
instance.FloatingIP = fp.FloatingIP
@@ -345,6 +358,7 @@ func reconcileNetworkComponents(log logr.Logger, osProviderClient *gophercloud.P
345358

346359
err = networkingService.ReconcileExternalNetwork(openStackCluster)
347360
if err != nil {
361+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to reconcile external network: %v", err))
348362
return errors.Errorf("failed to reconcile external network: %v", err)
349363
}
350364

@@ -354,12 +368,15 @@ func reconcileNetworkComponents(log logr.Logger, osProviderClient *gophercloud.P
354368
netOpts := networks.ListOpts(openStackCluster.Spec.Network)
355369
networkList, err := networkingService.GetNetworksByFilter(&netOpts)
356370
if err != nil {
371+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to find network: %v", err))
357372
return errors.Errorf("failed to find network: %v", err)
358373
}
359374
if len(networkList) == 0 {
375+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to find any network: %v", err))
360376
return errors.Errorf("failed to find any network: %v", err)
361377
}
362378
if len(networkList) > 1 {
379+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to find only one network (result: %v): %v", networkList, err))
363380
return errors.Errorf("failed to find only one network (result: %v): %v", networkList, err)
364381
}
365382
openStackCluster.Status.Network = &infrav1.Network{
@@ -372,9 +389,11 @@ func reconcileNetworkComponents(log logr.Logger, osProviderClient *gophercloud.P
372389
subnetOpts.NetworkID = networkList[0].ID
373390
subnetList, err := networkingService.GetSubnetsByFilter(&subnetOpts)
374391
if err != nil || len(subnetList) == 0 {
392+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to find subnet: %v", err))
375393
return errors.Errorf("failed to find subnet: %v", err)
376394
}
377395
if len(subnetList) > 1 {
396+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to find only one subnet (result: %v): %v", subnetList, err))
378397
return errors.Errorf("failed to find only one subnet (result: %v): %v", subnetList, err)
379398
}
380399
openStackCluster.Status.Network.Subnet = &infrav1.Subnet{
@@ -386,14 +405,17 @@ func reconcileNetworkComponents(log logr.Logger, osProviderClient *gophercloud.P
386405
} else {
387406
err := networkingService.ReconcileNetwork(openStackCluster, clusterName)
388407
if err != nil {
408+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to reconcile network: %v", err))
389409
return errors.Errorf("failed to reconcile network: %v", err)
390410
}
391411
err = networkingService.ReconcileSubnet(openStackCluster, clusterName)
392412
if err != nil {
413+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to reconcile subnets: %v", err))
393414
return errors.Errorf("failed to reconcile subnets: %v", err)
394415
}
395416
err = networkingService.ReconcileRouter(openStackCluster, clusterName)
396417
if err != nil {
418+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to reconcile router: %v", err))
397419
return errors.Errorf("failed to reconcile router: %v", err)
398420
}
399421
}
@@ -406,6 +428,7 @@ func reconcileNetworkComponents(log logr.Logger, osProviderClient *gophercloud.P
406428
}
407429
fp, err := networkingService.GetOrCreateFloatingIP(openStackCluster, clusterName, openStackCluster.Spec.APIServerFloatingIP)
408430
if err != nil {
431+
handleUpdateOSCError(openStackCluster, errors.Errorf("Floating IP cannot be got or created: %v", err))
409432
return errors.Errorf("Floating IP cannot be got or created: %v", err)
410433
}
411434
// Set APIEndpoints so the Cluster API Cluster Controller can pull them
@@ -417,12 +440,14 @@ func reconcileNetworkComponents(log logr.Logger, osProviderClient *gophercloud.P
417440

418441
err = networkingService.ReconcileSecurityGroups(openStackCluster, clusterName)
419442
if err != nil {
443+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to reconcile security groups: %v", err))
420444
return errors.Errorf("failed to reconcile security groups: %v", err)
421445
}
422446

423447
if openStackCluster.Spec.ManagedAPIServerLoadBalancer {
424448
err = loadBalancerService.ReconcileLoadBalancer(openStackCluster, clusterName)
425449
if err != nil {
450+
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to reconcile load balancer: %v", err))
426451
return errors.Errorf("failed to reconcile load balancer: %v", err)
427452
}
428453
}
@@ -478,3 +503,9 @@ func (r *OpenStackClusterReconciler) SetupWithManager(ctx context.Context, mgr c
478503
WithEventFilter(predicates.ResourceIsNotExternallyManaged(ctrl.LoggerFrom(ctx))).
479504
Complete(r)
480505
}
506+
507+
func handleUpdateOSCError(openstackCluster *infrav1.OpenStackCluster, message error) {
508+
err := capierrors.UpdateClusterError
509+
openstackCluster.Status.FailureReason = &err
510+
openstackCluster.Status.FailureMessage = pointer.StringPtr(message.Error())
511+
}

0 commit comments

Comments
 (0)