Skip to content

Commit 05ccd22

Browse files
committed
Improve error handling
To follow best practices for error and exception handling in Go and to prevent regressions, err113 and gosec checks in golang-ci-linter are now enabled. Errors now use API errors from k8s.io/apimachinery and predefined messages for status updates.
1 parent e5a56f9 commit 05ccd22

14 files changed

+54
-38
lines changed

.golangci.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@ linters:
77
- ginkgolinter
88
- gofmt
99
- govet
10+
- gosec
11+
- errname
12+
- err113
1013
run:
1114
timeout: 5m

api/v1beta1/conditions.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ const (
5656

5757
// Common Messages used by API objects.
5858
const (
59+
//NovaNetworkAttachmentsReadyInitMessage
60+
NovaNetworkAttachmentsReadyErrorMessage = "NetworkAttachments error occurred not all pods have interfaces with ips as configured in NetworkAttachments: %s"
61+
5962
// NovaAPIReadyInitMessage
6063
NovaAPIReadyInitMessage = "NovaAPI not started"
6164

@@ -172,4 +175,7 @@ const (
172175

173176
//CellHostDiscoverErrorMessage
174177
CellHostDiscoverErrorMessage = "CellHostDiscover error occurred %s"
178+
179+
//InputReadyErrorMessage
180+
InputReadyErrorMessage = "Input data error occurred %s"
175181
)

controllers/common.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ const (
9595

9696
// fields to index to reconcile when change
9797
passwordSecretField = ".spec.secret"
98-
caBundleSecretNameField = ".spec.tls.caBundleSecretName"
98+
caBundleSecretNameField = ".spec.tls.caBundleSecretName" // #nosec G101
9999
tlsAPIInternalField = ".spec.tls.api.internal.secretName"
100100
tlsAPIPublicField = ".spec.tls.api.public.secretName"
101101
tlsMetadataField = ".spec.tls.secretName"
@@ -186,8 +186,6 @@ type conditionUpdater interface {
186186
MarkTrue(t condition.Type, messageFormat string, messageArgs ...interface{})
187187
}
188188

189-
// ensureSecret - ensures that the Secret object exists and the expected fields
190-
// are in the Secret. It returns a hash of the values of the expected fields.
191189
func ensureSecret(
192190
ctx context.Context,
193191
secretName types.NamespacedName,
@@ -225,7 +223,10 @@ func ensureSecret(
225223
for _, field := range expectedFields {
226224
val, ok := secret.Data[field]
227225
if !ok {
228-
err := fmt.Errorf("field '%s' not found in secret/%s", field, secretName.Name)
226+
// Usage in the code
227+
err := k8s_errors.NewBadRequest(fmt.Sprintf("field '%s' not found in secret/%s", field, secretName.Name))
228+
// ensureSecret - ensures that the Secret object exists and the expected fields
229+
// are in the Secret. It returns a hash of the values of the expected fields.
229230
conditionUpdater.Set(condition.FalseCondition(
230231
condition.InputReadyCondition,
231232
condition.ErrorReason,
@@ -579,7 +580,7 @@ func getNovaClient(
579580
return nil, err
580581
}
581582
if (ctrlResult != ctrl.Result{}) {
582-
return nil, fmt.Errorf("the CABundleSecret %s not found", auth.GetCABundleSecretName())
583+
return nil, fmt.Errorf("the CABundleSecret %s not found: %w", auth.GetCABundleSecretName(), err)
583584
}
584585

585586
tlsConfig = &openstack.TLSConfig{
@@ -641,7 +642,7 @@ func ensureMemcached(
641642
condition.RequestedReason,
642643
condition.SeverityInfo,
643644
condition.MemcachedReadyWaitingMessage))
644-
return nil, fmt.Errorf("memcached %s not found", memcachedName)
645+
return nil, fmt.Errorf("%w: memcached %s not found", err, memcachedName)
645646
}
646647
conditionUpdater.Set(condition.FalseCondition(
647648
condition.MemcachedReadyCondition,
@@ -658,7 +659,7 @@ func ensureMemcached(
658659
condition.RequestedReason,
659660
condition.SeverityInfo,
660661
condition.MemcachedReadyWaitingMessage))
661-
return nil, fmt.Errorf("memcached %s is not ready", memcachedName)
662+
return nil, fmt.Errorf("%w: memcached %s is not ready", ErrResourceIsNotReady, memcachedName)
662663
}
663664
conditionUpdater.MarkTrue(condition.MemcachedReadyCondition, condition.MemcachedReadyMessage)
664665

controllers/errors.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package controllers
2+
3+
import (
4+
"errors"
5+
)
6+
7+
var (
8+
ErrResourceIsNotReady = errors.New("Resource is not ready")
9+
ErrInvalidStatus = errors.New("invalid status")
10+
ErrCannotUpdateObject = errors.New("cannot update object")
11+
ErrFieldNotFound = errors.New("field not found in Secret")
12+
)

controllers/nova_controller.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul
302302
case nova.DBCompleted:
303303
instance.Status.Conditions.MarkTrue(novav1.NovaAPIDBReadyCondition, condition.DBReadyMessage)
304304
default:
305-
return ctrl.Result{}, fmt.Errorf("invalid DatabaseStatus from ensureAPIDB: %d", apiDBStatus)
305+
return ctrl.Result{}, fmt.Errorf("%w from ensureAPIDB: %d", ErrInvalidStatus, apiDBStatus)
306306
}
307307

308308
// We need to create a list of cellNames to iterate on and as the map
@@ -332,7 +332,7 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul
332332
creatingDBs = append(creatingDBs, cellName)
333333
case nova.DBCompleted:
334334
default:
335-
return ctrl.Result{}, fmt.Errorf("invalid DatabaseStatus from ensureCellDB: %d for cell %s", status, cellName)
335+
return ctrl.Result{}, fmt.Errorf("%w from ensureCellDB: %d for cell %s", ErrInvalidStatus, status, cellName)
336336
}
337337
cellDBs[cellName] = &nova.Database{Database: cellDB, Status: status}
338338
}
@@ -380,7 +380,7 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul
380380
instance.Status.Conditions.MarkTrue(
381381
novav1.NovaAPIMQReadyCondition, novav1.NovaAPIMQReadyMessage)
382382
default:
383-
return ctrl.Result{}, fmt.Errorf("invalid MessageBusStatus from for the API MQ: %d", apiMQStatus)
383+
return ctrl.Result{}, fmt.Errorf("%w from for the API MQ: %d", ErrInvalidStatus, apiMQStatus)
384384
}
385385

386386
cellMQs := map[string]*nova.MessageBus{}
@@ -408,7 +408,7 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul
408408
creatingMQs = append(creatingMQs, cellName)
409409
case nova.MQCompleted:
410410
default:
411-
return ctrl.Result{}, fmt.Errorf("invalid MessageBusStatus from ensureMQ: %d for cell %s", status, cellName)
411+
return ctrl.Result{}, fmt.Errorf("%w from ensureMQ: %d for cell %s", ErrInvalidStatus, status, cellName)
412412
}
413413
cellMQs[cellName] = &nova.MessageBus{TransportURL: cellTransportURL, Status: status}
414414
}
@@ -1631,8 +1631,8 @@ func (r *NovaReconciler) ensureMQ(
16311631

16321632
url, ok := secret.Data[TransportURLSelector]
16331633
if !ok {
1634-
return "", nova.MQFailed, fmt.Errorf(
1635-
"the TransportURL secret %s does not have 'transport_url' field", transportURL.Status.SecretName)
1634+
return "", nova.MQFailed, k8s_errors.NewBadRequest(fmt.Sprintf(
1635+
"the TransportURL secret %s does not have 'transport_url' field", transportURL.Status.SecretName))
16361636
}
16371637

16381638
return string(url), nova.MQCompleted, nil
@@ -1673,7 +1673,7 @@ func (r *NovaReconciler) ensureMetadata(
16731673
// If it is not created by us, we don't touch it
16741674
if !k8s_errors.IsNotFound(err) && !OwnedBy(metadata, instance) {
16751675
err := fmt.Errorf(
1676-
"cannot update NovaMetadata/%s as the cell is not owning it", metadata.Name)
1676+
"%w NovaMetadata/%s as the cell is not owning it", ErrCannotUpdateObject, metadata.Name)
16771677
Log.Error(err,
16781678
"NovaMetadata is enabled, but there is a "+
16791679
"NovaMetadata CR not owned by us. We cannot update it. "+

controllers/novaapi_controller.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -588,13 +588,12 @@ func (r *NovaAPIReconciler) ensureDeployment(
588588
if networkReady {
589589
instance.Status.Conditions.MarkTrue(condition.NetworkAttachmentsReadyCondition, condition.NetworkAttachmentsReadyMessage)
590590
} else {
591-
err := fmt.Errorf("not all pods have interfaces with ips as configured in NetworkAttachments: %s", instance.Spec.NetworkAttachments)
592591
instance.Status.Conditions.Set(condition.FalseCondition(
593592
condition.NetworkAttachmentsReadyCondition,
594593
condition.ErrorReason,
595594
condition.SeverityWarning,
596-
condition.NetworkAttachmentsReadyErrorMessage,
597-
err.Error()))
595+
novav1.NovaNetworkAttachmentsReadyErrorMessage,
596+
instance.Spec.NetworkAttachments))
598597

599598
return ctrl.Result{}, err
600599
}

controllers/novacell_controller.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ func (r *NovaCellReconciler) ensureNoVNCProxy(
426426
// If it is not created by us, we don't touch it
427427
if !k8s_errors.IsNotFound(err) && !OwnedBy(novncproxy, instance) {
428428
err := fmt.Errorf(
429-
"cannot update NovaNoVNCProxy/%s as the cell is not owning it", novncproxyName.Name)
429+
"%w NovaNoVNCProxy/%s as the cell is not owning it", ErrCannotUpdateObject, novncproxyName.Name)
430430
Log.Error(err,
431431
"NovaNoVNCProxy is enabled in this cell, but there is a "+
432432
"NovaNoVNCProxy CR not owned by the cell. We cannot update it. "+
@@ -548,7 +548,7 @@ func (r *NovaCellReconciler) ensureMetadata(
548548
// If it is not created by us, we don't touch it
549549
if !k8s_errors.IsNotFound(err) && !OwnedBy(metadata, instance) {
550550
err := fmt.Errorf(
551-
"cannot update NovaMetadata/%s as the cell is not owning it", metadata.Name)
551+
"%w NovaMetadata/%s as the cell is not owning it", ErrCannotUpdateObject, metadata.Name)
552552
Log.Error(err,
553553
"NovaMetadata is enabled, but there is a "+
554554
"NovaMetadata CR not owned by us. We cannot update it. "+
@@ -708,7 +708,7 @@ func (r *NovaCellReconciler) ensureNovaCompute(
708708
// If it is not created by us, we don't touch it
709709
if !k8s_errors.IsNotFound(err) && !OwnedBy(novacompute, instance) {
710710
err := fmt.Errorf(
711-
"cannot update NovaCompute/%s as the cell is not owning it", novacompute.Name)
711+
"%w NovaCompute/%s as the cell is not owning it", ErrCannotUpdateObject, novacompute.Name)
712712
Log.Error(err,
713713
"NovaCompute is defined in the cell, but there is a "+
714714
"NovaCompute CR not owned by us. We cannot update it. "+

controllers/novacompute_controller.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,13 +403,12 @@ func (r *NovaComputeReconciler) ensureDeployment(
403403
if networkReady {
404404
instance.Status.Conditions.MarkTrue(condition.NetworkAttachmentsReadyCondition, condition.NetworkAttachmentsReadyMessage)
405405
} else {
406-
err := fmt.Errorf("not all pods have interfaces with ips as configured in NetworkAttachments: %s", instance.Spec.NetworkAttachments)
407406
instance.Status.Conditions.Set(condition.FalseCondition(
408407
condition.NetworkAttachmentsReadyCondition,
409408
condition.ErrorReason,
410409
condition.SeverityWarning,
411-
condition.NetworkAttachmentsReadyErrorMessage,
412-
err.Error()))
410+
novav1.NovaNetworkAttachmentsReadyErrorMessage,
411+
instance.Spec.NetworkAttachments))
413412

414413
return ctrl.Result{}, err
415414
}

controllers/novaconductor_controller.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -560,13 +560,12 @@ func (r *NovaConductorReconciler) ensureDeployment(
560560
if networkReady {
561561
instance.Status.Conditions.MarkTrue(condition.NetworkAttachmentsReadyCondition, condition.NetworkAttachmentsReadyMessage)
562562
} else {
563-
err := fmt.Errorf("not all pods have interfaces with ips as configured in NetworkAttachments: %s", instance.Spec.NetworkAttachments)
564563
instance.Status.Conditions.Set(condition.FalseCondition(
565564
condition.NetworkAttachmentsReadyCondition,
566565
condition.ErrorReason,
567566
condition.SeverityWarning,
568-
condition.NetworkAttachmentsReadyErrorMessage,
569-
err.Error()))
567+
novav1.NovaNetworkAttachmentsReadyErrorMessage,
568+
instance.Spec.NetworkAttachments))
570569

571570
return ctrl.Result{}, err
572571
}

controllers/novametadata_controller.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -598,13 +598,12 @@ func (r *NovaMetadataReconciler) ensureDeployment(
598598
if networkReady {
599599
instance.Status.Conditions.MarkTrue(condition.NetworkAttachmentsReadyCondition, condition.NetworkAttachmentsReadyMessage)
600600
} else {
601-
err := fmt.Errorf("not all pods have interfaces with ips as configured in NetworkAttachments: %s", instance.Spec.NetworkAttachments)
602601
instance.Status.Conditions.Set(condition.FalseCondition(
603602
condition.NetworkAttachmentsReadyCondition,
604603
condition.ErrorReason,
605604
condition.SeverityWarning,
606-
condition.NetworkAttachmentsReadyErrorMessage,
607-
err.Error()))
605+
novav1.NovaNetworkAttachmentsReadyErrorMessage,
606+
instance.Spec.NetworkAttachments))
608607

609608
return ctrl.Result{}, err
610609
}

controllers/novanovncproxy_controller.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -546,13 +546,12 @@ func (r *NovaNoVNCProxyReconciler) ensureDeployment(
546546
if networkReady {
547547
instance.Status.Conditions.MarkTrue(condition.NetworkAttachmentsReadyCondition, condition.NetworkAttachmentsReadyMessage)
548548
} else {
549-
err := fmt.Errorf("not all pods have interfaces with ips as configured in NetworkAttachments: %s", instance.Spec.NetworkAttachments)
550549
instance.Status.Conditions.Set(condition.FalseCondition(
551550
condition.NetworkAttachmentsReadyCondition,
552551
condition.ErrorReason,
553552
condition.SeverityWarning,
554-
condition.NetworkAttachmentsReadyErrorMessage,
555-
err.Error()))
553+
novav1.NovaNetworkAttachmentsReadyErrorMessage,
554+
instance.Spec.NetworkAttachments))
556555

557556
return ctrl.Result{}, err
558557
}

controllers/novascheduler_controller.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -613,13 +613,12 @@ func (r *NovaSchedulerReconciler) ensureDeployment(
613613
if networkReady {
614614
instance.Status.Conditions.MarkTrue(condition.NetworkAttachmentsReadyCondition, condition.NetworkAttachmentsReadyMessage)
615615
} else {
616-
err := fmt.Errorf("not all pods have interfaces with ips as configured in NetworkAttachments: %s", instance.Spec.NetworkAttachments)
617616
instance.Status.Conditions.Set(condition.FalseCondition(
618617
condition.NetworkAttachmentsReadyCondition,
619618
condition.ErrorReason,
620619
condition.SeverityWarning,
621-
condition.NetworkAttachmentsReadyErrorMessage,
622-
err.Error()))
620+
novav1.NovaNetworkAttachmentsReadyErrorMessage,
621+
instance.Spec.NetworkAttachments))
623622

624623
return ctrl.Result{}, err
625624
}

test/functional/novacell_controller_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ var _ = Describe("NovaCell controller", func() {
696696
corev1.ConditionFalse,
697697
condition.ErrorReason,
698698
fmt.Sprintf(
699-
"NovaNoVNCProxy error occurred cannot update "+
699+
"NovaNoVNCProxy error occurred cannot update object "+
700700
"NovaNoVNCProxy/%s as the cell is not owning it",
701701
cell2.NoVNCProxyName.Name,
702702
),
@@ -833,7 +833,7 @@ var _ = Describe("NovaCell controller", func() {
833833
corev1.ConditionFalse,
834834
condition.ErrorReason,
835835
fmt.Sprintf(
836-
"NovaMetadata error occurred cannot update "+
836+
"NovaMetadata error occurred cannot update object "+
837837
"NovaMetadata/%s as the cell is not owning it",
838838
cell2.MetadataName.Name,
839839
),

test/functional/suite_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ var _ = BeforeSuite(func() {
244244
dialer := &net.Dialer{Timeout: time.Duration(10) * time.Second}
245245
addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort)
246246
Eventually(func() error {
247-
conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true})
247+
conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true}) // #nosec G402
248248
if err != nil {
249249
return err
250250
}

0 commit comments

Comments
 (0)