@@ -20,6 +20,7 @@ import (
2020 "context"
2121 "fmt"
2222
23+ "go.miloapis.com/email-provider-resend/internal/emailprovider"
2324 notificationmiloapiscomv1alpha1 "go.miloapis.com/milo/pkg/apis/notification/v1alpha1"
2425 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2526
@@ -44,13 +45,15 @@ func buildContactNamespacedIndexKey(contactName, contactNamespace string) string
4445
4546// ContactReconciler reconciles a Contact object
4647type ContactController struct {
47- Client client.Client
48- Finalizers finalizer.Finalizers
48+ Client client.Client
49+ Finalizers finalizer.Finalizers
50+ EmailProvider emailprovider.Service
4951}
5052
5153// contactFinalizer is a finalizer for the Contact object
5254type contactFinalizer struct {
53- Client client.Client
55+ Client client.Client
56+ EmailProvider emailprovider.Service
5457}
5558
5659func (f * contactFinalizer ) Finalize (ctx context.Context , obj client.Object ) (finalizer.Result , error ) {
@@ -64,9 +67,20 @@ func (f *contactFinalizer) Finalize(ctx context.Context, obj client.Object) (fin
6467 return finalizer.Result {}, fmt .Errorf ("object is not a Contact" )
6568 }
6669
70+ // Delete Contact on email provider
71+ deleted , err := f .EmailProvider .DeleteContact (ctx , * contact )
72+ if err != nil && ! errors .IsNotFound (err ) {
73+ log .Error (err , "Failed to delete Contact on email provider" )
74+ return finalizer.Result {}, fmt .Errorf ("failed to delete Contact on email provider: %w" , err )
75+ }
76+ if err == nil && ! deleted .Deleted {
77+ log .Error (fmt .Errorf ("failed to delete Contact on email provider. Expected deleted to be true, got %t" , deleted .Deleted ), "Failed to delete Contact on email provider" )
78+ return finalizer.Result {}, fmt .Errorf ("failed to delete Contact on email provider. Expected deleted to be true, got %t" , deleted .Deleted )
79+ }
80+
6781 // Get associated ContactGroupMemberships to contact name
6882 contactGroupMemberships := & notificationmiloapiscomv1alpha1.ContactGroupMembershipList {}
69- err : = f .Client .List (ctx , contactGroupMemberships , client.MatchingFields {contactNamespacedIndexKey : buildContactNamespacedIndexKey (contact .Name , contact .Namespace )})
83+ err = f .Client .List (ctx , contactGroupMemberships , client.MatchingFields {contactNamespacedIndexKey : buildContactNamespacedIndexKey (contact .Name , contact .Namespace )})
7084 if err != nil {
7185 log .Error (err , "Failed to list ContactGroupMemberships" )
7286 return finalizer.Result {}, fmt .Errorf ("failed to list ContactGroupMemberships: %w" , err )
@@ -164,32 +178,59 @@ func (r *ContactController) Reconcile(ctx context.Context, req ctrl.Request) (ct
164178 switch {
165179 // First creation – condition not present yet
166180 case existingCond == nil :
181+ // Create Contact on email provider
182+ emailProviderContact , err := r .EmailProvider .CreateContactIdempotent (ctx , * contact )
183+ if err != nil {
184+ log .Error (err , "Failed to create Contact on email provider" )
185+ return ctrl.Result {}, fmt .Errorf ("failed to create Contact on email provider: %w" , err )
186+ }
187+ contact .Status .ProviderID = emailProviderContact .ContactId
188+
167189 log .Info ("Contact first creation" )
168190 meta .SetStatusCondition (& contact .Status .Conditions , metav1.Condition {
169191 Type : notificationmiloapiscomv1alpha1 .ContactReadyCondition ,
192+ Status : metav1 .ConditionFalse ,
193+ Reason : notificationmiloapiscomv1alpha1 .ContactCreatePendingReason ,
194+ Message : "Contact created. Waiting for email provider webhook confirmation" ,
195+ LastTransitionTime : metav1 .Now (),
196+ ObservedGeneration : contact .GetGeneration (),
197+ })
198+
199+ // Set ContactUpdatedCondition to true to indicate that the contact is ready to accept incoming updates
200+ meta .SetStatusCondition (& contact .Status .Conditions , metav1.Condition {
201+ Type : notificationmiloapiscomv1alpha1 .ContactUpdatedCondition ,
170202 Status : metav1 .ConditionTrue ,
171203 Reason : notificationmiloapiscomv1alpha1 .ContactCreatedReason ,
172- Message : "Contact created" ,
204+ Message : "Contact created. Contact is ready to accept incoming updates " ,
173205 LastTransitionTime : metav1 .Now (),
174206 ObservedGeneration : contact .GetGeneration (),
175207 })
176208
177209 // Update – generation changed since we last processed the object
178- case updatedCond == nil || updatedCond .ObservedGeneration != contact .GetGeneration ():
210+ case updatedCond != nil && updatedCond .ObservedGeneration != contact .GetGeneration ():
179211 log .Info ("Contact updated" )
212+
213+ // Update Contact on email provider
214+ emailProviderContact , err := r .EmailProvider .UpdateContactIdempotent (ctx , * contact )
215+ if err != nil {
216+ log .Error (err , "Failed to update Contact on email provider" )
217+ return ctrl.Result {}, fmt .Errorf ("failed to update Contact on email provider: %w" , err )
218+ }
219+ contact .Status .ProviderID = emailProviderContact .ContactId
220+
180221 // Update condition
181222 meta .SetStatusCondition (& contact .Status .Conditions , metav1.Condition {
182223 Type : notificationmiloapiscomv1alpha1 .ContactUpdatedCondition ,
183- Status : metav1 .ConditionTrue ,
184- Reason : notificationmiloapiscomv1alpha1 .ContactUpdatedReason ,
185- Message : "Contact updated" ,
224+ Status : metav1 .ConditionFalse ,
225+ Reason : notificationmiloapiscomv1alpha1 .ContactUpdatePendingReason ,
226+ Message : "Contact updated. Waiting for email provider webhook confirmation " ,
186227 LastTransitionTime : metav1 .Now (),
187228 ObservedGeneration : contact .GetGeneration (),
188229 })
189230
190231 // Get associated ContactGroupMemberships to contact
191232 contactGroupMemberships := & notificationmiloapiscomv1alpha1.ContactGroupMembershipList {}
192- err : = r .Client .List (ctx , contactGroupMemberships , client.MatchingFields {contactNamespacedIndexKey : buildContactNamespacedIndexKey (contact .Name , contact .Namespace )})
233+ err = r .Client .List (ctx , contactGroupMemberships , client.MatchingFields {contactNamespacedIndexKey : buildContactNamespacedIndexKey (contact .Name , contact .Namespace )})
193234 if err != nil {
194235 log .Error (err , "Failed to list ContactGroupMemberships" )
195236 return ctrl.Result {}, fmt .Errorf ("failed to list ContactGroupMemberships: %w" , err )
@@ -250,7 +291,9 @@ func (r *ContactController) SetupWithManager(mgr ctrl.Manager) error {
250291 // Register finalizer
251292 r .Finalizers = finalizer .NewFinalizers ()
252293 if err := r .Finalizers .Register (contactFinalizerKey , & contactFinalizer {
253- Client : r .Client }); err != nil {
294+ Client : r .Client ,
295+ EmailProvider : r .EmailProvider ,
296+ }); err != nil {
254297 return fmt .Errorf ("failed to register contact finalizer: %w" , err )
255298 }
256299
0 commit comments