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

Certificate Status Monitor Refactor #4103

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

Conversation

ArrisLee
Copy link
Collaborator

Which issue this PR addresses:

https://issues.redhat.com/browse/ARO-13644

What this PR does / why we need it:

  • Resolve some logic bugs in the original code.
  • Improve the readability
  • Add more error handling and edge case checking

Test plan for issue:

  • Unit test
  • CI/CD

@ArrisLee
Copy link
Collaborator Author

/azp run ci

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@ArrisLee ArrisLee changed the base branch from master to yjst2012/hotfix-dns-renaming February 25, 2025 06:35
@ArrisLee ArrisLee changed the base branch from yjst2012/hotfix-dns-renaming to master February 25, 2025 06:36
@ArrisLee ArrisLee force-pushed the arris/refactor/certstatusmon branch from f2966e1 to 0453877 Compare February 25, 2025 07:00
@ArrisLee ArrisLee closed this Feb 25, 2025
@ArrisLee ArrisLee force-pushed the arris/refactor/certstatusmon branch from 2b0a9f9 to 796738b Compare February 25, 2025 07:14
@ArrisLee ArrisLee reopened this Feb 25, 2025
Copy link
Contributor

@kimorris27 kimorris27 left a comment

Choose a reason for hiding this comment

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

It's a good refactor overall! The changes I'm suggesting are mostly regarding readability and potential for further refactoring.

mon.emitGauge(secretMissingMetricName, 1, secretMissingMetric(operator.Namespace, operator.SecretName))
return nil
}
return fmt.Errorf("emitting MDSD certificate expiration metrics: %w", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO there's not a lot of value in "customizing" the error messages throughout these functions by wrapping the underlying err in a new call to fmt.Errorf. We can seek an opinion from another reviewer too.

Or do you have some experiences from on call that led you to make these types of changes?

}

if ic.Spec.DefaultCertificate == nil {
return fmt.Errorf("ingresscontroller spec invalid, unable to get default certificate name")
return fmt.Errorf("ingress controller spec invalid, default certificate name not found")
Copy link
Contributor

Choose a reason for hiding this comment

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

For clarity when visually parsing logs:

Suggested change
return fmt.Errorf("ingress controller spec invalid, default certificate name not found")
return fmt.Errorf("error: ingress controller spec invalid, default certificate name not found")

if err != nil {
return err
// Log the error and continue processing other secrets.
mon.log.Printf("warning: parsing certificate in secret %q: %v", secretName, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Using Warningf will ensure the log level is set in the way I assume you want it:

Suggested change
mon.log.Printf("warning: parsing certificate in secret %q: %v", secretName, err)
mon.log.Warningf("error parsing certificate in secret %q: %v", secretName, err)

continue
}
if len(certs) == 0 {
mon.log.Printf("warning: no certificates found in secret %q", secretName)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
mon.log.Printf("warning: no certificates found in secret %q", secretName)
mon.log.Warningf("no certificates found in secret %q", secretName)

}
certData, ok := secret.Data[secretKey]
if !ok {
return nil, fmt.Errorf("secret %q in namespace %q does not contain key %q", secretName, secretNamespace, secretKey)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return nil, fmt.Errorf("secret %q in namespace %q does not contain key %q", secretName, secretNamespace, secretKey)
return nil, fmt.Errorf(error: "secret %q in namespace %q does not contain key %q", secretName, secretNamespace, secretKey)

Comment on lines +77 to +83
// Build a set of secret names to process, avoid duplicate processing.
secretNames := map[string]struct{}{
ingressSecretName: {},
}
// Also process the API Server certificate variant if it differs.
apiserverSecretName := strings.Replace(ingressSecretName, "-ingress", "-apiserver", 1)
secretNames[apiserverSecretName] = struct{}{}
Copy link
Contributor

Choose a reason for hiding this comment

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

Aren't the names of the two secrets always different? In what situation would the previous code have processed duplicates?

Comment on lines +115 to 147
secretList, err := mon.cli.CoreV1().Secrets(etcdNamespace).List(ctx, metav1.ListOptions{
FieldSelector: fmt.Sprintf("type=%s", corev1.SecretTypeTLS),
})
if err != nil {
return err
return fmt.Errorf("listing secrets in %q: %w", etcdNamespace, err)
}

for _, secret := range secretList.Items {
// Parse secrets with name containing "etcd-peer", "etcd-serving", "etcd-serving-metrics"
if strings.Contains(secret.ObjectMeta.Name, "etcd-peer") || strings.Contains(secret.ObjectMeta.Name, "etcd-serving") {
_, certs, err := pem.Parse(secret.Data[corev1.TLSCertKey])
secretName := secret.ObjectMeta.Name
// Only process secrets with names indicating ETCD certificates.
if strings.Contains(secretName, "etcd-peer") || strings.Contains(secretName, "etcd-serving") {
certData, ok := secret.Data[corev1.TLSCertKey]
if !ok {
mon.emitGauge(secretMissingMetricName, 1, secretMissingMetric(etcdNamespace, secretName))
continue
}
_, certs, err := pem.Parse(certData)
if err != nil {
return err
// Log the error and continue processing other secrets.
mon.log.Printf("warning: parsing certificate in secret %q: %v", secretName, err)
continue
}
if len(certs) == 0 {
mon.log.Printf("warning: no certificates found in secret %q", secretName)
continue
}
mon.emitGauge(certificateExpirationMetricName, int64(utilcert.DaysUntilExpiration(certs[0])), map[string]string{
"namespace": "openshift-etcd",
"name": secret.GetObjectMeta().GetName(),
"namespace": etcdNamespace,
"name": secretName,
"subject": certs[0].Subject.CommonName,
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of listing the Secrets and then iterating over them and calling mon.emitGauge yourself, why not rework this to leverage the new utility function you added (processCertificate)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
skippy pull requests raised by member of Team Skippy
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants