sigs.k8s.io/external-dns@v0.14.1/provider/safedns/safedns_test.go (about)

     1  /*
     2  Copyright 2021 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package safedns
    18  
    19  import (
    20  	"context"
    21  	"os"
    22  	"testing"
    23  
    24  	ansConnection "github.com/ans-group/sdk-go/pkg/connection"
    25  	"github.com/ans-group/sdk-go/pkg/service/safedns"
    26  	"github.com/stretchr/testify/assert"
    27  	"github.com/stretchr/testify/mock"
    28  	"github.com/stretchr/testify/require"
    29  
    30  	"sigs.k8s.io/external-dns/endpoint"
    31  	"sigs.k8s.io/external-dns/plan"
    32  )
    33  
    34  // Create an implementation of the SafeDNS interface for Mocking
    35  type MockSafeDNSService struct {
    36  	mock.Mock
    37  }
    38  
    39  func (m *MockSafeDNSService) CreateZoneRecord(zoneName string, req safedns.CreateRecordRequest) (int, error) {
    40  	args := m.Called(zoneName, req)
    41  	return args.Int(0), args.Error(1)
    42  }
    43  
    44  func (m *MockSafeDNSService) DeleteZoneRecord(zoneName string, recordID int) error {
    45  	args := m.Called(zoneName, recordID)
    46  	return args.Error(0)
    47  }
    48  
    49  func (m *MockSafeDNSService) GetZone(zoneName string) (safedns.Zone, error) {
    50  	args := m.Called(zoneName)
    51  	return args.Get(0).(safedns.Zone), args.Error(1)
    52  }
    53  
    54  func (m *MockSafeDNSService) GetZoneRecord(zoneName string, recordID int) (safedns.Record, error) {
    55  	args := m.Called(zoneName, recordID)
    56  	return args.Get(0).(safedns.Record), args.Error(1)
    57  }
    58  
    59  func (m *MockSafeDNSService) GetZoneRecords(zoneName string, parameters ansConnection.APIRequestParameters) ([]safedns.Record, error) {
    60  	args := m.Called(zoneName, parameters)
    61  	return args.Get(0).([]safedns.Record), args.Error(1)
    62  }
    63  
    64  func (m *MockSafeDNSService) GetZones(parameters ansConnection.APIRequestParameters) ([]safedns.Zone, error) {
    65  	args := m.Called(parameters)
    66  	return args.Get(0).([]safedns.Zone), args.Error(1)
    67  }
    68  
    69  func (m *MockSafeDNSService) PatchZoneRecord(zoneName string, recordID int, patch safedns.PatchRecordRequest) (int, error) {
    70  	args := m.Called(zoneName, recordID, patch)
    71  	return args.Int(0), args.Error(1)
    72  }
    73  
    74  func (m *MockSafeDNSService) UpdateZoneRecord(zoneName string, record safedns.Record) (int, error) {
    75  	args := m.Called(zoneName, record)
    76  	return args.Int(0), args.Error(1)
    77  }
    78  
    79  // Utility functions
    80  func createZones() []safedns.Zone {
    81  	return []safedns.Zone{
    82  		{Name: "foo.com", Description: "Foo dot com"},
    83  		{Name: "bar.io", Description: ""},
    84  		{Name: "baz.org", Description: "Org"},
    85  	}
    86  }
    87  
    88  func createFooRecords() []safedns.Record {
    89  	return []safedns.Record{
    90  		{
    91  			ID:      11,
    92  			Type:    safedns.RecordTypeA,
    93  			Name:    "foo.com",
    94  			Content: "targetFoo",
    95  			TTL:     safedns.RecordTTL(3600),
    96  		},
    97  		{
    98  			ID:      12,
    99  			Type:    safedns.RecordTypeTXT,
   100  			Name:    "foo.com",
   101  			Content: "text",
   102  			TTL:     safedns.RecordTTL(3600),
   103  		},
   104  		{
   105  			ID:      13,
   106  			Type:    safedns.RecordTypeCAA,
   107  			Name:    "foo.com",
   108  			Content: "",
   109  			TTL:     safedns.RecordTTL(3600),
   110  		},
   111  	}
   112  }
   113  
   114  func createBarRecords() []safedns.Record {
   115  	return []safedns.Record{}
   116  }
   117  
   118  func createBazRecords() []safedns.Record {
   119  	return []safedns.Record{
   120  		{
   121  			ID:      31,
   122  			Type:    safedns.RecordTypeA,
   123  			Name:    "baz.org",
   124  			Content: "targetBaz",
   125  			TTL:     safedns.RecordTTL(3600),
   126  		},
   127  		{
   128  			ID:      32,
   129  			Type:    safedns.RecordTypeTXT,
   130  			Name:    "baz.org",
   131  			Content: "text",
   132  			TTL:     safedns.RecordTTL(3600),
   133  		},
   134  		{
   135  			ID:      33,
   136  			Type:    safedns.RecordTypeA,
   137  			Name:    "api.baz.org",
   138  			Content: "targetBazAPI",
   139  			TTL:     safedns.RecordTTL(3600),
   140  		},
   141  		{
   142  			ID:      34,
   143  			Type:    safedns.RecordTypeTXT,
   144  			Name:    "api.baz.org",
   145  			Content: "text",
   146  			TTL:     safedns.RecordTTL(3600),
   147  		},
   148  	}
   149  }
   150  
   151  // Actual tests
   152  func TestNewSafeDNSProvider(t *testing.T) {
   153  	_ = os.Setenv("SAFEDNS_TOKEN", "DUMMYVALUE")
   154  	_, err := NewSafeDNSProvider(endpoint.NewDomainFilter([]string{"ext-dns-test.zalando.to."}), true)
   155  	require.NoError(t, err)
   156  
   157  	_ = os.Unsetenv("SAFEDNS_TOKEN")
   158  	_, err = NewSafeDNSProvider(endpoint.NewDomainFilter([]string{"ext-dns-test.zalando.to."}), true)
   159  	require.Error(t, err)
   160  }
   161  
   162  func TestRecords(t *testing.T) {
   163  	mockSafeDNSService := MockSafeDNSService{}
   164  
   165  	provider := &SafeDNSProvider{
   166  		Client:       &mockSafeDNSService,
   167  		domainFilter: endpoint.NewDomainFilter([]string{}),
   168  		DryRun:       false,
   169  	}
   170  
   171  	mockSafeDNSService.On(
   172  		"GetZones",
   173  		mock.Anything,
   174  	).Return(createZones(), nil).Once()
   175  
   176  	mockSafeDNSService.On(
   177  		"GetZoneRecords",
   178  		"foo.com",
   179  		mock.Anything,
   180  	).Return(createFooRecords(), nil).Once()
   181  
   182  	mockSafeDNSService.On(
   183  		"GetZoneRecords",
   184  		"bar.io",
   185  		mock.Anything,
   186  	).Return(createBarRecords(), nil).Once()
   187  
   188  	mockSafeDNSService.On(
   189  		"GetZoneRecords",
   190  		"baz.org",
   191  		mock.Anything,
   192  	).Return(createBazRecords(), nil).Once()
   193  
   194  	actual, err := provider.Records(context.Background())
   195  	require.NoError(t, err)
   196  
   197  	expected := []*endpoint.Endpoint{
   198  		{
   199  			DNSName:    "foo.com",
   200  			Targets:    []string{"targetFoo"},
   201  			RecordType: "A",
   202  			RecordTTL:  3600,
   203  			Labels:     endpoint.NewLabels(),
   204  		},
   205  		{
   206  			DNSName:    "foo.com",
   207  			Targets:    []string{"text"},
   208  			RecordType: "TXT",
   209  			RecordTTL:  3600,
   210  			Labels:     endpoint.NewLabels(),
   211  		},
   212  		{
   213  			DNSName:    "baz.org",
   214  			Targets:    []string{"targetBaz"},
   215  			RecordType: "A",
   216  			RecordTTL:  3600,
   217  			Labels:     endpoint.NewLabels(),
   218  		},
   219  		{
   220  			DNSName:    "baz.org",
   221  			Targets:    []string{"text"},
   222  			RecordType: "TXT",
   223  			RecordTTL:  3600,
   224  			Labels:     endpoint.NewLabels(),
   225  		},
   226  		{
   227  			DNSName:    "api.baz.org",
   228  			Targets:    []string{"targetBazAPI"},
   229  			RecordType: "A",
   230  			RecordTTL:  3600,
   231  			Labels:     endpoint.NewLabels(),
   232  		},
   233  		{
   234  			DNSName:    "api.baz.org",
   235  			Targets:    []string{"text"},
   236  			RecordType: "TXT",
   237  			RecordTTL:  3600,
   238  			Labels:     endpoint.NewLabels(),
   239  		},
   240  	}
   241  
   242  	mockSafeDNSService.AssertExpectations(t)
   243  	assert.Equal(t, expected, actual)
   244  }
   245  
   246  func TestSafeDNSApplyChanges(t *testing.T) {
   247  	mockSafeDNSService := MockSafeDNSService{}
   248  
   249  	provider := &SafeDNSProvider{
   250  		Client:       &mockSafeDNSService,
   251  		domainFilter: endpoint.NewDomainFilter([]string{}),
   252  		DryRun:       false,
   253  	}
   254  
   255  	// Dummy data
   256  	mockSafeDNSService.On(
   257  		"GetZones",
   258  		mock.Anything,
   259  	).Return(createZones(), nil).Once()
   260  	mockSafeDNSService.On(
   261  		"GetZones",
   262  		mock.Anything,
   263  	).Return(createZones(), nil).Once()
   264  
   265  	mockSafeDNSService.On(
   266  		"GetZoneRecords",
   267  		"foo.com",
   268  		mock.Anything,
   269  	).Return(createFooRecords(), nil).Once()
   270  
   271  	mockSafeDNSService.On(
   272  		"GetZoneRecords",
   273  		"bar.io",
   274  		mock.Anything,
   275  	).Return(createBarRecords(), nil).Once()
   276  
   277  	mockSafeDNSService.On(
   278  		"GetZoneRecords",
   279  		"baz.org",
   280  		mock.Anything,
   281  	).Return(createBazRecords(), nil).Once()
   282  
   283  	// Apply actions
   284  	mockSafeDNSService.On(
   285  		"DeleteZoneRecord",
   286  		"baz.org",
   287  		33,
   288  	).Return(nil).Once()
   289  	mockSafeDNSService.On(
   290  		"DeleteZoneRecord",
   291  		"baz.org",
   292  		34,
   293  	).Return(nil).Once()
   294  
   295  	TTL300 := safedns.RecordTTL(300)
   296  	mockSafeDNSService.On(
   297  		"PatchZoneRecord",
   298  		"foo.com",
   299  		11,
   300  		safedns.PatchRecordRequest{
   301  			Type:    "A",
   302  			Name:    "foo.com",
   303  			Content: "targetFoo",
   304  			TTL:     &TTL300,
   305  		},
   306  	).Return(123, nil).Once()
   307  
   308  	mockSafeDNSService.On(
   309  		"CreateZoneRecord",
   310  		"bar.io",
   311  		safedns.CreateRecordRequest{
   312  			Type:    "A",
   313  			Name:    "create.bar.io",
   314  			Content: "targetBar",
   315  		},
   316  	).Return(246, nil).Once()
   317  
   318  	mockSafeDNSService.On(
   319  		"CreateZoneRecord",
   320  		"bar.io",
   321  		safedns.CreateRecordRequest{
   322  			Type:    "A",
   323  			Name:    "bar.io",
   324  			Content: "targetBar",
   325  		},
   326  	).Return(369, nil).Once()
   327  
   328  	err := provider.ApplyChanges(context.Background(), &plan.Changes{
   329  		Create: []*endpoint.Endpoint{
   330  			{
   331  				DNSName:    "create.bar.io",
   332  				RecordType: "A",
   333  				Targets:    []string{"targetBar"},
   334  				RecordTTL:  3600,
   335  			},
   336  			{
   337  				DNSName:    "bar.io",
   338  				RecordType: "A",
   339  				Targets:    []string{"targetBar"},
   340  				RecordTTL:  3600,
   341  			},
   342  		},
   343  		Delete: []*endpoint.Endpoint{
   344  			{
   345  				DNSName:    "api.baz.org",
   346  				RecordType: "A",
   347  			},
   348  			{
   349  				DNSName:    "api.baz.org",
   350  				RecordType: "TXT",
   351  			},
   352  		},
   353  		UpdateNew: []*endpoint.Endpoint{
   354  			{
   355  				DNSName:    "foo.com",
   356  				RecordType: "A",
   357  				RecordTTL:  300,
   358  				Targets:    []string{"targetFoo"},
   359  			},
   360  		},
   361  		UpdateOld: []*endpoint.Endpoint{},
   362  	})
   363  	require.NoError(t, err)
   364  
   365  	mockSafeDNSService.AssertExpectations(t)
   366  }