sigs.k8s.io/external-dns@v0.14.1/source/f5_virtualserver_test.go (about)

     1  /*
     2  Copyright 2022 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 source
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	fakeDynamic "k8s.io/client-go/dynamic/fake"
    30  	fakeKube "k8s.io/client-go/kubernetes/fake"
    31  	"sigs.k8s.io/external-dns/endpoint"
    32  
    33  	f5 "github.com/F5Networks/k8s-bigip-ctlr/v2/config/apis/cis/v1"
    34  )
    35  
    36  const defaultF5VirtualServerNamespace = "virtualserver"
    37  
    38  func TestF5VirtualServerEndpoints(t *testing.T) {
    39  	t.Parallel()
    40  
    41  	tests := []struct {
    42  		name             string
    43  		annotationFilter string
    44  		virtualServer    f5.VirtualServer
    45  		expected         []*endpoint.Endpoint
    46  	}{
    47  		{
    48  			name:             "F5 VirtualServer with target annotation",
    49  			annotationFilter: "",
    50  			virtualServer: f5.VirtualServer{
    51  				TypeMeta: metav1.TypeMeta{
    52  					APIVersion: f5VirtualServerGVR.GroupVersion().String(),
    53  					Kind:       "VirtualServer",
    54  				},
    55  				ObjectMeta: metav1.ObjectMeta{
    56  					Name:      "test-vs",
    57  					Namespace: defaultF5VirtualServerNamespace,
    58  					Annotations: map[string]string{
    59  						targetAnnotationKey: "192.168.1.150",
    60  					},
    61  				},
    62  				Spec: f5.VirtualServerSpec{
    63  					Host:                 "www.example.com",
    64  					VirtualServerAddress: "192.168.1.100",
    65  				},
    66  				Status: f5.VirtualServerStatus{
    67  					VSAddress: "192.168.1.200",
    68  				},
    69  			},
    70  			expected: []*endpoint.Endpoint{
    71  				{
    72  					DNSName:    "www.example.com",
    73  					Targets:    []string{"192.168.1.150"},
    74  					RecordType: endpoint.RecordTypeA,
    75  					RecordTTL:  0,
    76  					Labels: endpoint.Labels{
    77  						"resource": "f5-virtualserver/virtualserver/test-vs",
    78  					},
    79  				},
    80  			},
    81  		},
    82  		{
    83  			name:             "F5 VirtualServer with host and virtualServerAddress set",
    84  			annotationFilter: "",
    85  			virtualServer: f5.VirtualServer{
    86  				TypeMeta: metav1.TypeMeta{
    87  					APIVersion: f5VirtualServerGVR.GroupVersion().String(),
    88  					Kind:       "VirtualServer",
    89  				},
    90  				ObjectMeta: metav1.ObjectMeta{
    91  					Name:      "test-vs",
    92  					Namespace: defaultF5VirtualServerNamespace,
    93  				},
    94  				Spec: f5.VirtualServerSpec{
    95  					Host:                 "www.example.com",
    96  					VirtualServerAddress: "192.168.1.100",
    97  				},
    98  				Status: f5.VirtualServerStatus{
    99  					VSAddress: "192.168.1.200",
   100  				},
   101  			},
   102  			expected: []*endpoint.Endpoint{
   103  				{
   104  					DNSName:    "www.example.com",
   105  					Targets:    []string{"192.168.1.100"},
   106  					RecordType: endpoint.RecordTypeA,
   107  					RecordTTL:  0,
   108  					Labels: endpoint.Labels{
   109  						"resource": "f5-virtualserver/virtualserver/test-vs",
   110  					},
   111  				},
   112  			},
   113  		},
   114  		{
   115  			name:             "F5 VirtualServer with host set and IP address from the status field",
   116  			annotationFilter: "",
   117  			virtualServer: f5.VirtualServer{
   118  				TypeMeta: metav1.TypeMeta{
   119  					APIVersion: f5VirtualServerGVR.GroupVersion().String(),
   120  					Kind:       "VirtualServer",
   121  				},
   122  				ObjectMeta: metav1.ObjectMeta{
   123  					Name:      "test-vs",
   124  					Namespace: defaultF5VirtualServerNamespace,
   125  				},
   126  				Spec: f5.VirtualServerSpec{
   127  					Host: "www.example.com",
   128  				},
   129  				Status: f5.VirtualServerStatus{
   130  					VSAddress: "192.168.1.100",
   131  				},
   132  			},
   133  			expected: []*endpoint.Endpoint{
   134  				{
   135  					DNSName:    "www.example.com",
   136  					Targets:    []string{"192.168.1.100"},
   137  					RecordType: endpoint.RecordTypeA,
   138  					RecordTTL:  0,
   139  					Labels: endpoint.Labels{
   140  						"resource": "f5-virtualserver/virtualserver/test-vs",
   141  					},
   142  				},
   143  			},
   144  		},
   145  		{
   146  			name:             "F5 VirtualServer with no IP address set",
   147  			annotationFilter: "",
   148  			virtualServer: f5.VirtualServer{
   149  				TypeMeta: metav1.TypeMeta{
   150  					APIVersion: f5VirtualServerGVR.GroupVersion().String(),
   151  					Kind:       "VirtualServer",
   152  				},
   153  				ObjectMeta: metav1.ObjectMeta{
   154  					Name:      "test-vs",
   155  					Namespace: defaultF5VirtualServerNamespace,
   156  				},
   157  				Spec: f5.VirtualServerSpec{
   158  					Host: "www.example.com",
   159  				},
   160  				Status: f5.VirtualServerStatus{
   161  					VSAddress: "",
   162  				},
   163  			},
   164  			expected: nil,
   165  		},
   166  		{
   167  			name:             "F5 VirtualServer with matching annotation filter",
   168  			annotationFilter: "foo=bar",
   169  			virtualServer: f5.VirtualServer{
   170  				TypeMeta: metav1.TypeMeta{
   171  					APIVersion: f5VirtualServerGVR.GroupVersion().String(),
   172  					Kind:       "VirtualServer",
   173  				},
   174  				ObjectMeta: metav1.ObjectMeta{
   175  					Name:      "test-vs",
   176  					Namespace: defaultF5VirtualServerNamespace,
   177  					Annotations: map[string]string{
   178  						"foo": "bar",
   179  					},
   180  				},
   181  				Spec: f5.VirtualServerSpec{
   182  					Host:                 "www.example.com",
   183  					VirtualServerAddress: "192.168.1.100",
   184  				},
   185  			},
   186  			expected: []*endpoint.Endpoint{
   187  				{
   188  					DNSName:    "www.example.com",
   189  					Targets:    []string{"192.168.1.100"},
   190  					RecordType: endpoint.RecordTypeA,
   191  					RecordTTL:  0,
   192  					Labels: endpoint.Labels{
   193  						"resource": "f5-virtualserver/virtualserver/test-vs",
   194  					},
   195  				},
   196  			},
   197  		},
   198  		{
   199  			name:             "F5 VirtualServer with non-matching annotation filter",
   200  			annotationFilter: "foo=bar",
   201  			virtualServer: f5.VirtualServer{
   202  				TypeMeta: metav1.TypeMeta{
   203  					APIVersion: f5VirtualServerGVR.GroupVersion().String(),
   204  					Kind:       "VirtualServer",
   205  				},
   206  				ObjectMeta: metav1.ObjectMeta{
   207  					Name:      "test-vs",
   208  					Namespace: defaultF5VirtualServerNamespace,
   209  					Annotations: map[string]string{
   210  						"bar": "foo",
   211  					},
   212  				},
   213  				Spec: f5.VirtualServerSpec{
   214  					Host:                 "www.example.com",
   215  					VirtualServerAddress: "192.168.1.100",
   216  				},
   217  			},
   218  			expected: nil,
   219  		},
   220  		{
   221  			name: "F5 VirtualServer TTL annotation",
   222  			virtualServer: f5.VirtualServer{
   223  				TypeMeta: metav1.TypeMeta{
   224  					APIVersion: f5VirtualServerGVR.GroupVersion().String(),
   225  					Kind:       "VirtualServer",
   226  				},
   227  				ObjectMeta: metav1.ObjectMeta{
   228  					Name:      "test-vs",
   229  					Namespace: defaultF5VirtualServerNamespace,
   230  					Annotations: map[string]string{
   231  						"external-dns.alpha.kubernetes.io/ttl": "600",
   232  					},
   233  				},
   234  				Spec: f5.VirtualServerSpec{
   235  					Host:                 "www.example.com",
   236  					VirtualServerAddress: "192.168.1.100",
   237  				},
   238  			},
   239  			expected: []*endpoint.Endpoint{
   240  				{
   241  					DNSName:    "www.example.com",
   242  					Targets:    []string{"192.168.1.100"},
   243  					RecordType: endpoint.RecordTypeA,
   244  					RecordTTL:  600,
   245  					Labels: endpoint.Labels{
   246  						"resource": "f5-virtualserver/virtualserver/test-vs",
   247  					},
   248  				},
   249  			},
   250  		},
   251  	}
   252  
   253  	for _, tc := range tests {
   254  		t.Run(tc.name, func(t *testing.T) {
   255  			fakeKubernetesClient := fakeKube.NewSimpleClientset()
   256  			scheme := runtime.NewScheme()
   257  			scheme.AddKnownTypes(f5VirtualServerGVR.GroupVersion(), &f5.VirtualServer{}, &f5.VirtualServerList{})
   258  			fakeDynamicClient := fakeDynamic.NewSimpleDynamicClient(scheme)
   259  
   260  			virtualServer := unstructured.Unstructured{}
   261  
   262  			virtualServerJSON, err := json.Marshal(tc.virtualServer)
   263  			require.NoError(t, err)
   264  			assert.NoError(t, virtualServer.UnmarshalJSON(virtualServerJSON))
   265  
   266  			// Create VirtualServer resources
   267  			_, err = fakeDynamicClient.Resource(f5VirtualServerGVR).Namespace(defaultF5VirtualServerNamespace).Create(context.Background(), &virtualServer, metav1.CreateOptions{})
   268  			assert.NoError(t, err)
   269  
   270  			source, err := NewF5VirtualServerSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultF5VirtualServerNamespace, tc.annotationFilter)
   271  			require.NoError(t, err)
   272  			assert.NotNil(t, source)
   273  
   274  			count := &unstructured.UnstructuredList{}
   275  			for len(count.Items) < 1 {
   276  				count, _ = fakeDynamicClient.Resource(f5VirtualServerGVR).Namespace(defaultF5VirtualServerNamespace).List(context.Background(), metav1.ListOptions{})
   277  			}
   278  
   279  			endpoints, err := source.Endpoints(context.Background())
   280  			require.NoError(t, err)
   281  			assert.Len(t, endpoints, len(tc.expected))
   282  			assert.Equal(t, endpoints, tc.expected)
   283  		})
   284  	}
   285  }