mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2026-05-05 22:56:09 +02:00
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:
parent
c6a64396c2
commit
7ddc9daba7
@ -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
2
go.mod
@ -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
10
main.go
@ -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":
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user