github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/k8s/status_test.go (about)

     1  package k8s
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/google/go-cmp/cmp"
     9  	conf_v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1"
    10  	conf_v1alpha1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1alpha1"
    11  	fake_v1alpha1 "github.com/nginxinc/kubernetes-ingress/pkg/client/clientset/versioned/fake"
    12  	v1 "k8s.io/api/core/v1"
    13  	networking "k8s.io/api/networking/v1beta1"
    14  	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  	"k8s.io/apimachinery/pkg/fields"
    16  	"k8s.io/apimachinery/pkg/util/intstr"
    17  	"k8s.io/client-go/kubernetes/fake"
    18  	"k8s.io/client-go/tools/cache"
    19  )
    20  
    21  func TestUpdateTransportServerStatus(t *testing.T) {
    22  	ts := &conf_v1alpha1.TransportServer{
    23  		ObjectMeta: meta_v1.ObjectMeta{
    24  			Name:      "ts-1",
    25  			Namespace: "default",
    26  		},
    27  		Status: conf_v1alpha1.TransportServerStatus{
    28  			State:   "before status",
    29  			Reason:  "before reason",
    30  			Message: "before message",
    31  		},
    32  	}
    33  
    34  	fakeClient := fake_v1alpha1.NewSimpleClientset(
    35  		&conf_v1alpha1.TransportServerList{
    36  			Items: []conf_v1alpha1.TransportServer{
    37  				*ts,
    38  			}})
    39  
    40  	tsLister := cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc)
    41  
    42  	err := tsLister.Add(ts)
    43  	if err != nil {
    44  		t.Errorf("Error adding TransportServer to the transportserver lister: %v", err)
    45  	}
    46  	su := statusUpdater{
    47  		transportServerLister: tsLister,
    48  		confClient:            fakeClient,
    49  		keyFunc:               cache.DeletionHandlingMetaNamespaceKeyFunc,
    50  	}
    51  
    52  	err = su.UpdateTransportServerStatus(ts, "after status", "after reason", "after message")
    53  	if err != nil {
    54  		t.Errorf("error updating transportserver status: %v", err)
    55  	}
    56  	updatedTs, _ := fakeClient.K8sV1alpha1().TransportServers(ts.Namespace).Get(context.TODO(), ts.Name, meta_v1.GetOptions{})
    57  
    58  	expectedStatus := conf_v1alpha1.TransportServerStatus{
    59  		State:   "after status",
    60  		Reason:  "after reason",
    61  		Message: "after message",
    62  	}
    63  
    64  	if diff := cmp.Diff(expectedStatus, updatedTs.Status); diff != "" {
    65  		t.Errorf("Unexpected status (-want +got):\n%s", diff)
    66  	}
    67  }
    68  
    69  func TestUpdateTransportServerStatusIgnoreNoChange(t *testing.T) {
    70  	ts := &conf_v1alpha1.TransportServer{
    71  		ObjectMeta: meta_v1.ObjectMeta{
    72  			Name:      "ts-1",
    73  			Namespace: "default",
    74  		},
    75  		Status: conf_v1alpha1.TransportServerStatus{
    76  			State:   "same status",
    77  			Reason:  "same reason",
    78  			Message: "same message",
    79  		},
    80  	}
    81  
    82  	fakeClient := fake_v1alpha1.NewSimpleClientset(
    83  		&conf_v1alpha1.TransportServerList{
    84  			Items: []conf_v1alpha1.TransportServer{
    85  				*ts,
    86  			}})
    87  
    88  	tsLister, _ := cache.NewInformer(
    89  		cache.NewListWatchFromClient(
    90  			fakeClient.K8sV1alpha1().RESTClient(),
    91  			"transportservers",
    92  			"nginx-ingress",
    93  			fields.Everything(),
    94  		),
    95  		&conf_v1alpha1.TransportServer{},
    96  		2,
    97  		nil,
    98  	)
    99  
   100  	err := tsLister.Add(ts)
   101  	if err != nil {
   102  		t.Errorf("Error adding TransportServer to the transportserver lister: %v", err)
   103  	}
   104  	su := statusUpdater{
   105  		transportServerLister: tsLister,
   106  		confClient:            fakeClient,
   107  		keyFunc:               cache.DeletionHandlingMetaNamespaceKeyFunc,
   108  	}
   109  
   110  	err = su.UpdateTransportServerStatus(ts, "same status", "same reason", "same message")
   111  	if err != nil {
   112  		t.Errorf("error updating transportserver status: %v", err)
   113  	}
   114  	updatedTs, _ := fakeClient.K8sV1alpha1().TransportServers(ts.Namespace).Get(context.TODO(), ts.Name, meta_v1.GetOptions{})
   115  
   116  	if updatedTs.Status.State != "same status" {
   117  		t.Errorf("expected: %v actual: %v", "same status", updatedTs.Status.State)
   118  	}
   119  	if updatedTs.Status.Message != "same message" {
   120  		t.Errorf("expected: %v actual: %v", "same message", updatedTs.Status.Message)
   121  	}
   122  	if updatedTs.Status.Reason != "same reason" {
   123  		t.Errorf("expected: %v actual: %v", "same reason", updatedTs.Status.Reason)
   124  	}
   125  }
   126  
   127  func TestUpdateTransportServerStatusMissingTransportServer(t *testing.T) {
   128  	ts := &conf_v1alpha1.TransportServer{
   129  		ObjectMeta: meta_v1.ObjectMeta{
   130  			Name:      "ts-1",
   131  			Namespace: "default",
   132  		},
   133  		Status: conf_v1alpha1.TransportServerStatus{
   134  			State:   "before status",
   135  			Reason:  "before reason",
   136  			Message: "before message",
   137  		},
   138  	}
   139  
   140  	fakeClient := fake_v1alpha1.NewSimpleClientset(
   141  		&conf_v1alpha1.TransportServerList{
   142  			Items: []conf_v1alpha1.TransportServer{}})
   143  
   144  	tsLister, _ := cache.NewInformer(
   145  		cache.NewListWatchFromClient(
   146  			fakeClient.K8sV1alpha1().RESTClient(),
   147  			"transportservers",
   148  			"nginx-ingress",
   149  			fields.Everything(),
   150  		),
   151  		&conf_v1alpha1.TransportServer{},
   152  		2,
   153  		nil,
   154  	)
   155  
   156  	su := statusUpdater{
   157  		transportServerLister: tsLister,
   158  		confClient:            fakeClient,
   159  		keyFunc:               cache.DeletionHandlingMetaNamespaceKeyFunc,
   160  		externalEndpoints: []conf_v1.ExternalEndpoint{
   161  			{
   162  				IP:    "123.123.123.123",
   163  				Ports: "1234",
   164  			},
   165  		},
   166  	}
   167  
   168  	err := su.UpdateTransportServerStatus(ts, "after status", "after reason", "after message")
   169  	if err != nil {
   170  		t.Errorf("unexpected error: %v, result should be empty as no matching TransportServer is present", err)
   171  	}
   172  
   173  	updatedTs, _ := fakeClient.K8sV1alpha1().TransportServers(ts.Namespace).Get(context.TODO(), ts.Name, meta_v1.GetOptions{})
   174  	if updatedTs != nil {
   175  		t.Errorf("expected TransportServer Store would be empty as provided TransportServer was not found. Unexpected updated TransportServer: %v", updatedTs)
   176  	}
   177  }
   178  
   179  func TestStatusUpdateWithExternalStatusAndExternalService(t *testing.T) {
   180  	ing := networking.Ingress{
   181  		ObjectMeta: meta_v1.ObjectMeta{
   182  			Name:      "ing-1",
   183  			Namespace: "namespace",
   184  		},
   185  		Status: networking.IngressStatus{
   186  			LoadBalancer: v1.LoadBalancerStatus{
   187  				Ingress: []v1.LoadBalancerIngress{
   188  					{
   189  						IP: "1.2.3.4",
   190  					},
   191  				},
   192  			},
   193  		},
   194  	}
   195  	fakeClient := fake.NewSimpleClientset(
   196  		&networking.IngressList{Items: []networking.Ingress{
   197  			ing,
   198  		}},
   199  	)
   200  	ingLister := storeToIngressLister{}
   201  	ingLister.Store, _ = cache.NewInformer(
   202  		cache.NewListWatchFromClient(fakeClient.NetworkingV1beta1().RESTClient(), "ingresses", "nginx-ingress", fields.Everything()),
   203  		&networking.Ingress{}, 2, nil)
   204  
   205  	err := ingLister.Store.Add(&ing)
   206  	if err != nil {
   207  		t.Errorf("Error adding Ingress to the ingress lister: %v", err)
   208  	}
   209  
   210  	su := statusUpdater{
   211  		client:                fakeClient,
   212  		namespace:             "namespace",
   213  		externalServiceName:   "service-name",
   214  		externalStatusAddress: "123.123.123.123",
   215  		ingressLister:         &ingLister,
   216  		keyFunc:               cache.DeletionHandlingMetaNamespaceKeyFunc,
   217  	}
   218  	err = su.ClearIngressStatus(ing)
   219  	if err != nil {
   220  		t.Errorf("error clearing ing status: %v", err)
   221  	}
   222  	ings, _ := fakeClient.NetworkingV1beta1().Ingresses("namespace").List(context.TODO(), meta_v1.ListOptions{})
   223  	ingf := ings.Items[0]
   224  	if !checkStatus("", ingf) {
   225  		t.Errorf("expected: %v actual: %v", "", ingf.Status.LoadBalancer.Ingress[0])
   226  	}
   227  
   228  	su.SaveStatusFromExternalStatus("1.1.1.1")
   229  	err = su.UpdateIngressStatus(ing)
   230  	if err != nil {
   231  		t.Errorf("error updating ing status: %v", err)
   232  	}
   233  	ring, _ := fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   234  	if !checkStatus("1.1.1.1", *ring) {
   235  		t.Errorf("expected: %v actual: %v", "", ring.Status.LoadBalancer.Ingress)
   236  	}
   237  
   238  	svc := v1.Service{
   239  		ObjectMeta: meta_v1.ObjectMeta{
   240  			Namespace: "namespace",
   241  			Name:      "service-name",
   242  		},
   243  		Status: v1.ServiceStatus{
   244  			LoadBalancer: v1.LoadBalancerStatus{
   245  				Ingress: []v1.LoadBalancerIngress{{
   246  					IP: "2.2.2.2",
   247  				}},
   248  			},
   249  		},
   250  	}
   251  	su.SaveStatusFromExternalService(&svc)
   252  	err = su.UpdateIngressStatus(ing)
   253  	if err != nil {
   254  		t.Errorf("error updating ing status: %v", err)
   255  	}
   256  	ring, _ = fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   257  	if !checkStatus("1.1.1.1", *ring) {
   258  		t.Errorf("expected: %v actual: %v", "1.1.1.1", ring.Status.LoadBalancer.Ingress)
   259  	}
   260  
   261  	su.SaveStatusFromExternalStatus("")
   262  	err = su.UpdateIngressStatus(ing)
   263  	if err != nil {
   264  		t.Errorf("error updating ing status: %v", err)
   265  	}
   266  	ring, _ = fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   267  	if !checkStatus("2.2.2.2", *ring) {
   268  		t.Errorf("expected: %v actual: %v", "2.2.2.2", ring.Status.LoadBalancer.Ingress)
   269  	}
   270  
   271  	su.ClearStatusFromExternalService()
   272  	err = su.UpdateIngressStatus(ing)
   273  	if err != nil {
   274  		t.Errorf("error updating ing status: %v", err)
   275  	}
   276  	ring, _ = fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   277  	if !checkStatus("", *ring) {
   278  		t.Errorf("expected: %v actual: %v", "", ring.Status.LoadBalancer.Ingress)
   279  	}
   280  }
   281  
   282  func TestStatusUpdateWithExternalStatusAndIngressLink(t *testing.T) {
   283  	ing := networking.Ingress{
   284  		ObjectMeta: meta_v1.ObjectMeta{
   285  			Name:      "ing-1",
   286  			Namespace: "namespace",
   287  		},
   288  		Status: networking.IngressStatus{
   289  			LoadBalancer: v1.LoadBalancerStatus{
   290  				Ingress: []v1.LoadBalancerIngress{
   291  					{
   292  						IP: "1.2.3.4",
   293  					},
   294  				},
   295  			},
   296  		},
   297  	}
   298  	fakeClient := fake.NewSimpleClientset(
   299  		&networking.IngressList{Items: []networking.Ingress{
   300  			ing,
   301  		}},
   302  	)
   303  	ingLister := storeToIngressLister{}
   304  	ingLister.Store, _ = cache.NewInformer(
   305  		cache.NewListWatchFromClient(fakeClient.NetworkingV1beta1().RESTClient(), "ingresses", "nginx-ingress", fields.Everything()),
   306  		&networking.Ingress{}, 2, nil)
   307  
   308  	err := ingLister.Store.Add(&ing)
   309  	if err != nil {
   310  		t.Errorf("Error adding Ingress to the ingress lister: %v", err)
   311  	}
   312  
   313  	su := statusUpdater{
   314  		client:                fakeClient,
   315  		namespace:             "namespace",
   316  		externalStatusAddress: "",
   317  		ingressLister:         &ingLister,
   318  		keyFunc:               cache.DeletionHandlingMetaNamespaceKeyFunc,
   319  	}
   320  
   321  	su.SaveStatusFromIngressLink("3.3.3.3")
   322  	err = su.UpdateIngressStatus(ing)
   323  	if err != nil {
   324  		t.Errorf("error updating ing status: %v", err)
   325  	}
   326  	ring, _ := fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   327  	if !checkStatus("3.3.3.3", *ring) {
   328  		t.Errorf("expected: %v actual: %v", "3.3.3.3", ring.Status.LoadBalancer.Ingress)
   329  	}
   330  
   331  	su.SaveStatusFromExternalStatus("1.1.1.1")
   332  	err = su.UpdateIngressStatus(ing)
   333  	if err != nil {
   334  		t.Errorf("error updating ing status: %v", err)
   335  	}
   336  	ring, _ = fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   337  	if !checkStatus("1.1.1.1", *ring) {
   338  		t.Errorf("expected: %v actual: %v", "1.1.1.1", ring.Status.LoadBalancer.Ingress)
   339  	}
   340  
   341  	su.ClearStatusFromIngressLink()
   342  	err = su.UpdateIngressStatus(ing)
   343  	if err != nil {
   344  		t.Errorf("error updating ing status: %v", err)
   345  	}
   346  	ring, _ = fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   347  	if !checkStatus("1.1.1.1", *ring) {
   348  		t.Errorf("expected: %v actual: %v", "1.1.1.1", ring.Status.LoadBalancer.Ingress)
   349  	}
   350  
   351  	su.SaveStatusFromIngressLink("4.4.4.4")
   352  	err = su.UpdateIngressStatus(ing)
   353  	if err != nil {
   354  		t.Errorf("error updating ing status: %v", err)
   355  	}
   356  	ring, _ = fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   357  	if !checkStatus("1.1.1.1", *ring) {
   358  		t.Errorf("expected: %v actual: %v", "1.1.1.1", ring.Status.LoadBalancer.Ingress)
   359  	}
   360  
   361  	su.SaveStatusFromExternalStatus("")
   362  	err = su.UpdateIngressStatus(ing)
   363  	if err != nil {
   364  		t.Errorf("error updating ing status: %v", err)
   365  	}
   366  	ring, _ = fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   367  	if !checkStatus("4.4.4.4", *ring) {
   368  		t.Errorf("expected: %v actual: %v", "4.4.4.4", ring.Status.LoadBalancer.Ingress)
   369  	}
   370  
   371  	su.ClearStatusFromIngressLink()
   372  	err = su.UpdateIngressStatus(ing)
   373  	if err != nil {
   374  		t.Errorf("error updating ing status: %v", err)
   375  	}
   376  	ring, _ = fakeClient.NetworkingV1beta1().Ingresses(ing.Namespace).Get(context.TODO(), ing.Name, meta_v1.GetOptions{})
   377  	if !checkStatus("", *ring) {
   378  		t.Errorf("expected: %v actual: %v", "", ring.Status.LoadBalancer.Ingress)
   379  	}
   380  }
   381  
   382  func checkStatus(expected string, actual networking.Ingress) bool {
   383  	if len(actual.Status.LoadBalancer.Ingress) == 0 {
   384  		return expected == ""
   385  	}
   386  	return expected == actual.Status.LoadBalancer.Ingress[0].IP
   387  }
   388  
   389  func TestGenerateExternalEndpointsFromStatus(t *testing.T) {
   390  	su := statusUpdater{
   391  		status: []v1.LoadBalancerIngress{
   392  			{
   393  				IP: "8.8.8.8",
   394  			},
   395  		},
   396  	}
   397  
   398  	expectedEndpoints := []conf_v1.ExternalEndpoint{
   399  		{IP: "8.8.8.8", Ports: ""},
   400  	}
   401  
   402  	endpoints := su.generateExternalEndpointsFromStatus(su.status)
   403  
   404  	if !reflect.DeepEqual(endpoints, expectedEndpoints) {
   405  		t.Errorf("generateExternalEndpointsFromStatus(%v) returned %v but expected %v", su.status, endpoints, expectedEndpoints)
   406  	}
   407  }
   408  
   409  func TestHasVsStatusChanged(t *testing.T) {
   410  	state := "Valid"
   411  	reason := "AddedOrUpdated"
   412  	msg := "Configuration was added or updated"
   413  
   414  	tests := []struct {
   415  		expected bool
   416  		vs       conf_v1.VirtualServer
   417  	}{
   418  		{
   419  			expected: false,
   420  			vs: conf_v1.VirtualServer{
   421  				Status: conf_v1.VirtualServerStatus{
   422  					State:   state,
   423  					Reason:  reason,
   424  					Message: msg,
   425  				},
   426  			},
   427  		},
   428  		{
   429  			expected: true,
   430  			vs: conf_v1.VirtualServer{
   431  				Status: conf_v1.VirtualServerStatus{
   432  					State:   "DifferentState",
   433  					Reason:  reason,
   434  					Message: msg,
   435  				},
   436  			},
   437  		},
   438  		{
   439  			expected: true,
   440  			vs: conf_v1.VirtualServer{
   441  				Status: conf_v1.VirtualServerStatus{
   442  					State:   state,
   443  					Reason:  "DifferentReason",
   444  					Message: msg,
   445  				},
   446  			},
   447  		},
   448  		{
   449  			expected: true,
   450  			vs: conf_v1.VirtualServer{
   451  				Status: conf_v1.VirtualServerStatus{
   452  					State:   state,
   453  					Reason:  reason,
   454  					Message: "DifferentMessage",
   455  				},
   456  			},
   457  		},
   458  	}
   459  
   460  	for _, test := range tests {
   461  		changed := hasVsStatusChanged(&test.vs, state, reason, msg)
   462  
   463  		if changed != test.expected {
   464  			t.Errorf("hasVsStatusChanged(%v, %v, %v, %v) returned %v but expected %v.", test.vs, state, reason, msg, changed, test.expected)
   465  		}
   466  	}
   467  }
   468  
   469  func TestHasVsrStatusChanged(t *testing.T) {
   470  
   471  	referencedBy := "namespace/name"
   472  	state := "Valid"
   473  	reason := "AddedOrUpdated"
   474  	msg := "Configuration was added or updated"
   475  
   476  	tests := []struct {
   477  		expected bool
   478  		vsr      conf_v1.VirtualServerRoute
   479  	}{
   480  		{
   481  			expected: false,
   482  			vsr: conf_v1.VirtualServerRoute{
   483  				Status: conf_v1.VirtualServerRouteStatus{
   484  					State:        state,
   485  					Reason:       reason,
   486  					Message:      msg,
   487  					ReferencedBy: referencedBy,
   488  				},
   489  			},
   490  		},
   491  		{
   492  			expected: true,
   493  			vsr: conf_v1.VirtualServerRoute{
   494  				Status: conf_v1.VirtualServerRouteStatus{
   495  					State:        "DifferentState",
   496  					Reason:       reason,
   497  					Message:      msg,
   498  					ReferencedBy: referencedBy,
   499  				},
   500  			},
   501  		},
   502  		{
   503  			expected: true,
   504  			vsr: conf_v1.VirtualServerRoute{
   505  				Status: conf_v1.VirtualServerRouteStatus{
   506  					State:        state,
   507  					Reason:       "DifferentReason",
   508  					Message:      msg,
   509  					ReferencedBy: referencedBy,
   510  				},
   511  			},
   512  		},
   513  		{
   514  			expected: true,
   515  			vsr: conf_v1.VirtualServerRoute{
   516  				Status: conf_v1.VirtualServerRouteStatus{
   517  					State:        state,
   518  					Reason:       reason,
   519  					Message:      "DifferentMessage",
   520  					ReferencedBy: referencedBy,
   521  				},
   522  			},
   523  		},
   524  		{
   525  			expected: true,
   526  			vsr: conf_v1.VirtualServerRoute{
   527  				Status: conf_v1.VirtualServerRouteStatus{
   528  					State:        state,
   529  					Reason:       reason,
   530  					Message:      msg,
   531  					ReferencedBy: "DifferentReferencedBy",
   532  				},
   533  			},
   534  		},
   535  	}
   536  
   537  	for _, test := range tests {
   538  		changed := hasVsrStatusChanged(&test.vsr, state, reason, msg, referencedBy)
   539  
   540  		if changed != test.expected {
   541  			t.Errorf("hasVsrStatusChanged(%v, %v, %v, %v) returned %v but expected %v.", test.vsr, state, reason, msg, changed, test.expected)
   542  		}
   543  	}
   544  }
   545  
   546  func TestGetExternalServicePorts(t *testing.T) {
   547  	svc := v1.Service{
   548  		Spec: v1.ServiceSpec{
   549  			Ports: []v1.ServicePort{
   550  				{
   551  					Port: int32(80),
   552  					TargetPort: intstr.IntOrString{
   553  						Type:   intstr.Int,
   554  						IntVal: 80,
   555  					},
   556  				},
   557  				{
   558  					Port: int32(443),
   559  					TargetPort: intstr.IntOrString{
   560  						Type:   intstr.Int,
   561  						IntVal: 443,
   562  					},
   563  				},
   564  			},
   565  		},
   566  	}
   567  
   568  	expected := "[80,443]"
   569  	ports := getExternalServicePorts(&svc)
   570  
   571  	if ports != expected {
   572  		t.Errorf("getExternalServicePorts(%v) returned %v but expected %v", svc, ports, expected)
   573  	}
   574  }
   575  
   576  func TestIsRequiredPort(t *testing.T) {
   577  	tests := []struct {
   578  		port     intstr.IntOrString
   579  		expected bool
   580  	}{
   581  		{
   582  			port: intstr.IntOrString{
   583  				Type:   intstr.Int,
   584  				IntVal: 999,
   585  			},
   586  			expected: false,
   587  		},
   588  		{
   589  			port: intstr.IntOrString{
   590  				Type:   intstr.Int,
   591  				IntVal: 80,
   592  			},
   593  			expected: true,
   594  		},
   595  		{
   596  			port: intstr.IntOrString{
   597  				Type:   intstr.Int,
   598  				IntVal: 443,
   599  			},
   600  			expected: true,
   601  		},
   602  		{
   603  			port: intstr.IntOrString{
   604  				Type:   intstr.String,
   605  				StrVal: "name",
   606  			},
   607  			expected: false,
   608  		},
   609  		{
   610  			port: intstr.IntOrString{
   611  				Type:   intstr.String,
   612  				StrVal: "http",
   613  			},
   614  			expected: true,
   615  		},
   616  		{
   617  			port: intstr.IntOrString{
   618  				Type:   intstr.String,
   619  				StrVal: "https",
   620  			},
   621  			expected: true,
   622  		},
   623  	}
   624  
   625  	for _, test := range tests {
   626  		result := isRequiredPort(test.port)
   627  
   628  		if result != test.expected {
   629  			t.Errorf("isRequiredPort(%+v) returned %v but expected %v", test.port, result, test.expected)
   630  		}
   631  	}
   632  }
   633  
   634  func TestHasPolicyStatusChanged(t *testing.T) {
   635  
   636  	state := "Valid"
   637  	reason := "AddedOrUpdated"
   638  	msg := "Configuration was added or updated"
   639  
   640  	tests := []struct {
   641  		expected bool
   642  		pol      conf_v1.Policy
   643  	}{
   644  		{
   645  			expected: false,
   646  			pol: conf_v1.Policy{
   647  				Status: conf_v1.PolicyStatus{
   648  					State:   state,
   649  					Reason:  reason,
   650  					Message: msg,
   651  				},
   652  			},
   653  		},
   654  		{
   655  			expected: true,
   656  			pol: conf_v1.Policy{
   657  				Status: conf_v1.PolicyStatus{
   658  					State:   "DifferentState",
   659  					Reason:  reason,
   660  					Message: msg,
   661  				},
   662  			},
   663  		},
   664  		{
   665  			expected: true,
   666  			pol: conf_v1.Policy{
   667  				Status: conf_v1.PolicyStatus{
   668  					State:   state,
   669  					Reason:  "DifferentReason",
   670  					Message: msg,
   671  				},
   672  			},
   673  		},
   674  		{
   675  			expected: true,
   676  			pol: conf_v1.Policy{
   677  				Status: conf_v1.PolicyStatus{
   678  					State:   state,
   679  					Reason:  reason,
   680  					Message: "DifferentMessage",
   681  				},
   682  			},
   683  		},
   684  	}
   685  
   686  	for _, test := range tests {
   687  		changed := hasPolicyStatusChanged(&test.pol, state, reason, msg)
   688  
   689  		if changed != test.expected {
   690  			t.Errorf("hasPolicyStatusChanged(%v, %v, %v, %v) returned %v but expected %v.", test.pol, state, reason, msg, changed, test.expected)
   691  		}
   692  	}
   693  }