@@ -62,6 +62,8 @@ const (
6262 kubeCloudConfigName = "kube-cloud-config"
6363 // cloudCABundleKey is the key in the kube cloud config ConfigMap where the custom CA bundle is located
6464 cloudCABundleKey = "ca-bundle.pem"
65+ // dnsRecordIndexFieldName is the key for the DNSRecord index, used to identify conflicting domain names.
66+ dnsRecordIndexFieldName = "Spec.DNSName"
6567)
6668
6769var log = logf .Logger .WithName (controllerName )
@@ -102,6 +104,12 @@ func New(mgr manager.Manager, config Config) (runtimecontroller.Controller, erro
102104 })); err != nil {
103105 return nil , err
104106 }
107+ if err := operatorCache .IndexField (context .Background (), & iov1.DNSRecord {}, dnsRecordIndexFieldName , func (o client.Object ) []string {
108+ dnsRecord := o .(* iov1.DNSRecord )
109+ return []string {dnsRecord .Spec .DNSName }
110+ }); err != nil {
111+ return nil , err
112+ }
105113 return c , nil
106114}
107115
@@ -341,8 +349,9 @@ func (r *reconciler) publishRecordToZones(zones []configv1.DNSZone, record *iov1
341349
342350 var err error
343351 var condition iov1.DNSZoneCondition
352+ var isDomainPublished bool
344353 if dnsPolicy == iov1 .UnmanagedDNS {
345- log .Info ("DNS record not published" , "record" , record .Spec )
354+ log .Info ("DNS record not published: DNS management policy is unmanaged " , "record" , record .Spec )
346355 condition = iov1.DNSZoneCondition {
347356 Message : "DNS record is currently not being managed by the operator" ,
348357 Reason : "UnmanagedDNS" ,
@@ -352,6 +361,24 @@ func (r *reconciler) publishRecordToZones(zones []configv1.DNSZone, record *iov1
352361 }
353362 } else if isRecordPublished {
354363 condition , err = r .replacePublishedRecord (zones [i ], record )
364+ } else if isDomainPublished , err = domainIsAlreadyPublishedInZone (context .Background (), r .cache , record , & zones [i ]); err != nil {
365+ log .Error (err , "failed to validate DNS record" , "record" , record .Spec )
366+ condition = iov1.DNSZoneCondition {
367+ Message : "Pre-publish validation failed" ,
368+ Reason : "InternalError" ,
369+ Status : string (operatorv1 .ConditionUnknown ),
370+ Type : iov1 .DNSRecordPublishedConditionType ,
371+ LastTransitionTime : metav1 .Now (),
372+ }
373+ } else if isDomainPublished {
374+ log .Info ("DNS record not published: domain name already used by another DNS record" , "record" , record .Spec )
375+ condition = iov1.DNSZoneCondition {
376+ Message : "Domain name is already in use" ,
377+ Reason : "DomainAlreadyInUse" ,
378+ Status : string (operatorv1 .ConditionUnknown ),
379+ Type : iov1 .DNSRecordPublishedConditionType ,
380+ LastTransitionTime : metav1 .Now (),
381+ }
355382 } else {
356383 condition , err = r .publishRecord (zones [i ], record )
357384 }
@@ -846,3 +873,32 @@ func getIbmDNSProvider(dnsConfig *configv1.DNS, creds *corev1.Secret, instanceCR
846873 return provider , nil
847874 }
848875}
876+
877+ // domainIsAlreadyPublishedInZone returns true if the domain name in the provided DNSRecord is already published by
878+ // another existing dnsRecord.
879+ func domainIsAlreadyPublishedInZone (ctx context.Context , cache cache.Cache , record * iov1.DNSRecord , zone * configv1.DNSZone ) (bool , error ) {
880+ records := iov1.DNSRecordList {}
881+ if err := cache .List (ctx , & records , client.MatchingFields {dnsRecordIndexFieldName : record .Spec .DNSName }); err != nil {
882+ return false , err
883+ }
884+
885+ if len (records .Items ) == 0 {
886+ return false , nil
887+ }
888+
889+ for _ , existingRecord := range records .Items {
890+ // we only care if the domain name is published by a different record, so ignore the matching record if it
891+ // already exists.
892+ // TODO: There's got to be a better way to match the same object
893+ if (record .Name == existingRecord .Name ) && (record .Namespace == existingRecord .Namespace ) {
894+ continue
895+ }
896+ if record .Spec .DNSName != existingRecord .Spec .DNSName {
897+ continue
898+ }
899+ if recordIsAlreadyPublishedToZone (record , zone ) {
900+ return true , nil
901+ }
902+ }
903+ return false , nil
904+ }
0 commit comments