Skip to content

Conversation

vrutkovs
Copy link
Member

@vrutkovs vrutkovs commented Aug 7, 2025

When secret/configmap is being updated, an event is being emitted. This event should include a more
specific reason why this resource was updated: content change, new annotation etc.

This ensures duplicate events are not being issued by the controller.

Testing this in openshift/cluster-kube-apiserver-operator#1894

@openshift-ci openshift-ci bot requested review from hexfusion and jsafrane August 7, 2025 06:45
Copy link
Contributor

openshift-ci bot commented Aug 7, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: vrutkovs
Once this PR has been reviewed and has the lgtm label, please assign jsafrane for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@vrutkovs vrutkovs force-pushed the certrotation-better-events branch 3 times, most recently from f4c5429 to 45778d8 Compare August 7, 2025 14:41
needsOwnerUpdate = ensureOwnerReference(&caBundleConfigMap.ObjectMeta, c.Owner)
updateRequired = ensureOwnerRefAndTLSAnnotationsForConfigMap(caBundleConfigMap, c.Owner, c.AdditionalAnnotations)
if updateRequired {
updateDetail = fmt.Sprintf("annotations set to %#v", c.AdditionalAnnotations)
Copy link
Contributor

Choose a reason for hiding this comment

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

What is only the owner was updated?

Copy link
Member Author

Choose a reason for hiding this comment

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

EnsureTLSMetadataUpdate was setting annotations, but it was unnecessarily setting needsMetadataUpdate and needsOwnerUpdate.

Copy link
Contributor

Choose a reason for hiding this comment

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

It reads like: if owner is updated or annotations are updated, event should say "annotations updated" (even if annotations were not updated).

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, I see. Okay, I'll issue "owner updated" and "annotations updated" separately

// Existing secret not found - no need to update metadata (will be done by needNewSigningCertKeyPair / NeedNewTargetCertKeyPair)
if len(secret.ResourceVersion) == 0 {
return false
func ensureOwnerRefAndTLSAnnotationsForConfigMap(configMap *corev1.ConfigMap, owner *metav1.OwnerReference, additionalAnnotations AdditionalAnnotations) string {
Copy link
Contributor

Choose a reason for hiding this comment

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

why not to have ensureOwnerRefAndTLSAnnotations((meta *metav1.ObjectMeta, owner *metav1.OwnerReference, additionalAnnotations AdditionalAnnotations) which could be used for both cm and secrets?

reason = fmt.Sprintf("signer update %s", signingCertKeyPairLocation)
}
c.EventRecorder.Eventf("CABundleUpdateRequired", "%q in %q requires a new cert: %s", c.Name, c.Namespace, reason)
updateDetail = fmt.Sprintf("content change: %s", reason)
Copy link
Contributor

Choose a reason for hiding this comment

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

mhm, will this remove the reason set inline 72 ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Reworked to make it append (adding a comma if necessary)

}

// run Update if metadata needs changing unless running in RefreshOnlyWhenExpired mode
updateDetail := ""
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: updateReason

Copy link
Member Author

Choose a reason for hiding this comment

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

updated


func ensureOwnerRefAndTLSAnnotations(secret *corev1.Secret, owner *metav1.OwnerReference, additionalAnnotations AdditionalAnnotations) bool {
needsMetadataUpdate := false
func ensureOwnerRefAndTLSAnnotationsForSecret(secret *corev1.Secret, owner *metav1.OwnerReference, additionalAnnotations AdditionalAnnotations) string {
Copy link
Contributor

Choose a reason for hiding this comment

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

change to ensureOwnerRefAndTLSAnnotations((meta *metav1.ObjectMeta, owner *metav1.OwnerReference, additionalAnnotations AdditionalAnnotations)

Copy link
Member Author

@vrutkovs vrutkovs Aug 13, 2025

Choose a reason for hiding this comment

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

Ah, I was not sure if setting annotations would stick. Unit tests show that it works

}

// run Update if metadata needs changing unless we're in RefreshOnlyWhenExpired mode
updateDetail := ""
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: updateReason

reason = "secret doesn't exist"
}
c.EventRecorder.Eventf("SignerUpdateRequired", "%q in %q requires a new signing cert/key pair: %v", c.Name, c.Namespace, reason)
updateDetail = fmt.Sprintf("signer update: %s", reason)
Copy link
Contributor

Choose a reason for hiding this comment

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

won't this remove the reason set in line 82?


if reason := c.CertCreator.NeedNewTargetCertKeyPair(targetCertKeyPairSecret, signingCertKeyPair, caBundleCerts, c.Refresh, c.RefreshOnlyWhenExpired, creationRequired); len(reason) > 0 {
c.EventRecorder.Eventf("TargetUpdateRequired", "%q in %q requires a new target cert/key pair: %v", c.Name, c.Namespace, reason)
updateDetail = fmt.Sprintf("content change: %s", reason)
Copy link
Contributor

Choose a reason for hiding this comment

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

same comment here.

@vrutkovs vrutkovs force-pushed the certrotation-better-events branch from 891c955 to f363b70 Compare August 13, 2025 11:07
@vrutkovs
Copy link
Member Author

Tested in openshift/cluster-kube-apiserver-operator#1894, see Loki output for example events

}
c.EventRecorder.Eventf("CABundleUpdateRequired", "%q in %q requires a new cert: %s", c.Name, c.Namespace, reason)
if len(updateReason) > 0 {
updateReason += ", "
Copy link
Contributor

Choose a reason for hiding this comment

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

mhm, how about using strings.Join(updateReasons, ", ") instead ?

}

// run Update if metadata needs changing unless running in RefreshOnlyWhenExpired mode
updateReason := ""
Copy link
Contributor

Choose a reason for hiding this comment

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

then this would become updateReasons := []string{}

}
needsMetadataUpdate := c.AdditionalAnnotations.EnsureTLSMetadataUpdate(&caBundleConfigMap.ObjectMeta)
updateRequired = needsOwnerUpdate || needsMetadataUpdate
updateReason = ensureOwnerRefAndTLSAnnotations(&caBundleConfigMap.ObjectMeta, c.Owner, c.AdditionalAnnotations)
Copy link
Contributor

Choose a reason for hiding this comment

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

then we would have to append here

if len(updateReason) > 0 {
updateReason += ", "
}
updateReason += fmt.Sprintf("content change: %s", reason)
Copy link
Contributor

Choose a reason for hiding this comment

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

and here

return nil, nil
}
resourcehelper.ReportUpdateEvent(c.EventRecorder, actualCABundleConfigMap, err)
resourcehelper.ReportUpdateEvent(c.EventRecorder, actualCABundleConfigMap, err, updateReason)
Copy link
Contributor

Choose a reason for hiding this comment

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

and here we could use strings.Join(updateReasons, ", ")

return nil, err
}
klog.V(2).Infof("Updated ca-bundle.crt configmap %s/%s with:\n%s", certs.CertificateBundleToString(updatedCerts), caBundleConfigMap.Namespace, caBundleConfigMap.Name)
klog.V(2).Infof("Updated ca-bundle.crt configmap %s/%s due to %s with:\n%s", caBundleConfigMap.Namespace, caBundleConfigMap.Name, updateReason, certs.CertificateBundleToString(updatedCerts))
Copy link
Contributor

Choose a reason for hiding this comment

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

strings.Join(updateReasons, ", ")


func ensureOwnerRefAndTLSAnnotations(secret *corev1.Secret, owner *metav1.OwnerReference, additionalAnnotations AdditionalAnnotations) bool {
needsMetadataUpdate := false
func ensureOwnerRefAndTLSAnnotations(meta *metav1.ObjectMeta, owner *metav1.OwnerReference, additionalAnnotations AdditionalAnnotations) string {
Copy link
Contributor

Choose a reason for hiding this comment

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

this could return []string

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea, this simplifies quite a few things (although its rare that an update changes both owners and annotations during normal update)

return additionalAnnotations.EnsureTLSMetadataUpdate(&secret.ObjectMeta) || needsMetadataUpdate
}

func ensureSecretTLSTypeSet(secret *corev1.Secret) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

not needed anymore ?

Copy link
Contributor

Choose a reason for hiding this comment

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

ping

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, no longer required. Last time we touched this was last year in 4.17, and now all new and upgraded clusters have secrets of the new type.

Copy link
Member Author

Choose a reason for hiding this comment

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

OKay, lets keep it. Since we now emit a more precise event message, we can also confirm this no longer happens

updateReason := ""
if !c.RefreshOnlyWhenExpired {
needsMetadataUpdate := ensureOwnerRefAndTLSAnnotations(signingCertKeyPairSecret, c.Owner, c.AdditionalAnnotations)
needsTypeChange := ensureSecretTLSTypeSet(signingCertKeyPairSecret)
Copy link
Contributor

Choose a reason for hiding this comment

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

not needed anymore ?

Copy link
Contributor

Choose a reason for hiding this comment

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

are we sure that all resources have been migrated?
maybe we should keep it for safety ?

updateReason := ""
if !c.RefreshOnlyWhenExpired {
needsMetadataUpdate := ensureOwnerRefAndTLSAnnotations(targetCertKeyPairSecret, c.Owner, c.AdditionalAnnotations)
needsTypeChange := ensureSecretTLSTypeSet(targetCertKeyPairSecret)
Copy link
Contributor

Choose a reason for hiding this comment

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

not needed anymore ?

@vrutkovs vrutkovs force-pushed the certrotation-better-events branch from f363b70 to d3b7cde Compare August 15, 2025 07:08
When secret/configmap is being update an event is being emitted. This event should include a more
specific reason why this resource was updated: content change, new annotation etc.

This ensures duplicate events are not being issued by the controller
@vrutkovs vrutkovs force-pushed the certrotation-better-events branch 2 times, most recently from d390383 to db1a930 Compare August 18, 2025 12:58
@vrutkovs vrutkovs force-pushed the certrotation-better-events branch from 70763c5 to 576d96f Compare August 20, 2025 12:16
Copy link
Contributor

openshift-ci bot commented Aug 20, 2025

@vrutkovs: all tests passed!

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Successfully merging this pull request may close these issues.

3 participants