From fabc588750b042ae5847a26c7d786d5462e6e07f Mon Sep 17 00:00:00 2001 From: Craig Post Date: Fri, 10 Feb 2023 13:29:53 -0700 Subject: [PATCH 1/2] Added name~ regex match to infoblox with --infoblox-name-regex argument --- main.go | 3 ++- pkg/apis/externaldns/types.go | 2 ++ provider/infoblox/infoblox.go | 23 ++++++++++++++------- provider/infoblox/infoblox_test.go | 33 +++++++++++++++++++++++++++--- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index df8eabb13a..2f9e146b3f 100644 --- a/main.go +++ b/main.go @@ -260,7 +260,8 @@ func main() { View: cfg.InfobloxView, MaxResults: cfg.InfobloxMaxResults, DryRun: cfg.DryRun, - FQDNRexEx: cfg.InfobloxFQDNRegEx, + FQDNRegEx: cfg.InfobloxFQDNRegEx, + NameRegEx: cfg.InfobloxNameRegEx, CreatePTR: cfg.InfobloxCreatePTR, CacheDuration: cfg.InfobloxCacheDuration, }, diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index 8224c80ee4..c77e3a3a0b 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -123,6 +123,7 @@ type Config struct { InfobloxView string InfobloxMaxResults int InfobloxFQDNRegEx string + InfobloxNameRegEx string InfobloxCreatePTR bool InfobloxCacheDuration int DynCustomerName string @@ -489,6 +490,7 @@ func (cfg *Config) ParseFlags(args []string) error { app.Flag("infoblox-view", "DNS view (default: \"\")").Default(defaultConfig.InfobloxView).StringVar(&cfg.InfobloxView) app.Flag("infoblox-max-results", "Add _max_results as query parameter to the URL on all API requests. The default is 0 which means _max_results is not set and the default of the server is used.").Default(strconv.Itoa(defaultConfig.InfobloxMaxResults)).IntVar(&cfg.InfobloxMaxResults) app.Flag("infoblox-fqdn-regex", "Apply this regular expression as a filter for obtaining zone_auth objects. This is disabled by default.").Default(defaultConfig.InfobloxFQDNRegEx).StringVar(&cfg.InfobloxFQDNRegEx) + app.Flag("infoblox-name-regex", "Apply this regular expression as a filter on the name field for obtaining infoblox records. This is disabled by default.").Default(defaultConfig.InfobloxNameRegEx).StringVar(&cfg.InfobloxNameRegEx) app.Flag("infoblox-create-ptr", "When using the Infoblox provider, create a ptr entry in addition to an entry").Default(strconv.FormatBool(defaultConfig.InfobloxCreatePTR)).BoolVar(&cfg.InfobloxCreatePTR) app.Flag("infoblox-cache-duration", "When using the Infoblox provider, set the record TTL (0s to disable).").Default(strconv.Itoa(defaultConfig.InfobloxCacheDuration)).IntVar(&cfg.InfobloxCacheDuration) app.Flag("dyn-customer-name", "When using the Dyn provider, specify the Customer Name").Default("").StringVar(&cfg.DynCustomerName) diff --git a/provider/infoblox/infoblox.go b/provider/infoblox/infoblox.go index 916dc9ef11..b6afb4e242 100644 --- a/provider/infoblox/infoblox.go +++ b/provider/infoblox/infoblox.go @@ -58,7 +58,8 @@ type StartupConfig struct { DryRun bool View string MaxResults int - FQDNRexEx string + FQDNRegEx string + NameRegEx string CreatePTR bool CacheDuration int } @@ -85,15 +86,17 @@ type infobloxRecordSet struct { // additional query parameter on all get requests type ExtendedRequestBuilder struct { fqdnRegEx string + nameRegEx string maxResults int ibclient.WapiRequestBuilder } // NewExtendedRequestBuilder returns a ExtendedRequestBuilder which adds // _max_results query parameter to all GET requests -func NewExtendedRequestBuilder(maxResults int, fqdnRegEx string) *ExtendedRequestBuilder { +func NewExtendedRequestBuilder(maxResults int, fqdnRegEx string, nameRegEx string) *ExtendedRequestBuilder { return &ExtendedRequestBuilder{ fqdnRegEx: fqdnRegEx, + nameRegEx: nameRegEx, maxResults: maxResults, } } @@ -107,10 +110,16 @@ func (mrb *ExtendedRequestBuilder) BuildRequest(t ibclient.RequestType, obj ibcl if mrb.maxResults > 0 { query.Set("_max_results", strconv.Itoa(mrb.maxResults)) } - _, ok := obj.(*ibclient.ZoneAuth) - if ok && t == ibclient.GET && mrb.fqdnRegEx != "" { + _, zoneAuthQuery := obj.(*ibclient.ZoneAuth) + if zoneAuthQuery && t == ibclient.GET && mrb.fqdnRegEx != "" { query.Set("fqdn~", mrb.fqdnRegEx) } + + // if we are not doing a ZoneAuth query, support the name filter + if !zoneAuthQuery && mrb.nameRegEx != "" { + query.Set("name~", mrb.nameRegEx) + } + req.URL.RawQuery = query.Encode() } return @@ -142,9 +151,9 @@ func NewInfobloxProvider(ibStartupCfg StartupConfig) (*ProviderConfig, error) { requestBuilder ibclient.HttpRequestBuilder err error ) - if ibStartupCfg.MaxResults != 0 || ibStartupCfg.FQDNRexEx != "" { + if ibStartupCfg.MaxResults != 0 || ibStartupCfg.FQDNRegEx != "" || ibStartupCfg.NameRegEx != "" { // use our own HttpRequestBuilder which sets _max_results parameter on GET requests - requestBuilder = NewExtendedRequestBuilder(ibStartupCfg.MaxResults, ibStartupCfg.FQDNRexEx) + requestBuilder = NewExtendedRequestBuilder(ibStartupCfg.MaxResults, ibStartupCfg.FQDNRegEx, ibStartupCfg.NameRegEx) } else { // use the default HttpRequestBuilder of the infoblox client requestBuilder, err = ibclient.NewWapiRequestBuilder(hostCfg, authCfg) @@ -166,7 +175,7 @@ func NewInfobloxProvider(ibStartupCfg StartupConfig) (*ProviderConfig, error) { zoneIDFilter: ibStartupCfg.ZoneIDFilter, dryRun: ibStartupCfg.DryRun, view: ibStartupCfg.View, - fqdnRegEx: ibStartupCfg.FQDNRexEx, + fqdnRegEx: ibStartupCfg.FQDNRegEx, createPTR: ibStartupCfg.CreatePTR, cacheDuration: ibStartupCfg.CacheDuration, } diff --git a/provider/infoblox/infoblox_test.go b/provider/infoblox/infoblox_test.go index 521b3f8f83..13b5e0b52e 100644 --- a/provider/infoblox/infoblox_test.go +++ b/provider/infoblox/infoblox_test.go @@ -698,7 +698,7 @@ func TestExtendedRequestFDQDRegExBuilder(t *testing.T) { Password: "abcd", } - requestBuilder := NewExtendedRequestBuilder(0, "^staging.*test.com$") + requestBuilder := NewExtendedRequestBuilder(0, "^staging.*test.com$", "") requestBuilder.Init(hostCfg, authCfg) obj := ibclient.NewZoneAuth(ibclient.ZoneAuth{}) @@ -712,6 +712,33 @@ func TestExtendedRequestFDQDRegExBuilder(t *testing.T) { assert.True(t, req.URL.Query().Get("fqdn~") == "") } +func TestExtendedRequestNameRegExBuilder(t *testing.T) { + hostCfg := ibclient.HostConfig{ + Host: "localhost", + Port: "8080", + Version: "2.3.1", + } + + authCfg := ibclient.AuthConfig{ + Username: "user", + Password: "abcd", + } + + requestBuilder := NewExtendedRequestBuilder(0, "", "^staging.*test.com$") + requestBuilder.Init(hostCfg, authCfg) + + obj := ibclient.NewEmptyRecordCNAME() + + req, _ := requestBuilder.BuildRequest(ibclient.GET, obj, "", &ibclient.QueryParams{}) + + assert.True(t, req.URL.Query().Get("name~") == "^staging.*test.com$") + + req, _ = requestBuilder.BuildRequest(ibclient.CREATE, obj, "", &ibclient.QueryParams{}) + + assert.True(t, req.URL.Query().Get("name~") == "") +} + + func TestExtendedRequestMaxResultsBuilder(t *testing.T) { hostCfg := ibclient.HostConfig{ Host: "localhost", @@ -724,7 +751,7 @@ func TestExtendedRequestMaxResultsBuilder(t *testing.T) { Password: "abcd", } - requestBuilder := NewExtendedRequestBuilder(54321, "") + requestBuilder := NewExtendedRequestBuilder(54321, "", "") requestBuilder.Init(hostCfg, authCfg) obj := ibclient.NewEmptyRecordCNAME() @@ -743,7 +770,7 @@ func TestGetObject(t *testing.T) { hostCfg := ibclient.HostConfig{} authCfg := ibclient.AuthConfig{} transportConfig := ibclient.TransportConfig{} - requestBuilder := NewExtendedRequestBuilder(1000, "mysite.com") + requestBuilder := NewExtendedRequestBuilder(1000, "mysite.com", "") requestor := mockRequestor{} client, _ := ibclient.NewConnector(hostCfg, authCfg, transportConfig, requestBuilder, &requestor) From 7cd5d5782a59b94bdbdbc34a63cd815b93ae98cc Mon Sep 17 00:00:00 2001 From: Craig Post Date: Fri, 10 Feb 2023 13:52:15 -0700 Subject: [PATCH 2/2] Updated infoblox docs with section on --infoblox-name-regex --- docs/tutorials/infoblox.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/tutorials/infoblox.md b/docs/tutorials/infoblox.md index eba10cf740..7e713e036e 100644 --- a/docs/tutorials/infoblox.md +++ b/docs/tutorials/infoblox.md @@ -271,6 +271,14 @@ There is also the ability to filter results from the Infoblox zone_auth service --infoblox-fqdn-regex=^staging.*test.com$ ``` +## Ability to filter A, Host, CNAME and TXT records from the by name using a regular expression + +Infoblox supports filtering records by name using a regular expression. See the [Infoblox API document](https://www.infoblox.com/wp-content/uploads/infoblox-deployment-infoblox-rest-api.pdf) for examples. To use this feature, set the parameter infoblox-name-regex for external-dns to a regular expression that makes sense for you. For instance, if all your dns records end with `cluster1.example.com`, you can fetch records matching this style by setting the following: + +``` +--infoblox-name-regex=cluster1.example.com +``` + ## Infoblox PTR record support There is an option to enable PTR records support for infoblox provider. PTR records allow to do reverse dns search. To enable PTR records support, add following into arguments for external-dns: