diff --git a/drivers/resipsgcp_dnsalias/main.go b/drivers/resipsgcp_dnsalias/main.go index 2f0fda5e1..cf0a6aacd 100644 --- a/drivers/resipsgcp_dnsalias/main.go +++ b/drivers/resipsgcp_dnsalias/main.go @@ -16,8 +16,6 @@ import ( "github.com/opensvc/om3/v3/util/sgcp" ) -const noneTarget = "none." - type ( T struct { resource.T @@ -33,7 +31,8 @@ type ( mgr *mgr // for tests - api apiProvider + api apiProvider + noneTarget string } mgr struct { @@ -52,7 +51,7 @@ type ( } aliasListResponse struct { - Aliases []sgcp.Alias `json:"aliases"` + CnameRecords []sgcp.Alias `json:"cnameRecords"` } apiProvider interface { @@ -62,10 +61,6 @@ type ( GetAliases(ctx context.Context, zoneID, name, uuid string) (method, url string, code int, data []byte, err error) UpdateAlias(ctx context.Context, zoneID string, aliasUUID string, name string, target string) (alias *sgcp.Alias, err error) } - - authInfoProvider interface { - GetAuthInfo(string) (*sgcp.AuthInfo, error) - } ) func New() resource.Driver { @@ -81,6 +76,11 @@ func (t *T) Configure() error { t.Target = hostname.Hostname() } + t.noneTarget = cfg.DNS.NoneTarget + if t.noneTarget == "" { + return fmt.Errorf("dns.none_target is required in sgcp config") + } + // secret is mandatory: define from keyword, fallback to cfg default, ensure not empty if t.Secret == "" { t.Secret = cfg.GetDefaultSecret() @@ -150,7 +150,7 @@ func (t *T) Start(ctx context.Context) error { func (t *T) Stop(ctx context.Context) error { // TODO: implement cache cleanup if t.UUID != "" { - return t.mgr.createOrUpdate(ctx, noneTarget) + return t.mgr.createOrUpdate(ctx, t.noneTarget) } return t.mgr.delete(ctx) } @@ -171,7 +171,7 @@ func (t *T) Status(ctx context.Context) status.T { return status.Warn } found := aliases[0] - if found.Target == noneTarget || found.Target == strings.TrimSuffix(noneTarget, ".") { + if found.Target == t.noneTarget || found.Target == strings.TrimSuffix(t.noneTarget, ".") { t.StatusLog().Info("alias target is disabled") return status.Down } diff --git a/drivers/resipsgcp_dnsalias/main_test.go b/drivers/resipsgcp_dnsalias/main_test.go index 85067112b..af59ce53c 100644 --- a/drivers/resipsgcp_dnsalias/main_test.go +++ b/drivers/resipsgcp_dnsalias/main_test.go @@ -55,7 +55,7 @@ func TestStatus(t *testing.T) { { UUID: "a1", Name: "svc1", - Target: "none.", + Target: "none.xxx", FQDN: "svc1.example.org", ZoneID: "z1", }, @@ -224,7 +224,7 @@ func TestStatus(t *testing.T) { resTarget: "tgt2", expectedStatus: status.Down, expectedStatusLog: []resource.StatusLogEntry{ - {Level: "error", Message: "get alias failed: unexpected status code for GET /file/alias got 500 wanted [200 404]"}, + {Level: "error", Message: "get alias failed: unexpected status code for GET https://dns.example.com/zones/z1/cname-records?name=bad500 got 500 wanted [200 404]"}, {Level: "info", Message: "not found"}, }, }, @@ -436,7 +436,7 @@ func TestStop(t *testing.T) { { UUID: "uuid-none", Name: "name-none", - Target: "none.", + Target: "none.xxx", FQDN: "name2.z1", ZoneID: "z1", }, @@ -521,22 +521,22 @@ func TestStop(t *testing.T) { alias, ok = db.Search(drv.ZoneID, drv.Name, drv.UUID) require.Truef(t, ok, "final found alias") t.Logf("final alias: %+v", alias) - require.Equal(t, noneTarget, alias.Target) + require.Equal(t, drv.noneTarget, alias.Target) }) t.Run("drv with kw uuid and target already none is noop", func(t *testing.T) { db, drv := newDBAndDrv(t, "rid1", dbEntries) drv.Name = "name-none" drv.UUID = "uuid-none" - drv.Target = "none." + drv.Target = "none.xxx" drv.ZoneID = "z1" require.NoError(t, drv.Configure()) - t.Log("verify initial exits with taget none") + t.Log("verify initial exits with target none") alias, ok := db.Search(drv.ZoneID, drv.Name, drv.UUID) require.Truef(t, ok, "initial found alias") t.Logf("initial alias: %+v", alias) - require.Equal(t, noneTarget, alias.Target) + require.Equal(t, drv.noneTarget, alias.Target) db.ResetCalls() t.Log("call Stop") @@ -548,11 +548,11 @@ func TestStop(t *testing.T) { require.Equal(t, 0, call.Update, "unexpected api update call") assert.Equal(t, 1, call.Search, "unexpected api search call") - t.Log("verify alias has been updated") + t.Log("verify alias has not been updated") alias, ok = db.Search(drv.ZoneID, drv.Name, drv.UUID) require.Truef(t, ok, "final found alias") t.Logf("final alias: %+v", alias) - require.Equal(t, noneTarget, alias.Target) + require.Equal(t, drv.noneTarget, alias.Target) }) t.Run("drv without kw uuid must delete alias", func(t *testing.T) { diff --git a/drivers/resipsgcp_dnsalias/mgr.go b/drivers/resipsgcp_dnsalias/mgr.go index ef4a606ff..e087c61c6 100644 --- a/drivers/resipsgcp_dnsalias/mgr.go +++ b/drivers/resipsgcp_dnsalias/mgr.go @@ -92,7 +92,7 @@ func (m *mgr) getAliases(ctx context.Context) ([]sgcp.Alias, error) { if err := json.Unmarshal(data, &resp); err != nil { return nil, fmt.Errorf("decode aliases: %w", err) } - return resp.Aliases, nil + return resp.CnameRecords, nil } // create creates a new alias with the specified target and returns the created alias or an error if the operation fails. diff --git a/util/sgcp/config.go b/util/sgcp/config.go index 5458f98c4..00107160e 100644 --- a/util/sgcp/config.go +++ b/util/sgcp/config.go @@ -32,8 +32,9 @@ type ( // DNSConfig contains DNS-related API configuration DNSConfig struct { - BaseURL string `yaml:"base_url"` - Path struct { + BaseURL string `yaml:"base_url"` + NoneTarget string `yaml:"none_target"` + Path struct { CName string `yaml:"cname"` Zone string `yaml:"zone"` } `yaml:"path"` diff --git a/util/sgcp/dns.go b/util/sgcp/dns.go index 1f89ccdfb..11b836489 100644 --- a/util/sgcp/dns.go +++ b/util/sgcp/dns.go @@ -24,12 +24,7 @@ type Alias struct { Name string `json:"name,omitempty"` Target string `json:"target,omitempty"` FQDN string `json:"fqdn,omitempty"` - ZoneID string `json:"zone_id,omitempty"` -} - -// aliasListResponse is the API response for listing aliases. -type aliasListResponse struct { - Aliases []Alias `json:"aliases"` + ZoneID string `json:"zoneId,omitempty"` } // NewDNSAPI creates a new DNSAPI instance. @@ -76,12 +71,12 @@ func (a *DNSAPI) CreateAlias(ctx context.Context, zoneID, name, target string) ( return &result, nil } -// UpdateAlias updates an existing DNS alias. +// UpdateAlias updates an existing DNS alias (PATCH, target only). func (a *DNSAPI) UpdateAlias(ctx context.Context, zoneID, aliasUUID, name, target string) (alias *Alias, err error) { - method := http.MethodPut + method := http.MethodPatch path := a.getAliasURL(zoneID, aliasUUID) - payload := map[string]any{"name": name, "target": target, "ttl": 60} + payload := map[string]any{"target": target, "ttl": 60} var b []byte b, err = json.Marshal(payload) if err != nil { @@ -121,7 +116,6 @@ func (a *DNSAPI) GetScopes(scopeType string) []string { // getAliasesURL constructs the URL for listing aliases with query parameters. func (a *DNSAPI) getAliasesURL(zoneID, name, uuid string) string { values := url.Values{} - values.Set("zone_id", zoneID) if name != "" { values.Set("name", name) } @@ -129,8 +123,9 @@ func (a *DNSAPI) getAliasesURL(zoneID, name, uuid string) string { values.Set("id", uuid) } base := strings.TrimRight(a.config.DNS.BaseURL, "/") - path := a.config.DNS.Path.CName - return fmt.Sprintf("%s%s?%s", base, path, values.Encode()) + zonePath := a.config.DNS.Path.Zone + aliasPath := a.config.DNS.Path.CName + return fmt.Sprintf("%s%s/%s%s?%s", base, zonePath, zoneID, aliasPath, values.Encode()) } // getAliasesCreateURL constructs the URL for creating an alias. diff --git a/util/sgcpdnstesthelper/main.go b/util/sgcpdnstesthelper/main.go index 4b095b117..cbd14dd6b 100644 --- a/util/sgcpdnstesthelper/main.go +++ b/util/sgcpdnstesthelper/main.go @@ -88,14 +88,22 @@ func (a *Api) GetAliases(_ context.Context, zoneID, name, uuid string) (method, a.callCount.Search++ a.rLock.RUnlock() method = http.MethodGet - url = "/file/alias" + base := "https://dns.example.com" + url = fmt.Sprintf("%s/zones/%s/cname-records", base, zoneID) + if name != "" && uuid != "" { + url += fmt.Sprintf("?name=%s&id=%s", name, uuid) + } else if name != "" { + url += fmt.Sprintf("?name=%s", name) + } else if uuid != "" { + url += fmt.Sprintf("?id=%s", uuid) + } if ok { code := resp.StatusCode if code == 0 { code = http.StatusOK } m := map[string][]sgcp.Alias{ - "aliases": resp.AliasL, + "cnameRecords": resp.AliasL, } b, err := json.Marshal(m) if err == nil { diff --git a/util/testsgcphelper/text/config.yaml b/util/testsgcphelper/text/config.yaml index c02fe89a8..7ac1e2f12 100644 --- a/util/testsgcphelper/text/config.yaml +++ b/util/testsgcphelper/text/config.yaml @@ -11,6 +11,7 @@ files: dns: base_url: "https://127.0.0.1:1215/dns" + none_target: "none.xxx" path: cname: "/cname-entry" zone: "/zone"