k8s.io/kubernetes@v1.29.3/pkg/api/v1/service/util_test.go (about)

     1  /*
     2  Copyright 2016 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 service
    18  
    19  import (
    20  	"strings"
    21  	"testing"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	utilnet "k8s.io/utils/net"
    25  )
    26  
    27  func TestGetLoadBalancerSourceRanges(t *testing.T) {
    28  	checkError := func(v string) {
    29  		t.Helper()
    30  		annotations := make(map[string]string)
    31  		annotations[v1.AnnotationLoadBalancerSourceRangesKey] = v
    32  		svc := v1.Service{}
    33  		svc.Annotations = annotations
    34  		_, err := GetLoadBalancerSourceRanges(&svc)
    35  		if err == nil {
    36  			t.Errorf("Expected error parsing: %q", v)
    37  		}
    38  		svc = v1.Service{}
    39  		svc.Spec.LoadBalancerSourceRanges = strings.Split(v, ",")
    40  		_, err = GetLoadBalancerSourceRanges(&svc)
    41  		if err == nil {
    42  			t.Errorf("Expected error parsing: %q", v)
    43  		}
    44  	}
    45  	checkError("10.0.0.1/33")
    46  	checkError("foo.bar")
    47  	checkError("10.0.0.1/32,*")
    48  	checkError("10.0.0.1/32,")
    49  	checkError("10.0.0.1/32, ")
    50  	checkError("10.0.0.1")
    51  
    52  	checkOK := func(v string) utilnet.IPNetSet {
    53  		t.Helper()
    54  		annotations := make(map[string]string)
    55  		annotations[v1.AnnotationLoadBalancerSourceRangesKey] = v
    56  		svc := v1.Service{}
    57  		svc.Annotations = annotations
    58  		_, err := GetLoadBalancerSourceRanges(&svc)
    59  		if err != nil {
    60  			t.Errorf("Unexpected error parsing: %q", v)
    61  		}
    62  		svc = v1.Service{}
    63  		svc.Spec.LoadBalancerSourceRanges = strings.Split(v, ",")
    64  		cidrs, err := GetLoadBalancerSourceRanges(&svc)
    65  		if err != nil {
    66  			t.Errorf("Unexpected error parsing: %q", v)
    67  		}
    68  		return cidrs
    69  	}
    70  	cidrs := checkOK("192.168.0.1/32")
    71  	if len(cidrs) != 1 {
    72  		t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice())
    73  	}
    74  	cidrs = checkOK("192.168.0.1/32,192.168.0.1/32")
    75  	if len(cidrs) != 1 {
    76  		t.Errorf("Expected exactly one CIDR (after de-dup): %v", cidrs.StringSlice())
    77  	}
    78  	cidrs = checkOK("192.168.0.1/32,192.168.0.2/32")
    79  	if len(cidrs) != 2 {
    80  		t.Errorf("Expected two CIDRs: %v", cidrs.StringSlice())
    81  	}
    82  	cidrs = checkOK("  192.168.0.1/32 , 192.168.0.2/32   ")
    83  	if len(cidrs) != 2 {
    84  		t.Errorf("Expected two CIDRs: %v", cidrs.StringSlice())
    85  	}
    86  	// check LoadBalancerSourceRanges not specified
    87  	svc := v1.Service{}
    88  	cidrs, err := GetLoadBalancerSourceRanges(&svc)
    89  	if err != nil {
    90  		t.Errorf("Unexpected error: %v", err)
    91  	}
    92  	if len(cidrs) != 1 {
    93  		t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice())
    94  	}
    95  	if !IsAllowAll(cidrs) {
    96  		t.Errorf("Expected default to be allow-all: %v", cidrs.StringSlice())
    97  	}
    98  	// check SourceRanges annotation is empty
    99  	annotations := make(map[string]string)
   100  	annotations[v1.AnnotationLoadBalancerSourceRangesKey] = ""
   101  	svc = v1.Service{}
   102  	svc.Annotations = annotations
   103  	cidrs, err = GetLoadBalancerSourceRanges(&svc)
   104  	if err != nil {
   105  		t.Errorf("Unexpected error: %v", err)
   106  	}
   107  	if len(cidrs) != 1 {
   108  		t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice())
   109  	}
   110  	if !IsAllowAll(cidrs) {
   111  		t.Errorf("Expected default to be allow-all: %v", cidrs.StringSlice())
   112  	}
   113  }
   114  
   115  func TestAllowAll(t *testing.T) {
   116  	checkAllowAll := func(allowAll bool, cidrs ...string) {
   117  		t.Helper()
   118  		ipnets, err := utilnet.ParseIPNets(cidrs...)
   119  		if err != nil {
   120  			t.Errorf("Unexpected error parsing cidrs: %v", cidrs)
   121  		}
   122  		if allowAll != IsAllowAll(ipnets) {
   123  			t.Errorf("IsAllowAll did not return expected value for %v", cidrs)
   124  		}
   125  	}
   126  	checkAllowAll(false, "10.0.0.1/32")
   127  	checkAllowAll(false, "10.0.0.1/32", "10.0.0.2/32")
   128  	checkAllowAll(false, "10.0.0.1/32", "10.0.0.1/32")
   129  
   130  	checkAllowAll(true, "0.0.0.0/0")
   131  	checkAllowAll(true, "192.168.0.0/0")
   132  	checkAllowAll(true, "192.168.0.1/32", "0.0.0.0/0")
   133  }
   134  
   135  func TestExternallyAccessible(t *testing.T) {
   136  	checkExternallyAccessible := func(expect bool, service *v1.Service) {
   137  		t.Helper()
   138  		res := ExternallyAccessible(service)
   139  		if res != expect {
   140  			t.Errorf("Expected ExternallyAccessible = %v, got %v", expect, res)
   141  		}
   142  	}
   143  
   144  	checkExternallyAccessible(false, &v1.Service{})
   145  	checkExternallyAccessible(false, &v1.Service{
   146  		Spec: v1.ServiceSpec{
   147  			Type: v1.ServiceTypeClusterIP,
   148  		},
   149  	})
   150  	checkExternallyAccessible(true, &v1.Service{
   151  		Spec: v1.ServiceSpec{
   152  			Type:        v1.ServiceTypeClusterIP,
   153  			ExternalIPs: []string{"1.2.3.4"},
   154  		},
   155  	})
   156  	checkExternallyAccessible(true, &v1.Service{
   157  		Spec: v1.ServiceSpec{
   158  			Type: v1.ServiceTypeLoadBalancer,
   159  		},
   160  	})
   161  	checkExternallyAccessible(true, &v1.Service{
   162  		Spec: v1.ServiceSpec{
   163  			Type: v1.ServiceTypeNodePort,
   164  		},
   165  	})
   166  	checkExternallyAccessible(false, &v1.Service{
   167  		Spec: v1.ServiceSpec{
   168  			Type: v1.ServiceTypeExternalName,
   169  		},
   170  	})
   171  	checkExternallyAccessible(false, &v1.Service{
   172  		Spec: v1.ServiceSpec{
   173  			Type:        v1.ServiceTypeExternalName,
   174  			ExternalIPs: []string{"1.2.3.4"},
   175  		},
   176  	})
   177  }
   178  
   179  func TestExternalPolicyLocal(t *testing.T) {
   180  	checkExternalPolicyLocal := func(requestsOnlyLocalTraffic bool, service *v1.Service) {
   181  		t.Helper()
   182  		res := ExternalPolicyLocal(service)
   183  		if res != requestsOnlyLocalTraffic {
   184  			t.Errorf("Expected requests OnlyLocal traffic = %v, got %v",
   185  				requestsOnlyLocalTraffic, res)
   186  		}
   187  	}
   188  
   189  	checkExternalPolicyLocal(false, &v1.Service{})
   190  	checkExternalPolicyLocal(false, &v1.Service{
   191  		Spec: v1.ServiceSpec{
   192  			Type: v1.ServiceTypeClusterIP,
   193  		},
   194  	})
   195  	checkExternalPolicyLocal(false, &v1.Service{
   196  		Spec: v1.ServiceSpec{
   197  			Type:        v1.ServiceTypeClusterIP,
   198  			ExternalIPs: []string{"1.2.3.4"},
   199  		},
   200  	})
   201  	checkExternalPolicyLocal(false, &v1.Service{
   202  		Spec: v1.ServiceSpec{
   203  			Type:                  v1.ServiceTypeClusterIP,
   204  			ExternalIPs:           []string{"1.2.3.4"},
   205  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyCluster,
   206  		},
   207  	})
   208  	checkExternalPolicyLocal(true, &v1.Service{
   209  		Spec: v1.ServiceSpec{
   210  			Type:                  v1.ServiceTypeClusterIP,
   211  			ExternalIPs:           []string{"1.2.3.4"},
   212  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyLocal,
   213  		},
   214  	})
   215  	checkExternalPolicyLocal(false, &v1.Service{
   216  		Spec: v1.ServiceSpec{
   217  			Type: v1.ServiceTypeNodePort,
   218  		},
   219  	})
   220  	checkExternalPolicyLocal(false, &v1.Service{
   221  		Spec: v1.ServiceSpec{
   222  			Type:                  v1.ServiceTypeNodePort,
   223  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyCluster,
   224  		},
   225  	})
   226  	checkExternalPolicyLocal(true, &v1.Service{
   227  		Spec: v1.ServiceSpec{
   228  			Type:                  v1.ServiceTypeNodePort,
   229  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyLocal,
   230  		},
   231  	})
   232  	checkExternalPolicyLocal(false, &v1.Service{
   233  		Spec: v1.ServiceSpec{
   234  			Type:                  v1.ServiceTypeLoadBalancer,
   235  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyCluster,
   236  		},
   237  	})
   238  	checkExternalPolicyLocal(true, &v1.Service{
   239  		Spec: v1.ServiceSpec{
   240  			Type:                  v1.ServiceTypeLoadBalancer,
   241  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyLocal,
   242  		},
   243  	})
   244  }
   245  
   246  func TestNeedsHealthCheck(t *testing.T) {
   247  	checkNeedsHealthCheck := func(needsHealthCheck bool, service *v1.Service) {
   248  		t.Helper()
   249  		res := NeedsHealthCheck(service)
   250  		if res != needsHealthCheck {
   251  			t.Errorf("Expected needs health check = %v, got %v",
   252  				needsHealthCheck, res)
   253  		}
   254  	}
   255  
   256  	checkNeedsHealthCheck(false, &v1.Service{
   257  		Spec: v1.ServiceSpec{
   258  			Type: v1.ServiceTypeClusterIP,
   259  		},
   260  	})
   261  	checkNeedsHealthCheck(false, &v1.Service{
   262  		Spec: v1.ServiceSpec{
   263  			Type:                  v1.ServiceTypeNodePort,
   264  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyCluster,
   265  		},
   266  	})
   267  	checkNeedsHealthCheck(false, &v1.Service{
   268  		Spec: v1.ServiceSpec{
   269  			Type:                  v1.ServiceTypeNodePort,
   270  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyLocal,
   271  		},
   272  	})
   273  	checkNeedsHealthCheck(false, &v1.Service{
   274  		Spec: v1.ServiceSpec{
   275  			Type:                  v1.ServiceTypeLoadBalancer,
   276  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyCluster,
   277  		},
   278  	})
   279  	checkNeedsHealthCheck(true, &v1.Service{
   280  		Spec: v1.ServiceSpec{
   281  			Type:                  v1.ServiceTypeLoadBalancer,
   282  			ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyLocal,
   283  		},
   284  	})
   285  }
   286  
   287  func TestInternalPolicyLocal(t *testing.T) {
   288  	checkInternalPolicyLocal := func(expected bool, service *v1.Service) {
   289  		t.Helper()
   290  		res := InternalPolicyLocal(service)
   291  		if res != expected {
   292  			t.Errorf("Expected internal local traffic = %v, got %v",
   293  				expected, res)
   294  		}
   295  	}
   296  
   297  	// default InternalTrafficPolicy is nil
   298  	checkInternalPolicyLocal(false, &v1.Service{})
   299  
   300  	local := v1.ServiceInternalTrafficPolicyLocal
   301  	checkInternalPolicyLocal(true, &v1.Service{
   302  		Spec: v1.ServiceSpec{
   303  			InternalTrafficPolicy: &local,
   304  		},
   305  	})
   306  
   307  	cluster := v1.ServiceInternalTrafficPolicyCluster
   308  	checkInternalPolicyLocal(false, &v1.Service{
   309  		Spec: v1.ServiceSpec{
   310  			InternalTrafficPolicy: &cluster,
   311  		},
   312  	})
   313  }