From 761d6551d391d12b21078ecb92fe1a7bb828c3e3 Mon Sep 17 00:00:00 2001 From: Raffaele Di Fazio Date: Sun, 28 Apr 2024 14:05:45 +0200 Subject: [PATCH 1/4] Initial support for forwarding wildcard annotations to webhook providers --- source/source.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source/source.go b/source/source.go index c7d46c970..149892853 100644 --- a/source/source.go +++ b/source/source.go @@ -60,6 +60,8 @@ const ( controllerAnnotationValue = "dns-controller" // The annotation used for defining the desired hostname internalHostnameAnnotationKey = "external-dns.alpha.kubernetes.io/internal-hostname" + // New annotation to support wildcard annotations for webhook providers + webhookWildcardAnnotationKey = "external-dns.alpha.kubernetes.io/webhook-*" ) const ( @@ -224,6 +226,13 @@ func getProviderSpecificAnnotations(annotations map[string]string) (endpoint.Pro Name: fmt.Sprintf("ibmcloud-%s", attr), Value: v, }) + } else if strings.HasPrefix(k, webhookWildcardAnnotationKey) { + // Support for wildcard annotations for webhook providers + attr := strings.TrimPrefix(k, "external-dns.alpha.kubernetes.io/webhook-") + providerSpecificAnnotations = append(providerSpecificAnnotations, endpoint.ProviderSpecificProperty{ + Name: fmt.Sprintf("webhook/%s", attr), + Value: v, + }) } } return providerSpecificAnnotations, setIdentifier From c375899f91deb0a29783aab6ed77b6c7ad506e4d Mon Sep 17 00:00:00 2001 From: Raffaele Di Fazio Date: Fri, 10 May 2024 20:11:38 +0200 Subject: [PATCH 2/4] test Signed-off-by: Raffaele Di Fazio --- provider/webhook/webhook_test.go | 54 ++++++++++++++++++++++++++++++++ source/source.go | 4 +-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/provider/webhook/webhook_test.go b/provider/webhook/webhook_test.go index 03b02c20f..ca36e38b8 100644 --- a/provider/webhook/webhook_test.go +++ b/provider/webhook/webhook_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/require" "sigs.k8s.io/external-dns/endpoint" + "sigs.k8s.io/external-dns/plan" "sigs.k8s.io/external-dns/provider" webhookapi "sigs.k8s.io/external-dns/provider/webhook/api" ) @@ -217,3 +218,56 @@ func TestAdjustendpointsWithError(t *testing.T) { require.Error(t, err) require.ErrorIs(t, err, provider.SoftError) } + +// test apply changes with an endpoint with a provider specific property +func TestApplyChangesWithProviderSpecificProperty(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" { + w.Header().Set(webhookapi.ContentTypeHeader, webhookapi.MediaTypeFormatAndVersion) + w.Write([]byte(`{}`)) + return + } + if r.URL.Path == "/records" { + w.Header().Set(webhookapi.ContentTypeHeader, webhookapi.MediaTypeFormatAndVersion) + // assert that the request contains the provider specific property + var changes plan.Changes + defer r.Body.Close() + b, err := io.ReadAll(r.Body) + if err != nil { + t.Fatal(err) + } + err = json.Unmarshal(b, &changes) + require.Nil(t, err) + require.Len(t, changes.Create, 1) + require.Len(t, changes.Create[0].ProviderSpecific, 1) + require.Equal(t, "prop1", changes.Create[0].ProviderSpecific[0].Name) + require.Equal(t, "value1", changes.Create[0].ProviderSpecific[0].Value) + w.WriteHeader(http.StatusNoContent) + return + } + })) + defer svr.Close() + + p, err := NewWebhookProvider(svr.URL) + require.NoError(t, err) + e := &endpoint.Endpoint{ + DNSName: "test.example.com", + RecordTTL: 10, + RecordType: "A", + Targets: endpoint.Targets{ + "", + }, + ProviderSpecific: endpoint.ProviderSpecific{ + endpoint.ProviderSpecificProperty{ + Name: "prop1", + Value: "value1", + }, + }, + } + err = p.ApplyChanges(context.TODO(), &plan.Changes{ + Create: []*endpoint.Endpoint{ + e, + }, + }) + require.NoError(t, err) +} diff --git a/source/source.go b/source/source.go index 149892853..132f40dcd 100644 --- a/source/source.go +++ b/source/source.go @@ -60,8 +60,6 @@ const ( controllerAnnotationValue = "dns-controller" // The annotation used for defining the desired hostname internalHostnameAnnotationKey = "external-dns.alpha.kubernetes.io/internal-hostname" - // New annotation to support wildcard annotations for webhook providers - webhookWildcardAnnotationKey = "external-dns.alpha.kubernetes.io/webhook-*" ) const ( @@ -226,7 +224,7 @@ func getProviderSpecificAnnotations(annotations map[string]string) (endpoint.Pro Name: fmt.Sprintf("ibmcloud-%s", attr), Value: v, }) - } else if strings.HasPrefix(k, webhookWildcardAnnotationKey) { + } else if strings.HasPrefix(k, "external-dns.alpha.kubernetes.io/webhook-") { // Support for wildcard annotations for webhook providers attr := strings.TrimPrefix(k, "external-dns.alpha.kubernetes.io/webhook-") providerSpecificAnnotations = append(providerSpecificAnnotations, endpoint.ProviderSpecificProperty{ From 574f86574131adb07adde4af74c5bd2a7b8d63ab Mon Sep 17 00:00:00 2001 From: Raffaele Di Fazio Date: Sat, 11 May 2024 14:55:33 +0200 Subject: [PATCH 3/4] consistency improvement Signed-off-by: Raffaele Di Fazio --- provider/webhook/webhook_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/provider/webhook/webhook_test.go b/provider/webhook/webhook_test.go index ca36e38b8..999cdc3bf 100644 --- a/provider/webhook/webhook_test.go +++ b/provider/webhook/webhook_test.go @@ -233,9 +233,7 @@ func TestApplyChangesWithProviderSpecificProperty(t *testing.T) { var changes plan.Changes defer r.Body.Close() b, err := io.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } + require.Nil(t, err) err = json.Unmarshal(b, &changes) require.Nil(t, err) require.Len(t, changes.Create, 1) From bfa4e0620d045fbaa708d4660b7cce620284c11b Mon Sep 17 00:00:00 2001 From: Raffaele Di Fazio Date: Fri, 24 May 2024 17:31:44 +0200 Subject: [PATCH 4/4] custom metrics docs --- docs/tutorials/webhook-provider.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/tutorials/webhook-provider.md b/docs/tutorials/webhook-provider.md index dd07e727f..c956ce325 100644 --- a/docs/tutorials/webhook-provider.md +++ b/docs/tutorials/webhook-provider.md @@ -31,11 +31,16 @@ The default recommended port is 8888, and should listen only on localhost (ie: o **NOTE**: only `5xx` responses will be retried and only `20x` will be considered as successful. All status codes different from those will be considered a failure on ExternalDNS's side. - ## Metrics support The metrics should listen ":8080" on `/metrics` following [Open Metrics](https://github.com/OpenObservability/OpenMetrics) format. +## Custom Annotations + +The Webhook provider supports custom annotations for DNS records. This feature allows users to define additional configuration options for DNS records managed by the Webhook provider. Custom annotations are defined using the annotation format `external-dns.alpha.kubernetes.io/webhook-`. + +Custom annotations can be used to influence DNS record creation and updates. Providers implementing the Webhook API should document the custom annotations they support and how they affect DNS record management. + ## Provider registry To simplify the discovery of providers, we will accept pull requests that will add links to providers in the [README](../../README.md) file. This list will only serve the purpose of simplifying finding providers and will not constitute an official endorsement of any of the externally implemented providers unless otherwise stated.