From 241dcc9e54eef3ace866983c819ff841351f684d Mon Sep 17 00:00:00 2001 From: jskrill Date: Mon, 11 Nov 2024 05:10:36 -0500 Subject: [PATCH] Fix pagination of auth zones and missing record view (#21) --- .github/workflows/release.yaml | 1 + .goreleaser.yml | 30 ++++++++++++------------- internal/infoblox/infoblox.go | 35 ++++++++++++++++++------------ internal/infoblox/infoblox_test.go | 19 +++++++++++++--- 4 files changed, 53 insertions(+), 32 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5a8cfb2..8cf9c74 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -91,3 +91,4 @@ jobs: CI_COMMIT_TIMESTAMP: ${{ github.event.repository.updated_at }} CI_COMMIT_SHA: ${{ github.sha }} CI_COMMIT_TAG: ${{ needs.release.outputs.tag_name }} + REPO_NAME: ${{ github.repository }} diff --git a/.goreleaser.yml b/.goreleaser.yml index 7298939..586937c 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -43,9 +43,9 @@ dockers: goos: linux goarch: amd64 image_templates: - - ghcr.io/absaoss/external-dns-infoblox-webhook:latest-amd64 - - ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_SHA }}-amd64 - - ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_TAG }}-amd64 + - ghcr.io/{{ .Env.REPO_NAME }}:latest-amd64 + - ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_SHA }}-amd64 + - ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_TAG }}-amd64 build_flag_templates: - --pull - --platform=linux/amd64 @@ -56,9 +56,9 @@ dockers: goos: linux goarch: arm64 image_templates: - - ghcr.io/absaoss/external-dns-infoblox-webhook:latest-arm64 - - ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_SHA }}-arm64 - - ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_TAG }}-arm64 + - ghcr.io/{{ .Env.REPO_NAME }}:latest-arm64 + - ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_SHA }}-arm64 + - ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_TAG }}-arm64 build_flag_templates: - --pull - --platform=linux/arm64 @@ -66,18 +66,18 @@ dockers: - --build-arg=CI_COMMIT_SHA="{{ .Env.CI_COMMIT_SHA }}" - --build-arg=CI_COMMIT_TAG="{{ .Env.CI_COMMIT_TAG }}" docker_manifests: - - name_template: ghcr.io/absaoss/external-dns-infoblox-webhook:latest + - name_template: ghcr.io/{{ .Env.REPO_NAME }}:latest image_templates: - - ghcr.io/absaoss/external-dns-infoblox-webhook:latest-amd64 - - ghcr.io/absaoss/external-dns-infoblox-webhook:latest-arm64 - - name_template: ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_SHA }} + - ghcr.io/{{ .Env.REPO_NAME }}:latest-amd64 + - ghcr.io/{{ .Env.REPO_NAME }}:latest-arm64 + - name_template: ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_SHA }} image_templates: - - ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_SHA }}-amd64 - - ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_SHA }}-arm64 - - name_template: ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_TAG }} + - ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_SHA }}-amd64 + - ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_SHA }}-arm64 + - name_template: ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_TAG }} image_templates: - - ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_TAG }}-amd64 - - ghcr.io/absaoss/external-dns-infoblox-webhook:{{ .Env.CI_COMMIT_TAG }}-arm64 + - ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_TAG }}-amd64 + - ghcr.io/{{ .Env.REPO_NAME }}:{{ .Env.CI_COMMIT_TAG }}-arm64 changelog: skip: true use: github diff --git a/internal/infoblox/infoblox.go b/internal/infoblox/infoblox.go index 88e45d6..9ca8caa 100644 --- a/internal/infoblox/infoblox.go +++ b/internal/infoblox/infoblox.go @@ -175,18 +175,6 @@ func NewInfobloxProvider(cfg *StartupConfig, domainFilter endpoint.DomainFilter) return provider, nil } -func recordQueryParams(zone string, view string) *ibclient.QueryParams { - searchFields := map[string]string{} - if zone != "" { - searchFields["zone"] = zone - } - - if view != "" { - searchFields["view"] = view - } - return ibclient.NewQueryParams(false, searchFields) -} - // Records gets the current records. func (p *Provider) Records(_ context.Context) (endpoints []*endpoint.Endpoint, err error) { zones, err := p.zones() @@ -568,8 +556,11 @@ func (p *Provider) zones() ([]ibclient.ZoneAuth, error) { View: &p.config.View, }, ) - queryParams := recordQueryParams("", p.config.View) - err := p.client.GetObject(obj, "", queryParams, &res) + searchFields := map[string]string{} + if p.config.View != "" { + searchFields["view"] = p.config.View + } + err := PagingGetObject(p.client, obj, "", searchFields, &res) if err != nil && !isNotFoundError(err) { return nil, err } @@ -686,6 +677,10 @@ func (p *Provider) recordSet(ep *endpoint.Endpoint, getObject bool) (recordSet i err = fmt.Errorf("could not fetch A record ['%s':'%s'] : %w", *obj.Name, *obj.Ipv4Addr, err) return } + } else { + // If getObject is not set (action == create), we need to set the View for Infoblox to find the parent zone + // If View is set for the other actions, Infoblox will complain that the view field is not allowed + obj.View = p.config.View } recordSet = infobloxRecordSet{ obj: obj, @@ -705,6 +700,10 @@ func (p *Provider) recordSet(ep *endpoint.Endpoint, getObject bool) (recordSet i if err != nil && !isNotFoundError(err) { return } + } else { + // If getObject is not set (action == create), we need to set the View for Infoblox to find the parent zone + // If View is set for the other actions, Infoblox will complain that the view field is not allowed + obj.View = p.config.View } recordSet = infobloxRecordSet{ obj: obj, @@ -723,6 +722,10 @@ func (p *Provider) recordSet(ep *endpoint.Endpoint, getObject bool) (recordSet i if err != nil && !isNotFoundError(err) { return } + } else { + // If getObject is not set (action == create), we need to set the View for Infoblox to find the parent zone + // If View is set for the other actions, Infoblox will complain that the view field is not allowed + obj.View = &p.config.View } recordSet = infobloxRecordSet{ obj: obj, @@ -747,6 +750,10 @@ func (p *Provider) recordSet(ep *endpoint.Endpoint, getObject bool) (recordSet i if err != nil && !isNotFoundError(err) { return } + } else { + // If getObject is not set (action == create), we need to set the View for Infoblox to find the parent zone + // If View is set for the other actions, Infoblox will complain that the view field is not allowed + obj.View = &p.config.View } recordSet = infobloxRecordSet{ obj: obj, diff --git a/internal/infoblox/infoblox_test.go b/internal/infoblox/infoblox_test.go index e68a69b..8a02c2b 100644 --- a/internal/infoblox/infoblox_test.go +++ b/internal/infoblox/infoblox_test.go @@ -192,6 +192,8 @@ func (client *mockIBConnector) CreateObject(obj ibclient.IBObject) (ref string, func (client *mockIBConnector) GetObject(obj ibclient.IBObject, ref string, queryParams *ibclient.QueryParams, res interface{}) (err error) { isPagingType := false switch res.(type) { + case *pagingResponseStruct[ibclient.ZoneAuth]: + isPagingType = true case *pagingResponseStruct[ibclient.RecordA]: isPagingType = true case *pagingResponseStruct[ibclient.HostRecord]: @@ -357,7 +359,11 @@ func (client *mockIBConnector) GetObject(obj ibclient.IBObject, ref string, quer *res.(*[]ibclient.RecordPTR) = result } case "zone_auth": - *res.(*[]ibclient.ZoneAuth) = *client.mockInfobloxZones + if isPagingType { + res.(*pagingResponseStruct[ibclient.ZoneAuth]).Result = *client.mockInfobloxZones + } else { + *res.(*[]ibclient.ZoneAuth) = *client.mockInfobloxZones + } } return } @@ -642,7 +648,10 @@ func TestInfobloxRecords(t *testing.T) { endpoint.NewEndpoint("host.example.com", endpoint.RecordTypeA, "125.1.1.1"), } validateEndpoints(t, actual, expected) - client.verifyGetObjectRequest(t, "zone_auth", "", &map[string]string{}). + client.verifyGetObjectRequest(t, "zone_auth", "", &map[string]string{ + "_max_results": "1000", + "_paging": "1", + "_return_as_object": "1"}). ExpectNotRequestURLQueryParam(t, "view"). ExpectNotRequestURLQueryParam(t, "zone") client.verifyGetObjectRequest(t, "record:a", "", &map[string]string{ @@ -698,7 +707,11 @@ func TestInfobloxRecordsWithView(t *testing.T) { endpoint.NewEndpoint("dog.bar.example.com", endpoint.RecordTypeA, "123.123.123.123"), } validateEndpoints(t, actual, expected) - client.verifyGetObjectRequest(t, "zone_auth", "", &map[string]string{"view": "Inside"}). + client.verifyGetObjectRequest(t, "zone_auth", "", &map[string]string{ + "_max_results": "1000", + "_paging": "1", + "_return_as_object": "1", + "view": "Inside"}). ExpectRequestURLQueryParam(t, "view", "Inside"). ExpectNotRequestURLQueryParam(t, "zone") client.verifyGetObjectRequest(t, "record:a", "", &map[string]string{