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

     1  package k8s
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/nginxinc/kubernetes-ingress/internal/configs"
     7  	conf_v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1"
     8  	conf_v1alpha1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1alpha1"
     9  	networking "k8s.io/api/networking/v1beta1"
    10  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    11  )
    12  
    13  func TestSecretIsReferencedByIngress(t *testing.T) {
    14  	tests := []struct {
    15  		ing             *networking.Ingress
    16  		secretNamespace string
    17  		secretName      string
    18  		isPlus          bool
    19  		expected        bool
    20  		msg             string
    21  	}{
    22  		{
    23  			ing: &networking.Ingress{
    24  				ObjectMeta: v1.ObjectMeta{
    25  					Namespace: "default",
    26  				},
    27  				Spec: networking.IngressSpec{
    28  					TLS: []networking.IngressTLS{
    29  						{
    30  							SecretName: "test-secret",
    31  						},
    32  					},
    33  				},
    34  			},
    35  			secretNamespace: "default",
    36  			secretName:      "test-secret",
    37  			isPlus:          false,
    38  			expected:        true,
    39  			msg:             "tls secret is referenced",
    40  		},
    41  		{
    42  			ing: &networking.Ingress{
    43  				ObjectMeta: v1.ObjectMeta{
    44  					Namespace: "default",
    45  				},
    46  				Spec: networking.IngressSpec{
    47  					TLS: []networking.IngressTLS{
    48  						{
    49  							SecretName: "test-secret",
    50  						},
    51  					},
    52  				},
    53  			},
    54  			secretNamespace: "default",
    55  			secretName:      "some-secret",
    56  			isPlus:          false,
    57  			expected:        false,
    58  			msg:             "wrong name for tls secret",
    59  		},
    60  		{
    61  			ing: &networking.Ingress{
    62  				ObjectMeta: v1.ObjectMeta{
    63  					Namespace: "default",
    64  				},
    65  				Spec: networking.IngressSpec{
    66  					TLS: []networking.IngressTLS{
    67  						{
    68  							SecretName: "test-secret",
    69  						},
    70  					},
    71  				},
    72  			},
    73  			secretNamespace: "some-namespace",
    74  			secretName:      "test-secret",
    75  			isPlus:          false,
    76  			expected:        false,
    77  			msg:             "wrong namespace for tls secret",
    78  		},
    79  		{
    80  			ing: &networking.Ingress{
    81  				ObjectMeta: v1.ObjectMeta{
    82  					Namespace: "default",
    83  					Annotations: map[string]string{
    84  						configs.JWTKeyAnnotation: "test-secret",
    85  					},
    86  				},
    87  			},
    88  			secretNamespace: "default",
    89  			secretName:      "test-secret",
    90  			isPlus:          true,
    91  			expected:        true,
    92  			msg:             "jwt secret is referenced for Plus",
    93  		},
    94  		{
    95  			ing: &networking.Ingress{
    96  				ObjectMeta: v1.ObjectMeta{
    97  					Namespace: "default",
    98  					Annotations: map[string]string{
    99  						configs.JWTKeyAnnotation: "test-secret",
   100  					},
   101  				},
   102  			},
   103  			secretNamespace: "default",
   104  			secretName:      "some-secret",
   105  			isPlus:          true,
   106  			expected:        false,
   107  			msg:             "wrong namespace for jwt secret for Plus",
   108  		},
   109  		{
   110  			ing: &networking.Ingress{
   111  				ObjectMeta: v1.ObjectMeta{
   112  					Namespace: "default",
   113  					Annotations: map[string]string{
   114  						configs.JWTKeyAnnotation: "test-secret",
   115  					},
   116  				},
   117  			},
   118  			secretNamespace: "default",
   119  			secretName:      "some-secret",
   120  			isPlus:          true,
   121  			expected:        false,
   122  			msg:             "wrong name for jwt secret for Plus",
   123  		},
   124  		{
   125  			ing: &networking.Ingress{
   126  				ObjectMeta: v1.ObjectMeta{
   127  					Namespace: "default",
   128  					Annotations: map[string]string{
   129  						configs.JWTKeyAnnotation: "test-secret",
   130  					},
   131  				},
   132  			},
   133  			secretNamespace: "some-namespace",
   134  			secretName:      "test-secret",
   135  			isPlus:          false,
   136  			expected:        false,
   137  			msg:             "jwt secret for NGINX OSS is ignored",
   138  		},
   139  	}
   140  
   141  	for _, test := range tests {
   142  		rc := newSecretReferenceChecker(test.isPlus)
   143  
   144  		result := rc.IsReferencedByIngress(test.secretNamespace, test.secretName, test.ing)
   145  		if result != test.expected {
   146  			t.Errorf("IsReferencedByIngress() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   147  		}
   148  	}
   149  }
   150  
   151  func TestSecretIsReferencedByMinion(t *testing.T) {
   152  	tests := []struct {
   153  		ing             *networking.Ingress
   154  		secretNamespace string
   155  		secretName      string
   156  		isPlus          bool
   157  		expected        bool
   158  		msg             string
   159  	}{
   160  		{
   161  			ing: &networking.Ingress{
   162  				ObjectMeta: v1.ObjectMeta{
   163  					Namespace: "default",
   164  					Annotations: map[string]string{
   165  						configs.JWTKeyAnnotation: "test-secret",
   166  					},
   167  				},
   168  			},
   169  			secretNamespace: "default",
   170  			secretName:      "test-secret",
   171  			isPlus:          true,
   172  			expected:        true,
   173  			msg:             "jwt secret is referenced for Plus",
   174  		},
   175  		{
   176  			ing: &networking.Ingress{
   177  				ObjectMeta: v1.ObjectMeta{
   178  					Namespace: "default",
   179  					Annotations: map[string]string{
   180  						configs.JWTKeyAnnotation: "test-secret",
   181  					},
   182  				},
   183  			},
   184  			secretNamespace: "default",
   185  			secretName:      "some-secret",
   186  			isPlus:          true,
   187  			expected:        false,
   188  			msg:             "wrong namespace for jwt secret for Plus",
   189  		},
   190  		{
   191  			ing: &networking.Ingress{
   192  				ObjectMeta: v1.ObjectMeta{
   193  					Namespace: "default",
   194  					Annotations: map[string]string{
   195  						configs.JWTKeyAnnotation: "test-secret",
   196  					},
   197  				},
   198  			},
   199  			secretNamespace: "default",
   200  			secretName:      "some-secret",
   201  			isPlus:          true,
   202  			expected:        false,
   203  			msg:             "wrong name for jwt secret for Plus",
   204  		},
   205  		{
   206  			ing: &networking.Ingress{
   207  				ObjectMeta: v1.ObjectMeta{
   208  					Namespace: "default",
   209  					Annotations: map[string]string{
   210  						configs.JWTKeyAnnotation: "test-secret",
   211  					},
   212  				},
   213  			},
   214  			secretNamespace: "default",
   215  			secretName:      "test-secret",
   216  			isPlus:          false,
   217  			expected:        false,
   218  			msg:             "jwt secret for NGINX OSS is ignored",
   219  		},
   220  	}
   221  
   222  	for _, test := range tests {
   223  		rc := newSecretReferenceChecker(test.isPlus)
   224  
   225  		result := rc.IsReferencedByMinion(test.secretNamespace, test.secretName, test.ing)
   226  		if result != test.expected {
   227  			t.Errorf("IsReferencedByMinion() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   228  		}
   229  	}
   230  }
   231  
   232  func TestSecretIsReferencedByVirtualServer(t *testing.T) {
   233  	tests := []struct {
   234  		vs              *conf_v1.VirtualServer
   235  		secretNamespace string
   236  		secretName      string
   237  		expected        bool
   238  		msg             string
   239  	}{
   240  		{
   241  			vs: &conf_v1.VirtualServer{
   242  				ObjectMeta: v1.ObjectMeta{
   243  					Namespace: "default",
   244  				},
   245  				Spec: conf_v1.VirtualServerSpec{
   246  					TLS: &conf_v1.TLS{
   247  						Secret: "test-secret",
   248  					},
   249  				},
   250  			},
   251  			secretNamespace: "default",
   252  			secretName:      "test-secret",
   253  			expected:        true,
   254  			msg:             "tls secret is referenced",
   255  		},
   256  		{
   257  			vs: &conf_v1.VirtualServer{
   258  				ObjectMeta: v1.ObjectMeta{
   259  					Namespace: "default",
   260  				},
   261  				Spec: conf_v1.VirtualServerSpec{
   262  					TLS: &conf_v1.TLS{
   263  						Secret: "test-secret",
   264  					},
   265  				},
   266  			},
   267  			secretNamespace: "default",
   268  			secretName:      "some-secret",
   269  			expected:        false,
   270  			msg:             "wrong name for tls secret",
   271  		},
   272  		{
   273  			vs: &conf_v1.VirtualServer{
   274  				ObjectMeta: v1.ObjectMeta{
   275  					Namespace: "default",
   276  				},
   277  				Spec: conf_v1.VirtualServerSpec{
   278  					TLS: &conf_v1.TLS{
   279  						Secret: "test-secret",
   280  					},
   281  				},
   282  			},
   283  			secretNamespace: "some-namespace",
   284  			secretName:      "test-secret",
   285  			expected:        false,
   286  			msg:             "wrong namespace for tls secret",
   287  		},
   288  	}
   289  
   290  	for _, test := range tests {
   291  		isPlus := false // doesn't matter for VirtualServer
   292  		rc := newSecretReferenceChecker(isPlus)
   293  
   294  		result := rc.IsReferencedByVirtualServer(test.secretNamespace, test.secretName, test.vs)
   295  		if result != test.expected {
   296  			t.Errorf("IsReferencedByVirtualServer() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   297  		}
   298  	}
   299  }
   300  
   301  func TestSecretIsReferencedByVirtualServerRoute(t *testing.T) {
   302  	isPlus := false // doesn't matter for VirtualServerRoute
   303  	rc := newSecretReferenceChecker(isPlus)
   304  
   305  	result := rc.IsReferencedByVirtualServerRoute("", "", nil)
   306  	if result != false {
   307  		t.Error("IsReferencedByVirtualServer() returned true but expected false")
   308  	}
   309  }
   310  
   311  func TestSecretIsReferencedByTransportServer(t *testing.T) {
   312  	isPlus := false // doesn't matter for TransportServer
   313  	rc := newSecretReferenceChecker(isPlus)
   314  
   315  	// always returns false
   316  	result := rc.IsReferencedByTransportServer("", "", nil)
   317  	if result != false {
   318  		t.Error("IsReferencedByTransportServer() returned true but expected false")
   319  	}
   320  }
   321  
   322  func TestServiceIsReferencedByIngressAndMinion(t *testing.T) {
   323  	tests := []struct {
   324  		ing              *networking.Ingress
   325  		serviceNamespace string
   326  		serviceName      string
   327  		expected         bool
   328  		msg              string
   329  	}{
   330  		{
   331  			ing: &networking.Ingress{
   332  				ObjectMeta: v1.ObjectMeta{
   333  					Namespace: "default",
   334  				},
   335  				Spec: networking.IngressSpec{
   336  					Backend: &networking.IngressBackend{
   337  						ServiceName: "test-service",
   338  					},
   339  				},
   340  			},
   341  			serviceNamespace: "default",
   342  			serviceName:      "test-service",
   343  			expected:         true,
   344  			msg:              "service is referenced in the default backend",
   345  		},
   346  		{
   347  			ing: &networking.Ingress{
   348  				ObjectMeta: v1.ObjectMeta{
   349  					Namespace: "default",
   350  				},
   351  				Spec: networking.IngressSpec{
   352  					Rules: []networking.IngressRule{
   353  						{
   354  							IngressRuleValue: networking.IngressRuleValue{
   355  								HTTP: &networking.HTTPIngressRuleValue{
   356  									Paths: []networking.HTTPIngressPath{
   357  										{
   358  											Backend: networking.IngressBackend{
   359  												ServiceName: "test-service",
   360  											},
   361  										},
   362  									},
   363  								},
   364  							},
   365  						},
   366  					},
   367  				},
   368  			},
   369  			serviceNamespace: "default",
   370  			serviceName:      "test-service",
   371  			expected:         true,
   372  			msg:              "service is referenced in a path",
   373  		},
   374  		{
   375  			ing: &networking.Ingress{
   376  				ObjectMeta: v1.ObjectMeta{
   377  					Namespace: "default",
   378  				},
   379  				Spec: networking.IngressSpec{
   380  					Rules: []networking.IngressRule{
   381  						{
   382  							IngressRuleValue: networking.IngressRuleValue{
   383  								HTTP: &networking.HTTPIngressRuleValue{
   384  									Paths: []networking.HTTPIngressPath{
   385  										{
   386  											Backend: networking.IngressBackend{
   387  												ServiceName: "test-service",
   388  											},
   389  										},
   390  									},
   391  								},
   392  							},
   393  						},
   394  					},
   395  				},
   396  			},
   397  			serviceNamespace: "default",
   398  			serviceName:      "some-service",
   399  			expected:         false,
   400  			msg:              "wrong name for service in a path",
   401  		},
   402  		{
   403  			ing: &networking.Ingress{
   404  				ObjectMeta: v1.ObjectMeta{
   405  					Namespace: "default",
   406  				},
   407  				Spec: networking.IngressSpec{
   408  					Rules: []networking.IngressRule{
   409  						{
   410  							IngressRuleValue: networking.IngressRuleValue{
   411  								HTTP: &networking.HTTPIngressRuleValue{
   412  									Paths: []networking.HTTPIngressPath{
   413  										{
   414  											Backend: networking.IngressBackend{
   415  												ServiceName: "test-service",
   416  											},
   417  										},
   418  									},
   419  								},
   420  							},
   421  						},
   422  					},
   423  				},
   424  			},
   425  			serviceNamespace: "some-namespace",
   426  			serviceName:      "test-service",
   427  			expected:         false,
   428  			msg:              "wrong namespace for service in a path",
   429  		},
   430  	}
   431  
   432  	for _, test := range tests {
   433  		rc := newServiceReferenceChecker(false)
   434  
   435  		result := rc.IsReferencedByIngress(test.serviceNamespace, test.serviceName, test.ing)
   436  		if result != test.expected {
   437  			t.Errorf("IsReferencedByIngress() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   438  		}
   439  
   440  		// same cases for Minions
   441  		result = rc.IsReferencedByMinion(test.serviceNamespace, test.serviceName, test.ing)
   442  		if result != test.expected {
   443  			t.Errorf("IsReferencedByMinion() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   444  		}
   445  	}
   446  }
   447  
   448  func TestServiceIsReferencedByVirtualServerAndVirtualServerRoutes(t *testing.T) {
   449  	tests := []struct {
   450  		vs               *conf_v1.VirtualServer
   451  		vsr              *conf_v1.VirtualServerRoute
   452  		serviceNamespace string
   453  		serviceName      string
   454  		expected         bool
   455  		msg              string
   456  	}{
   457  		{
   458  			vs: &conf_v1.VirtualServer{
   459  				ObjectMeta: v1.ObjectMeta{
   460  					Namespace: "default",
   461  				},
   462  				Spec: conf_v1.VirtualServerSpec{
   463  					Upstreams: []conf_v1.Upstream{
   464  						{
   465  							Service: "test-service",
   466  						},
   467  					},
   468  				},
   469  			},
   470  			vsr: &conf_v1.VirtualServerRoute{
   471  				ObjectMeta: v1.ObjectMeta{
   472  					Namespace: "default",
   473  				},
   474  				Spec: conf_v1.VirtualServerRouteSpec{
   475  					Upstreams: []conf_v1.Upstream{
   476  						{
   477  							Service: "test-service",
   478  						},
   479  					},
   480  				},
   481  			},
   482  			serviceNamespace: "default",
   483  			serviceName:      "test-service",
   484  			expected:         true,
   485  			msg:              "service is referenced in an upstream",
   486  		},
   487  		{
   488  			vs: &conf_v1.VirtualServer{
   489  				ObjectMeta: v1.ObjectMeta{
   490  					Namespace: "default",
   491  				},
   492  				Spec: conf_v1.VirtualServerSpec{
   493  					Upstreams: []conf_v1.Upstream{
   494  						{
   495  							Service: "test-service",
   496  						},
   497  					},
   498  				},
   499  			},
   500  			vsr: &conf_v1.VirtualServerRoute{
   501  				ObjectMeta: v1.ObjectMeta{
   502  					Namespace: "default",
   503  				},
   504  				Spec: conf_v1.VirtualServerRouteSpec{
   505  					Upstreams: []conf_v1.Upstream{
   506  						{
   507  							Service: "test-service",
   508  						},
   509  					},
   510  				},
   511  			},
   512  			serviceNamespace: "some-namespace",
   513  			serviceName:      "test-service",
   514  			expected:         false,
   515  			msg:              "wrong namespace for service in an upstream",
   516  		},
   517  		{
   518  			vs: &conf_v1.VirtualServer{
   519  				ObjectMeta: v1.ObjectMeta{
   520  					Namespace: "default",
   521  				},
   522  				Spec: conf_v1.VirtualServerSpec{
   523  					Upstreams: []conf_v1.Upstream{
   524  						{
   525  							Service: "test-service",
   526  						},
   527  					},
   528  				},
   529  			},
   530  			vsr: &conf_v1.VirtualServerRoute{
   531  				ObjectMeta: v1.ObjectMeta{
   532  					Namespace: "default",
   533  				},
   534  				Spec: conf_v1.VirtualServerRouteSpec{
   535  					Upstreams: []conf_v1.Upstream{
   536  						{
   537  							Service: "test-service",
   538  						},
   539  					},
   540  				},
   541  			},
   542  			serviceNamespace: "default",
   543  			serviceName:      "some-service",
   544  			expected:         false,
   545  			msg:              "wrong name for service in an upstream",
   546  		},
   547  	}
   548  
   549  	for _, test := range tests {
   550  		rc := newServiceReferenceChecker(false)
   551  
   552  		result := rc.IsReferencedByVirtualServer(test.serviceNamespace, test.serviceName, test.vs)
   553  		if result != test.expected {
   554  			t.Errorf("IsReferencedByVirtualServer() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   555  		}
   556  
   557  		result = rc.IsReferencedByVirtualServerRoute(test.serviceNamespace, test.serviceName, test.vsr)
   558  		if result != test.expected {
   559  			t.Errorf("IsReferencedByVirtualServerRoute() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   560  		}
   561  	}
   562  }
   563  
   564  func TestIsServiceReferencedByTransportServer(t *testing.T) {
   565  	tests := []struct {
   566  		ts               *conf_v1alpha1.TransportServer
   567  		serviceNamespace string
   568  		serviceName      string
   569  		expected         bool
   570  		msg              string
   571  	}{
   572  		{
   573  			ts: &conf_v1alpha1.TransportServer{
   574  				ObjectMeta: v1.ObjectMeta{
   575  					Namespace: "default",
   576  				},
   577  				Spec: conf_v1alpha1.TransportServerSpec{
   578  					Upstreams: []conf_v1alpha1.Upstream{
   579  						{
   580  							Service: "test-service",
   581  						},
   582  					},
   583  				},
   584  			},
   585  			serviceNamespace: "default",
   586  			serviceName:      "test-service",
   587  			expected:         true,
   588  			msg:              "service is referenced in an upstream",
   589  		},
   590  		{
   591  			ts: &conf_v1alpha1.TransportServer{
   592  				ObjectMeta: v1.ObjectMeta{
   593  					Namespace: "default",
   594  				},
   595  				Spec: conf_v1alpha1.TransportServerSpec{
   596  					Upstreams: []conf_v1alpha1.Upstream{
   597  						{
   598  							Service: "test-service",
   599  						},
   600  					},
   601  				},
   602  			},
   603  			serviceNamespace: "some-namespace",
   604  			serviceName:      "test-service",
   605  			expected:         false,
   606  			msg:              "wrong namespace for service in an upstream",
   607  		},
   608  		{
   609  			ts: &conf_v1alpha1.TransportServer{
   610  				ObjectMeta: v1.ObjectMeta{
   611  					Namespace: "default",
   612  				},
   613  				Spec: conf_v1alpha1.TransportServerSpec{
   614  					Upstreams: []conf_v1alpha1.Upstream{
   615  						{
   616  							Service: "test-service",
   617  						},
   618  					},
   619  				},
   620  			},
   621  			serviceNamespace: "default",
   622  			serviceName:      "some-service",
   623  			expected:         false,
   624  			msg:              "wrong name for service in an upstream",
   625  		},
   626  	}
   627  
   628  	for _, test := range tests {
   629  		rc := newServiceReferenceChecker(false)
   630  
   631  		result := rc.IsReferencedByTransportServer(test.serviceNamespace, test.serviceName, test.ts)
   632  		if result != test.expected {
   633  			t.Errorf("IsReferencedByTransportServer() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   634  		}
   635  	}
   636  }
   637  
   638  func TestPolicyIsReferencedByIngressesAndTransportServers(t *testing.T) {
   639  	rc := newPolicyReferenceChecker()
   640  
   641  	result := rc.IsReferencedByIngress("", "", nil)
   642  	if result != false {
   643  		t.Error("IsReferencedByIngress() returned true but expected false")
   644  	}
   645  
   646  	result = rc.IsReferencedByMinion("", "", nil)
   647  	if result != false {
   648  		t.Error("IsReferencedByMinion() returned true but expected false")
   649  	}
   650  
   651  	result = rc.IsReferencedByTransportServer("", "", nil)
   652  	if result != false {
   653  		t.Error("IsReferencedByTransportServer() returned true but expected false")
   654  	}
   655  }
   656  
   657  func TestPolicyIsReferencedByVirtualServerAndVirtualServerRoute(t *testing.T) {
   658  	tests := []struct {
   659  		vs              *conf_v1.VirtualServer
   660  		vsr             *conf_v1.VirtualServerRoute
   661  		policyNamespace string
   662  		policyName      string
   663  		expected        bool
   664  		msg             string
   665  	}{
   666  		{
   667  			vs: &conf_v1.VirtualServer{
   668  				ObjectMeta: v1.ObjectMeta{
   669  					Namespace: "default",
   670  				},
   671  				Spec: conf_v1.VirtualServerSpec{
   672  					Policies: []conf_v1.PolicyReference{
   673  						{
   674  							Name:      "test-policy",
   675  							Namespace: "default",
   676  						},
   677  					},
   678  				},
   679  			},
   680  			policyNamespace: "default",
   681  			policyName:      "test-policy",
   682  			expected:        true,
   683  			msg:             "policy is referenced at the spec level",
   684  		},
   685  		{
   686  			vs: &conf_v1.VirtualServer{
   687  				ObjectMeta: v1.ObjectMeta{
   688  					Namespace: "default",
   689  				},
   690  				Spec: conf_v1.VirtualServerSpec{
   691  					Policies: []conf_v1.PolicyReference{
   692  						{
   693  							Name:      "test-policy",
   694  							Namespace: "default",
   695  						},
   696  					},
   697  				},
   698  			},
   699  			policyNamespace: "some-namespace",
   700  			policyName:      "test-policy",
   701  			expected:        false,
   702  			msg:             "wrong namespace for policy at the spec level",
   703  		},
   704  		{
   705  			vs: &conf_v1.VirtualServer{
   706  				ObjectMeta: v1.ObjectMeta{
   707  					Namespace: "default",
   708  				},
   709  				Spec: conf_v1.VirtualServerSpec{
   710  					Policies: []conf_v1.PolicyReference{
   711  						{
   712  							Name:      "test-policy",
   713  							Namespace: "default",
   714  						},
   715  					},
   716  				},
   717  			},
   718  			policyNamespace: "default",
   719  			policyName:      "some-policy",
   720  			expected:        false,
   721  			msg:             "wrong name for policy at the spec level",
   722  		},
   723  		{
   724  			vs: &conf_v1.VirtualServer{
   725  				ObjectMeta: v1.ObjectMeta{
   726  					Namespace: "default",
   727  				},
   728  				Spec: conf_v1.VirtualServerSpec{
   729  					Routes: []conf_v1.Route{
   730  						{
   731  							Policies: []conf_v1.PolicyReference{
   732  								{
   733  									Name:      "test-policy",
   734  									Namespace: "default",
   735  								},
   736  							},
   737  						},
   738  					},
   739  				},
   740  			},
   741  			vsr: &conf_v1.VirtualServerRoute{
   742  				ObjectMeta: v1.ObjectMeta{
   743  					Namespace: "default",
   744  				},
   745  				Spec: conf_v1.VirtualServerRouteSpec{
   746  					Subroutes: []conf_v1.Route{
   747  						{
   748  							Policies: []conf_v1.PolicyReference{
   749  								{
   750  									Name:      "test-policy",
   751  									Namespace: "default",
   752  								},
   753  							},
   754  						},
   755  					},
   756  				},
   757  			},
   758  			policyNamespace: "default",
   759  			policyName:      "test-policy",
   760  			expected:        true,
   761  			msg:             "policy is referenced in a route",
   762  		},
   763  		{
   764  			vs: &conf_v1.VirtualServer{
   765  				ObjectMeta: v1.ObjectMeta{
   766  					Namespace: "default",
   767  				},
   768  				Spec: conf_v1.VirtualServerSpec{
   769  					Routes: []conf_v1.Route{
   770  						{
   771  							Policies: []conf_v1.PolicyReference{
   772  								{
   773  									Name:      "test-policy",
   774  									Namespace: "default",
   775  								},
   776  							},
   777  						},
   778  					},
   779  				},
   780  			},
   781  			vsr: &conf_v1.VirtualServerRoute{
   782  				ObjectMeta: v1.ObjectMeta{
   783  					Namespace: "default",
   784  				},
   785  				Spec: conf_v1.VirtualServerRouteSpec{
   786  					Subroutes: []conf_v1.Route{
   787  						{
   788  							Policies: []conf_v1.PolicyReference{
   789  								{
   790  									Name:      "test-policy",
   791  									Namespace: "default",
   792  								},
   793  							},
   794  						},
   795  					},
   796  				},
   797  			},
   798  			policyNamespace: "some-namespace",
   799  			policyName:      "test-policy",
   800  			expected:        false,
   801  			msg:             "wrong namespace for policy in a route",
   802  		},
   803  		{
   804  			vs: &conf_v1.VirtualServer{
   805  				ObjectMeta: v1.ObjectMeta{
   806  					Namespace: "default",
   807  				},
   808  				Spec: conf_v1.VirtualServerSpec{
   809  					Routes: []conf_v1.Route{
   810  						{
   811  							Policies: []conf_v1.PolicyReference{
   812  								{
   813  									Name:      "test-policy",
   814  									Namespace: "default",
   815  								},
   816  							},
   817  						},
   818  					},
   819  				},
   820  			},
   821  			vsr: &conf_v1.VirtualServerRoute{
   822  				ObjectMeta: v1.ObjectMeta{
   823  					Namespace: "default",
   824  				},
   825  				Spec: conf_v1.VirtualServerRouteSpec{
   826  					Subroutes: []conf_v1.Route{
   827  						{
   828  							Policies: []conf_v1.PolicyReference{
   829  								{
   830  									Name:      "test-policy",
   831  									Namespace: "default",
   832  								},
   833  							},
   834  						},
   835  					},
   836  				},
   837  			},
   838  			policyNamespace: "default",
   839  			policyName:      "some-policy",
   840  			expected:        false,
   841  			msg:             "wrong name for policy in a route",
   842  		},
   843  	}
   844  
   845  	for _, test := range tests {
   846  		rc := newPolicyReferenceChecker()
   847  
   848  		result := rc.IsReferencedByVirtualServer(test.policyNamespace, test.policyName, test.vs)
   849  		if result != test.expected {
   850  			t.Errorf("IsReferencedByVirtualServer() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   851  		}
   852  
   853  		if test.vsr == nil {
   854  			continue
   855  		}
   856  
   857  		result = rc.IsReferencedByVirtualServerRoute(test.policyNamespace, test.policyName, test.vsr)
   858  		if result != test.expected {
   859  			t.Errorf("IsReferencedByVirtualServerRoute() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   860  		}
   861  	}
   862  }
   863  
   864  func TestAppProtectResourceIsReferencedByIngresses(t *testing.T) {
   865  	tests := []struct {
   866  		ing               *networking.Ingress
   867  		resourceNamespace string
   868  		resourceName      string
   869  		expected          bool
   870  		msg               string
   871  	}{
   872  		{
   873  			ing: &networking.Ingress{
   874  				ObjectMeta: v1.ObjectMeta{
   875  					Namespace: "default",
   876  					Annotations: map[string]string{
   877  						"test-annotation": "default/test-resource",
   878  					},
   879  				},
   880  			},
   881  			resourceNamespace: "default",
   882  			resourceName:      "test-resource",
   883  			expected:          true,
   884  			msg:               "resource is referenced",
   885  		},
   886  		{
   887  			ing: &networking.Ingress{
   888  				ObjectMeta: v1.ObjectMeta{
   889  					Namespace: "default",
   890  					Annotations: map[string]string{
   891  						"test-annotation": "test-resource",
   892  					},
   893  				},
   894  			},
   895  			resourceNamespace: "default",
   896  			resourceName:      "test-resource",
   897  			expected:          true,
   898  			msg:               "resource is referenced with implicit namespace",
   899  		},
   900  		{
   901  			ing: &networking.Ingress{
   902  				ObjectMeta: v1.ObjectMeta{
   903  					Namespace: "default",
   904  					Annotations: map[string]string{
   905  						"test-annotation": "default/test-resource",
   906  					},
   907  				},
   908  			},
   909  			resourceNamespace: "default",
   910  			resourceName:      "some-resource",
   911  			expected:          false,
   912  			msg:               "wrong name",
   913  		},
   914  		{
   915  			ing: &networking.Ingress{
   916  				ObjectMeta: v1.ObjectMeta{
   917  					Namespace: "default",
   918  					Annotations: map[string]string{
   919  						"test-annotation": "default/test-resource",
   920  					},
   921  				},
   922  			},
   923  			resourceNamespace: "some-namespace",
   924  			resourceName:      "test-resource",
   925  			expected:          false,
   926  			msg:               "wrong namespace",
   927  		},
   928  		{
   929  			ing: &networking.Ingress{
   930  				ObjectMeta: v1.ObjectMeta{
   931  					Namespace: "default",
   932  					Annotations: map[string]string{
   933  						"test-annotation": "test-resource",
   934  					},
   935  				},
   936  			},
   937  			resourceNamespace: "some-namespace",
   938  			resourceName:      "test-resource",
   939  			expected:          false,
   940  			msg:               "wrong namespace with implicit namespace",
   941  		},
   942  		{
   943  			ing: &networking.Ingress{
   944  				ObjectMeta: v1.ObjectMeta{
   945  					Namespace: "default",
   946  					Annotations: map[string]string{
   947  						"test-annotation": "some-namespace/test-resource,some-namespace/different-resource",
   948  					},
   949  				},
   950  			},
   951  			resourceNamespace: "some-namespace",
   952  			resourceName:      "test-resource",
   953  			expected:          true,
   954  			msg:               "resource is referenced with namespace within multiple resources",
   955  		},
   956  		{
   957  			ing: &networking.Ingress{
   958  				ObjectMeta: v1.ObjectMeta{
   959  					Namespace: "default",
   960  					Annotations: map[string]string{
   961  						"test-annotation": "test-resource,some-namespace/different-resource",
   962  					},
   963  				},
   964  			},
   965  			resourceNamespace: "default",
   966  			resourceName:      "test-resource",
   967  			expected:          true,
   968  			msg:               "resource is referenced with implicit namespace within multiple resources",
   969  		},
   970  		{
   971  			ing: &networking.Ingress{
   972  				ObjectMeta: v1.ObjectMeta{
   973  					Namespace: "default",
   974  					Annotations: map[string]string{
   975  						"test-annotation": "test-resource,some-namespace/different-resource",
   976  					},
   977  				},
   978  			},
   979  			resourceNamespace: "some-namespace",
   980  			resourceName:      "test-resource",
   981  			expected:          false,
   982  			msg:               "wrong namespace within multiple resources",
   983  		},
   984  	}
   985  
   986  	for _, test := range tests {
   987  		rc := newAppProtectResourceReferenceChecker("test-annotation")
   988  
   989  		result := rc.IsReferencedByIngress(test.resourceNamespace, test.resourceName, test.ing)
   990  		if result != test.expected {
   991  			t.Errorf("IsReferencedByIngress() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
   992  		}
   993  
   994  		result = rc.IsReferencedByMinion(test.resourceNamespace, test.resourceName, test.ing)
   995  		if result != false {
   996  			t.Errorf("IsReferencedByMinion() returned true but expected false for the case of %s", test.msg)
   997  		}
   998  	}
   999  }
  1000  
  1001  func TestAppProtectResourceIsReferenced(t *testing.T) {
  1002  	rc := newAppProtectResourceReferenceChecker("test")
  1003  
  1004  	result := rc.IsReferencedByVirtualServer("", "", nil)
  1005  	if result != false {
  1006  		t.Error("IsReferencedByVirtualServer() returned true but expected false")
  1007  	}
  1008  
  1009  	result = rc.IsReferencedByVirtualServerRoute("", "", nil)
  1010  	if result != false {
  1011  		t.Error("IsReferencedByVirtualServer() returned true but expected false")
  1012  	}
  1013  
  1014  	result = rc.IsReferencedByTransportServer("", "", nil)
  1015  	if result != false {
  1016  		t.Error("IsReferencedByTransportServer() returned true but expected false")
  1017  	}
  1018  }
  1019  
  1020  func TestIsPolicyIsReferenced(t *testing.T) {
  1021  	tests := []struct {
  1022  		policies          []conf_v1.PolicyReference
  1023  		resourceNamespace string
  1024  		policyNamespace   string
  1025  		policyName        string
  1026  		expected          bool
  1027  		msg               string
  1028  	}{
  1029  		{
  1030  			policies: []conf_v1.PolicyReference{
  1031  				{
  1032  					Name: "test-policy",
  1033  				},
  1034  			},
  1035  			resourceNamespace: "ns-1",
  1036  			policyNamespace:   "ns-1",
  1037  			policyName:        "test-policy",
  1038  			expected:          true,
  1039  			msg:               "reference with implicit namespace",
  1040  		},
  1041  		{
  1042  			policies: []conf_v1.PolicyReference{
  1043  				{
  1044  					Name:      "test-policy",
  1045  					Namespace: "ns-1",
  1046  				},
  1047  			},
  1048  			resourceNamespace: "ns-1",
  1049  			policyNamespace:   "ns-1",
  1050  			policyName:        "test-policy",
  1051  			expected:          true,
  1052  			msg:               "reference with explicit namespace",
  1053  		},
  1054  		{
  1055  			policies: []conf_v1.PolicyReference{
  1056  				{
  1057  					Name: "test-policy",
  1058  				},
  1059  			},
  1060  			resourceNamespace: "ns-2",
  1061  			policyNamespace:   "ns-1",
  1062  			policyName:        "test-policy",
  1063  			expected:          false,
  1064  			msg:               "wrong namespace with implicit namespace",
  1065  		},
  1066  		{
  1067  			policies: []conf_v1.PolicyReference{
  1068  				{
  1069  					Name:      "test-policy",
  1070  					Namespace: "ns-2",
  1071  				},
  1072  			},
  1073  			resourceNamespace: "ns-2",
  1074  			policyNamespace:   "ns-1",
  1075  			policyName:        "test-policy",
  1076  			expected:          false,
  1077  			msg:               "wrong namespace with explicit namespace",
  1078  		},
  1079  	}
  1080  
  1081  	for _, test := range tests {
  1082  		result := isPolicyReferenced(test.policies, test.resourceNamespace, test.policyNamespace, test.policyName)
  1083  		if result != test.expected {
  1084  			t.Errorf("isPolicyReferenced() returned %v but expected %v for the case of %s", result,
  1085  				test.expected, test.msg)
  1086  		}
  1087  	}
  1088  }
  1089  
  1090  func TestEndpointIsReferencedByVirtualServerAndVirtualServerRoutes(t *testing.T) {
  1091  	tests := []struct {
  1092  		vs               *conf_v1.VirtualServer
  1093  		vsr              *conf_v1.VirtualServerRoute
  1094  		serviceNamespace string
  1095  		serviceName      string
  1096  		expected         bool
  1097  		msg              string
  1098  	}{
  1099  		{
  1100  			vs: &conf_v1.VirtualServer{
  1101  				ObjectMeta: v1.ObjectMeta{
  1102  					Namespace: "default",
  1103  				},
  1104  				Spec: conf_v1.VirtualServerSpec{
  1105  					Upstreams: []conf_v1.Upstream{
  1106  						{
  1107  							Service: "test-service",
  1108  						},
  1109  					},
  1110  				},
  1111  			},
  1112  			vsr: &conf_v1.VirtualServerRoute{
  1113  				ObjectMeta: v1.ObjectMeta{
  1114  					Namespace: "default",
  1115  				},
  1116  				Spec: conf_v1.VirtualServerRouteSpec{
  1117  					Upstreams: []conf_v1.Upstream{
  1118  						{
  1119  							Service: "test-service",
  1120  						},
  1121  					},
  1122  				},
  1123  			},
  1124  			serviceNamespace: "default",
  1125  			serviceName:      "test-service",
  1126  			expected:         true,
  1127  			msg:              "service is referenced in an upstream",
  1128  		},
  1129  		{
  1130  			vs: &conf_v1.VirtualServer{
  1131  				ObjectMeta: v1.ObjectMeta{
  1132  					Namespace: "default",
  1133  				},
  1134  				Spec: conf_v1.VirtualServerSpec{
  1135  					Upstreams: []conf_v1.Upstream{
  1136  						{
  1137  							Service:      "test-service",
  1138  							UseClusterIP: true,
  1139  						},
  1140  					},
  1141  				},
  1142  			},
  1143  			vsr: &conf_v1.VirtualServerRoute{
  1144  				ObjectMeta: v1.ObjectMeta{
  1145  					Namespace: "default",
  1146  				},
  1147  				Spec: conf_v1.VirtualServerRouteSpec{
  1148  					Upstreams: []conf_v1.Upstream{
  1149  						{
  1150  							Service:      "test-service",
  1151  							UseClusterIP: true,
  1152  						},
  1153  					},
  1154  				},
  1155  			},
  1156  			serviceNamespace: "default",
  1157  			serviceName:      "test-service",
  1158  			expected:         false,
  1159  			msg:              "upstream uses clusterIP",
  1160  		},
  1161  		{
  1162  			vs: &conf_v1.VirtualServer{
  1163  				ObjectMeta: v1.ObjectMeta{
  1164  					Namespace: "default",
  1165  				},
  1166  				Spec: conf_v1.VirtualServerSpec{
  1167  					Upstreams: []conf_v1.Upstream{
  1168  						{
  1169  							Service:      "test-service",
  1170  							UseClusterIP: true,
  1171  						},
  1172  						{
  1173  							Service: "test-service",
  1174  						},
  1175  					},
  1176  				},
  1177  			},
  1178  			vsr: &conf_v1.VirtualServerRoute{
  1179  				ObjectMeta: v1.ObjectMeta{
  1180  					Namespace: "default",
  1181  				},
  1182  				Spec: conf_v1.VirtualServerRouteSpec{
  1183  					Upstreams: []conf_v1.Upstream{
  1184  						{
  1185  							Service:      "test-service",
  1186  							UseClusterIP: true,
  1187  						},
  1188  						{
  1189  							Service: "test-service",
  1190  						},
  1191  					},
  1192  				},
  1193  			},
  1194  			serviceNamespace: "default",
  1195  			serviceName:      "test-service",
  1196  			expected:         true,
  1197  			msg:              "one upstream without Cluster IP",
  1198  		},
  1199  	}
  1200  
  1201  	for _, test := range tests {
  1202  		rc := newServiceReferenceChecker(true)
  1203  
  1204  		result := rc.IsReferencedByVirtualServer(test.serviceNamespace, test.serviceName, test.vs)
  1205  		if result != test.expected {
  1206  			t.Errorf("IsReferencedByVirtualServer() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
  1207  		}
  1208  
  1209  		result = rc.IsReferencedByVirtualServerRoute(test.serviceNamespace, test.serviceName, test.vsr)
  1210  		if result != test.expected {
  1211  			t.Errorf("IsReferencedByVirtualServerRoute() returned %v but expected %v for the case of %s", result, test.expected, test.msg)
  1212  		}
  1213  	}
  1214  }