Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error handling #916

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mrkisaolamb
Copy link
Contributor

@mrkisaolamb mrkisaolamb commented Jan 10, 2025

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.

Resolve: https://issues.redhat.com/browse/OSPRH-9046

Copy link
Contributor

openshift-ci bot commented Jan 10, 2025

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

Copy link
Contributor

openshift-ci bot commented Jan 10, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mrkisaolamb

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@mrkisaolamb mrkisaolamb changed the title WIP error handling Improve error handling Jan 10, 2025
@mrkisaolamb mrkisaolamb marked this pull request as ready for review January 10, 2025 13:20
@mrkisaolamb mrkisaolamb requested review from gibizer and stuggi January 13, 2025 10:39
Copy link

Build failed (check pipeline). Post recheck (without leading slash)
to rerun all jobs. Make sure the failure cause has been resolved before
you rerun jobs.

https://softwarefactory-project.io/zuul/t/rdoproject.org/buildset/3d86a4af47ab4c45957184d8e9c14dde

✔️ openstack-meta-content-provider SUCCESS in 2h 40m 52s
nova-operator-kuttl RETRY_LIMIT in 30m 20s
✔️ nova-operator-tempest-multinode SUCCESS in 2h 05m 24s
✔️ nova-operator-tempest-multinode-ceph SUCCESS in 2h 23m 32s

instance.Status.Conditions.Set(condition.FalseCondition(
condition.NetworkAttachmentsReadyCondition,
condition.ErrorReason,
condition.SeverityWarning,
condition.NetworkAttachmentsReadyErrorMessage,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used in common.go ensureNetworkAttachments() as well, but you did not changed it there. Is it because there the message using an error coming from a call instead of defined locally?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes exactly that was the reasone

@@ -56,6 +56,9 @@ const (

// Common Messages used by API objects.
const (
//NovaNetworkAttachmentsReadyInitMessage
NovaNetworkAttachmentsReadyErrorMessage = "NetworkAttachments error occurred not all pods have interfaces with ips as configured in NetworkAttachments: %s"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes eventually we can move to lib-common all common errors

@@ -225,7 +223,10 @@ func ensureSecret(
for _, field := range expectedFields {
val, ok := secret.Data[field]
if !ok {
err := fmt.Errorf("field '%s' not found in secret/%s", field, secretName.Name)
// Usage in the code
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get this comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Comment on lines 228 to 229
// ensureSecret - ensures that the Secret object exists and the expected fields
// are in the Secret. It returns a hash of the values of the expected fields.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This belongs to the function definition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

@@ -579,7 +580,7 @@ func getNovaClient(
return nil, err
}
if (ctrlResult != ctrl.Result{}) {
return nil, fmt.Errorf("the CABundleSecret %s not found", auth.GetCABundleSecretName())
return nil, fmt.Errorf("the CABundleSecret %s not found: %w", auth.GetCABundleSecretName(), err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as far as I see err will be always nil here as if not then the previous condition is true and the function returns.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ou true so I create originall error that we lost during geting secret

@@ -225,7 +223,10 @@ func ensureSecret(
for _, field := range expectedFields {
val, ok := secret.Data[field]
if !ok {
err := fmt.Errorf("field '%s' not found in secret/%s", field, secretName.Name)
// Usage in the code
err := k8s_errors.NewBadRequest(fmt.Sprintf("field '%s' not found in secret/%s", field, secretName.Name))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we call ensureSecret from the validation webhook? As far as I remember we don't. So it is a bit strange to me to use HTTP response codes as errors here. I.e. the NewBadRequest creates a StatusError where the description says:

StatusError is an error intended for consumption by a REST API server; it can also be reconstructed by clients from a REST response. Public to allow easy type switches.

https://pkg.go.dev/k8s.io/apimachinery/pkg/api/errors#StatusError

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used error that I already created ErrFieldNotFound

@@ -641,7 +642,7 @@ func ensureMemcached(
condition.RequestedReason,
condition.SeverityInfo,
condition.MemcachedReadyWaitingMessage))
return nil, fmt.Errorf("memcached %s not found", memcachedName)
return nil, fmt.Errorf("%w: memcached %s not found", err, memcachedName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yepp this is a good improvement. Thanks.

@@ -1631,8 +1631,8 @@ func (r *NovaReconciler) ensureMQ(

url, ok := secret.Data[TransportURLSelector]
if !ok {
return "", nova.MQFailed, fmt.Errorf(
"the TransportURL secret %s does not have 'transport_url' field", transportURL.Status.SecretName)
return "", nova.MQFailed, k8s_errors.NewBadRequest(fmt.Sprintf(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto REST errors feels strange to me inside the reconciler loop

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor Author

@mrkisaolamb mrkisaolamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for review!

@@ -56,6 +56,9 @@ const (

// Common Messages used by API objects.
const (
//NovaNetworkAttachmentsReadyInitMessage
NovaNetworkAttachmentsReadyErrorMessage = "NetworkAttachments error occurred not all pods have interfaces with ips as configured in NetworkAttachments: %s"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes eventually we can move to lib-common all common errors

@@ -225,7 +223,10 @@ func ensureSecret(
for _, field := range expectedFields {
val, ok := secret.Data[field]
if !ok {
err := fmt.Errorf("field '%s' not found in secret/%s", field, secretName.Name)
// Usage in the code
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

@@ -225,7 +223,10 @@ func ensureSecret(
for _, field := range expectedFields {
val, ok := secret.Data[field]
if !ok {
err := fmt.Errorf("field '%s' not found in secret/%s", field, secretName.Name)
// Usage in the code
err := k8s_errors.NewBadRequest(fmt.Sprintf("field '%s' not found in secret/%s", field, secretName.Name))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used error that I already created ErrFieldNotFound

Comment on lines 228 to 229
// ensureSecret - ensures that the Secret object exists and the expected fields
// are in the Secret. It returns a hash of the values of the expected fields.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

@@ -579,7 +580,7 @@ func getNovaClient(
return nil, err
}
if (ctrlResult != ctrl.Result{}) {
return nil, fmt.Errorf("the CABundleSecret %s not found", auth.GetCABundleSecretName())
return nil, fmt.Errorf("the CABundleSecret %s not found: %w", auth.GetCABundleSecretName(), err)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ou true so I create originall error that we lost during geting secret

@@ -1631,8 +1631,8 @@ func (r *NovaReconciler) ensureMQ(

url, ok := secret.Data[TransportURLSelector]
if !ok {
return "", nova.MQFailed, fmt.Errorf(
"the TransportURL secret %s does not have 'transport_url' field", transportURL.Status.SecretName)
return "", nova.MQFailed, k8s_errors.NewBadRequest(fmt.Sprintf(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

instance.Status.Conditions.Set(condition.FalseCondition(
condition.NetworkAttachmentsReadyCondition,
condition.ErrorReason,
condition.SeverityWarning,
condition.NetworkAttachmentsReadyErrorMessage,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes exactly that was the reasone

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.
Copy link

Build failed (check pipeline). Post recheck (without leading slash)
to rerun all jobs. Make sure the failure cause has been resolved before
you rerun jobs.

https://softwarefactory-project.io/zuul/t/rdoproject.org/buildset/d46f9fd903354941affead375c45cedb

✔️ openstack-meta-content-provider SUCCESS in 5h 42m 59s
nova-operator-kuttl FAILURE in 34m 33s
✔️ nova-operator-tempest-multinode SUCCESS in 2h 16m 22s
✔️ nova-operator-tempest-multinode-ceph SUCCESS in 2h 54m 10s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants