Skip to content

Commit 63f3e69

Browse files
authored
[release-v1.16] Catch-up with upstream (#1211)
* Improve CM Cert reconcile and deletion if feature is turned off (knative#8519) refactor CM Cert reconciler and take care of delete if feature is disabled Signed-off-by: Matthias Wessendorf <[email protected]> * Propagate Cert-Manager Certificate status to the one from the IntegrationSink (knative#8527) * Propagate Cert-Manager Certificate status to the one from the IntegrationSink Signed-off-by: Matthias Wessendorf <[email protected]> * Remove cert from top level condition set Signed-off-by: Matthias Wessendorf <[email protected]> --------- Signed-off-by: Matthias Wessendorf <[email protected]> * Fix one more dep Signed-off-by: Matthias Wessendorf <[email protected]> --------- Signed-off-by: Matthias Wessendorf <[email protected]>
1 parent 926fbe0 commit 63f3e69

File tree

3 files changed

+154
-30
lines changed

3 files changed

+154
-30
lines changed

pkg/apis/sinks/v1alpha1/integration_sink_lifecycle.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package v1alpha1
1818

1919
import (
20+
cmv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
21+
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
2022
appsv1 "k8s.io/api/apps/v1"
2123
corev1 "k8s.io/api/core/v1"
2224
"knative.dev/pkg/apis"
@@ -35,6 +37,12 @@ const (
3537
// IntegrationSinkConditionEventPoliciesReady has status True when all the applying EventPolicies for this
3638
// IntegrationSink are ready.
3739
IntegrationSinkConditionEventPoliciesReady apis.ConditionType = "EventPoliciesReady"
40+
41+
// IntegrationSinkConditionCertificateReady has status True when the IntegrationSink's certificate is ready.
42+
IntegrationSinkConditionCertificateReady apis.ConditionType = "CertificateReady"
43+
44+
// Certificate related condition reasons
45+
IntegrationSinkCertificateNotReady string = "CertificateNotReady"
3846
)
3947

4048
var IntegrationSinkCondSet = apis.NewLivingConditionSet(
@@ -112,6 +120,37 @@ func (s *IntegrationSinkStatus) PropagateDeploymentStatus(d *appsv1.DeploymentSt
112120
}
113121
}
114122

123+
func (s *IntegrationSinkStatus) PropagateCertificateStatus(cs cmv1.CertificateStatus) bool {
124+
var topLevel *cmv1.CertificateCondition
125+
for _, cond := range cs.Conditions {
126+
if cond.Type == cmv1.CertificateConditionReady {
127+
topLevel = &cond
128+
break
129+
}
130+
}
131+
132+
if topLevel == nil {
133+
IntegrationSinkCondSet.Manage(s).MarkUnknown(IntegrationSinkConditionCertificateReady,
134+
IntegrationSinkCertificateNotReady, "Certificate is progressing")
135+
return false
136+
}
137+
138+
if topLevel.Status == cmmeta.ConditionUnknown {
139+
IntegrationSinkCondSet.Manage(s).MarkUnknown(IntegrationSinkConditionCertificateReady,
140+
IntegrationSinkCertificateNotReady, "Certificate is progressing, "+topLevel.Reason+" Message: "+topLevel.Message)
141+
return false
142+
}
143+
144+
if topLevel.Status == cmmeta.ConditionFalse {
145+
IntegrationSinkCondSet.Manage(s).MarkFalse(IntegrationSinkConditionCertificateReady,
146+
IntegrationSinkCertificateNotReady, "Certificate is not ready, "+topLevel.Reason+" Message: "+topLevel.Message)
147+
return false
148+
}
149+
150+
IntegrationSinkCondSet.Manage(s).MarkTrue(IntegrationSinkConditionCertificateReady)
151+
return true
152+
}
153+
115154
func (s *IntegrationSinkStatus) SetAddress(address *duckv1.Addressable) {
116155
s.Address = address
117156
if address == nil || address.URL.IsEmpty() {

pkg/reconciler/integration/sink/integrationsink.go

Lines changed: 101 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const (
6363
deploymentUpdated = "DeploymentUpdated"
6464
serviceCreated = "ServiceCreated"
6565
certificateCreated = "CertificateCreated"
66+
certificateUpdated = "CertificateUpdated"
6667
serviceUpdated = "ServiceUpdated"
6768
)
6869

@@ -87,31 +88,35 @@ func newReconciledNormal(namespace, name string) reconciler.Event {
8788

8889
func (r *Reconciler) ReconcileKind(ctx context.Context, sink *sinks.IntegrationSink) reconciler.Event {
8990
featureFlags := feature.FromContext(ctx)
91+
logger := logging.FromContext(ctx)
9092

91-
if featureFlags.IsPermissiveTransportEncryption() || featureFlags.IsStrictTransportEncryption() {
92-
_, err := r.reconcileCMCertificate(ctx, sink)
93-
if err != nil {
94-
logging.FromContext(ctx).Errorw("Error reconciling Certificate", zap.Error(err))
95-
return err
96-
}
93+
logger.Debugw("Reconciling IntegrationSink Certificate")
94+
_, err := r.reconcileIntegrationSinkCertificate(ctx, sink)
95+
if err != nil {
96+
logging.FromContext(ctx).Errorw("Error reconciling Certificate", zap.Error(err))
97+
return err
9798
}
9899

99-
_, err := r.reconcileDeployment(ctx, sink, featureFlags)
100+
logger.Debugw("Reconciling IntegrationSink Deployment")
101+
_, err = r.reconcileDeployment(ctx, sink, featureFlags)
100102
if err != nil {
101103
logging.FromContext(ctx).Errorw("Error reconciling Pod", zap.Error(err))
102104
return err
103105
}
104106

107+
logger.Debugw("Reconciling IntegrationSink Service")
105108
_, err = r.reconcileService(ctx, sink)
106109
if err != nil {
107110
logging.FromContext(ctx).Errorw("Error reconciling Service", zap.Error(err))
108111
return err
109112
}
110113

114+
logger.Debugw("Reconciling IntegrationSink address")
111115
if err := r.reconcileAddress(ctx, sink); err != nil {
112116
return fmt.Errorf("failed to reconcile address: %w", err)
113117
}
114118

119+
logger.Debugw("Updating IntegrationSink status with EventPolicies")
115120
err = auth.UpdateStatusWithEventPolicies(featureFlags, &sink.Status.AppliedEventPoliciesStatus, &sink.Status, r.eventPolicyLister, sinks.SchemeGroupVersion.WithKind("IntegrationSink"), sink.ObjectMeta)
116121
if err != nil {
117122
return fmt.Errorf("could not update IntegrationSink status with EventPolicies: %v", err)
@@ -171,34 +176,78 @@ func (r *Reconciler) reconcileService(ctx context.Context, sink *sinks.Integrati
171176
return svc, nil
172177
}
173178

174-
func (r *Reconciler) reconcileCMCertificate(ctx context.Context, sink *sinks.IntegrationSink) (*cmv1.Certificate, error) {
179+
func (r *Reconciler) reconcileIntegrationSinkCertificate(ctx context.Context, sink *sinks.IntegrationSink) (*cmv1.Certificate, error) {
180+
if f := feature.FromContext(ctx); !f.IsStrictTransportEncryption() && !f.IsPermissiveTransportEncryption() {
181+
return nil, r.deleteIntegrationSinkCertificate(ctx, sink)
182+
}
175183

176-
expected := certificates.MakeCertificate(sink, certificates.WithDNSNames(
177-
network.GetServiceHostname(resources.DeploymentName(sink.GetName()), sink.GetNamespace()),
178-
fmt.Sprintf("%s.%s.svc", resources.DeploymentName(sink.GetName()), sink.GetNamespace()),
179-
))
184+
expected := integrationSinkCertificate(sink)
180185

181-
lister := r.cmCertificateLister.Load()
182-
if lister == nil || *lister == nil {
186+
cmCertificateLister := r.cmCertificateLister.Load()
187+
if cmCertificateLister == nil || *cmCertificateLister == nil {
183188
return nil, fmt.Errorf("no cert-manager certificate lister created yet, this should rarely happen and recover")
184189
}
185190

186-
cert, err := (*lister).Certificates(sink.Namespace).Get(expected.Name)
191+
curr, err := (*cmCertificateLister).Certificates(expected.GetNamespace()).Get(expected.GetName())
187192
if apierrors.IsNotFound(err) {
188-
cert, err := r.certManagerClient.CertmanagerV1().Certificates(sink.Namespace).Create(ctx, expected, metav1.CreateOptions{})
193+
created, err := r.createCertificate(ctx, sink, expected)
189194
if err != nil {
190-
return nil, fmt.Errorf("creating new Certificate: %v", err)
195+
return nil, err
191196
}
192-
controller.GetEventRecorder(ctx).Eventf(sink, corev1.EventTypeNormal, certificateCreated, "Certificate created %q", cert.Name)
193-
} else if err != nil {
194-
return nil, fmt.Errorf("getting Certificate: %v", err)
195-
} else if !metav1.IsControlledBy(cert, sink) {
196-
return nil, fmt.Errorf("Certificate %q is not owned by IntegrationSink %q", cert.Name, sink.Name)
197-
} else {
198-
logging.FromContext(ctx).Debugw("Reusing existing Certificate", zap.Any("Certificate", cert))
197+
if !sink.Status.PropagateCertificateStatus(created.Status) {
198+
// Wait for Certificate to become ready before continuing.
199+
return nil, controller.NewSkipKey("")
200+
}
201+
return created, nil
202+
}
203+
if err != nil {
204+
return nil, fmt.Errorf("failed to get certificate %s/%s: %w", expected.GetNamespace(), expected.GetName(), err)
199205
}
200206

201-
return cert, nil
207+
if equality.Semantic.DeepDerivative(expected.Spec, curr.Spec) &&
208+
equality.Semantic.DeepDerivative(expected.Labels, curr.Labels) &&
209+
equality.Semantic.DeepDerivative(expected.Annotations, curr.Annotations) {
210+
if !sink.Status.PropagateCertificateStatus(curr.Status) {
211+
// Wait for Certificate to become ready before continuing.
212+
return nil, controller.NewSkipKey("")
213+
}
214+
return curr, nil
215+
}
216+
expected.ResourceVersion = curr.ResourceVersion
217+
updated, err := r.updateCertificate(ctx, sink, expected)
218+
if err != nil {
219+
return nil, err
220+
}
221+
if !sink.Status.PropagateCertificateStatus(updated.Status) {
222+
// Wait for Certificate to become ready before continuing.
223+
return nil, controller.NewSkipKey("")
224+
}
225+
return updated, nil
226+
}
227+
228+
func (r *Reconciler) deleteIntegrationSinkCertificate(ctx context.Context, sink *sinks.IntegrationSink) error {
229+
certificate := integrationSinkCertificate(sink)
230+
231+
cmCertificateLister := r.cmCertificateLister.Load()
232+
if cmCertificateLister != nil && *cmCertificateLister != nil {
233+
_, err := (*cmCertificateLister).Certificates(certificate.GetNamespace()).Get(certificate.GetName())
234+
if apierrors.IsNotFound(err) {
235+
return nil
236+
}
237+
if err != nil {
238+
return fmt.Errorf("failed to get certificate %s/%s: %w", certificate.GetNamespace(), certificate.GetName(), err)
239+
}
240+
}
241+
242+
err := r.certManagerClient.CertmanagerV1().Certificates(certificate.GetNamespace()).Delete(ctx, certificate.GetName(), metav1.DeleteOptions{})
243+
if apierrors.IsNotFound(err) {
244+
return nil
245+
}
246+
if err != nil {
247+
return fmt.Errorf("failed to delete certificate %s/%s: %w", certificate.GetNamespace(), certificate.GetName(), err)
248+
}
249+
controller.GetEventRecorder(ctx).Event(sink, corev1.EventTypeNormal, "IntegrationSinkCertificateDeleted", certificate.GetName())
250+
return nil
202251
}
203252

204253
func (r *Reconciler) reconcileAddress(ctx context.Context, sink *sinks.IntegrationSink) error {
@@ -303,3 +352,30 @@ func (r *Reconciler) podSpecChanged(oldPodSpec corev1.PodSpec, newPodSpec corev1
303352
}
304353
return false
305354
}
355+
356+
func integrationSinkCertificate(sink *sinks.IntegrationSink) *cmv1.Certificate {
357+
return certificates.MakeCertificate(sink,
358+
certificates.WithDNSNames(
359+
network.GetServiceHostname(resources.DeploymentName(sink.Name), sink.Namespace),
360+
fmt.Sprintf("%s.%s.svc", resources.DeploymentName(sink.Name), sink.Namespace),
361+
),
362+
)
363+
}
364+
365+
func (r *Reconciler) createCertificate(ctx context.Context, sink *sinks.IntegrationSink, expected *cmv1.Certificate) (*cmv1.Certificate, error) {
366+
created, err := r.certManagerClient.CertmanagerV1().Certificates(expected.GetNamespace()).Create(ctx, expected, metav1.CreateOptions{})
367+
if err != nil {
368+
return nil, fmt.Errorf("creating new Certificate %s/%s: %w", expected.GetNamespace(), expected.GetName(), err)
369+
}
370+
controller.GetEventRecorder(ctx).Eventf(sink, corev1.EventTypeNormal, certificateCreated, "Certificate created %q", expected.GetName())
371+
return created, nil
372+
}
373+
374+
func (r *Reconciler) updateCertificate(ctx context.Context, sink *sinks.IntegrationSink, expected *cmv1.Certificate) (*cmv1.Certificate, error) {
375+
updated, err := r.certManagerClient.CertmanagerV1().Certificates(expected.GetNamespace()).Update(ctx, expected, metav1.UpdateOptions{})
376+
if err != nil {
377+
return nil, fmt.Errorf("failed to update certificate %s/%s: %w", expected.GetNamespace(), expected.GetName(), err)
378+
}
379+
controller.GetEventRecorder(ctx).Event(sink, corev1.EventTypeNormal, certificateUpdated, expected.GetName())
380+
return updated, nil
381+
}

pkg/reconciler/integration/sink/integrationsink_test.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ package sink
1818

1919
import (
2020
"fmt"
21+
"sync/atomic"
22+
23+
cmlisters "github.com/cert-manager/cert-manager/pkg/client/listers/certmanager/v1"
2124

2225
"knative.dev/eventing/pkg/certificates"
2326

@@ -151,12 +154,18 @@ func TestReconcile(t *testing.T) {
151154
logger := logtesting.TestLogger(t)
152155
table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher) controller.Reconciler {
153156
ctx = addressable.WithDuck(ctx)
157+
158+
cmCertificatesListerAtomic := &atomic.Pointer[cmlisters.CertificateLister]{}
159+
cmCertificatesLister := listers.GetCertificateLister()
160+
cmCertificatesListerAtomic.Store(&cmCertificatesLister)
161+
154162
r := &Reconciler{
155-
kubeClientSet: fakekubeclient.Get(ctx),
156-
deploymentLister: listers.GetDeploymentLister(),
157-
serviceLister: listers.GetServiceLister(),
158-
secretLister: listers.GetSecretLister(),
159-
eventPolicyLister: listers.GetEventPolicyLister(),
163+
kubeClientSet: fakekubeclient.Get(ctx),
164+
deploymentLister: listers.GetDeploymentLister(),
165+
serviceLister: listers.GetServiceLister(),
166+
secretLister: listers.GetSecretLister(),
167+
cmCertificateLister: cmCertificatesListerAtomic,
168+
eventPolicyLister: listers.GetEventPolicyLister(),
160169
}
161170

162171
return integrationsink.NewReconciler(ctx, logging.FromContext(ctx), fakeeventingclient.Get(ctx), listers.GetIntegrationSinkLister(), controller.GetEventRecorder(ctx), r)

0 commit comments

Comments
 (0)