From 20e269dd3092aaf4ea4388f04855fd1d84122fcf Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Mon, 19 Jan 2026 14:24:09 +0100 Subject: [PATCH] wip: try an alternative approach --- providers/dns/bluecatv2/bluecatv2.go | 30 ++++++++- providers/dns/bluecatv2/bluecatv2_test.go | 74 +++++++++++++++++++++++ 2 files changed, 102 insertions(+), 2 deletions(-) diff --git a/providers/dns/bluecatv2/bluecatv2.go b/providers/dns/bluecatv2/bluecatv2.go index ffa9c31b2..225d033ec 100644 --- a/providers/dns/bluecatv2/bluecatv2.go +++ b/providers/dns/bluecatv2/bluecatv2.go @@ -134,7 +134,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("bluecatv2: %w", err) } - zone, err := d.findZone(ctx, info.EffectiveFQDN) + zone, err := d.findZoneAlt(ctx, info.EffectiveFQDN) if err != nil { return fmt.Errorf("bluecatv2: %w", err) } @@ -221,6 +221,32 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } +func (d *DNSProvider) findZoneAlt(ctx context.Context, fqdn string) (*internal.ZoneResource, error) { + for name := range dns01.UnFqdnDomainsSeq(fqdn) { + opts := &internal.CollectionOptions{ + Filter: internal.And( + internal.Eq("absoluteName", name), + internal.Eq("configuration.name", d.config.ConfigName), + internal.Eq("view.name", d.config.ViewName), + ).String(), + } + + zones, err := d.client.RetrieveZones(ctx, opts) + if err != nil { + // TODO(ldez) maybe add a log in v5. + continue + } + + for _, zone := range zones { + if zone.AbsoluteName == name { + return &zone, nil + } + } + } + + return nil, fmt.Errorf("no zone found for fqdn: %s", fqdn) +} + func (d *DNSProvider) findZone(ctx context.Context, fqdn string) (*internal.ZoneResource, error) { configuration, err := d.findConfiguration(ctx) if err != nil { @@ -294,7 +320,7 @@ func (d *DNSProvider) findViewZone(ctx context.Context, viewID int64, fqdn strin zones, err := d.client.RetrieveViewZones(ctx, viewID, &options) if err != nil { - // TODO (ldez) maybe add a log in v5. + // TODO(ldez) maybe add a log in v5. continue } diff --git a/providers/dns/bluecatv2/bluecatv2_test.go b/providers/dns/bluecatv2/bluecatv2_test.go index c62414d78..9038b4f3e 100644 --- a/providers/dns/bluecatv2/bluecatv2_test.go +++ b/providers/dns/bluecatv2/bluecatv2_test.go @@ -3,6 +3,7 @@ package bluecatv2 import ( "net/http" "net/http/httptest" + "strings" "testing" "github.com/go-acme/lego/v4/platform/tester" @@ -19,6 +20,7 @@ var envTest = tester.NewEnvTest( EnvPassword, EnvConfigName, EnvViewName, + EnvSkipDeploy, ).WithDomain(envDomain) func TestNewDNSProvider(t *testing.T) { @@ -262,6 +264,8 @@ func mockBuilder() *servermock.Builder[*DNSProvider] { } func TestDNSProvider_Present(t *testing.T) { + t.Skip("wip on alt") + provider := mockBuilder(). Route("POST /api/v2/sessions", servermock.ResponseFromInternal("postSession.json"), @@ -307,6 +311,76 @@ func TestDNSProvider_Present(t *testing.T) { } func TestDNSProvider_CleanUp(t *testing.T) { + t.Skip("wip on alt") + + provider := mockBuilder(). + Route("POST /api/v2/sessions", + servermock.ResponseFromInternal("postSession.json"), + servermock.CheckRequestJSONBodyFromInternal("postSession-request.json"), + ). + Route("DELETE /api/v2/resourceRecords/12345", + servermock.ResponseFromInternal("deleteResourceRecord.json"), + ). + Route("POST /api/v2/zones/456789/deployments", + servermock.ResponseFromInternal("postZoneDeployment.json"). + WithStatusCode(http.StatusCreated), + servermock.CheckRequestJSONBodyFromInternal("postZoneDeployment-request.json"), + ). + Build(t) + + provider.zoneIDs["abc"] = 456789 + provider.recordIDs["abc"] = 12345 + + err := provider.CleanUp("example.com", "abc", "123d==") + require.NoError(t, err) +} + +func TestDNSProvider_Present_alt(t *testing.T) { + provider := mockBuilder(). + Route("POST /api/v2/sessions", + servermock.ResponseFromInternal("postSession.json"), + servermock.CheckRequestJSONBodyFromInternal("postSession-request.json"), + ). + Route("GET /api/v2/configurations", + servermock.ResponseFromInternal("configurations.json"), + servermock.CheckQueryParameter().Strict(). + With("filter", "name:eq('myConfiguration')"), + ). + Route("GET /api/v2/configurations/12345/views", + servermock.ResponseFromInternal("views.json"), + servermock.CheckQueryParameter().Strict(). + With("filter", "name:eq('myView')"), + ). + Route("GET /api/v2/zones", + http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + filter := req.URL.Query().Get("filter") + + if strings.Contains(filter, internal.Eq("absoluteName", "example.com").String()) { + servermock.ResponseFromInternal("zones.json").ServeHTTP(rw, req) + + return + } + + servermock.ResponseFromInternal("error.json"). + WithStatusCode(http.StatusNotFound).ServeHTTP(rw, req) + }), + ). + Route("POST /api/v2/zones/12345/resourceRecords", + servermock.ResponseFromInternal("postZoneResourceRecord.json"), + servermock.CheckRequestJSONBodyFromInternal("postZoneResourceRecord-request.json"), + ). + Route("POST /api/v2/zones/12345/deployments", + servermock.ResponseFromInternal("postZoneDeployment.json"). + WithStatusCode(http.StatusCreated), + servermock.CheckRequestJSONBodyFromInternal("postZoneDeployment-request.json"), + ). + Build(t) + + err := provider.Present("example.com", "abc", "123d==") + require.NoError(t, err) +} + +func TestDNSProvider_CleanUp_alt(t *testing.T) { provider := mockBuilder(). Route("POST /api/v2/sessions", servermock.ResponseFromInternal("postSession.json"),