Skip to content

Commit

Permalink
wip: update implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez committed Dec 19, 2024
1 parent 360a52e commit 6c01ee7
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 28 deletions.
16 changes: 12 additions & 4 deletions providers/dns/manageengine/internal/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
Expand Down Expand Up @@ -74,8 +75,8 @@ func (c *Client) GetAllZoneRecords(ctx context.Context, zoneID int) ([]ZoneRecor

// DeleteZoneRecord deletes a "zone record".
// https://pitstop.manageengine.com/portal/en/kb/articles/manageengine-clouddns-rest-api-documentation#DEL_Delete_10
func (c *Client) DeleteZoneRecord(ctx context.Context, zoneID int, recordID int) error {
endpoint := c.baseURL.JoinPath("dns", "domain", strconv.Itoa(zoneID), "records", "SPF_TXT", strconv.Itoa(recordID), "/")
func (c *Client) DeleteZoneRecord(ctx context.Context, zoneID int, domainID int) error {
endpoint := c.baseURL.JoinPath("dns", "domain", strconv.Itoa(zoneID), "records", "SPF_TXT", strconv.Itoa(domainID))

req, err := newRequest(ctx, http.MethodDelete, endpoint, nil)
if err != nil {
Expand Down Expand Up @@ -104,8 +105,15 @@ func (c *Client) CreateZoneRecord(ctx context.Context, zoneID int, record ZoneRe

// UpdateZoneRecord update an existing "zone record".
// https://pitstop.manageengine.com/portal/en/kb/articles/manageengine-clouddns-rest-api-documentation#PUT_Update_10
func (c *Client) UpdateZoneRecord(ctx context.Context, zoneID int, record ZoneRecord) error {
endpoint := c.baseURL.JoinPath("dns", "domain", strconv.Itoa(zoneID), "records", "SPF_TXT", "/")
func (c *Client) UpdateZoneRecord(ctx context.Context, record ZoneRecord) error {
if record.SpfTxtDomainID == 0 {
return errors.New("SpfTxtDomainID is empty")
}
if record.ZoneID == 0 {
return errors.New("ZoneID is empty")
}

endpoint := c.baseURL.JoinPath("dns", "domain", strconv.Itoa(record.ZoneID), "records", "SPF_TXT", strconv.Itoa(record.SpfTxtDomainID), "/")

req, err := newRequest(ctx, http.MethodPut, endpoint, []ZoneRecord{record})
if err != nil {
Expand Down
22 changes: 14 additions & 8 deletions providers/dns/manageengine/internal/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,14 @@ func TestClient_GetAllZoneRecords_error(t *testing.T) {
}

func TestClient_DeleteZoneRecord(t *testing.T) {
client := setupTest(t, "DELETE /dns/domain/4/records/SPF_TXT/6/", http.StatusOK, "zone_record_delete.json")
client := setupTest(t, "DELETE /dns/domain/4/records/SPF_TXT/6", http.StatusOK, "zone_record_delete.json")

err := client.DeleteZoneRecord(context.Background(), 4, 6)
require.NoError(t, err)
}

func TestClient_DeleteZoneRecord_error(t *testing.T) {
client := setupTest(t, "DELETE /dns/domain/4/records/SPF_TXT/6/", http.StatusUnauthorized, "error.json")
client := setupTest(t, "DELETE /dns/domain/4/records/SPF_TXT/6", http.StatusUnauthorized, "error.json")

err := client.DeleteZoneRecord(context.Background(), 4, 6)
require.Error(t, err)
Expand Down Expand Up @@ -236,20 +236,26 @@ func TestClient_CreateZoneRecord_error_bad_request(t *testing.T) {
}

func TestClient_UpdateZoneRecord(t *testing.T) {
client := setupTest(t, "PUT /dns/domain/4/records/SPF_TXT/", http.StatusOK, "zone_record_update.json")
client := setupTest(t, "PUT /dns/domain/4/records/SPF_TXT/6/", http.StatusOK, "zone_record_update.json")

record := ZoneRecord{}
record := ZoneRecord{
SpfTxtDomainID: 6,
ZoneID: 4,
}

err := client.UpdateZoneRecord(context.Background(), 4, record)
err := client.UpdateZoneRecord(context.Background(), record)
require.NoError(t, err)
}

func TestClient_UpdateZoneRecord_error(t *testing.T) {
client := setupTest(t, "PUT /dns/domain/4/records/SPF_TXT/", http.StatusUnauthorized, "error.json")
client := setupTest(t, "PUT /dns/domain/4/records/SPF_TXT/6/", http.StatusUnauthorized, "error.json")

record := ZoneRecord{}
record := ZoneRecord{
SpfTxtDomainID: 6,
ZoneID: 4,
}

err := client.UpdateZoneRecord(context.Background(), 4, record)
err := client.UpdateZoneRecord(context.Background(), record)
require.Error(t, err)

require.EqualError(t, err, "[status code: 401] Authentication credentials were not provided.")
Expand Down
73 changes: 57 additions & 16 deletions providers/dns/manageengine/manageengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ const (
EnvTTL = envNamespace + "TTL"
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
EnvSequenceInterval = envNamespace + "SEQUENCE_INTERVAL"
)

// Config is used to configure the creation of the DNSProvider.
Expand All @@ -34,7 +33,6 @@ type Config struct {

PropagationTimeout time.Duration
PollingInterval time.Duration
SequenceInterval time.Duration
TTL int
}

Expand All @@ -44,7 +42,6 @@ func NewDefaultConfig() *Config {
TTL: env.GetOrDefaultInt(EnvTTL, dns01.DefaultTTL),
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout),
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
SequenceInterval: env.GetOrDefaultSecond(EnvSequenceInterval, 10*time.Second),
}
}

Expand Down Expand Up @@ -107,17 +104,38 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
return fmt.Errorf("manageengine: find zone record: %w", err)
}

// Update the existing zone record.
if zoneRecord != nil {
for _, record := range zoneRecord.Records {
// Delete the zone record.
err = d.client.DeleteZoneRecord(ctx, zoneID, record.ID)
if slices.Contains(record.Values, info.Value) {
continue
}

zr := internal.ZoneRecord{
ZoneID: zoneID,
SpfTxtDomainID: zoneRecord.SpfTxtDomainID,
DomainName: info.EffectiveFQDN,
DomainTTL: d.config.TTL,
RecordType: "TXT",
Records: []internal.Record{{
Values: append(record.Values, info.Value),
DomainID: zoneRecord.SpfTxtDomainID,
}},
}

// Update the zone record.
err = d.client.UpdateZoneRecord(ctx, zr)
if err != nil {
return fmt.Errorf("manageengine: delete zone record: %w", err)
return fmt.Errorf("manageengine: update zone record: %w", err)
}

return nil
}

return errors.New("manageengine: zone already contains the TXT record value")
}

// Create a zone record.
// Create a new zone record.
record := internal.ZoneRecord{
ZoneID: zoneID,
DomainName: info.EffectiveFQDN,
Expand Down Expand Up @@ -163,9 +181,38 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
}

// Delete the zone record.
err = d.client.DeleteZoneRecord(ctx, zoneID, record.ID)
if len(record.Values) <= 1 {
err = d.client.DeleteZoneRecord(ctx, zoneID, zoneRecord.SpfTxtDomainID)
if err != nil {
return fmt.Errorf("manageengine: delete zone record: %w", err)
}

return nil
}

// Update the zone record.
var values []string
for _, value := range record.Values {
if value != info.Value {
values = append(values, value)
}
}

zr := internal.ZoneRecord{
ZoneID: zoneID,
SpfTxtDomainID: zoneRecord.SpfTxtDomainID,
DomainName: info.EffectiveFQDN,
DomainTTL: d.config.TTL,
RecordType: "TXT",
Records: []internal.Record{{
Values: values,
DomainID: zoneRecord.SpfTxtDomainID,
}},
}

err = d.client.UpdateZoneRecord(ctx, zr)
if err != nil {
return fmt.Errorf("manageengine: delete zone record: %w", err)
return fmt.Errorf("manageengine: create zone record: %w", err)
}

return nil
Expand All @@ -180,12 +227,6 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval
}

// Sequential All DNS challenges for this provider will be resolved sequentially.
// Returns the interval between each iteration.
func (d *DNSProvider) Sequential() time.Duration {
return d.config.SequenceInterval
}

func (d *DNSProvider) findZoneID(ctx context.Context, authZone string) (int, error) {
zones, err := d.client.GetAllZones(ctx)
if err != nil {
Expand All @@ -198,7 +239,7 @@ func (d *DNSProvider) findZoneID(ctx context.Context, authZone string) (int, err
}
}

return 0, fmt.Errorf(" zone not found %s", authZone)
return 0, fmt.Errorf("zone not found %s", authZone)
}

func (d *DNSProvider) findZoneRecord(ctx context.Context, zoneID int, fqdn string) (*internal.ZoneRecord, error) {
Expand Down

0 comments on commit 6c01ee7

Please sign in to comment.