exoscale provider: migrate to exoscale API v2 (#2917)

* exoscale provider: migrate to exoscale API v2

* exoscale: fix comment typo

* exoscale: remove debug line from test

* exoscale: replace endpoint config with environment

* exoscale: update Config

* Update pkg/apis/externaldns/types.go

Co-authored-by: John Gardiner Myers <jgmyers@proofpoint.com>

* exoscale: document api zone & environment flags

* exoscale: update tutorial

* Sync deps with master

---------

Co-authored-by: John Gardiner Myers <jgmyers@proofpoint.com>
This commit is contained in:
Predrag Janosevic 2023-08-14 14:57:21 +00:00 committed by GitHub
parent c6a64396c2
commit 7ddc9daba7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 234 additions and 135 deletions

View File

@ -13,7 +13,6 @@ Additionally you will have to provide the Exoscale...:
* API Key
* API Secret
* API Endpoint
* Elastic IP address, to access the workers
## Deployment
@ -48,11 +47,15 @@ spec:
- --domain-filter={{ my-domain }}
- --policy=sync # if you want DNS entries to get deleted as well
- --txt-owner-id={{ owner-id-for-this-external-dns }}
- --exoscale-endpoint={{ endpoint }} # usually https://api.exoscale.ch/dns
- --exoscale-apikey={{ api-key}}
- --exoscale-apisecret={{ api-secret }}
# - --exoscale-apizone={{ api-zone }}
# - --exoscale-apienv={{ api-env }}
```
Optional arguments `--exoscale-apizone` and `--exoscale-apienv` define [Exoscale API Zone](https://community.exoscale.com/documentation/platform/exoscale-datacenter-zones/)
(default `ch-gva-2`) and Exoscale API environment (default `api`, can be used to target non-production API server) respectively.
## RBAC
If your cluster is RBAC enabled, you also need to setup the following, before you can run external-dns:
@ -121,6 +124,7 @@ spec:
name: "nginx"
port:
number: 80
path: /
pathType: Prefix
---

2
go.mod
View File

@ -30,6 +30,7 @@ require (
github.com/ffledgling/pdns-go v0.0.0-20180219074714-524e7daccd99
github.com/go-gandi/go-gandi v0.6.0
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.0
github.com/gophercloud/gophercloud v1.5.0
github.com/hooklift/gowsdl v0.5.0
github.com/infobloxopen/infoblox-go-client/v2 v2.3.0
@ -123,7 +124,6 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect

10
main.go
View File

@ -309,7 +309,15 @@ func main() {
},
)
case "exoscale":
p, err = exoscale.NewExoscaleProvider(cfg.ExoscaleEndpoint, cfg.ExoscaleAPIKey, cfg.ExoscaleAPISecret, cfg.DryRun, exoscale.ExoscaleWithDomain(domainFilter), exoscale.ExoscaleWithLogging()), nil
p, err = exoscale.NewExoscaleProvider(
cfg.ExoscaleAPIEnvironment,
cfg.ExoscaleAPIZone,
cfg.ExoscaleAPIKey,
cfg.ExoscaleAPISecret,
cfg.DryRun,
exoscale.ExoscaleWithDomain(domainFilter),
exoscale.ExoscaleWithLogging(),
)
case "inmemory":
p, err = inmemory.NewInMemoryProvider(inmemory.InMemoryInitZones(cfg.InMemoryZones), inmemory.InMemoryWithDomain(domainFilter), inmemory.InMemoryWithLogging()), nil
case "designate":

View File

@ -164,6 +164,8 @@ type Config struct {
ExoscaleEndpoint string
ExoscaleAPIKey string `secure:"yes"`
ExoscaleAPISecret string `secure:"yes"`
ExoscaleAPIEnvironment string
ExoscaleAPIZone string
CRDSourceAPIVersion string
CRDSourceKind string
ServiceTypeFilter []string
@ -310,7 +312,8 @@ var defaultConfig = &Config{
LogFormat: "text",
MetricsAddress: ":7979",
LogLevel: logrus.InfoLevel.String(),
ExoscaleEndpoint: "https://api.exoscale.ch/dns",
ExoscaleAPIEnvironment: "api",
ExoscaleAPIZone: "ch-gva-2",
ExoscaleAPIKey: "",
ExoscaleAPISecret: "",
CRDSourceAPIVersion: "externaldns.k8s.io/v1alpha1",
@ -534,7 +537,9 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("tls-client-cert", "When using TLS communication, the path to the certificate to present as a client (not required for TLS)").Default(defaultConfig.TLSClientCert).StringVar(&cfg.TLSClientCert)
app.Flag("tls-client-cert-key", "When using TLS communication, the path to the certificate key to use with the client certificate (not required for TLS)").Default(defaultConfig.TLSClientCertKey).StringVar(&cfg.TLSClientCertKey)
app.Flag("exoscale-endpoint", "Provide the endpoint for the Exoscale provider").Default(defaultConfig.ExoscaleEndpoint).StringVar(&cfg.ExoscaleEndpoint)
// Flags related to Exoscale provider
app.Flag("exoscale-apienv", "When using Exoscale provider, specify the API environment (optional)").Default(defaultConfig.ExoscaleAPIEnvironment).StringVar(&cfg.ExoscaleAPIEnvironment)
app.Flag("exoscale-apizone", "When using Exoscale provider, specify the API Zone (optional)").Default(defaultConfig.ExoscaleAPIZone).StringVar(&cfg.ExoscaleAPIZone)
app.Flag("exoscale-apikey", "Provide your API Key for the Exoscale provider").Default(defaultConfig.ExoscaleAPIKey).StringVar(&cfg.ExoscaleAPIKey)
app.Flag("exoscale-apisecret", "Provide your API Secret for the Exoscale provider").Default(defaultConfig.ExoscaleAPISecret).StringVar(&cfg.ExoscaleAPISecret)

View File

@ -113,7 +113,8 @@ var (
MetricsAddress: ":7979",
LogLevel: logrus.InfoLevel.String(),
ConnectorSourceServer: "localhost:8080",
ExoscaleEndpoint: "https://api.exoscale.ch/dns",
ExoscaleAPIEnvironment: "api",
ExoscaleAPIZone: "ch-gva-2",
ExoscaleAPIKey: "",
ExoscaleAPISecret: "",
CRDSourceAPIVersion: "externaldns.k8s.io/v1alpha1",
@ -222,7 +223,8 @@ var (
MetricsAddress: "127.0.0.1:9099",
LogLevel: logrus.DebugLevel.String(),
ConnectorSourceServer: "localhost:8081",
ExoscaleEndpoint: "https://api.foo.ch/dns",
ExoscaleAPIEnvironment: "api1",
ExoscaleAPIZone: "zone1",
ExoscaleAPIKey: "1",
ExoscaleAPISecret: "2",
CRDSourceAPIVersion: "test.k8s.io/v1alpha1",
@ -360,7 +362,8 @@ func TestParseFlags(t *testing.T) {
"--metrics-address=127.0.0.1:9099",
"--log-level=debug",
"--connector-source-server=localhost:8081",
"--exoscale-endpoint=https://api.foo.ch/dns",
"--exoscale-apienv=api1",
"--exoscale-apizone=zone1",
"--exoscale-apikey=1",
"--exoscale-apisecret=2",
"--crd-source-apiversion=test.k8s.io/v1alpha1",
@ -479,7 +482,8 @@ func TestParseFlags(t *testing.T) {
"EXTERNAL_DNS_METRICS_ADDRESS": "127.0.0.1:9099",
"EXTERNAL_DNS_LOG_LEVEL": "debug",
"EXTERNAL_DNS_CONNECTOR_SOURCE_SERVER": "localhost:8081",
"EXTERNAL_DNS_EXOSCALE_ENDPOINT": "https://api.foo.ch/dns",
"EXTERNAL_DNS_EXOSCALE_APIENV": "api1",
"EXTERNAL_DNS_EXOSCALE_APIZONE": "zone1",
"EXTERNAL_DNS_EXOSCALE_APIKEY": "1",
"EXTERNAL_DNS_EXOSCALE_APISECRET": "2",
"EXTERNAL_DNS_CRD_SOURCE_APIVERSION": "test.k8s.io/v1alpha1",

View File

@ -20,7 +20,8 @@ import (
"context"
"strings"
"github.com/exoscale/egoscale"
egoscale "github.com/exoscale/egoscale/v2"
exoapi "github.com/exoscale/egoscale/v2/api"
log "github.com/sirupsen/logrus"
"sigs.k8s.io/external-dns/endpoint"
@ -30,11 +31,12 @@ import (
// EgoscaleClientI for replaceable implementation
type EgoscaleClientI interface {
GetRecords(context.Context, string) ([]egoscale.DNSRecord, error)
GetDomains(context.Context) ([]egoscale.DNSDomain, error)
CreateRecord(context.Context, string, egoscale.DNSRecord) (*egoscale.DNSRecord, error)
DeleteRecord(context.Context, string, int64) error
UpdateRecord(context.Context, string, egoscale.UpdateDNSRecord) (*egoscale.DNSRecord, error)
ListDNSDomainRecords(context.Context, string, string) ([]egoscale.DNSDomainRecord, error)
ListDNSDomains(context.Context, string) ([]egoscale.DNSDomain, error)
GetDNSDomainRecord(context.Context, string, string, string) (*egoscale.DNSDomainRecord, error)
CreateDNSDomainRecord(context.Context, string, string, *egoscale.DNSDomainRecord) (*egoscale.DNSDomainRecord, error)
DeleteDNSDomainRecord(context.Context, string, string, *egoscale.DNSDomainRecord) error
UpdateDNSDomainRecord(context.Context, string, string, *egoscale.DNSDomainRecord) error
}
// ExoscaleProvider initialized as dns provider with no records
@ -42,6 +44,8 @@ type ExoscaleProvider struct {
provider.BaseProvider
domain endpoint.DomainFilter
client EgoscaleClientI
apiEnv string
apiZone string
filter *zoneFilter
OnApplyChanges func(changes *plan.Changes)
dryRun bool
@ -51,18 +55,27 @@ type ExoscaleProvider struct {
type ExoscaleOption func(*ExoscaleProvider)
// NewExoscaleProvider returns ExoscaleProvider DNS provider interface implementation
func NewExoscaleProvider(endpoint, apiKey, apiSecret string, dryRun bool, opts ...ExoscaleOption) *ExoscaleProvider {
client := egoscale.NewClient(endpoint, apiKey, apiSecret)
return NewExoscaleProviderWithClient(endpoint, apiKey, apiSecret, client, dryRun, opts...)
func NewExoscaleProvider(env, zone, key, secret string, dryRun bool, opts ...ExoscaleOption) (*ExoscaleProvider, error) {
client, err := egoscale.NewClient(
key,
secret,
)
if err != nil {
return nil, err
}
return NewExoscaleProviderWithClient(client, env, zone, dryRun, opts...), nil
}
// NewExoscaleProviderWithClient returns ExoscaleProvider DNS provider interface implementation (Client provided)
func NewExoscaleProviderWithClient(_, apiKey, apiSecret string, client EgoscaleClientI, dryRun bool, opts ...ExoscaleOption) *ExoscaleProvider {
func NewExoscaleProviderWithClient(client EgoscaleClientI, env, zone string, dryRun bool, opts ...ExoscaleOption) *ExoscaleProvider {
ep := &ExoscaleProvider{
filter: &zoneFilter{},
OnApplyChanges: func(changes *plan.Changes) {},
domain: endpoint.NewDomainFilter([]string{""}),
client: client,
apiEnv: env,
apiZone: zone,
dryRun: dryRun,
}
for _, opt := range opts {
@ -71,16 +84,18 @@ func NewExoscaleProviderWithClient(_, apiKey, apiSecret string, client EgoscaleC
return ep
}
func (ep *ExoscaleProvider) getZones(ctx context.Context) (map[int64]string, error) {
dom, err := ep.client.GetDomains(ctx)
func (ep *ExoscaleProvider) getZones(ctx context.Context) (map[string]string, error) {
ctx = exoapi.WithEndpoint(ctx, exoapi.NewReqEndpoint(ep.apiEnv, ep.apiZone))
domains, err := ep.client.ListDNSDomains(ctx, ep.apiZone)
if err != nil {
return nil, err
}
zones := map[int64]string{}
for _, d := range dom {
zones[d.ID] = d.Name
zones := map[string]string{}
for _, domain := range domains {
zones[*domain.ID] = *domain.UnicodeName
}
return zones, nil
}
@ -95,52 +110,79 @@ func (ep *ExoscaleProvider) ApplyChanges(ctx context.Context, changes *plan.Chan
return nil
}
ctx = exoapi.WithEndpoint(ctx, exoapi.NewReqEndpoint(ep.apiEnv, ep.apiZone))
zones, err := ep.getZones(ctx)
if err != nil {
return err
}
for _, epoint := range changes.Create {
if ep.domain.Match(epoint.DNSName) {
if zoneID, name := ep.filter.EndpointZoneID(epoint, zones); zoneID != 0 {
rec := egoscale.DNSRecord{
Name: name,
RecordType: epoint.RecordType,
TTL: int(epoint.RecordTTL),
Content: epoint.Targets[0],
}
_, err := ep.client.CreateRecord(ctx, zones[zoneID], rec)
if err != nil {
return err
}
}
if !ep.domain.Match(epoint.DNSName) {
continue
}
zoneID, name := ep.filter.EndpointZoneID(epoint, zones)
if zoneID == "" {
continue
}
// API does not accept 0 as default TTL but wants nil pointer instead
var ttl *int64
if epoint.RecordTTL != 0 {
t := int64(epoint.RecordTTL)
ttl = &t
}
record := egoscale.DNSDomainRecord{
Name: &name,
Type: &epoint.RecordType,
TTL: ttl,
Content: &epoint.Targets[0],
}
_, err := ep.client.CreateDNSDomainRecord(ctx, ep.apiZone, zoneID, &record)
if err != nil {
return err
}
}
for _, epoint := range changes.UpdateNew {
if ep.domain.Match(epoint.DNSName) {
if zoneID, name := ep.filter.EndpointZoneID(epoint, zones); zoneID != 0 {
records, err := ep.client.GetRecords(ctx, zones[zoneID])
if err != nil {
return err
}
for _, r := range records {
if r.Name == name {
rec := egoscale.UpdateDNSRecord{
ID: r.ID,
DomainID: r.DomainID,
Name: name,
RecordType: epoint.RecordType,
TTL: int(epoint.RecordTTL),
Content: epoint.Targets[0],
Prio: r.Prio,
}
if _, err := ep.client.UpdateRecord(ctx, zones[zoneID], rec); err != nil {
return err
}
break
}
}
if !ep.domain.Match(epoint.DNSName) {
continue
}
zoneID, name := ep.filter.EndpointZoneID(epoint, zones)
if zoneID == "" {
continue
}
records, err := ep.client.ListDNSDomainRecords(ctx, ep.apiZone, zoneID)
if err != nil {
return err
}
for _, r := range records {
if *r.Name != name {
continue
}
record, err := ep.client.GetDNSDomainRecord(ctx, ep.apiZone, zoneID, *r.ID)
if err != nil {
return err
}
record.Type = &epoint.RecordType
record.Content = &epoint.Targets[0]
if epoint.RecordTTL != 0 {
ttl := int64(epoint.RecordTTL)
record.TTL = &ttl
}
err = ep.client.UpdateDNSDomainRecord(ctx, ep.apiZone, zoneID, record)
if err != nil {
return err
}
break
}
}
@ -151,22 +193,31 @@ func (ep *ExoscaleProvider) ApplyChanges(ctx context.Context, changes *plan.Chan
}
for _, epoint := range changes.Delete {
if ep.domain.Match(epoint.DNSName) {
if zoneID, name := ep.filter.EndpointZoneID(epoint, zones); zoneID != 0 {
records, err := ep.client.GetRecords(ctx, zones[zoneID])
if err != nil {
return err
}
if !ep.domain.Match(epoint.DNSName) {
continue
}
for _, r := range records {
if r.Name == name {
if err := ep.client.DeleteRecord(ctx, zones[zoneID], r.ID); err != nil {
return err
}
break
}
}
zoneID, name := ep.filter.EndpointZoneID(epoint, zones)
if zoneID == "" {
continue
}
records, err := ep.client.ListDNSDomainRecords(ctx, ep.apiZone, zoneID)
if err != nil {
return err
}
for _, record := range records {
if *record.Name != name {
continue
}
err = ep.client.DeleteDNSDomainRecord(ctx, ep.apiZone, zoneID, &egoscale.DNSDomainRecord{ID: record.ID})
if err != nil {
return err
}
break
}
}
@ -175,27 +226,34 @@ func (ep *ExoscaleProvider) ApplyChanges(ctx context.Context, changes *plan.Chan
// Records returns the list of endpoints
func (ep *ExoscaleProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
ctx = exoapi.WithEndpoint(ctx, exoapi.NewReqEndpoint(ep.apiEnv, ep.apiZone))
endpoints := make([]*endpoint.Endpoint, 0)
domains, err := ep.client.GetDomains(ctx)
domains, err := ep.client.ListDNSDomains(ctx, ep.apiZone)
if err != nil {
return nil, err
}
for _, d := range domains {
record, err := ep.client.GetRecords(ctx, d.Name)
for _, domain := range domains {
records, err := ep.client.ListDNSDomainRecords(ctx, ep.apiZone, *domain.ID)
if err != nil {
return nil, err
}
for _, r := range record {
switch r.RecordType {
case egoscale.A.String(), egoscale.CNAME.String(), egoscale.TXT.String():
for _, r := range records {
record, err := ep.client.GetDNSDomainRecord(ctx, ep.apiZone, *domain.ID, *r.ID)
if err != nil {
return nil, err
}
switch *record.Type {
case "A", "CNAME", "TXT":
break
default:
continue
}
ep := endpoint.NewEndpointWithTTL(r.Name+"."+d.Name, r.RecordType, endpoint.TTL(r.TTL), r.Content)
endpoints = append(endpoints, ep)
e := endpoint.NewEndpointWithTTL((*record.Name)+"."+(*domain.UnicodeName), *record.Type, endpoint.TTL(*r.TTL), *record.Content)
endpoints = append(endpoints, e)
}
}
@ -235,8 +293,8 @@ type zoneFilter struct {
}
// Zones filters map[zoneID]zoneName for names having f.domain as suffix
func (f *zoneFilter) Zones(zones map[int64]string) map[int64]string {
result := map[int64]string{}
func (f *zoneFilter) Zones(zones map[string]string) map[string]string {
result := map[string]string{}
for zoneID, zoneName := range zones {
if strings.HasSuffix(zoneName, f.domain) {
result[zoneID] = zoneName
@ -246,9 +304,9 @@ func (f *zoneFilter) Zones(zones map[int64]string) map[int64]string {
}
// EndpointZoneID determines zoneID for endpoint from map[zoneID]zoneName by taking longest suffix zoneName match in endpoint DNSName
// returns 0 if no matches are found
func (f *zoneFilter) EndpointZoneID(endpoint *endpoint.Endpoint, zones map[int64]string) (zoneID int64, name string) {
var matchZoneID int64
// returns empty string if no matches are found
func (f *zoneFilter) EndpointZoneID(endpoint *endpoint.Endpoint, zones map[string]string) (zoneID string, name string) {
var matchZoneID string
var matchZoneName string
for zoneID, zoneName := range zones {
if strings.HasSuffix(endpoint.DNSName, "."+zoneName) && len(zoneName) > len(matchZoneName) {

View File

@ -18,29 +18,31 @@ package exoscale
import (
"context"
"strings"
"errors"
"testing"
"github.com/exoscale/egoscale"
egoscale "github.com/exoscale/egoscale/v2"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/external-dns/endpoint"
"sigs.k8s.io/external-dns/plan"
"github.com/google/uuid"
)
type createRecordExoscale struct {
name string
rec egoscale.DNSRecord
domainID string
record *egoscale.DNSDomainRecord
}
type deleteRecordExoscale struct {
name string
recordID int64
domainID string
recordID string
}
type updateRecordExoscale struct {
name string
updateDNSRecord egoscale.UpdateDNSRecord
domainID string
record *egoscale.DNSDomainRecord
}
var (
@ -49,6 +51,29 @@ var (
updateExoscale []updateRecordExoscale
)
var defaultTTL int64 = 3600
var domainIDs = []string{uuid.New().String(), uuid.New().String(), uuid.New().String(), uuid.New().String()}
var groups = map[string][]egoscale.DNSDomainRecord{
domainIDs[0]: {
{ID: strPtr(uuid.New().String()), Name: strPtr("v1"), Type: strPtr("TXT"), Content: strPtr("test"), TTL: &defaultTTL},
{ID: strPtr(uuid.New().String()), Name: strPtr("v2"), Type: strPtr("CNAME"), Content: strPtr("test"), TTL: &defaultTTL},
},
domainIDs[1]: {
{ID: strPtr(uuid.New().String()), Name: strPtr("v2"), Type: strPtr("A"), Content: strPtr("test"), TTL: &defaultTTL},
{ID: strPtr(uuid.New().String()), Name: strPtr("v3"), Type: strPtr("ALIAS"), Content: strPtr("test"), TTL: &defaultTTL},
},
domainIDs[2]: {
{ID: strPtr(uuid.New().String()), Name: strPtr("v1"), Type: strPtr("TXT"), Content: strPtr("test"), TTL: &defaultTTL},
},
domainIDs[3]: {
{ID: strPtr(uuid.New().String()), Name: strPtr("v4"), Type: strPtr("ALIAS"), Content: strPtr("test"), TTL: &defaultTTL},
},
}
func strPtr(s string) *string {
return &s
}
type ExoscaleClientStub struct{}
func NewExoscaleClientStub() EgoscaleClientI {
@ -56,48 +81,42 @@ func NewExoscaleClientStub() EgoscaleClientI {
return ep
}
func (ep *ExoscaleClientStub) DeleteRecord(ctx context.Context, name string, recordID int64) error {
deleteExoscale = append(deleteExoscale, deleteRecordExoscale{name: name, recordID: recordID})
return nil
func (ep *ExoscaleClientStub) ListDNSDomains(ctx context.Context, _ string) ([]egoscale.DNSDomain, error) {
domains := []egoscale.DNSDomain{
{ID: &domainIDs[0], UnicodeName: strPtr("foo.com")},
{ID: &domainIDs[1], UnicodeName: strPtr("bar.com")},
}
return domains, nil
}
func (ep *ExoscaleClientStub) GetRecords(ctx context.Context, name string) ([]egoscale.DNSRecord, error) {
init := []egoscale.DNSRecord{
{ID: 0, Name: "v4.barfoo.com", RecordType: "ALIAS"},
{ID: 1, Name: "v1.foo.com", RecordType: "TXT"},
{ID: 2, Name: "v2.bar.com", RecordType: "A"},
{ID: 3, Name: "v3.bar.com", RecordType: "ALIAS"},
{ID: 4, Name: "v2.foo.com", RecordType: "CNAME"},
{ID: 5, Name: "v1.foobar.com", RecordType: "TXT"},
}
func (ep *ExoscaleClientStub) ListDNSDomainRecords(ctx context.Context, _, domainID string) ([]egoscale.DNSDomainRecord, error) {
return groups[domainID], nil
}
rec := make([]egoscale.DNSRecord, 0)
for _, r := range init {
if strings.HasSuffix(r.Name, "."+name) {
r.Name = strings.TrimSuffix(r.Name, "."+name)
rec = append(rec, r)
func (ep *ExoscaleClientStub) GetDNSDomainRecord(ctx context.Context, _, domainID, recordID string) (*egoscale.DNSDomainRecord, error) {
group := groups[domainID]
for _, record := range group {
if *record.ID == recordID {
return &record, nil
}
}
return rec, nil
return nil, errors.New("not found")
}
func (ep *ExoscaleClientStub) UpdateRecord(ctx context.Context, name string, rec egoscale.UpdateDNSRecord) (*egoscale.DNSRecord, error) {
updateExoscale = append(updateExoscale, updateRecordExoscale{name: name, updateDNSRecord: rec})
return nil, nil
func (ep *ExoscaleClientStub) CreateDNSDomainRecord(ctx context.Context, _, domainID string, record *egoscale.DNSDomainRecord) (*egoscale.DNSDomainRecord, error) {
createExoscale = append(createExoscale, createRecordExoscale{domainID: domainID, record: record})
return record, nil
}
func (ep *ExoscaleClientStub) CreateRecord(ctx context.Context, name string, rec egoscale.DNSRecord) (*egoscale.DNSRecord, error) {
createExoscale = append(createExoscale, createRecordExoscale{name: name, rec: rec})
return nil, nil
func (ep *ExoscaleClientStub) DeleteDNSDomainRecord(ctx context.Context, _, domainID string, record *egoscale.DNSDomainRecord) error {
deleteExoscale = append(deleteExoscale, deleteRecordExoscale{domainID: domainID, recordID: *record.ID})
return nil
}
func (ep *ExoscaleClientStub) GetDomains(ctx context.Context) ([]egoscale.DNSDomain, error) {
dom := []egoscale.DNSDomain{
{ID: 1, Name: "foo.com"},
{ID: 2, Name: "bar.com"},
}
return dom, nil
func (ep *ExoscaleClientStub) UpdateDNSDomainRecord(ctx context.Context, _, domainID string, record *egoscale.DNSDomainRecord) error {
updateExoscale = append(updateExoscale, updateRecordExoscale{domainID: domainID, record: record})
return nil
}
func contains(arr []*endpoint.Endpoint, name string) bool {
@ -110,9 +129,10 @@ func contains(arr []*endpoint.Endpoint, name string) bool {
}
func TestExoscaleGetRecords(t *testing.T) {
provider := NewExoscaleProviderWithClient("", "", "", NewExoscaleClientStub(), false)
provider := NewExoscaleProviderWithClient(NewExoscaleClientStub(), "", "", false)
if recs, err := provider.Records(context.Background()); err == nil {
recs, err := provider.Records(context.Background())
if err == nil {
assert.Equal(t, 3, len(recs))
assert.True(t, contains(recs, "v1.foo.com"))
assert.True(t, contains(recs, "v2.bar.com"))
@ -125,7 +145,7 @@ func TestExoscaleGetRecords(t *testing.T) {
}
func TestExoscaleApplyChanges(t *testing.T) {
provider := NewExoscaleProviderWithClient("", "", "", NewExoscaleClientStub(), false)
provider := NewExoscaleProviderWithClient(NewExoscaleClientStub(), "", "", false)
plan := &plan.Changes{
Create: []*endpoint.Endpoint{
@ -183,16 +203,16 @@ func TestExoscaleApplyChanges(t *testing.T) {
provider.ApplyChanges(context.Background(), plan)
assert.Equal(t, 1, len(createExoscale))
assert.Equal(t, "foo.com", createExoscale[0].name)
assert.Equal(t, "v1", createExoscale[0].rec.Name)
assert.Equal(t, domainIDs[0], createExoscale[0].domainID)
assert.Equal(t, "v1", *createExoscale[0].record.Name)
assert.Equal(t, 1, len(deleteExoscale))
assert.Equal(t, "foo.com", deleteExoscale[0].name)
assert.Equal(t, int64(1), deleteExoscale[0].recordID)
assert.Equal(t, domainIDs[0], deleteExoscale[0].domainID)
assert.Equal(t, *groups[domainIDs[0]][0].ID, deleteExoscale[0].recordID)
assert.Equal(t, 1, len(updateExoscale))
assert.Equal(t, "foo.com", updateExoscale[0].name)
assert.Equal(t, int64(1), updateExoscale[0].updateDNSRecord.ID)
assert.Equal(t, domainIDs[0], updateExoscale[0].domainID)
assert.Equal(t, *groups[domainIDs[0]][0].ID, *updateExoscale[0].record.ID)
}
func TestExoscaleMerge_NoUpdateOnTTL0Changes(t *testing.T) {