mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 17:46:57 +02:00
add unit tests for plural provider (#11)
This commit is contained in:
parent
3f5ea38814
commit
79b7fe93d8
@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package plural
|
||||
|
||||
import (
|
||||
@ -20,6 +36,12 @@ func (t *authedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return t.wrapped.RoundTrip(req)
|
||||
}
|
||||
|
||||
type Client interface {
|
||||
DnsRecords() ([]*DnsRecord, error)
|
||||
CreateRecord(record *DnsRecord) (*DnsRecord, error)
|
||||
DeleteRecord(name, ttype string) error
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Token string
|
||||
Endpoint string
|
||||
@ -27,7 +49,7 @@ type Config struct {
|
||||
Provider string
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
type client struct {
|
||||
ctx context.Context
|
||||
pluralClient *gqlclient.Client
|
||||
config *Config
|
||||
@ -39,7 +61,7 @@ type DnsRecord struct {
|
||||
Records []string
|
||||
}
|
||||
|
||||
func NewClient(conf *Config) *Client {
|
||||
func NewClient(conf *Config) Client {
|
||||
base := conf.BaseUrl()
|
||||
httpClient := http.Client{
|
||||
Transport: &authedTransport{
|
||||
@ -48,7 +70,7 @@ func NewClient(conf *Config) *Client {
|
||||
},
|
||||
}
|
||||
endpoint := base + "/gql"
|
||||
return &Client{
|
||||
return &client{
|
||||
ctx: context.Background(),
|
||||
pluralClient: gqlclient.NewClient(&httpClient, endpoint),
|
||||
config: conf,
|
||||
@ -63,7 +85,7 @@ func (c *Config) BaseUrl() string {
|
||||
return host
|
||||
}
|
||||
|
||||
func (client *Client) DnsRecords() ([]*DnsRecord, error) {
|
||||
func (client *client) DnsRecords() ([]*DnsRecord, error) {
|
||||
resp, err := client.pluralClient.GetDNSRecords(client.ctx, client.config.Cluster, gqlclient.Provider(strings.ToUpper(client.config.Provider)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -83,7 +105,7 @@ func (client *Client) DnsRecords() ([]*DnsRecord, error) {
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func (client *Client) CreateRecord(record *DnsRecord) (*DnsRecord, error) {
|
||||
func (client *client) CreateRecord(record *DnsRecord) (*DnsRecord, error) {
|
||||
provider := gqlclient.Provider(strings.ToUpper(client.config.Provider))
|
||||
cluster := client.config.Cluster
|
||||
attr := gqlclient.DNSRecordAttributes{
|
||||
@ -108,7 +130,7 @@ func (client *Client) CreateRecord(record *DnsRecord) (*DnsRecord, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (client *Client) DeleteRecord(name, ttype string) error {
|
||||
func (client *client) DeleteRecord(name, ttype string) error {
|
||||
if _, err := client.pluralClient.DeleteDNSRecord(client.ctx, name, gqlclient.DNSRecordType(ttype)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package plural
|
||||
|
||||
import (
|
||||
@ -18,7 +34,7 @@ const (
|
||||
|
||||
type PluralProvider struct {
|
||||
provider.BaseProvider
|
||||
Client *Client
|
||||
Client Client
|
||||
}
|
||||
|
||||
type RecordChange struct {
|
||||
@ -47,7 +63,7 @@ func NewPluralProvider(cluster, provider string) (*PluralProvider, error) {
|
||||
return prov, nil
|
||||
}
|
||||
|
||||
func (p *PluralProvider) Records(ctx context.Context) (endpoints []*endpoint.Endpoint, err error) {
|
||||
func (p *PluralProvider) Records(_ context.Context) (endpoints []*endpoint.Endpoint, err error) {
|
||||
records, err := p.Client.DnsRecords()
|
||||
if err != nil {
|
||||
return
|
||||
@ -68,8 +84,8 @@ func (p *PluralProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) []*endp
|
||||
return endpoints
|
||||
}
|
||||
|
||||
func (p *PluralProvider) ApplyChanges(ctx context.Context, diffs *plan.Changes) error {
|
||||
changes := []*RecordChange{}
|
||||
func (p *PluralProvider) ApplyChanges(_ context.Context, diffs *plan.Changes) error {
|
||||
var changes []*RecordChange
|
||||
for _, endpoint := range diffs.Create {
|
||||
changes = append(changes, makeChange(CreateAction, endpoint.Targets, endpoint))
|
||||
}
|
||||
|
381
provider/plural/plural_test.go
Normal file
381
provider/plural/plural_test.go
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package plural
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/external-dns/plan"
|
||||
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
"sigs.k8s.io/external-dns/internal/testutils"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"sigs.k8s.io/external-dns/provider"
|
||||
)
|
||||
|
||||
type ClientStub struct {
|
||||
mockDnsRecords []*DnsRecord
|
||||
}
|
||||
|
||||
// CreateRecord provides a mock function with given fields: record
|
||||
func (c *ClientStub) CreateRecord(record *DnsRecord) (*DnsRecord, error) {
|
||||
c.mockDnsRecords = append(c.mockDnsRecords, record)
|
||||
return record, nil
|
||||
}
|
||||
|
||||
// DeleteRecord provides a mock function with given fields: name, ttype
|
||||
func (c *ClientStub) DeleteRecord(name string, ttype string) error {
|
||||
newRecords := make([]*DnsRecord, 0)
|
||||
for _, record := range c.mockDnsRecords {
|
||||
if record.Name == name && record.Type == ttype {
|
||||
continue
|
||||
}
|
||||
newRecords = append(newRecords, record)
|
||||
}
|
||||
c.mockDnsRecords = newRecords
|
||||
return nil
|
||||
}
|
||||
|
||||
// DnsRecords provides a mock function with given fields:
|
||||
func (c *ClientStub) DnsRecords() ([]*DnsRecord, error) {
|
||||
return c.mockDnsRecords, nil
|
||||
}
|
||||
|
||||
func newPluralProvider(pluralDNSRecord []*DnsRecord) *PluralProvider {
|
||||
if pluralDNSRecord == nil {
|
||||
pluralDNSRecord = make([]*DnsRecord, 0)
|
||||
}
|
||||
return &PluralProvider{
|
||||
BaseProvider: provider.BaseProvider{},
|
||||
Client: &ClientStub{
|
||||
mockDnsRecords: pluralDNSRecord,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluralRecords(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
expectedEndpoints []*endpoint.Endpoint
|
||||
records []*DnsRecord
|
||||
}{
|
||||
{
|
||||
name: "check records",
|
||||
records: []*DnsRecord{
|
||||
{
|
||||
Type: endpoint.RecordTypeA,
|
||||
Name: "example.com",
|
||||
Records: []string{"123.123.123.122"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeA,
|
||||
Name: "nginx.example.com",
|
||||
Records: []string{"123.123.123.123"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeCNAME,
|
||||
Name: "hack.example.com",
|
||||
Records: []string{"bluecatnetworks.com"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeTXT,
|
||||
Name: "kdb.example.com",
|
||||
Records: []string{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
|
||||
},
|
||||
},
|
||||
expectedEndpoints: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.122"},
|
||||
},
|
||||
{
|
||||
DNSName: "nginx.example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.123"},
|
||||
},
|
||||
{
|
||||
DNSName: "hack.example.com",
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Targets: endpoint.Targets{"bluecatnetworks.com"},
|
||||
},
|
||||
{
|
||||
DNSName: "kdb.example.com",
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
Targets: endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
provider := newPluralProvider(test.records)
|
||||
|
||||
actual, err := provider.Records(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
validateEndpoints(t, actual, test.expectedEndpoints)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestPluralApplyChangesCreate(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
expectedEndpoints []*endpoint.Endpoint
|
||||
}{
|
||||
{
|
||||
name: "create new endpoints",
|
||||
expectedEndpoints: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.122"},
|
||||
},
|
||||
{
|
||||
DNSName: "nginx.example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.123"},
|
||||
},
|
||||
{
|
||||
DNSName: "hack.example.com",
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Targets: endpoint.Targets{"bluecatnetworks.com"},
|
||||
},
|
||||
{
|
||||
DNSName: "kdb.example.com",
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
Targets: endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
provider := newPluralProvider(nil)
|
||||
|
||||
// no records
|
||||
actual, err := provider.Records(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, len(actual), 0, "expected no entries")
|
||||
|
||||
err = provider.ApplyChanges(context.Background(), &plan.Changes{Create: test.expectedEndpoints})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
actual, err = provider.Records(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
validateEndpoints(t, actual, test.expectedEndpoints)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluralApplyChangesDelete(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
records []*DnsRecord
|
||||
deleteEndpoints []*endpoint.Endpoint
|
||||
expectedEndpoints []*endpoint.Endpoint
|
||||
}{
|
||||
{
|
||||
name: "delete not existing record",
|
||||
records: []*DnsRecord{
|
||||
{
|
||||
Type: endpoint.RecordTypeA,
|
||||
Name: "example.com",
|
||||
Records: []string{"123.123.123.122"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeA,
|
||||
Name: "nginx.example.com",
|
||||
Records: []string{"123.123.123.123"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeCNAME,
|
||||
Name: "hack.example.com",
|
||||
Records: []string{"bluecatnetworks.com"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeTXT,
|
||||
Name: "kdb.example.com",
|
||||
Records: []string{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
|
||||
},
|
||||
},
|
||||
deleteEndpoints: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "fake.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
},
|
||||
expectedEndpoints: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.122"},
|
||||
},
|
||||
{
|
||||
DNSName: "nginx.example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.123"},
|
||||
},
|
||||
{
|
||||
DNSName: "hack.example.com",
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Targets: endpoint.Targets{"bluecatnetworks.com"},
|
||||
},
|
||||
{
|
||||
DNSName: "kdb.example.com",
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
Targets: endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "delete one record",
|
||||
records: []*DnsRecord{
|
||||
{
|
||||
Type: endpoint.RecordTypeA,
|
||||
Name: "example.com",
|
||||
Records: []string{"123.123.123.122"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeA,
|
||||
Name: "nginx.example.com",
|
||||
Records: []string{"123.123.123.123"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeCNAME,
|
||||
Name: "hack.example.com",
|
||||
Records: []string{"bluecatnetworks.com"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeTXT,
|
||||
Name: "kdb.example.com",
|
||||
Records: []string{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
|
||||
},
|
||||
},
|
||||
deleteEndpoints: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "kdb.example.com",
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
Targets: endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
|
||||
},
|
||||
},
|
||||
expectedEndpoints: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.122"},
|
||||
},
|
||||
{
|
||||
DNSName: "nginx.example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.123"},
|
||||
},
|
||||
{
|
||||
DNSName: "hack.example.com",
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Targets: endpoint.Targets{"bluecatnetworks.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "delete all records",
|
||||
records: []*DnsRecord{
|
||||
{
|
||||
Type: endpoint.RecordTypeA,
|
||||
Name: "example.com",
|
||||
Records: []string{"123.123.123.122"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeA,
|
||||
Name: "nginx.example.com",
|
||||
Records: []string{"123.123.123.123"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeCNAME,
|
||||
Name: "hack.example.com",
|
||||
Records: []string{"bluecatnetworks.com"},
|
||||
},
|
||||
{
|
||||
Type: endpoint.RecordTypeTXT,
|
||||
Name: "kdb.example.com",
|
||||
Records: []string{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
|
||||
},
|
||||
},
|
||||
deleteEndpoints: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "kdb.example.com",
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
Targets: endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
|
||||
},
|
||||
{
|
||||
DNSName: "example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.122"},
|
||||
},
|
||||
{
|
||||
DNSName: "nginx.example.com",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"123.123.123.123"},
|
||||
},
|
||||
{
|
||||
DNSName: "hack.example.com",
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Targets: endpoint.Targets{"bluecatnetworks.com"},
|
||||
},
|
||||
},
|
||||
expectedEndpoints: []*endpoint.Endpoint{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
provider := newPluralProvider(test.records)
|
||||
|
||||
err := provider.ApplyChanges(context.Background(), &plan.Changes{Delete: test.deleteEndpoints})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
actual, err := provider.Records(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
validateEndpoints(t, actual, test.expectedEndpoints)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func validateEndpoints(t *testing.T, endpoints []*endpoint.Endpoint, expected []*endpoint.Endpoint) {
|
||||
assert.True(t, testutils.SameEndpoints(endpoints, expected), "expected and actual endpoints don't match. %s:%s", endpoints, expected)
|
||||
}
|
Loading…
Reference in New Issue
Block a user