k8s.io/kubernetes@v1.29.3/pkg/api/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  	api "k8s.io/kubernetes/pkg/apis/core"
    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[api.AnnotationLoadBalancerSourceRangesKey] = v
    32  		svc := api.Service{}
    33  		svc.Annotations = annotations
    34  		_, err := GetLoadBalancerSourceRanges(&svc)
    35  		if err == nil {
    36  			t.Errorf("Expected error parsing: %q", v)
    37  		}
    38  		svc = api.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[api.AnnotationLoadBalancerSourceRangesKey] = v
    56  		svc := api.Service{}
    57  		svc.Annotations = annotations
    58  		_, err := GetLoadBalancerSourceRanges(&svc)
    59  		if err != nil {
    60  			t.Errorf("Unexpected error parsing: %q", v)
    61  		}
    62  		svc = api.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 := api.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[api.AnnotationLoadBalancerSourceRangesKey] = ""
   101  	svc = api.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 *api.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, &api.Service{})
   145  	checkExternallyAccessible(false, &api.Service{
   146  		Spec: api.ServiceSpec{
   147  			Type: api.ServiceTypeClusterIP,
   148  		},
   149  	})
   150  	checkExternallyAccessible(true, &api.Service{
   151  		Spec: api.ServiceSpec{
   152  			Type:        api.ServiceTypeClusterIP,
   153  			ExternalIPs: []string{"1.2.3.4"},
   154  		},
   155  	})
   156  	checkExternallyAccessible(true, &api.Service{
   157  		Spec: api.ServiceSpec{
   158  			Type: api.ServiceTypeLoadBalancer,
   159  		},
   160  	})
   161  	checkExternallyAccessible(true, &api.Service{
   162  		Spec: api.ServiceSpec{
   163  			Type: api.ServiceTypeNodePort,
   164  		},
   165  	})
   166  	checkExternallyAccessible(false, &api.Service{
   167  		Spec: api.ServiceSpec{
   168  			Type: api.ServiceTypeExternalName,
   169  		},
   170  	})
   171  	checkExternallyAccessible(false, &api.Service{
   172  		Spec: api.ServiceSpec{
   173  			Type:        api.ServiceTypeExternalName,
   174  			ExternalIPs: []string{"1.2.3.4"},
   175  		},
   176  	})
   177  }
   178  
   179  func TestRequestsOnlyLocalTraffic(t *testing.T) {
   180  	checkRequestsOnlyLocalTraffic := func(requestsOnlyLocalTraffic bool, service *api.Service) {
   181  		t.Helper()
   182  		res := RequestsOnlyLocalTraffic(service)
   183  		if res != requestsOnlyLocalTraffic {
   184  			t.Errorf("Expected requests OnlyLocal traffic = %v, got %v",
   185  				requestsOnlyLocalTraffic, res)
   186  		}
   187  	}
   188  
   189  	checkRequestsOnlyLocalTraffic(false, &api.Service{})
   190  	checkRequestsOnlyLocalTraffic(false, &api.Service{
   191  		Spec: api.ServiceSpec{
   192  			Type: api.ServiceTypeClusterIP,
   193  		},
   194  	})
   195  	checkRequestsOnlyLocalTraffic(false, &api.Service{
   196  		Spec: api.ServiceSpec{
   197  			Type: api.ServiceTypeNodePort,
   198  		},
   199  	})
   200  	checkRequestsOnlyLocalTraffic(false, &api.Service{
   201  		Spec: api.ServiceSpec{
   202  			Type:                  api.ServiceTypeNodePort,
   203  			ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyCluster,
   204  		},
   205  	})
   206  	checkRequestsOnlyLocalTraffic(true, &api.Service{
   207  		Spec: api.ServiceSpec{
   208  			Type:                  api.ServiceTypeNodePort,
   209  			ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyLocal,
   210  		},
   211  	})
   212  	checkRequestsOnlyLocalTraffic(false, &api.Service{
   213  		Spec: api.ServiceSpec{
   214  			Type:                  api.ServiceTypeLoadBalancer,
   215  			ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyCluster,
   216  		},
   217  	})
   218  	checkRequestsOnlyLocalTraffic(true, &api.Service{
   219  		Spec: api.ServiceSpec{
   220  			Type:                  api.ServiceTypeLoadBalancer,
   221  			ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyLocal,
   222  		},
   223  	})
   224  }
   225  
   226  func TestNeedsHealthCheck(t *testing.T) {
   227  	checkNeedsHealthCheck := func(needsHealthCheck bool, service *api.Service) {
   228  		t.Helper()
   229  		res := NeedsHealthCheck(service)
   230  		if res != needsHealthCheck {
   231  			t.Errorf("Expected needs health check = %v, got %v",
   232  				needsHealthCheck, res)
   233  		}
   234  	}
   235  
   236  	checkNeedsHealthCheck(false, &api.Service{
   237  		Spec: api.ServiceSpec{
   238  			Type: api.ServiceTypeClusterIP,
   239  		},
   240  	})
   241  	checkNeedsHealthCheck(false, &api.Service{
   242  		Spec: api.ServiceSpec{
   243  			Type:                  api.ServiceTypeNodePort,
   244  			ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyCluster,
   245  		},
   246  	})
   247  	checkNeedsHealthCheck(false, &api.Service{
   248  		Spec: api.ServiceSpec{
   249  			Type:                  api.ServiceTypeNodePort,
   250  			ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyLocal,
   251  		},
   252  	})
   253  	checkNeedsHealthCheck(false, &api.Service{
   254  		Spec: api.ServiceSpec{
   255  			Type:                  api.ServiceTypeLoadBalancer,
   256  			ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyCluster,
   257  		},
   258  	})
   259  	checkNeedsHealthCheck(true, &api.Service{
   260  		Spec: api.ServiceSpec{
   261  			Type:                  api.ServiceTypeLoadBalancer,
   262  			ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyLocal,
   263  		},
   264  	})
   265  }