k8s.io/kubernetes@v1.29.3/pkg/api/service/testing/make.go (about) 1 /* 2 Copyright 2021 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 testing 18 19 import ( 20 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 "k8s.io/apimachinery/pkg/util/intstr" 22 utilpointer "k8s.io/utils/pointer" 23 24 api "k8s.io/kubernetes/pkg/apis/core" 25 ) 26 27 // Tweak is a function that modifies a Service. 28 type Tweak func(*api.Service) 29 30 // MakeService helps construct Service objects (which pass API validation) more 31 // legibly and tersely than a Go struct definition. By default this produces 32 // a ClusterIP service with a single port and a trivial selector. The caller 33 // can pass any number of tweak functions to further modify the result. 34 func MakeService(name string, tweaks ...Tweak) *api.Service { 35 // NOTE: Any field that would be populated by defaulting needs to be 36 // present and valid here. 37 svc := &api.Service{ 38 ObjectMeta: metav1.ObjectMeta{ 39 Name: name, 40 Namespace: metav1.NamespaceDefault, 41 }, 42 Spec: api.ServiceSpec{ 43 Selector: map[string]string{"k": "v"}, 44 SessionAffinity: api.ServiceAffinityNone, 45 }, 46 } 47 // Default to ClusterIP 48 SetTypeClusterIP(svc) 49 // Default to 1 port 50 SetPorts(MakeServicePort("", 93, intstr.FromInt32(76), api.ProtocolTCP))(svc) 51 52 for _, tweak := range tweaks { 53 tweak(svc) 54 } 55 56 return svc 57 } 58 59 // SetTypeClusterIP sets the service type to ClusterIP and clears other fields. 60 func SetTypeClusterIP(svc *api.Service) { 61 svc.Spec.Type = api.ServiceTypeClusterIP 62 for i := range svc.Spec.Ports { 63 svc.Spec.Ports[i].NodePort = 0 64 } 65 svc.Spec.ExternalName = "" 66 svc.Spec.ExternalTrafficPolicy = "" 67 svc.Spec.AllocateLoadBalancerNodePorts = nil 68 internalTrafficPolicy := api.ServiceInternalTrafficPolicyCluster 69 svc.Spec.InternalTrafficPolicy = &internalTrafficPolicy 70 } 71 72 // SetTypeNodePort sets the service type to NodePort and clears other fields. 73 func SetTypeNodePort(svc *api.Service) { 74 svc.Spec.Type = api.ServiceTypeNodePort 75 svc.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyCluster 76 svc.Spec.ExternalName = "" 77 svc.Spec.AllocateLoadBalancerNodePorts = nil 78 internalTrafficPolicy := api.ServiceInternalTrafficPolicyCluster 79 svc.Spec.InternalTrafficPolicy = &internalTrafficPolicy 80 } 81 82 // SetTypeLoadBalancer sets the service type to LoadBalancer and clears other fields. 83 func SetTypeLoadBalancer(svc *api.Service) { 84 svc.Spec.Type = api.ServiceTypeLoadBalancer 85 svc.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyCluster 86 svc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(true) 87 svc.Spec.ExternalName = "" 88 internalTrafficPolicy := api.ServiceInternalTrafficPolicyCluster 89 svc.Spec.InternalTrafficPolicy = &internalTrafficPolicy 90 } 91 92 // SetTypeExternalName sets the service type to ExternalName and clears other fields. 93 func SetTypeExternalName(svc *api.Service) { 94 svc.Spec.Type = api.ServiceTypeExternalName 95 svc.Spec.ExternalName = "example.com" 96 svc.Spec.ExternalTrafficPolicy = "" 97 svc.Spec.ClusterIP = "" 98 svc.Spec.ClusterIPs = nil 99 svc.Spec.AllocateLoadBalancerNodePorts = nil 100 svc.Spec.InternalTrafficPolicy = nil 101 } 102 103 // SetPorts sets the service ports list. 104 func SetPorts(ports ...api.ServicePort) Tweak { 105 return func(svc *api.Service) { 106 svc.Spec.Ports = ports 107 } 108 } 109 110 // MakeServicePort helps construct ServicePort objects which pass API 111 // validation. 112 func MakeServicePort(name string, port int, tgtPort intstr.IntOrString, proto api.Protocol) api.ServicePort { 113 return api.ServicePort{ 114 Name: name, 115 Port: int32(port), 116 TargetPort: tgtPort, 117 Protocol: proto, 118 } 119 } 120 121 // SetHeadless sets the service as headless and clears other fields. 122 func SetHeadless(svc *api.Service) { 123 SetTypeClusterIP(svc) 124 SetClusterIPs(api.ClusterIPNone)(svc) 125 } 126 127 // SetSelector sets the service selector. 128 func SetSelector(sel map[string]string) Tweak { 129 return func(svc *api.Service) { 130 svc.Spec.Selector = map[string]string{} 131 for k, v := range sel { 132 svc.Spec.Selector[k] = v 133 } 134 } 135 } 136 137 // SetClusterIP sets the service ClusterIP fields. 138 func SetClusterIP(ip string) Tweak { 139 return func(svc *api.Service) { 140 svc.Spec.ClusterIP = ip 141 } 142 } 143 144 // SetClusterIPs sets the service ClusterIP and ClusterIPs fields. 145 func SetClusterIPs(ips ...string) Tweak { 146 return func(svc *api.Service) { 147 svc.Spec.ClusterIP = ips[0] 148 svc.Spec.ClusterIPs = ips 149 } 150 } 151 152 // SetIPFamilies sets the service IPFamilies field. 153 func SetIPFamilies(families ...api.IPFamily) Tweak { 154 return func(svc *api.Service) { 155 svc.Spec.IPFamilies = families 156 } 157 } 158 159 // SetIPFamilyPolicy sets the service IPFamilyPolicy field. 160 func SetIPFamilyPolicy(policy api.IPFamilyPolicy) Tweak { 161 return func(svc *api.Service) { 162 svc.Spec.IPFamilyPolicy = &policy 163 } 164 } 165 166 // SetNodePorts sets the values for each node port, in order. If less values 167 // are specified than there are ports, the rest are untouched. 168 func SetNodePorts(values ...int) Tweak { 169 return func(svc *api.Service) { 170 for i := range svc.Spec.Ports { 171 if i >= len(values) { 172 break 173 } 174 svc.Spec.Ports[i].NodePort = int32(values[i]) 175 } 176 } 177 } 178 179 // SetInternalTrafficPolicy sets the internalTrafficPolicy field for a Service. 180 func SetInternalTrafficPolicy(policy api.ServiceInternalTrafficPolicy) Tweak { 181 return func(svc *api.Service) { 182 svc.Spec.InternalTrafficPolicy = &policy 183 } 184 } 185 186 // SetExternalTrafficPolicy sets the externalTrafficPolicy field for a Service. 187 func SetExternalTrafficPolicy(policy api.ServiceExternalTrafficPolicy) Tweak { 188 return func(svc *api.Service) { 189 svc.Spec.ExternalTrafficPolicy = policy 190 } 191 } 192 193 // SetAllocateLoadBalancerNodePorts sets the allocate LB node port field. 194 func SetAllocateLoadBalancerNodePorts(val bool) Tweak { 195 return func(svc *api.Service) { 196 svc.Spec.AllocateLoadBalancerNodePorts = utilpointer.BoolPtr(val) 197 } 198 } 199 200 // SetUniqueNodePorts sets all nodeports to unique values. 201 func SetUniqueNodePorts(svc *api.Service) { 202 for i := range svc.Spec.Ports { 203 svc.Spec.Ports[i].NodePort = int32(30000 + i) 204 } 205 } 206 207 // SetHealthCheckNodePort sets the healthCheckNodePort field for a Service. 208 func SetHealthCheckNodePort(value int32) Tweak { 209 return func(svc *api.Service) { 210 svc.Spec.HealthCheckNodePort = value 211 } 212 } 213 214 // SetSessionAffinity sets the SessionAffinity field. 215 func SetSessionAffinity(affinity api.ServiceAffinity) Tweak { 216 return func(svc *api.Service) { 217 svc.Spec.SessionAffinity = affinity 218 switch affinity { 219 case api.ServiceAffinityNone: 220 svc.Spec.SessionAffinityConfig = nil 221 case api.ServiceAffinityClientIP: 222 timeout := int32(10) 223 svc.Spec.SessionAffinityConfig = &api.SessionAffinityConfig{ 224 ClientIP: &api.ClientIPConfig{ 225 TimeoutSeconds: &timeout, 226 }, 227 } 228 } 229 } 230 } 231 232 // SetExternalName sets the ExternalName field. 233 func SetExternalName(val string) Tweak { 234 return func(svc *api.Service) { 235 svc.Spec.ExternalName = val 236 } 237 }