Merge pull request #2110 from mmerrill3/feature/infoblox-reg-ex

Adding ability to query Infoblox API using regex for fqdn (#2102)
This commit is contained in:
Kubernetes Prow Robot 2021-06-23 01:04:10 -07:00 committed by GitHub
commit 43ce441e08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 12 deletions

View File

@ -260,3 +260,11 @@ $ curl -kl \
-u ${WAPI_USERNAME}:${WAPI_PASSWORD} \
https://${GRID_HOST}:${WAPI_PORT}/wapi/v${WAPI_VERSION}/zone_auth?fqdn=example.com
```
## Ability to filter results from the zone auth API using a regular expression
There is also the ability to filter results from the Infoblox zone_auth service based upon 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 for the zone_auth service, set the parameter infoblox-fqdn-regex for external-dns to a regular expression that makes sense for you. For instance, to only return hosted zones that start with staging in the test.com domain (like staging.beta.test.com, or staging.test.com), use the following command line option when starting external-dns
```
--infoblox-fqdn-regex=^staging.*test.com$
```

View File

@ -241,6 +241,7 @@ func main() {
View: cfg.InfobloxView,
MaxResults: cfg.InfobloxMaxResults,
DryRun: cfg.DryRun,
FQDNRexEx: cfg.InfobloxFQDNRegEx,
},
)
case "dyn":

View File

@ -105,6 +105,7 @@ type Config struct {
InfobloxSSLVerify bool
InfobloxView string
InfobloxMaxResults int
InfobloxFQDNRegEx string
DynCustomerName string
DynUsername string
DynPassword string `secure:"yes"`
@ -228,6 +229,7 @@ var defaultConfig = &Config{
InfobloxSSLVerify: true,
InfobloxView: "",
InfobloxMaxResults: 0,
InfobloxFQDNRegEx: "",
OCIConfigFile: "/etc/kubernetes/oci.yaml",
InMemoryZones: []string{},
OVHEndpoint: "ovh-eu",
@ -410,6 +412,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("infoblox-ssl-verify", "When using the Infoblox provider, specify whether to verify the SSL certificate (default: true, disable with --no-infoblox-ssl-verify)").Default(strconv.FormatBool(defaultConfig.InfobloxSSLVerify)).BoolVar(&cfg.InfobloxSSLVerify)
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("dyn-customer-name", "When using the Dyn provider, specify the Customer Name").Default("").StringVar(&cfg.DynCustomerName)
app.Flag("dyn-username", "When using the Dyn provider, specify the Username").Default("").StringVar(&cfg.DynUsername)
app.Flag("dyn-password", "When using the Dyn provider, specify the password").Default("").StringVar(&cfg.DynPassword)

View File

@ -46,6 +46,7 @@ type InfobloxConfig struct {
DryRun bool
View string
MaxResults int
FQDNRexEx string
}
// InfobloxProvider implements the DNS provider for Infoblox.
@ -56,6 +57,7 @@ type InfobloxProvider struct {
zoneIDFilter provider.ZoneIDFilter
view string
dryRun bool
fqdnRegEx string
}
type infobloxRecordSet struct {
@ -63,28 +65,36 @@ type infobloxRecordSet struct {
res interface{}
}
// MaxResultsRequestBuilder implements a HttpRequestBuilder which sets the
// _max_results query parameter on all get requests
type MaxResultsRequestBuilder struct {
// ExtendedRequestBuilder implements a HttpRequestBuilder which sets
// additional query parameter on all get requests
type ExtendedRequestBuilder struct {
fqdnRegEx string
maxResults int
ibclient.WapiRequestBuilder
}
// NewMaxResultsRequestBuilder returns a MaxResultsRequestBuilder which adds
// NewExtendedRequestBuilder returns a ExtendedRequestBuilder which adds
// _max_results query parameter to all GET requests
func NewMaxResultsRequestBuilder(maxResults int) *MaxResultsRequestBuilder {
return &MaxResultsRequestBuilder{
func NewExtendedRequestBuilder(maxResults int, fqdnRegEx string) *ExtendedRequestBuilder {
return &ExtendedRequestBuilder{
fqdnRegEx: fqdnRegEx,
maxResults: maxResults,
}
}
// BuildRequest prepares the api request. it uses BuildRequest of
// WapiRequestBuilder and then add the _max_requests parameter
func (mrb *MaxResultsRequestBuilder) BuildRequest(t ibclient.RequestType, obj ibclient.IBObject, ref string, queryParams ibclient.QueryParams) (req *http.Request, err error) {
func (mrb *ExtendedRequestBuilder) BuildRequest(t ibclient.RequestType, obj ibclient.IBObject, ref string, queryParams ibclient.QueryParams) (req *http.Request, err error) {
req, err = mrb.WapiRequestBuilder.BuildRequest(t, obj, ref, queryParams)
if req.Method == "GET" {
query := req.URL.Query()
query.Set("_max_results", strconv.Itoa(mrb.maxResults))
if mrb.maxResults > 0 {
query.Set("_max_results", strconv.Itoa(mrb.maxResults))
}
_, ok := obj.(*ibclient.ZoneAuth)
if ok && t == ibclient.GET && mrb.fqdnRegEx != "" {
query.Set("fqdn~", mrb.fqdnRegEx)
}
req.URL.RawQuery = query.Encode()
}
return
@ -110,9 +120,9 @@ func NewInfobloxProvider(infobloxConfig InfobloxConfig) (*InfobloxProvider, erro
)
var requestBuilder ibclient.HttpRequestBuilder
if infobloxConfig.MaxResults != 0 {
if infobloxConfig.MaxResults != 0 || infobloxConfig.FQDNRexEx != "" {
// use our own HttpRequestBuilder which sets _max_results parameter on GET requests
requestBuilder = NewMaxResultsRequestBuilder(infobloxConfig.MaxResults)
requestBuilder = NewExtendedRequestBuilder(infobloxConfig.MaxResults, infobloxConfig.FQDNRexEx)
} else {
// use the default HttpRequestBuilder of the infoblox client
requestBuilder = &ibclient.WapiRequestBuilder{}
@ -132,6 +142,7 @@ func NewInfobloxProvider(infobloxConfig InfobloxConfig) (*InfobloxProvider, erro
zoneIDFilter: infobloxConfig.ZoneIDFilter,
dryRun: infobloxConfig.DryRun,
view: infobloxConfig.View,
fqdnRegEx: infobloxConfig.FQDNRexEx,
}
return provider, nil

View File

@ -533,7 +533,7 @@ func TestInfobloxZones(t *testing.T) {
assert.Equal(t, provider.findZone(zones, "lvl2-2.lvl1-2.example.com").Fqdn, "example.com")
}
func TestMaxResultsRequestBuilder(t *testing.T) {
func TestExtendedRequestFDQDRegExBuilder(t *testing.T) {
hostConfig := ibclient.HostConfig{
Host: "localhost",
Port: "8080",
@ -542,7 +542,29 @@ func TestMaxResultsRequestBuilder(t *testing.T) {
Version: "2.3.1",
}
requestBuilder := NewMaxResultsRequestBuilder(54321)
requestBuilder := NewExtendedRequestBuilder(0, "^staging.*test.com$")
requestBuilder.Init(hostConfig)
obj := ibclient.NewZoneAuth(ibclient.ZoneAuth{})
req, _ := requestBuilder.BuildRequest(ibclient.GET, obj, "", ibclient.QueryParams{})
assert.True(t, req.URL.Query().Get("fqdn~") == "^staging.*test.com$")
req, _ = requestBuilder.BuildRequest(ibclient.CREATE, obj, "", ibclient.QueryParams{})
assert.True(t, req.URL.Query().Get("fqdn~") == "")
}
func TestExtendedRequestMaxResultsBuilder(t *testing.T) {
hostConfig := ibclient.HostConfig{
Host: "localhost",
Port: "8080",
Username: "user",
Password: "abcd",
Version: "2.3.1",
}
requestBuilder := NewExtendedRequestBuilder(54321, "")
requestBuilder.Init(hostConfig)
obj := ibclient.NewRecordCNAME(ibclient.RecordCNAME{Zone: "foo.bar.com"})