From 62d1a343a7600e73d8742a218c468e9304d0b926 Mon Sep 17 00:00:00 2001 From: Rasel Hossain <59439107+Superm4n97@users.noreply.github.com> Date: Wed, 26 Oct 2022 14:43:44 +0600 Subject: [PATCH] Keep dns records in ExternalDNS Status (#4) Signed-off-by: rasel rasel@appscode.com --- .../v1alpha1/externaldns_types.go | 15 +++++++ .../v1alpha1/zz_generated.deepcopy.go | 20 ++++++++++ ...external-dns.appscode.com_externaldns.yaml | 13 ++++++ .../external-dns/externaldns_controller.go | 20 ++++++++-- pkg/plan/plan.go | 40 ++++++++++--------- 5 files changed, 86 insertions(+), 22 deletions(-) diff --git a/apis/external-dns/v1alpha1/externaldns_types.go b/apis/external-dns/v1alpha1/externaldns_types.go index f793e837..26001790 100644 --- a/apis/external-dns/v1alpha1/externaldns_types.go +++ b/apis/external-dns/v1alpha1/externaldns_types.go @@ -489,6 +489,17 @@ type ExternalDNSSpec struct { TXTWildcardReplacement *string `json:"txtWildcardReplacement,omitempty"` } +// DNSRecord hold the DNS name and target address, if there are multiple target address then the addresses are joint by separator ';' between them (ex: 1:2:3:4;6:7:8:9) +type DNSRecord struct { + // target is the list of target address + // +optional + Target string `json:"target,omitempty"` + + // dns name is the domain name for this record + // +optional + Name string `json:"name,omitempty"` +} + // ExternalDNSStatus defines the observed state of ExternalDNS type ExternalDNSStatus struct { // Phase indicates the current state of the controller (ex: Failed,InProgress,Current) @@ -502,6 +513,10 @@ type ExternalDNSStatus struct { // Conditions describe the current condition of the CRD // +optional Conditions []kmapi.Condition `json:"conditions,omitempty"` + + // DNSRecord is the list of records that this external dns operator registered + // +optional + DNSRecords []DNSRecord `json:"dnsRecords,omitempty"` } //+kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.phase" diff --git a/apis/external-dns/v1alpha1/zz_generated.deepcopy.go b/apis/external-dns/v1alpha1/zz_generated.deepcopy.go index 9578f44e..147531b6 100644 --- a/apis/external-dns/v1alpha1/zz_generated.deepcopy.go +++ b/apis/external-dns/v1alpha1/zz_generated.deepcopy.go @@ -147,6 +147,21 @@ func (in *CloudflareProvider) DeepCopy() *CloudflareProvider { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNSRecord) DeepCopyInto(out *DNSRecord) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSRecord. +func (in *DNSRecord) DeepCopy() *DNSRecord { + if in == nil { + return nil + } + out := new(DNSRecord) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExternalDNS) DeepCopyInto(out *ExternalDNS) { *out = *in @@ -328,6 +343,11 @@ func (in *ExternalDNSStatus) DeepCopyInto(out *ExternalDNSStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.DNSRecords != nil { + in, out := &in.DNSRecords, &out.DNSRecords + *out = make([]DNSRecord, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalDNSStatus. diff --git a/config/crd/bases/external-dns.appscode.com_externaldns.yaml b/config/crd/bases/external-dns.appscode.com_externaldns.yaml index 3f39b0ed..3726393c 100644 --- a/config/crd/bases/external-dns.appscode.com_externaldns.yaml +++ b/config/crd/bases/external-dns.appscode.com_externaldns.yaml @@ -391,6 +391,19 @@ spec: - type type: object type: array + dnsRecords: + description: DNSRecord is the list of records that this external dns + operator registered + items: + properties: + name: + description: dns name is the domain name for this record + type: string + target: + description: target is the list of target address + type: string + type: object + type: array observedGeneration: description: ObservedGeneration indicates the latest generation that successfully reconciled diff --git a/controllers/external-dns/externaldns_controller.go b/controllers/external-dns/externaldns_controller.go index 793572f7..d2c4d146 100644 --- a/controllers/external-dns/externaldns_controller.go +++ b/controllers/external-dns/externaldns_controller.go @@ -79,6 +79,16 @@ func (r *ExternalDNSReconciler) updateEdnsStatus(ctx context.Context, edns *exte return patchErr } +func (r ExternalDNSReconciler) patchDNSRecords(ctx context.Context, edns *externaldnsv1alpha1.ExternalDNS, dnsRecs []externaldnsv1alpha1.DNSRecord) error { + _, _, patchErr := kmc.PatchStatus(ctx, r.Client, edns, func(obj client.Object) client.Object { + in := obj.(*externaldnsv1alpha1.ExternalDNS) + in.Status.DNSRecords = dnsRecs + return in + }) + + return patchErr +} + func (r *ExternalDNSReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { _ = log.FromContext(ctx) @@ -130,13 +140,17 @@ func (r *ExternalDNSReconciler) Reconcile(ctx context.Context, req ctrl.Request) // APPLY DNS RECORD //SetDNSRecords creates the dns record according to user information //successMsg is used to identify whether the 'plan applied' or 'already up to date' - successMsg, err := plan.SetDNSRecords(edns, ctx) - + dnsRecs, err := plan.SetDNSRecords(ctx, edns) if err != nil { return ctrl.Result{}, r.updateEdnsStatus(ctx, edns, newConditionPtr(externaldnsv1alpha1.CreateAndApplyPlan, err.Error(), edns.Generation, false), phasePointer(externaldnsv1alpha1.ExternalDNSPhaseFailed)) } - return ctrl.Result{}, r.updateEdnsStatus(ctx, edns, newConditionPtr(externaldnsv1alpha1.CreateAndApplyPlan, successMsg, edns.Generation, true), phasePointer(externaldnsv1alpha1.ExternalDNSPhaseCurrent)) + err = r.patchDNSRecords(ctx, edns, dnsRecs) + if err != nil { + return ctrl.Result{}, err + } + + return ctrl.Result{}, r.updateEdnsStatus(ctx, edns, newConditionPtr(externaldnsv1alpha1.CreateAndApplyPlan, "plan applied", edns.Generation, true), phasePointer(externaldnsv1alpha1.ExternalDNSPhaseCurrent)) } // SetupWithManager sets up the controller with the Manager. diff --git a/pkg/plan/plan.go b/pkg/plan/plan.go index 777a2ed9..8361180b 100644 --- a/pkg/plan/plan.go +++ b/pkg/plan/plan.go @@ -184,7 +184,8 @@ var defaultConfig = externaldns.Config{ IBMCloudConfigFile: "/etc/kubernetes/ibmcloud.json", } -func createAndApplyPlan(ctx context.Context, cfg *externaldns.Config, r registry.Registry, endpointSource source.Source) (string, error) { +//create and apply dns plan, If plan is successfully applied then returns dns record, which defines the desired records of the plan +func createAndApplyPlan(ctx context.Context, cfg *externaldns.Config, r registry.Registry, endpointSource source.Source) ([]externaldnsv1alpha1.DNSRecord, error) { var domainFilter endpoint.DomainFilter if cfg.RegexDomainFilter.String() != "" { @@ -195,7 +196,7 @@ func createAndApplyPlan(ctx context.Context, cfg *externaldns.Config, r registry records, err := r.Records(ctx) if err != nil { - return "", err + return nil, err } missingRecords := r.MissingRecords() @@ -203,7 +204,7 @@ func createAndApplyPlan(ctx context.Context, cfg *externaldns.Config, r registry ctx = context.WithValue(ctx, provider.RecordsContextKey, records) endpoints, err := endpointSource.Endpoints(ctx) if err != nil { - return "", err + return nil, err } endpoints = r.AdjustEndpoints(endpoints) @@ -221,7 +222,7 @@ func createAndApplyPlan(ctx context.Context, cfg *externaldns.Config, r registry if missingRecordsPlan.Changes.HasChanges() { err = r.ApplyChanges(ctx, missingRecordsPlan.Changes) if err != nil { - return "", err + return nil, err } klog.Info("all missing records are created") } @@ -240,22 +241,24 @@ func createAndApplyPlan(ctx context.Context, cfg *externaldns.Config, r registry klog.Info("Desired: ", pln.Desired) klog.Info("Current: ", pln.Current) - var successMsg = "" + dnsRecs := make([]externaldnsv1alpha1.DNSRecord, 0) if pln.Changes.HasChanges() { err = r.ApplyChanges(ctx, pln.Changes) if err != nil { klog.Error("failed to apply plan") - return "", err + return nil, err } klog.Info("plan applied") - successMsg = "plan applied" + } else { klog.Info("all records are already up to date") - successMsg = "all records are already up to date" } - return successMsg, nil + for _, rec := range pln.Desired { + dnsRecs = append(dnsRecs, externaldnsv1alpha1.DNSRecord{Name: rec.DNSName, Target: rec.Targets.String()}) + } + return dnsRecs, nil } func convertEDNSObjectToCfg(crd *externaldnsv1alpha1.ExternalDNS) (*externaldns.Config, error) { @@ -748,37 +751,36 @@ func createRegistry(cfg *externaldns.Config, p provider.Provider) (registry.Regi return r, err } -func SetDNSRecords(edns *externaldnsv1alpha1.ExternalDNS, ctx context.Context) (string, error) { +func SetDNSRecords(ctx context.Context, edns *externaldnsv1alpha1.ExternalDNS) ([]externaldnsv1alpha1.DNSRecord, error) { cfg, err := convertEDNSObjectToCfg(edns) if err != nil { klog.Error("failed to convert crd into cfg.", err.Error()) - return "", err + return nil, err } endpointsSource, err := createEndpointsSource(ctx, cfg) if err != nil { klog.Error("failed to create endpoints source.", err.Error()) - return "", err + return nil, err } pvdr, err := createProviderFromCfg(ctx, cfg, endpointsSource) if err != nil { klog.Error("failed to create provider.", err.Error()) - return "", err + return nil, err } reg, err := createRegistry(cfg, *pvdr) if err != nil { klog.Errorf("failed to create Registry.", err.Error()) - return "", err + return nil, err } - var successMsg string - successMsg, err = createAndApplyPlan(ctx, cfg, reg, endpointsSource) - if err != nil { + dnsRecs, e := createAndApplyPlan(ctx, cfg, reg, endpointsSource) + if e != nil { klog.Errorf("failed to create and apply plan: %s", err.Error()) - return "", err + return nil, e } - return successMsg, nil + return dnsRecs, nil }