diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 9f582bd223c..95029920faf 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -10897,6 +10897,10 @@ "description": "hostname of this endpoint. This field may be used by consumers of endpoints to distinguish endpoints from each other (e.g. in DNS names). Multiple endpoints which use the same hostname should be considered fungible (e.g. multiple A values in DNS). Must be lowercase and pass DNS Label (RFC 1123) validation.", "type": "string" }, + "nodeName": { + "description": "nodeName represents the name of the Node hosting this endpoint. This can be used to determine endpoints local to a Node. This field can be enabled with the EndpointSliceNodeName feature gate.", + "type": "string" + }, "targetRef": { "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference", "description": "targetRef is a reference to a Kubernetes object that represents this endpoint." @@ -10905,7 +10909,7 @@ "additionalProperties": { "type": "string" }, - "description": "topology contains arbitrary topology information associated with the endpoint. These key/value pairs must conform with the label format. https://kubernetes.io/docs/concepts/overview/working-with-objects/labels Topology may include a maximum of 16 key/value pairs. This includes, but is not limited to the following well known keys: * kubernetes.io/hostname: the value indicates the hostname of the node\n where the endpoint is located. This should match the corresponding\n node label.\n* topology.kubernetes.io/zone: the value indicates the zone where the\n endpoint is located. This should match the corresponding node label.\n* topology.kubernetes.io/region: the value indicates the region where the\n endpoint is located. This should match the corresponding node label.", + "description": "topology contains arbitrary topology information associated with the endpoint. These key/value pairs must conform with the label format. https://kubernetes.io/docs/concepts/overview/working-with-objects/labels Topology may include a maximum of 16 key/value pairs. This includes, but is not limited to the following well known keys: * kubernetes.io/hostname: the value indicates the hostname of the node\n where the endpoint is located. This should match the corresponding\n node label.\n* topology.kubernetes.io/zone: the value indicates the zone where the\n endpoint is located. This should match the corresponding node label.\n* topology.kubernetes.io/region: the value indicates the region where the\n endpoint is located. This should match the corresponding node label.\nThis field is deprecated and will be removed in future api versions.", "type": "object" } }, @@ -10922,11 +10926,11 @@ "type": "boolean" }, "serving": { - "description": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition.", + "description": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", "type": "boolean" }, "terminating": { - "description": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating.", + "description": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", "type": "boolean" } }, diff --git a/pkg/apis/discovery/types.go b/pkg/apis/discovery/types.go index 6fa6624270c..1201d4abbc4 100644 --- a/pkg/apis/discovery/types.go +++ b/pkg/apis/discovery/types.go @@ -57,12 +57,6 @@ type EndpointSlice struct { type AddressType string const ( - // AddressTypeIP represents an IP Address. - // This address type has been deprecated and has been replaced by the IPv4 - // and IPv6 adddress types. New resources with this address type will be - // considered invalid. This will be fully removed in 1.18. - // +deprecated - AddressTypeIP = AddressType("IP") // AddressTypeIPv4 represents an IPv4 Address. AddressTypeIPv4 = AddressType(api.IPv4Protocol) // AddressTypeIPv6 represents an IPv6 Address. @@ -105,8 +99,14 @@ type Endpoint struct { // endpoint is located. This should match the corresponding node label. // * topology.kubernetes.io/region: the value indicates the region where the // endpoint is located. This should match the corresponding node label. + // This field is deprecated and will be removed in future api versions. // +optional Topology map[string]string + // nodeName represents the name of the Node hosting this endpoint. This can + // be used to determine endpoints local to a Node. This field can be enabled + // with the EndpointSliceNodeName feature gate. + // +optional + NodeName *string } // EndpointConditions represents the current condition of an endpoint. @@ -118,15 +118,18 @@ type EndpointConditions struct { // "true" for terminating endpoints. Ready *bool - // serving is identical to ready except that it is set regardless of the terminating - // state of endpoints. This condition should be set to true for a ready endpoint that - // is terminating. If nil, consumers should defer to the ready condition. + // serving is identical to ready except that it is set regardless of the + // terminating state of endpoints. This condition should be set to true for + // a ready endpoint that is terminating. If nil, consumers should defer to + // the ready condition. This field can be enabled with the + // EndpointSliceTerminatingCondition feature gate. // +optional Serving *bool - // terminating indicates that this endpoint is terminating. A nil value indicates an - // unknown state. Consumers should interpret this unknown state to mean that the - // endpoint is not terminating. + // terminating indicates that this endpoint is terminating. A nil value + // indicates an unknown state. Consumers should interpret this unknown state + // to mean that the endpoint is not terminating. This field can be enabled + // with the EndpointSliceTerminatingCondition feature gate. // +optional Terminating *bool } diff --git a/pkg/apis/discovery/v1alpha1/zz_generated.conversion.go b/pkg/apis/discovery/v1alpha1/zz_generated.conversion.go index 46412fd0c52..0f65d9579aa 100644 --- a/pkg/apis/discovery/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/discovery/v1alpha1/zz_generated.conversion.go @@ -99,6 +99,7 @@ func autoConvert_v1alpha1_Endpoint_To_discovery_Endpoint(in *v1alpha1.Endpoint, out.Hostname = (*string)(unsafe.Pointer(in.Hostname)) out.TargetRef = (*core.ObjectReference)(unsafe.Pointer(in.TargetRef)) out.Topology = *(*map[string]string)(unsafe.Pointer(&in.Topology)) + out.NodeName = (*string)(unsafe.Pointer(in.NodeName)) return nil } @@ -115,6 +116,7 @@ func autoConvert_discovery_Endpoint_To_v1alpha1_Endpoint(in *discovery.Endpoint, out.Hostname = (*string)(unsafe.Pointer(in.Hostname)) out.TargetRef = (*v1.ObjectReference)(unsafe.Pointer(in.TargetRef)) out.Topology = *(*map[string]string)(unsafe.Pointer(&in.Topology)) + out.NodeName = (*string)(unsafe.Pointer(in.NodeName)) return nil } diff --git a/pkg/apis/discovery/v1beta1/zz_generated.conversion.go b/pkg/apis/discovery/v1beta1/zz_generated.conversion.go index f06d2d0ef56..2640deee901 100644 --- a/pkg/apis/discovery/v1beta1/zz_generated.conversion.go +++ b/pkg/apis/discovery/v1beta1/zz_generated.conversion.go @@ -99,6 +99,7 @@ func autoConvert_v1beta1_Endpoint_To_discovery_Endpoint(in *v1beta1.Endpoint, ou out.Hostname = (*string)(unsafe.Pointer(in.Hostname)) out.TargetRef = (*core.ObjectReference)(unsafe.Pointer(in.TargetRef)) out.Topology = *(*map[string]string)(unsafe.Pointer(&in.Topology)) + out.NodeName = (*string)(unsafe.Pointer(in.NodeName)) return nil } @@ -115,6 +116,7 @@ func autoConvert_discovery_Endpoint_To_v1beta1_Endpoint(in *discovery.Endpoint, out.Hostname = (*string)(unsafe.Pointer(in.Hostname)) out.TargetRef = (*v1.ObjectReference)(unsafe.Pointer(in.TargetRef)) out.Topology = *(*map[string]string)(unsafe.Pointer(&in.Topology)) + out.NodeName = (*string)(unsafe.Pointer(in.NodeName)) return nil } diff --git a/pkg/apis/discovery/validation/validation.go b/pkg/apis/discovery/validation/validation.go index 810f2ca124d..8499e7a696a 100644 --- a/pkg/apis/discovery/validation/validation.go +++ b/pkg/apis/discovery/validation/validation.go @@ -33,9 +33,6 @@ var ( string(discovery.AddressTypeIPv6), string(discovery.AddressTypeFQDN), ) - deprecatedAddressTypes = sets.NewString( - string(discovery.AddressTypeIP), - ) supportedPortProtocols = sets.NewString( string(api.ProtocolTCP), string(api.ProtocolUDP), @@ -53,9 +50,9 @@ var ( var ValidateEndpointSliceName = apimachineryvalidation.NameIsDNSSubdomain // ValidateEndpointSlice validates an EndpointSlice. -func ValidateEndpointSlice(endpointSlice *discovery.EndpointSlice, validAddressTypes sets.String) field.ErrorList { +func ValidateEndpointSlice(endpointSlice *discovery.EndpointSlice) field.ErrorList { allErrs := apivalidation.ValidateObjectMeta(&endpointSlice.ObjectMeta, true, ValidateEndpointSliceName, field.NewPath("metadata")) - allErrs = append(allErrs, validateAddressType(endpointSlice.AddressType, validAddressTypes)...) + allErrs = append(allErrs, validateAddressType(endpointSlice.AddressType)...) allErrs = append(allErrs, validateEndpoints(endpointSlice.Endpoints, endpointSlice.AddressType, field.NewPath("endpoints"))...) allErrs = append(allErrs, validatePorts(endpointSlice.Ports, field.NewPath("ports"))...) @@ -64,12 +61,12 @@ func ValidateEndpointSlice(endpointSlice *discovery.EndpointSlice, validAddressT // ValidateEndpointSliceCreate validates an EndpointSlice when it is created. func ValidateEndpointSliceCreate(endpointSlice *discovery.EndpointSlice) field.ErrorList { - return ValidateEndpointSlice(endpointSlice, supportedAddressTypes) + return ValidateEndpointSlice(endpointSlice) } // ValidateEndpointSliceUpdate validates an EndpointSlice when it is updated. func ValidateEndpointSliceUpdate(newEndpointSlice, oldEndpointSlice *discovery.EndpointSlice) field.ErrorList { - allErrs := ValidateEndpointSlice(newEndpointSlice, supportedAddressTypes.Union(deprecatedAddressTypes)) + allErrs := ValidateEndpointSlice(newEndpointSlice) allErrs = append(allErrs, apivalidation.ValidateImmutableField(newEndpointSlice.AddressType, oldEndpointSlice.AddressType, field.NewPath("addressType"))...) return allErrs @@ -97,10 +94,6 @@ func validateEndpoints(endpoints []discovery.Endpoint, addrType discovery.Addres // This validates known address types, unknown types fall through // and do not get validated. switch addrType { - case discovery.AddressTypeIP: - for _, msg := range validation.IsValidIP(address) { - allErrs = append(allErrs, field.Invalid(addressPath.Index(i), address, msg)) - } case discovery.AddressTypeIPv4: allErrs = append(allErrs, validation.IsValidIPv4Address(addressPath.Index(i), address)...) case discovery.AddressTypeIPv6: @@ -110,6 +103,13 @@ func validateEndpoints(endpoints []discovery.Endpoint, addrType discovery.Addres } } + if endpoint.NodeName != nil { + nnPath := idxPath.Child("nodeName") + for _, msg := range apivalidation.ValidateNodeName(*endpoint.NodeName, false) { + allErrs = append(allErrs, field.Invalid(nnPath, *endpoint.NodeName, msg)) + } + } + topologyPath := idxPath.Child("topology") if len(endpoint.Topology) > maxTopologyLabels { allErrs = append(allErrs, field.TooMany(topologyPath, len(endpoint.Topology), maxTopologyLabels)) @@ -162,13 +162,13 @@ func validatePorts(endpointPorts []discovery.EndpointPort, fldPath *field.Path) return allErrs } -func validateAddressType(addressType discovery.AddressType, validAddressTypes sets.String) field.ErrorList { +func validateAddressType(addressType discovery.AddressType) field.ErrorList { allErrs := field.ErrorList{} if addressType == "" { allErrs = append(allErrs, field.Required(field.NewPath("addressType"), "")) - } else if !validAddressTypes.Has(string(addressType)) { - allErrs = append(allErrs, field.NotSupported(field.NewPath("addressType"), addressType, validAddressTypes.List())) + } else if !supportedAddressTypes.Has(string(addressType)) { + allErrs = append(allErrs, field.NotSupported(field.NewPath("addressType"), addressType, supportedAddressTypes.List())) } return allErrs diff --git a/pkg/apis/discovery/validation/validation_test.go b/pkg/apis/discovery/validation/validation_test.go index 060545f93ab..5c7d478eb7e 100644 --- a/pkg/apis/discovery/validation/validation_test.go +++ b/pkg/apis/discovery/validation/validation_test.go @@ -92,7 +92,7 @@ func TestValidateEndpointSlice(t *testing.T) { expectedErrors: 0, endpointSlice: &discovery.EndpointSlice{ ObjectMeta: standardMeta, - AddressType: discovery.AddressTypeIP, + AddressType: discovery.AddressTypeIPv4, Ports: []discovery.EndpointPort{{ Name: utilpointer.StringPtr("one"), Protocol: protocolPtr(api.ProtocolTCP), @@ -378,7 +378,7 @@ func TestValidateEndpointSlice(t *testing.T) { expectedErrors: 1, endpointSlice: &discovery.EndpointSlice{ ObjectMeta: standardMeta, - AddressType: discovery.AddressTypeIP, + AddressType: discovery.AddressTypeIPv4, Ports: []discovery.EndpointPort{{ Name: utilpointer.StringPtr("http"), Protocol: protocolPtr(api.ProtocolTCP), @@ -438,7 +438,7 @@ func TestValidateEndpointSlice(t *testing.T) { expectedErrors: 1, endpointSlice: &discovery.EndpointSlice{ ObjectMeta: standardMeta, - AddressType: discovery.AddressTypeIP, + AddressType: discovery.AddressTypeIPv4, Ports: []discovery.EndpointPort{{ Name: utilpointer.StringPtr("http"), Protocol: protocolPtr(api.ProtocolTCP), @@ -458,7 +458,7 @@ func TestValidateEndpointSlice(t *testing.T) { for name, testCase := range testCases { t.Run(name, func(t *testing.T) { - errs := ValidateEndpointSlice(testCase.endpointSlice, supportedAddressTypes.Union(deprecatedAddressTypes)) + errs := ValidateEndpointSlice(testCase.endpointSlice) if len(errs) != testCase.expectedErrors { t.Errorf("Expected %d errors, got %d errors: %v", testCase.expectedErrors, len(errs), errs) } @@ -473,8 +473,9 @@ func TestValidateEndpointSliceCreate(t *testing.T) { } testCases := map[string]struct { - expectedErrors int - endpointSlice *discovery.EndpointSlice + expectedErrors int + endpointSlice *discovery.EndpointSlice + nodeNameGateEnabled bool }{ "good-slice": { expectedErrors: 0, @@ -491,13 +492,45 @@ func TestValidateEndpointSliceCreate(t *testing.T) { }}, }, }, + "good-slice-node-name": { + expectedErrors: 0, + endpointSlice: &discovery.EndpointSlice{ + ObjectMeta: standardMeta, + AddressType: discovery.AddressTypeIPv4, + Ports: []discovery.EndpointPort{{ + Name: utilpointer.StringPtr("http"), + Protocol: protocolPtr(api.ProtocolTCP), + }}, + Endpoints: []discovery.Endpoint{{ + Addresses: generateIPAddresses(1), + Hostname: utilpointer.StringPtr("valid-123"), + NodeName: utilpointer.StringPtr("valid-node-name"), + }}, + }, + }, // expected failures + "bad-node-name": { + expectedErrors: 1, + endpointSlice: &discovery.EndpointSlice{ + ObjectMeta: standardMeta, + AddressType: discovery.AddressTypeIPv4, + Ports: []discovery.EndpointPort{{ + Name: utilpointer.StringPtr("http"), + Protocol: protocolPtr(api.ProtocolTCP), + }}, + Endpoints: []discovery.Endpoint{{ + Addresses: generateIPAddresses(1), + Hostname: utilpointer.StringPtr("valid-123"), + NodeName: utilpointer.StringPtr("INvalid-node-name"), + }}, + }, + }, "deprecated-address-type": { expectedErrors: 1, endpointSlice: &discovery.EndpointSlice{ ObjectMeta: standardMeta, - AddressType: discovery.AddressTypeIP, + AddressType: discovery.AddressType("IP"), Ports: []discovery.EndpointPort{{ Name: utilpointer.StringPtr("http"), Protocol: protocolPtr(api.ProtocolTCP), @@ -537,56 +570,78 @@ func TestValidateEndpointSliceUpdate(t *testing.T) { standardMeta := metav1.ObjectMeta{Name: "es1", Namespace: "test"} testCases := map[string]struct { - expectedErrors int - newEndpointSlice *discovery.EndpointSlice - oldEndpointSlice *discovery.EndpointSlice + expectedErrors int + nodeNameGateEnabled bool + oldEndpointSlice *discovery.EndpointSlice + newEndpointSlice *discovery.EndpointSlice }{ "valid and identical slices": { - newEndpointSlice: &discovery.EndpointSlice{ + oldEndpointSlice: &discovery.EndpointSlice{ ObjectMeta: standardMeta, AddressType: discovery.AddressTypeIPv6, }, - oldEndpointSlice: &discovery.EndpointSlice{ + newEndpointSlice: &discovery.EndpointSlice{ ObjectMeta: standardMeta, AddressType: discovery.AddressTypeIPv6, }, expectedErrors: 0, }, - "deprecated address type": { - expectedErrors: 0, - newEndpointSlice: &discovery.EndpointSlice{ - ObjectMeta: standardMeta, - AddressType: discovery.AddressTypeIP, - }, + + // expected errors + "invalide node name set": { oldEndpointSlice: &discovery.EndpointSlice{ ObjectMeta: standardMeta, - AddressType: discovery.AddressTypeIP, + AddressType: discovery.AddressTypeIPv4, + Endpoints: []discovery.Endpoint{{ + Addresses: []string{"10.1.2.3"}, + }}, + }, + newEndpointSlice: &discovery.EndpointSlice{ + ObjectMeta: standardMeta, + AddressType: discovery.AddressTypeIPv4, + Endpoints: []discovery.Endpoint{{ + Addresses: []string{"10.1.2.3"}, + NodeName: utilpointer.StringPtr("INVALID foo"), + }}, + }, + expectedErrors: 1, + }, + + "deprecated address type": { + expectedErrors: 1, + oldEndpointSlice: &discovery.EndpointSlice{ + ObjectMeta: standardMeta, + AddressType: discovery.AddressType("IP"), + }, + newEndpointSlice: &discovery.EndpointSlice{ + ObjectMeta: standardMeta, + AddressType: discovery.AddressType("IP"), }, }, "valid and identical slices with different address types": { - newEndpointSlice: &discovery.EndpointSlice{ - ObjectMeta: standardMeta, - AddressType: discovery.AddressTypeIP, - }, oldEndpointSlice: &discovery.EndpointSlice{ ObjectMeta: standardMeta, AddressType: discovery.AddressType("other"), }, + newEndpointSlice: &discovery.EndpointSlice{ + ObjectMeta: standardMeta, + AddressType: discovery.AddressTypeIPv4, + }, expectedErrors: 1, }, "invalid slices with valid address types": { + oldEndpointSlice: &discovery.EndpointSlice{ + ObjectMeta: standardMeta, + AddressType: discovery.AddressTypeIPv4, + }, newEndpointSlice: &discovery.EndpointSlice{ ObjectMeta: standardMeta, - AddressType: discovery.AddressTypeIP, + AddressType: discovery.AddressTypeIPv4, Ports: []discovery.EndpointPort{{ Name: utilpointer.StringPtr(""), Protocol: protocolPtr(api.Protocol("invalid")), }}, }, - oldEndpointSlice: &discovery.EndpointSlice{ - ObjectMeta: standardMeta, - AddressType: discovery.AddressTypeIP, - }, expectedErrors: 1, }, } diff --git a/pkg/apis/discovery/zz_generated.deepcopy.go b/pkg/apis/discovery/zz_generated.deepcopy.go index bb6b56c0763..aba324f34c7 100644 --- a/pkg/apis/discovery/zz_generated.deepcopy.go +++ b/pkg/apis/discovery/zz_generated.deepcopy.go @@ -51,6 +51,11 @@ func (in *Endpoint) DeepCopyInto(out *Endpoint) { (*out)[key] = val } } + if in.NodeName != nil { + in, out := &in.NodeName, &out.NodeName + *out = new(string) + **out = **in + } return } diff --git a/pkg/controller/endpointslice/reconciler_test.go b/pkg/controller/endpointslice/reconciler_test.go index a4d37d7a2f5..522881dda83 100644 --- a/pkg/controller/endpointslice/reconciler_test.go +++ b/pkg/controller/endpointslice/reconciler_test.go @@ -917,7 +917,8 @@ func TestReconcileEndpointSlicesReplaceDeprecated(t *testing.T) { namespace := "test" svc, endpointMeta := newServiceAndEndpointMeta("foo", namespace) - endpointMeta.AddressType = discovery.AddressTypeIP + // "IP" is a deprecated address type, ensuring that it is handled properly. + endpointMeta.AddressType = discovery.AddressType("IP") existingSlices := []*discovery.EndpointSlice{} pods := []*corev1.Pod{} diff --git a/pkg/controller/endpointslice/utils.go b/pkg/controller/endpointslice/utils.go index 29b52c127b5..d3738cc7af4 100644 --- a/pkg/controller/endpointslice/utils.go +++ b/pkg/controller/endpointslice/utils.go @@ -87,6 +87,10 @@ func podToEndpoint(pod *corev1.Pod, node *corev1.Node, service *corev1.Service, ep.Conditions.Terminating = &terminating } + if pod.Spec.NodeName != "" && utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceNodeName) { + ep.NodeName = &pod.Spec.NodeName + } + if endpointutil.ShouldSetHostname(pod, service) { ep.Hostname = &pod.Spec.Hostname } diff --git a/pkg/controller/endpointslice/utils_test.go b/pkg/controller/endpointslice/utils_test.go index 68f654f9fc4..5c61dc3946f 100644 --- a/pkg/controller/endpointslice/utils_test.go +++ b/pkg/controller/endpointslice/utils_test.go @@ -252,6 +252,7 @@ func TestPodToEndpoint(t *testing.T) { expectedEndpoint discovery.Endpoint publishNotReadyAddresses bool terminatingGateEnabled bool + nodeNameGateEnabled bool }{ { name: "Ready pod", @@ -321,6 +322,25 @@ func TestPodToEndpoint(t *testing.T) { }, }, }, + { + name: "Ready pod + node name gate enabled", + pod: readyPod, + svc: &svc, + nodeNameGateEnabled: true, + expectedEndpoint: discovery.Endpoint{ + Addresses: []string{"1.2.3.5"}, + Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)}, + Topology: map[string]string{"kubernetes.io/hostname": "node-1"}, + NodeName: utilpointer.StringPtr("node-1"), + TargetRef: &v1.ObjectReference{ + Kind: "Pod", + Namespace: ns, + Name: readyPod.Name, + UID: readyPod.UID, + ResourceVersion: readyPod.ResourceVersion, + }, + }, + }, { name: "Ready pod + node labels", pod: readyPod, @@ -499,6 +519,7 @@ func TestPodToEndpoint(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testCase.terminatingGateEnabled)() + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceNodeName, testCase.nodeNameGateEnabled)() endpoint := podToEndpoint(testCase.pod, testCase.node, testCase.svc, discovery.AddressTypeIPv4) if !reflect.DeepEqual(testCase.expectedEndpoint, endpoint) { diff --git a/pkg/controller/endpointslicemirroring/BUILD b/pkg/controller/endpointslicemirroring/BUILD index 41919a6f2d7..ede6890250e 100644 --- a/pkg/controller/endpointslicemirroring/BUILD +++ b/pkg/controller/endpointslicemirroring/BUILD @@ -18,6 +18,7 @@ go_library( "//pkg/controller:go_default_library", "//pkg/controller/endpointslicemirroring/metrics:go_default_library", "//pkg/controller/util/endpoint:go_default_library", + "//pkg/features:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/discovery/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", @@ -28,6 +29,7 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/discovery/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", @@ -58,6 +60,7 @@ go_test( deps = [ "//pkg/controller:go_default_library", "//pkg/controller/endpointslicemirroring/metrics:go_default_library", + "//pkg/features:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/discovery/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -66,6 +69,7 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/rand:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", @@ -73,6 +77,7 @@ go_test( "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library", + "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", "//staging/src/k8s.io/component-base/metrics/testutil:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", diff --git a/pkg/controller/endpointslicemirroring/utils.go b/pkg/controller/endpointslicemirroring/utils.go index 66ddbf8eee9..3eb555f263d 100644 --- a/pkg/controller/endpointslicemirroring/utils.go +++ b/pkg/controller/endpointslicemirroring/utils.go @@ -27,10 +27,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/leaderelection/resourcelock" "k8s.io/kubernetes/pkg/apis/discovery/validation" endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint" + "k8s.io/kubernetes/pkg/features" ) // addrTypePortMapKey is used to uniquely identify groups of endpoint ports and @@ -138,6 +140,9 @@ func addressToEndpoint(address corev1.EndpointAddress, ready bool) *discovery.En endpoint.Topology = map[string]string{ "kubernetes.io/hostname": *address.NodeName, } + if utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceNodeName) { + endpoint.NodeName = address.NodeName + } } if address.Hostname != "" { endpoint.Hostname = &address.Hostname diff --git a/pkg/controller/endpointslicemirroring/utils_test.go b/pkg/controller/endpointslicemirroring/utils_test.go index 9944f191edf..3b6bd5cf4be 100644 --- a/pkg/controller/endpointslicemirroring/utils_test.go +++ b/pkg/controller/endpointslicemirroring/utils_test.go @@ -27,8 +27,12 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/rand" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/kubernetes/fake" k8stesting "k8s.io/client-go/testing" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/kubernetes/pkg/features" + utilpointer "k8s.io/utils/pointer" ) func TestNewEndpointSlice(t *testing.T) { @@ -76,6 +80,86 @@ func TestNewEndpointSlice(t *testing.T) { } } +func TestAddressToEndpoint(t *testing.T) { + testCases := []struct { + name string + epAddress v1.EndpointAddress + expectedEndpoint discovery.Endpoint + ready bool + nodeNameGateEnabled bool + }{{ + name: "simple + gate enabled", + epAddress: v1.EndpointAddress{ + IP: "10.1.2.3", + Hostname: "foo", + NodeName: utilpointer.StringPtr("node-abc"), + TargetRef: &v1.ObjectReference{ + APIVersion: "v1", + Kind: "Pod", + Namespace: "default", + Name: "foo", + }, + }, + ready: true, + nodeNameGateEnabled: true, + expectedEndpoint: discovery.Endpoint{ + Addresses: []string{"10.1.2.3"}, + Hostname: utilpointer.StringPtr("foo"), + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + }, + Topology: map[string]string{ + "kubernetes.io/hostname": "node-abc", + }, + TargetRef: &v1.ObjectReference{ + APIVersion: "v1", + Kind: "Pod", + Namespace: "default", + Name: "foo", + }, + NodeName: utilpointer.StringPtr("node-abc"), + }, + }, { + name: "simple + gate disabled", + epAddress: v1.EndpointAddress{ + IP: "10.1.2.3", + Hostname: "foo", + NodeName: utilpointer.StringPtr("node-abc"), + TargetRef: &v1.ObjectReference{ + APIVersion: "v1", + Kind: "Pod", + Namespace: "default", + Name: "foo", + }, + }, + ready: true, + nodeNameGateEnabled: false, + expectedEndpoint: discovery.Endpoint{ + Addresses: []string{"10.1.2.3"}, + Hostname: utilpointer.StringPtr("foo"), + Conditions: discovery.EndpointConditions{ + Ready: utilpointer.BoolPtr(true), + }, + Topology: map[string]string{ + "kubernetes.io/hostname": "node-abc", + }, + TargetRef: &v1.ObjectReference{ + APIVersion: "v1", + Kind: "Pod", + Namespace: "default", + Name: "foo", + }, + }, + }} + + for _, tc := range testCases { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceNodeName, tc.nodeNameGateEnabled)() + + ep := addressToEndpoint(tc.epAddress, tc.ready) + assert.EqualValues(t, tc.expectedEndpoint, *ep) + } +} + // Test helpers func newClientset() *fake.Clientset { diff --git a/pkg/controlplane/reconcilers/BUILD b/pkg/controlplane/reconcilers/BUILD index 55146b8b1fb..6e108dfb3fc 100644 --- a/pkg/controlplane/reconcilers/BUILD +++ b/pkg/controlplane/reconcilers/BUILD @@ -14,6 +14,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/api/v1/endpoints:go_default_library", + "//pkg/features:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/discovery/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", @@ -23,6 +24,7 @@ go_library( "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/discovery/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/util/retry:go_default_library", diff --git a/pkg/controlplane/reconcilers/endpointsadapter.go b/pkg/controlplane/reconcilers/endpointsadapter.go index 54e74c15bae..99d8f6b62a5 100644 --- a/pkg/controlplane/reconcilers/endpointsadapter.go +++ b/pkg/controlplane/reconcilers/endpointsadapter.go @@ -23,8 +23,10 @@ import ( apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilfeature "k8s.io/apiserver/pkg/util/feature" corev1client "k8s.io/client-go/kubernetes/typed/core/v1" discoveryclient "k8s.io/client-go/kubernetes/typed/discovery/v1beta1" + "k8s.io/kubernetes/pkg/features" utilnet "k8s.io/utils/net" ) @@ -166,17 +168,22 @@ func getEndpointsFromAddresses(addresses []corev1.EndpointAddress, addressType d // endpointFromAddress generates an Endpoint from an EndpointAddress resource. func endpointFromAddress(address corev1.EndpointAddress, ready bool) discovery.Endpoint { - topology := map[string]string{} - if address.NodeName != nil { - topology["kubernetes.io/hostname"] = *address.NodeName - } - - return discovery.Endpoint{ + ep := discovery.Endpoint{ Addresses: []string{address.IP}, Conditions: discovery.EndpointConditions{Ready: &ready}, TargetRef: address.TargetRef, - Topology: topology, } + + if address.NodeName != nil { + ep.Topology = map[string]string{ + "kubernetes.io/hostname": *address.NodeName, + } + if utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceNodeName) { + ep.NodeName = address.NodeName + } + } + + return ep } // allAddressesIPv6 returns true if all provided addresses are IPv6. diff --git a/pkg/controlplane/reconcilers/endpointsadapter_test.go b/pkg/controlplane/reconcilers/endpointsadapter_test.go index d8febe69a3e..531b1e2a31c 100644 --- a/pkg/controlplane/reconcilers/endpointsadapter_test.go +++ b/pkg/controlplane/reconcilers/endpointsadapter_test.go @@ -232,7 +232,8 @@ func TestEndpointsAdapterUpdate(t *testing.T) { // with one that has an IPv4 address type. endpoints4, _ := generateEndpointsAndSlice("foo", "testing", []int{80}, []string{"10.1.2.7", "10.1.2.8"}) _, epSlice4IP := generateEndpointsAndSlice("foo", "testing", []int{80}, []string{"10.1.2.7", "10.1.2.8"}) - epSlice4IP.AddressType = discovery.AddressTypeIP + // "IP" is a deprecated address type, ensuring that it is handled properly. + epSlice4IP.AddressType = discovery.AddressType("IP") _, epSlice4IPv4 := generateEndpointsAndSlice("foo", "testing", []int{80}, []string{"10.1.2.7", "10.1.2.8"}) testCases := map[string]struct { diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index fd1b1d742d9..628c6bbb54d 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -670,6 +670,12 @@ const ( // Enable Terminating condition in Endpoint Slices. EndpointSliceTerminatingCondition featuregate.Feature = "EndpointSliceTerminatingCondition" + // owner: @robscott + // alpha: v1.20 + // + // Enable NodeName field on Endpoint Slices. + EndpointSliceNodeName featuregate.Feature = "EndpointSliceNodeName" + // owner: @derekwaynecarr // alpha: v1.20 // @@ -787,6 +793,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS EndpointSlice: {Default: true, PreRelease: featuregate.Beta}, EndpointSliceProxying: {Default: true, PreRelease: featuregate.Beta}, EndpointSliceTerminatingCondition: {Default: false, PreRelease: featuregate.Alpha}, + EndpointSliceNodeName: {Default: false, PreRelease: featuregate.Alpha}, WindowsEndpointSliceProxying: {Default: false, PreRelease: featuregate.Alpha}, EvenPodsSpread: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.21 StartupProbe: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.23 diff --git a/pkg/proxy/BUILD b/pkg/proxy/BUILD index 8b3ac576e71..089a9d6df96 100644 --- a/pkg/proxy/BUILD +++ b/pkg/proxy/BUILD @@ -19,6 +19,7 @@ go_library( importpath = "k8s.io/kubernetes/pkg/proxy", deps = [ "//pkg/api/v1/service:go_default_library", + "//pkg/features:go_default_library", "//pkg/proxy/config:go_default_library", "//pkg/proxy/metrics:go_default_library", "//pkg/proxy/util:go_default_library", @@ -26,6 +27,7 @@ go_library( "//staging/src/k8s.io/api/discovery/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/klog/v2:go_default_library", "//vendor/k8s.io/utils/net:go_default_library", diff --git a/pkg/proxy/endpoints.go b/pkg/proxy/endpoints.go index fdbe1315be2..0de805dc2c1 100644 --- a/pkg/proxy/endpoints.go +++ b/pkg/proxy/endpoints.go @@ -36,7 +36,6 @@ import ( ) var supportedEndpointSliceAddressTypes = sets.NewString( - string(discovery.AddressTypeIP), // IP is a deprecated address type string(discovery.AddressTypeIPv4), string(discovery.AddressTypeIPv6), ) diff --git a/pkg/proxy/endpointslicecache.go b/pkg/proxy/endpointslicecache.go index b049481a372..bb180adcfcd 100644 --- a/pkg/proxy/endpointslicecache.go +++ b/pkg/proxy/endpointslicecache.go @@ -26,8 +26,10 @@ import ( "k8s.io/api/core/v1" discovery "k8s.io/api/discovery/v1beta1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/record" "k8s.io/klog/v2" + "k8s.io/kubernetes/pkg/features" utilproxy "k8s.io/kubernetes/pkg/proxy/util" utilnet "k8s.io/utils/net" ) @@ -76,6 +78,7 @@ type endpointSliceInfo struct { // Addresses and Topology are copied from EndpointSlice Endpoints. type endpointInfo struct { Addresses []string + NodeName *string Topology map[string]string } @@ -120,10 +123,14 @@ func newEndpointSliceInfo(endpointSlice *discovery.EndpointSlice, remove bool) * if !remove { for _, endpoint := range endpointSlice.Endpoints { if endpoint.Conditions.Ready == nil || *endpoint.Conditions.Ready { - esInfo.Endpoints = append(esInfo.Endpoints, &endpointInfo{ + eInfo := endpointInfo{ Addresses: endpoint.Addresses, Topology: endpoint.Topology, - }) + } + if utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceNodeName) { + eInfo.NodeName = endpoint.NodeName + } + esInfo.Endpoints = append(esInfo.Endpoints, &eInfo) } } @@ -255,7 +262,13 @@ func (cache *EndpointSliceCache) addEndpointsByIP(serviceNN types.NamespacedName continue } - isLocal := cache.isLocal(endpoint.Topology[v1.LabelHostname]) + isLocal := false + if endpoint.NodeName != nil { + isLocal = cache.isLocal(*endpoint.NodeName) + } else { + isLocal = cache.isLocal(endpoint.Topology[v1.LabelHostname]) + } + endpointInfo := newBaseEndpointInfo(endpoint.Addresses[0], portNum, isLocal, endpoint.Topology) // This logic ensures we're deduping potential overlapping endpoints diff --git a/pkg/registry/discovery/endpointslice/strategy.go b/pkg/registry/discovery/endpointslice/strategy.go index 9e2c48bc246..92cb2e65e06 100644 --- a/pkg/registry/discovery/endpointslice/strategy.go +++ b/pkg/registry/discovery/endpointslice/strategy.go @@ -50,7 +50,7 @@ func (endpointSliceStrategy) PrepareForCreate(ctx context.Context, obj runtime.O endpointSlice := obj.(*discovery.EndpointSlice) endpointSlice.Generation = 1 - dropDisabledConditionsOnCreate(endpointSlice) + dropDisabledFieldsOnCreate(endpointSlice) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -72,7 +72,7 @@ func (endpointSliceStrategy) PrepareForUpdate(ctx context.Context, obj, old runt newEPS.ObjectMeta = ogNewMeta oldEPS.ObjectMeta = ogOldMeta - dropDisabledConditionsOnUpdate(oldEPS, newEPS) + dropDisabledFieldsOnUpdate(oldEPS, newEPS) } // Validate validates a new EndpointSlice. @@ -103,41 +103,56 @@ func (endpointSliceStrategy) AllowUnconditionalUpdate() bool { return true } -// dropDisabledConditionsOnCreate will drop the terminating condition if the -// EndpointSliceTerminatingCondition is disabled. Otherwise the field is left untouched. -func dropDisabledConditionsOnCreate(endpointSlice *discovery.EndpointSlice) { - if utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition) { - return - } +// dropDisabledConditionsOnCreate will drop any fields that are disabled. +func dropDisabledFieldsOnCreate(endpointSlice *discovery.EndpointSlice) { + dropNodeName := !utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceNodeName) + dropTerminating := !utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition) - // Always drop the serving/terminating conditions on create when feature gate is disabled. - for i := range endpointSlice.Endpoints { - endpointSlice.Endpoints[i].Conditions.Serving = nil - endpointSlice.Endpoints[i].Conditions.Terminating = nil + if dropNodeName || dropTerminating { + for i := range endpointSlice.Endpoints { + if dropNodeName { + endpointSlice.Endpoints[i].NodeName = nil + } + if dropTerminating { + endpointSlice.Endpoints[i].Conditions.Serving = nil + endpointSlice.Endpoints[i].Conditions.Terminating = nil + } + } } } -// dropDisabledConditionsOnUpdate will drop the terminating condition field if the EndpointSliceTerminatingCondition -// feature gate is disabled unless an existing EndpointSlice object has the field already set. This ensures -// the field is not dropped on rollback. -func dropDisabledConditionsOnUpdate(oldEPS, newEPS *discovery.EndpointSlice) { - if utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition) { - return - } - - // Only drop the serving/terminating condition if the existing EndpointSlice doesn't have it set. - dropConditions := true - for _, ep := range oldEPS.Endpoints { - if ep.Conditions.Serving != nil || ep.Conditions.Terminating != nil { - dropConditions = false - break +// dropDisabledFieldsOnUpdate will drop any disable fields that have not already +// been set on the EndpointSlice. +func dropDisabledFieldsOnUpdate(oldEPS, newEPS *discovery.EndpointSlice) { + dropNodeName := !utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceNodeName) + if dropNodeName { + for _, ep := range oldEPS.Endpoints { + if ep.NodeName != nil { + dropNodeName = false + break + } } } - if dropConditions { + dropTerminating := !utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition) + if dropTerminating { + for _, ep := range oldEPS.Endpoints { + if ep.Conditions.Serving != nil || ep.Conditions.Terminating != nil { + dropTerminating = false + break + } + } + } + + if dropNodeName || dropTerminating { for i := range newEPS.Endpoints { - newEPS.Endpoints[i].Conditions.Serving = nil - newEPS.Endpoints[i].Conditions.Terminating = nil + if dropNodeName { + newEPS.Endpoints[i].NodeName = nil + } + if dropTerminating { + newEPS.Endpoints[i].Conditions.Serving = nil + newEPS.Endpoints[i].Conditions.Terminating = nil + } } } } diff --git a/pkg/registry/discovery/endpointslice/strategy_test.go b/pkg/registry/discovery/endpointslice/strategy_test.go index 81bb687b8eb..fce0bf76231 100644 --- a/pkg/registry/discovery/endpointslice/strategy_test.go +++ b/pkg/registry/discovery/endpointslice/strategy_test.go @@ -27,15 +27,16 @@ import ( utilpointer "k8s.io/utils/pointer" ) -func Test_dropConditionsOnCreate(t *testing.T) { +func Test_dropDisabledFieldsOnCreate(t *testing.T) { testcases := []struct { name string terminatingGateEnabled bool + nodeNameGateEnabled bool eps *discovery.EndpointSlice expectedEPS *discovery.EndpointSlice }{ { - name: "gate enabled, field should be allowed", + name: "terminating gate enabled, field should be allowed", terminatingGateEnabled: true, eps: &discovery.EndpointSlice{ Endpoints: []discovery.Endpoint{ @@ -83,7 +84,7 @@ func Test_dropConditionsOnCreate(t *testing.T) { }, }, { - name: "gate disabled, field should be set to nil", + name: "terminating gate disabled, field should be set to nil", terminatingGateEnabled: false, eps: &discovery.EndpointSlice{ Endpoints: []discovery.Endpoint{ @@ -130,13 +131,62 @@ func Test_dropConditionsOnCreate(t *testing.T) { }, }, }, + { + name: "node name gate enabled, field should be allowed", + nodeNameGateEnabled: true, + eps: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: utilpointer.StringPtr("node-1"), + }, + { + NodeName: utilpointer.StringPtr("node-2"), + }, + }, + }, + expectedEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: utilpointer.StringPtr("node-1"), + }, + { + NodeName: utilpointer.StringPtr("node-2"), + }, + }, + }, + }, + { + name: "node name gate disabled, field should be allowed", + nodeNameGateEnabled: false, + eps: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: utilpointer.StringPtr("node-1"), + }, + { + NodeName: utilpointer.StringPtr("node-2"), + }, + }, + }, + expectedEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: nil, + }, + { + NodeName: nil, + }, + }, + }, + }, } for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testcase.terminatingGateEnabled)() + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceNodeName, testcase.nodeNameGateEnabled)() - dropDisabledConditionsOnCreate(testcase.eps) + dropDisabledFieldsOnCreate(testcase.eps) if !apiequality.Semantic.DeepEqual(testcase.eps, testcase.expectedEPS) { t.Logf("actual endpointslice: %v", testcase.eps) t.Logf("expected endpointslice: %v", testcase.expectedEPS) @@ -146,16 +196,17 @@ func Test_dropConditionsOnCreate(t *testing.T) { } } -func Test_dropTerminatingConditionOnUpdate(t *testing.T) { +func Test_dropDisabledFieldsOnUpdate(t *testing.T) { testcases := []struct { name string terminatingGateEnabled bool + nodeNameGateEnabled bool oldEPS *discovery.EndpointSlice newEPS *discovery.EndpointSlice expectedEPS *discovery.EndpointSlice }{ { - name: "gate enabled, field should be allowed", + name: "terminating gate enabled, field should be allowed", terminatingGateEnabled: true, oldEPS: &discovery.EndpointSlice{ Endpoints: []discovery.Endpoint{ @@ -225,7 +276,7 @@ func Test_dropTerminatingConditionOnUpdate(t *testing.T) { }, }, { - name: "gate disabled, and not set on existing EPS", + name: "terminating gate disabled, and not set on existing EPS", terminatingGateEnabled: false, oldEPS: &discovery.EndpointSlice{ Endpoints: []discovery.Endpoint{ @@ -295,7 +346,7 @@ func Test_dropTerminatingConditionOnUpdate(t *testing.T) { }, }, { - name: "gate disabled, and set on existing EPS", + name: "terminating gate disabled, and set on existing EPS", terminatingGateEnabled: false, oldEPS: &discovery.EndpointSlice{ Endpoints: []discovery.Endpoint{ @@ -365,7 +416,7 @@ func Test_dropTerminatingConditionOnUpdate(t *testing.T) { }, }, { - name: "gate disabled, and set on existing EPS with new values", + name: "terminating gate disabled, and set on existing EPS with new values", terminatingGateEnabled: false, oldEPS: &discovery.EndpointSlice{ Endpoints: []discovery.Endpoint{ @@ -431,13 +482,116 @@ func Test_dropTerminatingConditionOnUpdate(t *testing.T) { }, }, }, + { + name: "node name gate enabled, set on new EPS", + nodeNameGateEnabled: true, + oldEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: nil, + }, + { + NodeName: nil, + }, + }, + }, + newEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: utilpointer.StringPtr("node-1"), + }, + { + NodeName: utilpointer.StringPtr("node-2"), + }, + }, + }, + expectedEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: utilpointer.StringPtr("node-1"), + }, + { + NodeName: utilpointer.StringPtr("node-2"), + }, + }, + }, + }, + { + name: "node name gate disabled, set on new EPS", + nodeNameGateEnabled: false, + oldEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: nil, + }, + { + NodeName: nil, + }, + }, + }, + newEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: utilpointer.StringPtr("node-1"), + }, + { + NodeName: utilpointer.StringPtr("node-2"), + }, + }, + }, + expectedEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: nil, + }, + { + NodeName: nil, + }, + }, + }, + }, + { + name: "node name gate disabled, set on old and updated EPS", + nodeNameGateEnabled: false, + oldEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: utilpointer.StringPtr("node-1-old"), + }, + { + NodeName: utilpointer.StringPtr("node-2-old"), + }, + }, + }, + newEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: utilpointer.StringPtr("node-1"), + }, + { + NodeName: utilpointer.StringPtr("node-2"), + }, + }, + }, + expectedEPS: &discovery.EndpointSlice{ + Endpoints: []discovery.Endpoint{ + { + NodeName: utilpointer.StringPtr("node-1"), + }, + { + NodeName: utilpointer.StringPtr("node-2"), + }, + }, + }, + }, } for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testcase.terminatingGateEnabled)() + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceNodeName, testcase.nodeNameGateEnabled)() - dropDisabledConditionsOnUpdate(testcase.oldEPS, testcase.newEPS) + dropDisabledFieldsOnUpdate(testcase.oldEPS, testcase.newEPS) if !apiequality.Semantic.DeepEqual(testcase.newEPS, testcase.expectedEPS) { t.Logf("actual endpointslice: %v", testcase.newEPS) t.Logf("expected endpointslice: %v", testcase.expectedEPS) diff --git a/staging/src/k8s.io/api/discovery/v1alpha1/generated.pb.go b/staging/src/k8s.io/api/discovery/v1alpha1/generated.pb.go index 4f1f7306690..5cbee6168c1 100644 --- a/staging/src/k8s.io/api/discovery/v1alpha1/generated.pb.go +++ b/staging/src/k8s.io/api/discovery/v1alpha1/generated.pb.go @@ -200,57 +200,58 @@ func init() { } var fileDescriptor_772f83c5b34e07a5 = []byte{ - // 787 bytes of a gzipped FileDescriptorProto + // 801 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x4d, 0x8f, 0xe3, 0x44, - 0x10, 0x8d, 0x27, 0x13, 0xad, 0xdd, 0xd9, 0x11, 0xbb, 0x2d, 0x0e, 0xd1, 0x00, 0xf6, 0x28, 0x08, - 0x11, 0x69, 0xa0, 0x4d, 0x46, 0x80, 0x56, 0x70, 0x1a, 0xc3, 0xf2, 0x21, 0xf1, 0x31, 0xf4, 0xce, - 0x01, 0x21, 0x0e, 0xf4, 0xd8, 0xb5, 0x8e, 0x49, 0xec, 0xb6, 0xba, 0x3b, 0x91, 0x72, 0xe3, 0x1f, - 0xc0, 0x0f, 0xe2, 0x88, 0xd0, 0x1c, 0xf7, 0xb8, 0x27, 0x8b, 0xf1, 0xfe, 0x8b, 0x39, 0xa1, 0x6e, - 0x7f, 0x0e, 0x01, 0x36, 0x37, 0xf7, 0xab, 0x7a, 0xaf, 0xea, 0x95, 0xab, 0xd0, 0x67, 0xcb, 0x47, - 0x92, 0x24, 0xdc, 0x5f, 0xae, 0xaf, 0x40, 0x64, 0xa0, 0x40, 0xfa, 0x1b, 0xc8, 0x22, 0x2e, 0xfc, - 0x3a, 0xc0, 0xf2, 0xc4, 0x8f, 0x12, 0x19, 0xf2, 0x0d, 0x88, 0xad, 0xbf, 0x99, 0xb3, 0x55, 0xbe, - 0x60, 0x73, 0x3f, 0x86, 0x0c, 0x04, 0x53, 0x10, 0x91, 0x5c, 0x70, 0xc5, 0xf1, 0x1b, 0x55, 0x3a, - 0x61, 0x79, 0x42, 0xda, 0x74, 0xd2, 0xa4, 0x1f, 0xbf, 0x1b, 0x27, 0x6a, 0xb1, 0xbe, 0x22, 0x21, - 0x4f, 0xfd, 0x98, 0xc7, 0xdc, 0x37, 0xac, 0xab, 0xf5, 0x53, 0xf3, 0x32, 0x0f, 0xf3, 0x55, 0xa9, - 0x1d, 0x4f, 0x7b, 0xc5, 0x43, 0x2e, 0xc0, 0xdf, 0xec, 0x54, 0x3c, 0x7e, 0xbf, 0xcb, 0x49, 0x59, - 0xb8, 0x48, 0x32, 0xdd, 0x5f, 0xbe, 0x8c, 0x35, 0x20, 0xfd, 0x14, 0x14, 0xfb, 0x37, 0x96, 0xff, - 0x5f, 0x2c, 0xb1, 0xce, 0x54, 0x92, 0xc2, 0x0e, 0xe1, 0xc3, 0x97, 0x11, 0x64, 0xb8, 0x80, 0x94, - 0xfd, 0x93, 0x37, 0xfd, 0x7d, 0x88, 0xec, 0xc7, 0x59, 0x94, 0xf3, 0x24, 0x53, 0xf8, 0x14, 0x39, - 0x2c, 0x8a, 0x04, 0x48, 0x09, 0x72, 0x62, 0x9d, 0x0c, 0x67, 0x4e, 0x70, 0x54, 0x16, 0x9e, 0x73, - 0xde, 0x80, 0xb4, 0x8b, 0x63, 0x40, 0x28, 0xe4, 0x59, 0x94, 0xa8, 0x84, 0x67, 0x72, 0x72, 0x70, - 0x62, 0xcd, 0xc6, 0x67, 0x73, 0xf2, 0xbf, 0xf3, 0x25, 0x4d, 0xa5, 0x4f, 0x5a, 0x62, 0x80, 0xaf, - 0x0b, 0x6f, 0x50, 0x16, 0x1e, 0xea, 0x30, 0xda, 0x13, 0xc6, 0x33, 0x64, 0x2f, 0xb8, 0x54, 0x19, - 0x4b, 0x61, 0x32, 0x3c, 0xb1, 0x66, 0x4e, 0x70, 0xbf, 0x2c, 0x3c, 0xfb, 0x8b, 0x1a, 0xa3, 0x6d, - 0x14, 0x5f, 0x20, 0x47, 0x31, 0x11, 0x83, 0xa2, 0xf0, 0x74, 0x72, 0x68, 0xfa, 0x79, 0xb3, 0xdf, - 0x8f, 0xfe, 0x43, 0x64, 0x33, 0x27, 0xdf, 0x5e, 0xfd, 0x0c, 0xa1, 0x4e, 0x02, 0x01, 0x59, 0x08, - 0x95, 0xc5, 0xcb, 0x86, 0x49, 0x3b, 0x11, 0x1c, 0x22, 0x5b, 0xf1, 0x9c, 0xaf, 0x78, 0xbc, 0x9d, - 0x8c, 0x4e, 0x86, 0xb3, 0xf1, 0xd9, 0x07, 0x7b, 0x1a, 0x24, 0x97, 0x35, 0xef, 0x71, 0xa6, 0xc4, - 0x36, 0x78, 0x50, 0x9b, 0xb4, 0x1b, 0x98, 0xb6, 0xc2, 0xc7, 0x1f, 0xa3, 0xa3, 0x3b, 0xc9, 0xf8, - 0x01, 0x1a, 0x2e, 0x61, 0x3b, 0xb1, 0xb4, 0x59, 0xaa, 0x3f, 0xf1, 0xab, 0x68, 0xb4, 0x61, 0xab, - 0x35, 0x98, 0x29, 0x3b, 0xb4, 0x7a, 0x7c, 0x74, 0xf0, 0xc8, 0x9a, 0xfe, 0x6a, 0x21, 0xbc, 0x3b, - 0x54, 0xec, 0xa1, 0x91, 0x00, 0x16, 0x55, 0x22, 0x76, 0xe0, 0x94, 0x85, 0x37, 0xa2, 0x1a, 0xa0, - 0x15, 0x8e, 0xdf, 0x42, 0xf7, 0x24, 0x88, 0x4d, 0x92, 0xc5, 0x46, 0xd3, 0x0e, 0xc6, 0x65, 0xe1, - 0xdd, 0x7b, 0x52, 0x41, 0xb4, 0x89, 0xe1, 0x39, 0x1a, 0x2b, 0x10, 0x69, 0x92, 0x31, 0xa5, 0x53, - 0x87, 0x26, 0xf5, 0x95, 0xb2, 0xf0, 0xc6, 0x97, 0x1d, 0x4c, 0xfb, 0x39, 0xd3, 0x3f, 0x2d, 0x74, - 0xbf, 0xe9, 0xe8, 0x82, 0x0b, 0x85, 0x5f, 0x47, 0x87, 0xe6, 0xe7, 0x19, 0x3f, 0x81, 0x5d, 0x16, - 0xde, 0xe1, 0x37, 0xfa, 0xc7, 0x19, 0x14, 0x7f, 0x8e, 0x6c, 0xb3, 0x88, 0x21, 0x5f, 0x55, 0xee, - 0x82, 0x53, 0x3d, 0xa7, 0x8b, 0x1a, 0xbb, 0x2d, 0xbc, 0xd7, 0x76, 0x8f, 0x8c, 0x34, 0x61, 0xda, - 0x92, 0x75, 0x99, 0x9c, 0x0b, 0x65, 0x7a, 0x1c, 0x55, 0x65, 0x74, 0x79, 0x6a, 0x50, 0x6d, 0x84, - 0xe5, 0x79, 0x43, 0x33, 0xdb, 0xe1, 0x54, 0x46, 0xce, 0x3b, 0x98, 0xf6, 0x73, 0xa6, 0x2f, 0x0e, - 0xd0, 0x51, 0x63, 0xe4, 0xc9, 0x2a, 0x09, 0x01, 0xff, 0x84, 0x6c, 0x7d, 0xaf, 0x11, 0x53, 0xcc, - 0xb8, 0x19, 0x9f, 0xbd, 0xd7, 0x5b, 0x87, 0xf6, 0xec, 0x48, 0xbe, 0x8c, 0x35, 0x20, 0x89, 0xce, - 0xee, 0x36, 0xee, 0x6b, 0x50, 0xac, 0x5b, 0xf7, 0x0e, 0xa3, 0xad, 0x2a, 0xfe, 0x14, 0x8d, 0xeb, - 0x03, 0xbb, 0xdc, 0xe6, 0x50, 0xb7, 0x39, 0xad, 0x29, 0xe3, 0xf3, 0x2e, 0x74, 0x7b, 0xf7, 0x49, - 0xfb, 0x34, 0xfc, 0x3d, 0x72, 0xa0, 0x6e, 0x5c, 0x1f, 0xa6, 0xde, 0xdb, 0xb7, 0xf7, 0xdc, 0xdb, - 0xe0, 0x61, 0x5d, 0xcc, 0x69, 0x10, 0x49, 0x3b, 0x31, 0x7c, 0x81, 0x46, 0x7a, 0x9c, 0x72, 0x32, - 0x34, 0xaa, 0xa7, 0x7b, 0xaa, 0xea, 0x1f, 0x11, 0x1c, 0xd5, 0xca, 0x23, 0xfd, 0x92, 0xb4, 0x12, - 0x9a, 0xfe, 0x61, 0xa1, 0x87, 0x77, 0xa6, 0xfc, 0x55, 0x22, 0x15, 0xfe, 0x71, 0x67, 0xd2, 0x64, - 0xbf, 0x49, 0x6b, 0xb6, 0x99, 0x73, 0x7b, 0x71, 0x0d, 0xd2, 0x9b, 0xf2, 0x77, 0x68, 0x94, 0x28, - 0x48, 0x9b, 0xd9, 0xbc, 0xb3, 0xa7, 0x0b, 0xd3, 0x5e, 0x67, 0xe3, 0x4b, 0x2d, 0x41, 0x2b, 0xa5, - 0x80, 0x5c, 0xdf, 0xb8, 0x83, 0x67, 0x37, 0xee, 0xe0, 0xf9, 0x8d, 0x3b, 0xf8, 0xa5, 0x74, 0xad, - 0xeb, 0xd2, 0xb5, 0x9e, 0x95, 0xae, 0xf5, 0xbc, 0x74, 0xad, 0xbf, 0x4a, 0xd7, 0xfa, 0xed, 0x85, - 0x3b, 0xf8, 0xc1, 0x6e, 0x34, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xa7, 0x11, 0xa7, 0x0f, 0xd0, - 0x06, 0x00, 0x00, + 0x10, 0x8d, 0x27, 0x13, 0xd6, 0xee, 0xec, 0x88, 0xdd, 0x16, 0x87, 0x68, 0x00, 0x7b, 0x14, 0x84, + 0x88, 0x34, 0xd0, 0x26, 0x23, 0x40, 0x2b, 0x38, 0x8d, 0x61, 0xf9, 0x90, 0x60, 0x19, 0x7a, 0xe7, + 0x80, 0x10, 0x07, 0x7a, 0xec, 0x5a, 0xc7, 0x24, 0x76, 0x5b, 0xdd, 0x9d, 0x48, 0xb9, 0xf1, 0x0f, + 0xe0, 0x47, 0x21, 0x34, 0xc7, 0x3d, 0xee, 0xc9, 0x62, 0xbc, 0x12, 0x3f, 0x62, 0x4f, 0xa8, 0xdb, + 0x9f, 0x43, 0x80, 0xcd, 0xcd, 0xfd, 0xaa, 0xde, 0xab, 0x7a, 0xe5, 0x2a, 0xf4, 0xf9, 0xf2, 0x81, + 0x24, 0x09, 0xf7, 0x97, 0xeb, 0x2b, 0x10, 0x19, 0x28, 0x90, 0xfe, 0x06, 0xb2, 0x88, 0x0b, 0xbf, + 0x0e, 0xb0, 0x3c, 0xf1, 0xa3, 0x44, 0x86, 0x7c, 0x03, 0x62, 0xeb, 0x6f, 0xe6, 0x6c, 0x95, 0x2f, + 0xd8, 0xdc, 0x8f, 0x21, 0x03, 0xc1, 0x14, 0x44, 0x24, 0x17, 0x5c, 0x71, 0xfc, 0x66, 0x95, 0x4e, + 0x58, 0x9e, 0x90, 0x36, 0x9d, 0x34, 0xe9, 0xc7, 0xef, 0xc5, 0x89, 0x5a, 0xac, 0xaf, 0x48, 0xc8, + 0x53, 0x3f, 0xe6, 0x31, 0xf7, 0x0d, 0xeb, 0x6a, 0xfd, 0xc4, 0xbc, 0xcc, 0xc3, 0x7c, 0x55, 0x6a, + 0xc7, 0xd3, 0x5e, 0xf1, 0x90, 0x0b, 0xf0, 0x37, 0x3b, 0x15, 0x8f, 0x3f, 0xe8, 0x72, 0x52, 0x16, + 0x2e, 0x92, 0x4c, 0xf7, 0x97, 0x2f, 0x63, 0x0d, 0x48, 0x3f, 0x05, 0xc5, 0xfe, 0x8d, 0xe5, 0xff, + 0x17, 0x4b, 0xac, 0x33, 0x95, 0xa4, 0xb0, 0x43, 0xf8, 0xe8, 0x65, 0x04, 0x19, 0x2e, 0x20, 0x65, + 0xff, 0xe4, 0x4d, 0xff, 0x1a, 0x22, 0xfb, 0x61, 0x16, 0xe5, 0x3c, 0xc9, 0x14, 0x3e, 0x45, 0x0e, + 0x8b, 0x22, 0x01, 0x52, 0x82, 0x9c, 0x58, 0x27, 0xc3, 0x99, 0x13, 0x1c, 0x95, 0x85, 0xe7, 0x9c, + 0x37, 0x20, 0xed, 0xe2, 0x18, 0x10, 0x0a, 0x79, 0x16, 0x25, 0x2a, 0xe1, 0x99, 0x9c, 0x1c, 0x9c, + 0x58, 0xb3, 0xf1, 0xd9, 0x9c, 0xfc, 0xef, 0x7c, 0x49, 0x53, 0xe9, 0xd3, 0x96, 0x18, 0xe0, 0xeb, + 0xc2, 0x1b, 0x94, 0x85, 0x87, 0x3a, 0x8c, 0xf6, 0x84, 0xf1, 0x0c, 0xd9, 0x0b, 0x2e, 0x55, 0xc6, + 0x52, 0x98, 0x0c, 0x4f, 0xac, 0x99, 0x13, 0xdc, 0x2d, 0x0b, 0xcf, 0xfe, 0xb2, 0xc6, 0x68, 0x1b, + 0xc5, 0x17, 0xc8, 0x51, 0x4c, 0xc4, 0xa0, 0x28, 0x3c, 0x99, 0x1c, 0x9a, 0x7e, 0xde, 0xea, 0xf7, + 0xa3, 0xff, 0x10, 0xd9, 0xcc, 0xc9, 0xb7, 0x57, 0x3f, 0x43, 0xa8, 0x93, 0x40, 0x40, 0x16, 0x42, + 0x65, 0xf1, 0xb2, 0x61, 0xd2, 0x4e, 0x04, 0x87, 0xc8, 0x56, 0x3c, 0xe7, 0x2b, 0x1e, 0x6f, 0x27, + 0xa3, 0x93, 0xe1, 0x6c, 0x7c, 0xf6, 0xe1, 0x9e, 0x06, 0xc9, 0x65, 0xcd, 0x7b, 0x98, 0x29, 0xb1, + 0x0d, 0xee, 0xd5, 0x26, 0xed, 0x06, 0xa6, 0xad, 0xb0, 0x36, 0x98, 0xf1, 0x08, 0x1e, 0x69, 0x83, + 0xaf, 0x74, 0x06, 0x1f, 0xd5, 0x18, 0x6d, 0xa3, 0xc7, 0x9f, 0xa0, 0xa3, 0x5b, 0xb2, 0xf8, 0x1e, + 0x1a, 0x2e, 0x61, 0x3b, 0xb1, 0x34, 0x8b, 0xea, 0x4f, 0xfc, 0x1a, 0x1a, 0x6d, 0xd8, 0x6a, 0x0d, + 0xe6, 0x7f, 0x38, 0xb4, 0x7a, 0x7c, 0x7c, 0xf0, 0xc0, 0x9a, 0xfe, 0x6a, 0x21, 0xbc, 0x3b, 0x7e, + 0xec, 0xa1, 0x91, 0x00, 0x16, 0x55, 0x22, 0x76, 0xe0, 0x94, 0x85, 0x37, 0xa2, 0x1a, 0xa0, 0x15, + 0x8e, 0xdf, 0x46, 0x77, 0x24, 0x88, 0x4d, 0x92, 0xc5, 0x46, 0xd3, 0x0e, 0xc6, 0x65, 0xe1, 0xdd, + 0x79, 0x5c, 0x41, 0xb4, 0x89, 0xe1, 0x39, 0x1a, 0x2b, 0x10, 0x69, 0x92, 0x31, 0xa5, 0x53, 0x87, + 0x26, 0xf5, 0xd5, 0xb2, 0xf0, 0xc6, 0x97, 0x1d, 0x4c, 0xfb, 0x39, 0xd3, 0x3f, 0x2c, 0x74, 0xb7, + 0xe9, 0xe8, 0x82, 0x0b, 0x85, 0xdf, 0x40, 0x87, 0xe6, 0x37, 0x1b, 0x3f, 0x81, 0x5d, 0x16, 0xde, + 0xa1, 0x99, 0x80, 0x41, 0xf1, 0x17, 0xc8, 0x36, 0x2b, 0x1b, 0xf2, 0x55, 0xe5, 0x2e, 0x38, 0xd5, + 0x73, 0xba, 0xa8, 0xb1, 0x17, 0x85, 0xf7, 0xfa, 0xee, 0x39, 0x92, 0x26, 0x4c, 0x5b, 0xb2, 0x2e, + 0x93, 0x73, 0xa1, 0x4c, 0x8f, 0xa3, 0xaa, 0x8c, 0x2e, 0x4f, 0x0d, 0xaa, 0x8d, 0xb0, 0x3c, 0x6f, + 0x68, 0x66, 0x8f, 0x9c, 0xca, 0xc8, 0x79, 0x07, 0xd3, 0x7e, 0xce, 0xf4, 0xf9, 0x01, 0x3a, 0x6a, + 0x8c, 0x3c, 0x5e, 0x25, 0x21, 0xe0, 0x9f, 0x90, 0xad, 0x2f, 0x3b, 0x62, 0x8a, 0x19, 0x37, 0xe3, + 0xb3, 0xf7, 0x7b, 0x8b, 0xd3, 0x1e, 0x28, 0xc9, 0x97, 0xb1, 0x06, 0x24, 0xd1, 0xd9, 0xdd, 0x6e, + 0x7e, 0x03, 0x8a, 0x75, 0x87, 0xd1, 0x61, 0xb4, 0x55, 0xc5, 0x9f, 0xa1, 0x71, 0x7d, 0x8a, 0x97, + 0xdb, 0x1c, 0xea, 0x36, 0xa7, 0x35, 0x65, 0x7c, 0xde, 0x85, 0x5e, 0xdc, 0x7e, 0xd2, 0x3e, 0x0d, + 0x7f, 0x8f, 0x1c, 0xa8, 0x1b, 0xd7, 0x27, 0xac, 0x37, 0xfc, 0x9d, 0x3d, 0x37, 0x3c, 0xb8, 0x5f, + 0x17, 0x73, 0x1a, 0x44, 0xd2, 0x4e, 0x0c, 0x5f, 0xa0, 0x91, 0x1e, 0xa7, 0x9c, 0x0c, 0x8d, 0xea, + 0xe9, 0x9e, 0xaa, 0xfa, 0x47, 0x04, 0x47, 0xb5, 0xf2, 0x48, 0xbf, 0x24, 0xad, 0x84, 0xa6, 0xbf, + 0x5b, 0xe8, 0xfe, 0xad, 0x29, 0x7f, 0x9d, 0x48, 0x85, 0x7f, 0xdc, 0x99, 0x34, 0xd9, 0x6f, 0xd2, + 0x9a, 0x6d, 0xe6, 0xdc, 0xde, 0x66, 0x83, 0xf4, 0xa6, 0xfc, 0x1d, 0x1a, 0x25, 0x0a, 0xd2, 0x66, + 0x36, 0xef, 0xee, 0xe9, 0xc2, 0xb4, 0xd7, 0xd9, 0xf8, 0x4a, 0x4b, 0xd0, 0x4a, 0x29, 0x20, 0xd7, + 0x37, 0xee, 0xe0, 0xe9, 0x8d, 0x3b, 0x78, 0x76, 0xe3, 0x0e, 0x7e, 0x29, 0x5d, 0xeb, 0xba, 0x74, + 0xad, 0xa7, 0xa5, 0x6b, 0x3d, 0x2b, 0x5d, 0xeb, 0xcf, 0xd2, 0xb5, 0x7e, 0x7b, 0xee, 0x0e, 0x7e, + 0xb0, 0x1b, 0xcd, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x03, 0x95, 0x92, 0xa5, 0xfa, 0x06, 0x00, + 0x00, } func (m *Endpoint) Marshal() (dAtA []byte, err error) { @@ -273,6 +274,13 @@ func (m *Endpoint) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.NodeName != nil { + i -= len(*m.NodeName) + copy(dAtA[i:], *m.NodeName) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.NodeName))) + i-- + dAtA[i] = 0x32 + } if len(m.Topology) > 0 { keysForTopology := make([]string, 0, len(m.Topology)) for k := range m.Topology { @@ -594,6 +602,10 @@ func (m *Endpoint) Size() (n int) { n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) } } + if m.NodeName != nil { + l = len(*m.NodeName) + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -707,6 +719,7 @@ func (this *Endpoint) String() string { `Hostname:` + valueToStringGenerated(this.Hostname) + `,`, `TargetRef:` + strings.Replace(fmt.Sprintf("%v", this.TargetRef), "ObjectReference", "v1.ObjectReference", 1) + `,`, `Topology:` + mapStringForTopology + `,`, + `NodeName:` + valueToStringGenerated(this.NodeName) + `,`, `}`, }, "") return s @@ -1073,6 +1086,39 @@ func (m *Endpoint) Unmarshal(dAtA []byte) error { } m.Topology[mapkey] = mapvalue iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NodeName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(dAtA[iNdEx:postIndex]) + m.NodeName = &s + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/staging/src/k8s.io/api/discovery/v1alpha1/generated.proto b/staging/src/k8s.io/api/discovery/v1alpha1/generated.proto index dc9a168b1f7..4b66a6c57bf 100644 --- a/staging/src/k8s.io/api/discovery/v1alpha1/generated.proto +++ b/staging/src/k8s.io/api/discovery/v1alpha1/generated.proto @@ -67,8 +67,15 @@ message Endpoint { // endpoint is located. This should match the corresponding node label. // * topology.kubernetes.io/region: the value indicates the region where the // endpoint is located. This should match the corresponding node label. + // This field is deprecated and will be removed in future api versions. // +optional map topology = 5; + + // nodeName represents the name of the Node hosting this endpoint. This can + // be used to determine endpoints local to a Node. This field can be enabled + // with the EndpointSliceNodeName feature gate. + // +optional + optional string nodeName = 6; } // EndpointConditions represents the current condition of an endpoint. @@ -81,15 +88,18 @@ message EndpointConditions { // +optional optional bool ready = 1; - // serving is identical to ready except that it is set regardless of the terminating - // state of endpoints. This condition should be set to true for a ready endpoint that - // is terminating. If nil, consumers should defer to the ready condition. + // serving is identical to ready except that it is set regardless of the + // terminating state of endpoints. This condition should be set to true for + // a ready endpoint that is terminating. If nil, consumers should defer to + // the ready condition. This field can be enabled with the + // EndpointSliceTerminatingCondition feature gate. // +optional optional bool serving = 2; - // terminating indicates that this endpoint is terminating. A nil value indicates an - // unknown state. Consumers should interpret this unknown state to mean that the - // endpoint is not terminating. + // terminating indicates that this endpoint is terminating. A nil value + // indicates an unknown state. Consumers should interpret this unknown state + // to mean that the endpoint is not terminating. This field can be enabled + // with the EndpointSliceTerminatingCondition feature gate. // +optional optional bool terminating = 3; } diff --git a/staging/src/k8s.io/api/discovery/v1alpha1/types.go b/staging/src/k8s.io/api/discovery/v1alpha1/types.go index a846cd7cacc..34b706ea897 100644 --- a/staging/src/k8s.io/api/discovery/v1alpha1/types.go +++ b/staging/src/k8s.io/api/discovery/v1alpha1/types.go @@ -106,8 +106,14 @@ type Endpoint struct { // endpoint is located. This should match the corresponding node label. // * topology.kubernetes.io/region: the value indicates the region where the // endpoint is located. This should match the corresponding node label. + // This field is deprecated and will be removed in future api versions. // +optional Topology map[string]string `json:"topology,omitempty" protobuf:"bytes,5,opt,name=topology"` + // nodeName represents the name of the Node hosting this endpoint. This can + // be used to determine endpoints local to a Node. This field can be enabled + // with the EndpointSliceNodeName feature gate. + // +optional + NodeName *string `json:"nodeName,omitempty" protobuf:"bytes,6,opt,name=nodeName"` } // EndpointConditions represents the current condition of an endpoint. @@ -120,15 +126,18 @@ type EndpointConditions struct { // +optional Ready *bool `json:"ready,omitempty" protobuf:"bytes,1,name=ready"` - // serving is identical to ready except that it is set regardless of the terminating - // state of endpoints. This condition should be set to true for a ready endpoint that - // is terminating. If nil, consumers should defer to the ready condition. + // serving is identical to ready except that it is set regardless of the + // terminating state of endpoints. This condition should be set to true for + // a ready endpoint that is terminating. If nil, consumers should defer to + // the ready condition. This field can be enabled with the + // EndpointSliceTerminatingCondition feature gate. // +optional Serving *bool `json:"serving,omitempty" protobuf:"bytes,2,name=serving"` - // terminating indicates that this endpoint is terminating. A nil value indicates an - // unknown state. Consumers should interpret this unknown state to mean that the - // endpoint is not terminating. + // terminating indicates that this endpoint is terminating. A nil value + // indicates an unknown state. Consumers should interpret this unknown state + // to mean that the endpoint is not terminating. This field can be enabled + // with the EndpointSliceTerminatingCondition feature gate. // +optional Terminating *bool `json:"terminating,omitempty" protobuf:"bytes,3,name=terminating"` } diff --git a/staging/src/k8s.io/api/discovery/v1alpha1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/discovery/v1alpha1/types_swagger_doc_generated.go index 6e8ada2d0c8..f6c983689a1 100644 --- a/staging/src/k8s.io/api/discovery/v1alpha1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/discovery/v1alpha1/types_swagger_doc_generated.go @@ -33,7 +33,8 @@ var map_Endpoint = map[string]string{ "conditions": "conditions contains information about the current status of the endpoint.", "hostname": "hostname of this endpoint. This field may be used by consumers of endpoints to distinguish endpoints from each other (e.g. in DNS names). Multiple endpoints which use the same hostname should be considered fungible (e.g. multiple A values in DNS). Must be lowercase and pass DNS label (RFC 1123) validation.", "targetRef": "targetRef is a reference to a Kubernetes object that represents this endpoint.", - "topology": "topology contains arbitrary topology information associated with the endpoint. These key/value pairs must conform with the label format. https://kubernetes.io/docs/concepts/overview/working-with-objects/labels Topology may include a maximum of 16 key/value pairs. This includes, but is not limited to the following well known keys: * kubernetes.io/hostname: the value indicates the hostname of the node\n where the endpoint is located. This should match the corresponding\n node label.\n* topology.kubernetes.io/zone: the value indicates the zone where the\n endpoint is located. This should match the corresponding node label.\n* topology.kubernetes.io/region: the value indicates the region where the\n endpoint is located. This should match the corresponding node label.", + "topology": "topology contains arbitrary topology information associated with the endpoint. These key/value pairs must conform with the label format. https://kubernetes.io/docs/concepts/overview/working-with-objects/labels Topology may include a maximum of 16 key/value pairs. This includes, but is not limited to the following well known keys: * kubernetes.io/hostname: the value indicates the hostname of the node\n where the endpoint is located. This should match the corresponding\n node label.\n* topology.kubernetes.io/zone: the value indicates the zone where the\n endpoint is located. This should match the corresponding node label.\n* topology.kubernetes.io/region: the value indicates the region where the\n endpoint is located. This should match the corresponding node label.\nThis field is deprecated and will be removed in future api versions.", + "nodeName": "nodeName represents the name of the Node hosting this endpoint. This can be used to determine endpoints local to a Node. This field can be enabled with the EndpointSliceNodeName feature gate.", } func (Endpoint) SwaggerDoc() map[string]string { @@ -43,8 +44,8 @@ func (Endpoint) SwaggerDoc() map[string]string { var map_EndpointConditions = map[string]string{ "": "EndpointConditions represents the current condition of an endpoint.", "ready": "ready indicates that this endpoint is prepared to receive traffic, according to whatever system is managing the endpoint. A nil value indicates an unknown state. In most cases consumers should interpret this unknown state as ready. For compatibility reasons, ready should never be \"true\" for terminating endpoints.", - "serving": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition.", - "terminating": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating.", + "serving": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + "terminating": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", } func (EndpointConditions) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/discovery/v1alpha1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/discovery/v1alpha1/zz_generated.deepcopy.go index c29e1ac34d7..13e54d50071 100644 --- a/staging/src/k8s.io/api/discovery/v1alpha1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/discovery/v1alpha1/zz_generated.deepcopy.go @@ -51,6 +51,11 @@ func (in *Endpoint) DeepCopyInto(out *Endpoint) { (*out)[key] = val } } + if in.NodeName != nil { + in, out := &in.NodeName, &out.NodeName + *out = new(string) + **out = **in + } return } diff --git a/staging/src/k8s.io/api/discovery/v1beta1/generated.pb.go b/staging/src/k8s.io/api/discovery/v1beta1/generated.pb.go index d01f1351733..6caab402ca3 100644 --- a/staging/src/k8s.io/api/discovery/v1beta1/generated.pb.go +++ b/staging/src/k8s.io/api/discovery/v1beta1/generated.pb.go @@ -200,56 +200,57 @@ func init() { } var fileDescriptor_ece80bbc872d519b = []byte{ - // 784 bytes of a gzipped FileDescriptorProto + // 798 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x4d, 0x8f, 0xe3, 0x44, - 0x10, 0x8d, 0x27, 0x63, 0x8d, 0xdd, 0xd9, 0x11, 0xbb, 0x2d, 0x0e, 0xd1, 0xb0, 0xb2, 0x47, 0x41, - 0xa0, 0x88, 0xd1, 0xda, 0xcc, 0x6a, 0x85, 0x56, 0x70, 0x1a, 0xc3, 0x08, 0x90, 0x80, 0x8d, 0x7a, - 0x23, 0x21, 0x21, 0x0e, 0x74, 0xec, 0x5a, 0xc7, 0x24, 0x76, 0x5b, 0xdd, 0x9d, 0x48, 0xb9, 0xf1, - 0x0f, 0xe0, 0xf7, 0x70, 0x45, 0x42, 0x73, 0xdc, 0xe3, 0x9e, 0x2c, 0x62, 0xfe, 0xc5, 0x9c, 0x50, - 0xb7, 0xbf, 0x12, 0xc2, 0x47, 0x6e, 0xee, 0x57, 0xf5, 0x5e, 0xd5, 0x2b, 0x57, 0xa1, 0xdb, 0xc5, - 0x73, 0xe1, 0x25, 0xcc, 0x5f, 0xac, 0x66, 0xc0, 0x33, 0x90, 0x20, 0xfc, 0x35, 0x64, 0x11, 0xe3, - 0x7e, 0x1d, 0xa0, 0x79, 0xe2, 0x47, 0x89, 0x08, 0xd9, 0x1a, 0xf8, 0xc6, 0x5f, 0x5f, 0xcf, 0x40, - 0xd2, 0x6b, 0x3f, 0x86, 0x0c, 0x38, 0x95, 0x10, 0x79, 0x39, 0x67, 0x92, 0xe1, 0xc7, 0x55, 0xb6, - 0x47, 0xf3, 0xc4, 0x6b, 0xb3, 0xbd, 0x3a, 0xfb, 0xe2, 0x49, 0x9c, 0xc8, 0xf9, 0x6a, 0xe6, 0x85, - 0x2c, 0xf5, 0x63, 0x16, 0x33, 0x5f, 0x93, 0x66, 0xab, 0x57, 0xfa, 0xa5, 0x1f, 0xfa, 0xab, 0x12, - 0xbb, 0x18, 0xed, 0x94, 0x0e, 0x19, 0x07, 0x7f, 0x7d, 0x50, 0xf0, 0xe2, 0x59, 0x97, 0x93, 0xd2, - 0x70, 0x9e, 0x64, 0xaa, 0xbb, 0x7c, 0x11, 0x2b, 0x40, 0xf8, 0x29, 0x48, 0xfa, 0x4f, 0x2c, 0xff, - 0xdf, 0x58, 0x7c, 0x95, 0xc9, 0x24, 0x85, 0x03, 0xc2, 0x47, 0xff, 0x47, 0x10, 0xe1, 0x1c, 0x52, - 0xfa, 0x77, 0xde, 0xe8, 0xd7, 0x3e, 0xb2, 0x6e, 0xb3, 0x28, 0x67, 0x49, 0x26, 0xf1, 0x15, 0xb2, - 0x69, 0x14, 0x71, 0x10, 0x02, 0xc4, 0xd0, 0xb8, 0xec, 0x8f, 0xed, 0xe0, 0xbc, 0x2c, 0x5c, 0xfb, - 0xa6, 0x01, 0x49, 0x17, 0xc7, 0x11, 0x42, 0x21, 0xcb, 0xa2, 0x44, 0x26, 0x2c, 0x13, 0xc3, 0x93, - 0x4b, 0x63, 0x3c, 0x78, 0xfa, 0xa1, 0xf7, 0x5f, 0xe3, 0xf5, 0x9a, 0x42, 0x9f, 0xb6, 0xbc, 0x00, - 0xdf, 0x15, 0x6e, 0xaf, 0x2c, 0x5c, 0xd4, 0x61, 0x64, 0x47, 0x17, 0x8f, 0x91, 0x35, 0x67, 0x42, - 0x66, 0x34, 0x85, 0x61, 0xff, 0xd2, 0x18, 0xdb, 0xc1, 0x83, 0xb2, 0x70, 0xad, 0x2f, 0x6a, 0x8c, - 0xb4, 0x51, 0x3c, 0x41, 0xb6, 0xa4, 0x3c, 0x06, 0x49, 0xe0, 0xd5, 0xf0, 0x54, 0xb7, 0xf3, 0xee, - 0x6e, 0x3b, 0xea, 0x07, 0x79, 0xeb, 0x6b, 0xef, 0xc5, 0xec, 0x47, 0x08, 0x55, 0x12, 0x70, 0xc8, - 0x42, 0xa8, 0x1c, 0x4e, 0x1b, 0x26, 0xe9, 0x44, 0xf0, 0x0c, 0x59, 0x92, 0xe5, 0x6c, 0xc9, 0xe2, - 0xcd, 0xd0, 0xbc, 0xec, 0x8f, 0x07, 0x4f, 0x9f, 0x1d, 0xe7, 0xcf, 0x9b, 0xd6, 0xb4, 0xdb, 0x4c, - 0xf2, 0x4d, 0xf0, 0xb0, 0xf6, 0x68, 0x35, 0x30, 0x69, 0x75, 0x2f, 0x3e, 0x41, 0xe7, 0x7b, 0xc9, - 0xf8, 0x21, 0xea, 0x2f, 0x60, 0x33, 0x34, 0x94, 0x57, 0xa2, 0x3e, 0xf1, 0xdb, 0xc8, 0x5c, 0xd3, - 0xe5, 0x0a, 0xf4, 0x8c, 0x6d, 0x52, 0x3d, 0x3e, 0x3e, 0x79, 0x6e, 0x8c, 0x7e, 0x36, 0x10, 0x3e, - 0x9c, 0x29, 0x76, 0x91, 0xc9, 0x81, 0x46, 0x95, 0x88, 0x15, 0xd8, 0x65, 0xe1, 0x9a, 0x44, 0x01, - 0xa4, 0xc2, 0xf1, 0x7b, 0xe8, 0x4c, 0x00, 0x5f, 0x27, 0x59, 0xac, 0x35, 0xad, 0x60, 0x50, 0x16, - 0xee, 0xd9, 0xcb, 0x0a, 0x22, 0x4d, 0x0c, 0x5f, 0xa3, 0x81, 0x04, 0x9e, 0x26, 0x19, 0x95, 0x2a, - 0xb5, 0xaf, 0x53, 0xdf, 0x2a, 0x0b, 0x77, 0x30, 0xed, 0x60, 0xb2, 0x9b, 0x33, 0xfa, 0xdd, 0x40, - 0x0f, 0x9a, 0x8e, 0x26, 0x8c, 0x4b, 0xfc, 0x18, 0x9d, 0xea, 0x7f, 0xa7, 0xfd, 0x04, 0x56, 0x59, - 0xb8, 0xa7, 0xdf, 0xa8, 0xff, 0xa6, 0x51, 0xfc, 0x39, 0xb2, 0xf4, 0x1a, 0x86, 0x6c, 0x59, 0xb9, - 0x0b, 0xae, 0xd4, 0x9c, 0x26, 0x35, 0x76, 0x5f, 0xb8, 0xef, 0x1c, 0x9e, 0x98, 0xd7, 0x84, 0x49, - 0x4b, 0x56, 0x65, 0x72, 0xc6, 0xa5, 0xee, 0xd1, 0xac, 0xca, 0xa8, 0xf2, 0x44, 0xa3, 0xca, 0x08, - 0xcd, 0xf3, 0x86, 0xa6, 0x97, 0xc3, 0xae, 0x8c, 0xdc, 0x74, 0x30, 0xd9, 0xcd, 0x19, 0x6d, 0x4f, - 0xd0, 0x79, 0x63, 0xe4, 0xe5, 0x32, 0x09, 0x01, 0xff, 0x80, 0x2c, 0x75, 0xad, 0x11, 0x95, 0x54, - 0xbb, 0xd9, 0xdf, 0xf6, 0xf6, 0xe8, 0xbc, 0x7c, 0x11, 0x2b, 0x40, 0x78, 0x2a, 0xbb, 0x5b, 0xb8, - 0xaf, 0x41, 0xd2, 0x6e, 0xdb, 0x3b, 0x8c, 0xb4, 0xaa, 0xf8, 0x33, 0x34, 0xa8, 0xcf, 0x6b, 0xba, - 0xc9, 0xa1, 0x6e, 0x73, 0x54, 0x53, 0x06, 0x37, 0x5d, 0xe8, 0x7e, 0xff, 0x49, 0x76, 0x69, 0xf8, - 0x5b, 0x64, 0x43, 0xdd, 0xb8, 0x3a, 0x4b, 0xb5, 0xb6, 0xef, 0x1f, 0xb7, 0xb6, 0xc1, 0xa3, 0xba, - 0x96, 0xdd, 0x20, 0x82, 0x74, 0x5a, 0xf8, 0x05, 0x32, 0xd5, 0x34, 0xc5, 0xb0, 0xaf, 0x45, 0x3f, - 0x38, 0x4e, 0x54, 0xfd, 0x86, 0xe0, 0xbc, 0x16, 0x36, 0xd5, 0x4b, 0x90, 0x4a, 0x67, 0xf4, 0x9b, - 0x81, 0x1e, 0xed, 0xcd, 0xf8, 0xab, 0x44, 0x48, 0xfc, 0xfd, 0xc1, 0x9c, 0xbd, 0xe3, 0xe6, 0xac, - 0xd8, 0x7a, 0xca, 0xed, 0xbd, 0x35, 0xc8, 0xce, 0x8c, 0x27, 0xc8, 0x4c, 0x24, 0xa4, 0xcd, 0x64, - 0xae, 0x8e, 0x33, 0xa1, 0xbb, 0xeb, 0x5c, 0x7c, 0xa9, 0x14, 0x48, 0x25, 0x14, 0x3c, 0xb9, 0xdb, - 0x3a, 0xbd, 0xd7, 0x5b, 0xa7, 0xf7, 0x66, 0xeb, 0xf4, 0x7e, 0x2a, 0x1d, 0xe3, 0xae, 0x74, 0x8c, - 0xd7, 0xa5, 0x63, 0xbc, 0x29, 0x1d, 0xe3, 0x8f, 0xd2, 0x31, 0x7e, 0xf9, 0xd3, 0xe9, 0x7d, 0x77, - 0x56, 0x4b, 0xfe, 0x15, 0x00, 0x00, 0xff, 0xff, 0x95, 0x55, 0x4b, 0x65, 0xc8, 0x06, 0x00, 0x00, + 0x10, 0x8d, 0x27, 0x63, 0xc6, 0xee, 0xec, 0x88, 0xdd, 0x16, 0x87, 0x68, 0x58, 0xd9, 0xa3, 0x20, + 0x50, 0xc4, 0x68, 0x6d, 0x66, 0xb5, 0x42, 0x2b, 0x38, 0x8d, 0x61, 0x04, 0x48, 0xb0, 0x1b, 0xf5, + 0x46, 0x42, 0x42, 0x1c, 0xe8, 0xd8, 0xb5, 0x8e, 0x49, 0xec, 0xb6, 0xba, 0x3b, 0x91, 0x72, 0xe3, + 0x1f, 0xc0, 0x7f, 0x42, 0x42, 0x73, 0xdc, 0xe3, 0x9e, 0x2c, 0x62, 0xf8, 0x15, 0x7b, 0x42, 0xdd, + 0xfe, 0x4a, 0x08, 0x1f, 0xb9, 0x75, 0xbf, 0xaa, 0xf7, 0xaa, 0x5e, 0x75, 0x17, 0xba, 0x5d, 0x3c, + 0x15, 0x5e, 0xc2, 0xfc, 0xc5, 0x6a, 0x06, 0x3c, 0x03, 0x09, 0xc2, 0x5f, 0x43, 0x16, 0x31, 0xee, + 0xd7, 0x01, 0x9a, 0x27, 0x7e, 0x94, 0x88, 0x90, 0xad, 0x81, 0x6f, 0xfc, 0xf5, 0xf5, 0x0c, 0x24, + 0xbd, 0xf6, 0x63, 0xc8, 0x80, 0x53, 0x09, 0x91, 0x97, 0x73, 0x26, 0x19, 0x7e, 0x58, 0x65, 0x7b, + 0x34, 0x4f, 0xbc, 0x36, 0xdb, 0xab, 0xb3, 0x2f, 0x1e, 0xc5, 0x89, 0x9c, 0xaf, 0x66, 0x5e, 0xc8, + 0x52, 0x3f, 0x66, 0x31, 0xf3, 0x35, 0x69, 0xb6, 0x7a, 0xa9, 0x6f, 0xfa, 0xa2, 0x4f, 0x95, 0xd8, + 0xc5, 0x68, 0xa7, 0x74, 0xc8, 0x38, 0xf8, 0xeb, 0x83, 0x82, 0x17, 0x4f, 0xba, 0x9c, 0x94, 0x86, + 0xf3, 0x24, 0x53, 0xdd, 0xe5, 0x8b, 0x58, 0x01, 0xc2, 0x4f, 0x41, 0xd2, 0x7f, 0x62, 0xf9, 0xff, + 0xc6, 0xe2, 0xab, 0x4c, 0x26, 0x29, 0x1c, 0x10, 0x3e, 0xfe, 0x3f, 0x82, 0x08, 0xe7, 0x90, 0xd2, + 0xbf, 0xf3, 0x46, 0x7f, 0xf6, 0x91, 0x75, 0x9b, 0x45, 0x39, 0x4b, 0x32, 0x89, 0xaf, 0x90, 0x4d, + 0xa3, 0x88, 0x83, 0x10, 0x20, 0x86, 0xc6, 0x65, 0x7f, 0x6c, 0x07, 0xe7, 0x65, 0xe1, 0xda, 0x37, + 0x0d, 0x48, 0xba, 0x38, 0x8e, 0x10, 0x0a, 0x59, 0x16, 0x25, 0x32, 0x61, 0x99, 0x18, 0x9e, 0x5c, + 0x1a, 0xe3, 0xc1, 0xe3, 0x8f, 0xbc, 0xff, 0x1a, 0xaf, 0xd7, 0x14, 0xfa, 0xac, 0xe5, 0x05, 0xf8, + 0xae, 0x70, 0x7b, 0x65, 0xe1, 0xa2, 0x0e, 0x23, 0x3b, 0xba, 0x78, 0x8c, 0xac, 0x39, 0x13, 0x32, + 0xa3, 0x29, 0x0c, 0xfb, 0x97, 0xc6, 0xd8, 0x0e, 0xee, 0x95, 0x85, 0x6b, 0x7d, 0x59, 0x63, 0xa4, + 0x8d, 0xe2, 0x09, 0xb2, 0x25, 0xe5, 0x31, 0x48, 0x02, 0x2f, 0x87, 0xa7, 0xba, 0x9d, 0xf7, 0x76, + 0xdb, 0x51, 0x0f, 0xe4, 0xad, 0xaf, 0xbd, 0xe7, 0xb3, 0x1f, 0x21, 0x54, 0x49, 0xc0, 0x21, 0x0b, + 0xa1, 0x72, 0x38, 0x6d, 0x98, 0xa4, 0x13, 0xc1, 0x33, 0x64, 0x49, 0x96, 0xb3, 0x25, 0x8b, 0x37, + 0x43, 0xf3, 0xb2, 0x3f, 0x1e, 0x3c, 0x7e, 0x72, 0x9c, 0x3f, 0x6f, 0x5a, 0xd3, 0x6e, 0x33, 0xc9, + 0x37, 0xc1, 0xfd, 0xda, 0xa3, 0xd5, 0xc0, 0xa4, 0xd5, 0x55, 0xfe, 0x32, 0x16, 0xc1, 0x33, 0xe5, + 0xef, 0xad, 0xce, 0xdf, 0xb3, 0x1a, 0x23, 0x6d, 0xf4, 0xe2, 0x53, 0x74, 0xbe, 0x27, 0x8b, 0xef, + 0xa3, 0xfe, 0x02, 0x36, 0x43, 0x43, 0xb1, 0x88, 0x3a, 0xe2, 0x77, 0x90, 0xb9, 0xa6, 0xcb, 0x15, + 0xe8, 0xd7, 0xb0, 0x49, 0x75, 0xf9, 0xe4, 0xe4, 0xa9, 0x31, 0xfa, 0xd9, 0x40, 0xf8, 0x70, 0xfa, + 0xd8, 0x45, 0x26, 0x07, 0x1a, 0x55, 0x22, 0x56, 0x60, 0x97, 0x85, 0x6b, 0x12, 0x05, 0x90, 0x0a, + 0xc7, 0xef, 0xa3, 0x33, 0x01, 0x7c, 0x9d, 0x64, 0xb1, 0xd6, 0xb4, 0x82, 0x41, 0x59, 0xb8, 0x67, + 0x2f, 0x2a, 0x88, 0x34, 0x31, 0x7c, 0x8d, 0x06, 0x12, 0x78, 0x9a, 0x64, 0x54, 0xaa, 0xd4, 0xbe, + 0x4e, 0x7d, 0xbb, 0x2c, 0xdc, 0xc1, 0xb4, 0x83, 0xc9, 0x6e, 0xce, 0xe8, 0x37, 0x03, 0xdd, 0x6b, + 0x3a, 0x9a, 0x30, 0x2e, 0xf1, 0x43, 0x74, 0xaa, 0x5f, 0x59, 0xfb, 0x09, 0xac, 0xb2, 0x70, 0x4f, + 0xf5, 0x04, 0x34, 0x8a, 0xbf, 0x40, 0x96, 0xfe, 0xb0, 0x21, 0x5b, 0x56, 0xee, 0x82, 0x2b, 0x35, + 0xa7, 0x49, 0x8d, 0xbd, 0x29, 0xdc, 0x77, 0x0f, 0x97, 0xd1, 0x6b, 0xc2, 0xa4, 0x25, 0xab, 0x32, + 0x39, 0xe3, 0x52, 0xf7, 0x68, 0x56, 0x65, 0x54, 0x79, 0xa2, 0x51, 0x65, 0x84, 0xe6, 0x79, 0x43, + 0xd3, 0xdf, 0xc8, 0xae, 0x8c, 0xdc, 0x74, 0x30, 0xd9, 0xcd, 0x19, 0x6d, 0x4f, 0xd0, 0x79, 0x63, + 0xe4, 0xc5, 0x32, 0x09, 0x01, 0xff, 0x80, 0x2c, 0xb5, 0xd7, 0x11, 0x95, 0x54, 0xbb, 0xd9, 0xdf, + 0x8b, 0x76, 0x3d, 0xbd, 0x7c, 0x11, 0x2b, 0x40, 0x78, 0x2a, 0xbb, 0xfb, 0x9a, 0xdf, 0x80, 0xa4, + 0xdd, 0x5e, 0x74, 0x18, 0x69, 0x55, 0xf1, 0xe7, 0x68, 0x50, 0x2f, 0xe2, 0x74, 0x93, 0x43, 0xdd, + 0xe6, 0xa8, 0xa6, 0x0c, 0x6e, 0xba, 0xd0, 0x9b, 0xfd, 0x2b, 0xd9, 0xa5, 0xe1, 0x6f, 0x91, 0x0d, + 0x75, 0xe3, 0x6a, 0x81, 0xd5, 0x07, 0xff, 0xe0, 0xb8, 0x0f, 0x1e, 0x3c, 0xa8, 0x6b, 0xd9, 0x0d, + 0x22, 0x48, 0xa7, 0x85, 0x9f, 0x23, 0x53, 0x4d, 0x53, 0x0c, 0xfb, 0x5a, 0xf4, 0xc3, 0xe3, 0x44, + 0xd5, 0x33, 0x04, 0xe7, 0xb5, 0xb0, 0xa9, 0x6e, 0x82, 0x54, 0x3a, 0xa3, 0x5f, 0x0d, 0xf4, 0x60, + 0x6f, 0xc6, 0x5f, 0x27, 0x42, 0xe2, 0xef, 0x0f, 0xe6, 0xec, 0x1d, 0x37, 0x67, 0xc5, 0xd6, 0x53, + 0x6e, 0x37, 0xb3, 0x41, 0x76, 0x66, 0x3c, 0x41, 0x66, 0x22, 0x21, 0x6d, 0x26, 0x73, 0x75, 0x9c, + 0x09, 0xdd, 0x5d, 0xe7, 0xe2, 0x2b, 0xa5, 0x40, 0x2a, 0xa1, 0xe0, 0xd1, 0xdd, 0xd6, 0xe9, 0xbd, + 0xda, 0x3a, 0xbd, 0xd7, 0x5b, 0xa7, 0xf7, 0x53, 0xe9, 0x18, 0x77, 0xa5, 0x63, 0xbc, 0x2a, 0x1d, + 0xe3, 0x75, 0xe9, 0x18, 0xbf, 0x97, 0x8e, 0xf1, 0xcb, 0x1f, 0x4e, 0xef, 0xbb, 0xb3, 0x5a, 0xf2, + 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa6, 0x35, 0xe6, 0xf5, 0xf2, 0x06, 0x00, 0x00, } func (m *Endpoint) Marshal() (dAtA []byte, err error) { @@ -272,6 +273,13 @@ func (m *Endpoint) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.NodeName != nil { + i -= len(*m.NodeName) + copy(dAtA[i:], *m.NodeName) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.NodeName))) + i-- + dAtA[i] = 0x32 + } if len(m.Topology) > 0 { keysForTopology := make([]string, 0, len(m.Topology)) for k := range m.Topology { @@ -593,6 +601,10 @@ func (m *Endpoint) Size() (n int) { n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) } } + if m.NodeName != nil { + l = len(*m.NodeName) + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -706,6 +718,7 @@ func (this *Endpoint) String() string { `Hostname:` + valueToStringGenerated(this.Hostname) + `,`, `TargetRef:` + strings.Replace(fmt.Sprintf("%v", this.TargetRef), "ObjectReference", "v1.ObjectReference", 1) + `,`, `Topology:` + mapStringForTopology + `,`, + `NodeName:` + valueToStringGenerated(this.NodeName) + `,`, `}`, }, "") return s @@ -1072,6 +1085,39 @@ func (m *Endpoint) Unmarshal(dAtA []byte) error { } m.Topology[mapkey] = mapvalue iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NodeName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(dAtA[iNdEx:postIndex]) + m.NodeName = &s + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/staging/src/k8s.io/api/discovery/v1beta1/generated.proto b/staging/src/k8s.io/api/discovery/v1beta1/generated.proto index cdf1a21999b..e5d21caadf2 100644 --- a/staging/src/k8s.io/api/discovery/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/discovery/v1beta1/generated.proto @@ -67,8 +67,15 @@ message Endpoint { // endpoint is located. This should match the corresponding node label. // * topology.kubernetes.io/region: the value indicates the region where the // endpoint is located. This should match the corresponding node label. + // This field is deprecated and will be removed in future api versions. // +optional map topology = 5; + + // nodeName represents the name of the Node hosting this endpoint. This can + // be used to determine endpoints local to a Node. This field can be enabled + // with the EndpointSliceNodeName feature gate. + // +optional + optional string nodeName = 6; } // EndpointConditions represents the current condition of an endpoint. @@ -81,15 +88,18 @@ message EndpointConditions { // +optional optional bool ready = 1; - // serving is identical to ready except that it is set regardless of the terminating - // state of endpoints. This condition should be set to true for a ready endpoint that - // is terminating. If nil, consumers should defer to the ready condition. + // serving is identical to ready except that it is set regardless of the + // terminating state of endpoints. This condition should be set to true for + // a ready endpoint that is terminating. If nil, consumers should defer to + // the ready condition. This field can be enabled with the + // EndpointSliceTerminatingCondition feature gate. // +optional optional bool serving = 2; - // terminating indicates that this endpoint is terminating. A nil value indicates an - // unknown state. Consumers should interpret this unknown state to mean that the - // endpoint is not terminating. + // terminating indicates that this endpoint is terminating. A nil value + // indicates an unknown state. Consumers should interpret this unknown state + // to mean that the endpoint is not terminating. This field can be enabled + // with the EndpointSliceTerminatingCondition feature gate. // +optional optional bool terminating = 3; } diff --git a/staging/src/k8s.io/api/discovery/v1beta1/types.go b/staging/src/k8s.io/api/discovery/v1beta1/types.go index d65a079876a..e14088e8b2c 100644 --- a/staging/src/k8s.io/api/discovery/v1beta1/types.go +++ b/staging/src/k8s.io/api/discovery/v1beta1/types.go @@ -60,12 +60,6 @@ type EndpointSlice struct { type AddressType string const ( - // AddressTypeIP represents an IP Address. - // This address type has been deprecated and has been replaced by the IPv4 - // and IPv6 adddress types. New resources with this address type will be - // considered invalid. This will be fully removed in 1.18. - // +deprecated - AddressTypeIP = AddressType("IP") // AddressTypeIPv4 represents an IPv4 Address. AddressTypeIPv4 = AddressType(v1.IPv4Protocol) // AddressTypeIPv6 represents an IPv6 Address. @@ -108,8 +102,14 @@ type Endpoint struct { // endpoint is located. This should match the corresponding node label. // * topology.kubernetes.io/region: the value indicates the region where the // endpoint is located. This should match the corresponding node label. + // This field is deprecated and will be removed in future api versions. // +optional Topology map[string]string `json:"topology,omitempty" protobuf:"bytes,5,opt,name=topology"` + // nodeName represents the name of the Node hosting this endpoint. This can + // be used to determine endpoints local to a Node. This field can be enabled + // with the EndpointSliceNodeName feature gate. + // +optional + NodeName *string `json:"nodeName,omitempty" protobuf:"bytes,6,opt,name=nodeName"` } // EndpointConditions represents the current condition of an endpoint. @@ -122,15 +122,18 @@ type EndpointConditions struct { // +optional Ready *bool `json:"ready,omitempty" protobuf:"bytes,1,name=ready"` - // serving is identical to ready except that it is set regardless of the terminating - // state of endpoints. This condition should be set to true for a ready endpoint that - // is terminating. If nil, consumers should defer to the ready condition. + // serving is identical to ready except that it is set regardless of the + // terminating state of endpoints. This condition should be set to true for + // a ready endpoint that is terminating. If nil, consumers should defer to + // the ready condition. This field can be enabled with the + // EndpointSliceTerminatingCondition feature gate. // +optional Serving *bool `json:"serving,omitempty" protobuf:"bytes,2,name=serving"` - // terminating indicates that this endpoint is terminating. A nil value indicates an - // unknown state. Consumers should interpret this unknown state to mean that the - // endpoint is not terminating. + // terminating indicates that this endpoint is terminating. A nil value + // indicates an unknown state. Consumers should interpret this unknown state + // to mean that the endpoint is not terminating. This field can be enabled + // with the EndpointSliceTerminatingCondition feature gate. // +optional Terminating *bool `json:"terminating,omitempty" protobuf:"bytes,3,name=terminating"` } diff --git a/staging/src/k8s.io/api/discovery/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/discovery/v1beta1/types_swagger_doc_generated.go index 07033c48497..d48b93d8b50 100644 --- a/staging/src/k8s.io/api/discovery/v1beta1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/discovery/v1beta1/types_swagger_doc_generated.go @@ -33,7 +33,8 @@ var map_Endpoint = map[string]string{ "conditions": "conditions contains information about the current status of the endpoint.", "hostname": "hostname of this endpoint. This field may be used by consumers of endpoints to distinguish endpoints from each other (e.g. in DNS names). Multiple endpoints which use the same hostname should be considered fungible (e.g. multiple A values in DNS). Must be lowercase and pass DNS Label (RFC 1123) validation.", "targetRef": "targetRef is a reference to a Kubernetes object that represents this endpoint.", - "topology": "topology contains arbitrary topology information associated with the endpoint. These key/value pairs must conform with the label format. https://kubernetes.io/docs/concepts/overview/working-with-objects/labels Topology may include a maximum of 16 key/value pairs. This includes, but is not limited to the following well known keys: * kubernetes.io/hostname: the value indicates the hostname of the node\n where the endpoint is located. This should match the corresponding\n node label.\n* topology.kubernetes.io/zone: the value indicates the zone where the\n endpoint is located. This should match the corresponding node label.\n* topology.kubernetes.io/region: the value indicates the region where the\n endpoint is located. This should match the corresponding node label.", + "topology": "topology contains arbitrary topology information associated with the endpoint. These key/value pairs must conform with the label format. https://kubernetes.io/docs/concepts/overview/working-with-objects/labels Topology may include a maximum of 16 key/value pairs. This includes, but is not limited to the following well known keys: * kubernetes.io/hostname: the value indicates the hostname of the node\n where the endpoint is located. This should match the corresponding\n node label.\n* topology.kubernetes.io/zone: the value indicates the zone where the\n endpoint is located. This should match the corresponding node label.\n* topology.kubernetes.io/region: the value indicates the region where the\n endpoint is located. This should match the corresponding node label.\nThis field is deprecated and will be removed in future api versions.", + "nodeName": "nodeName represents the name of the Node hosting this endpoint. This can be used to determine endpoints local to a Node. This field can be enabled with the EndpointSliceNodeName feature gate.", } func (Endpoint) SwaggerDoc() map[string]string { @@ -43,8 +44,8 @@ func (Endpoint) SwaggerDoc() map[string]string { var map_EndpointConditions = map[string]string{ "": "EndpointConditions represents the current condition of an endpoint.", "ready": "ready indicates that this endpoint is prepared to receive traffic, according to whatever system is managing the endpoint. A nil value indicates an unknown state. In most cases consumers should interpret this unknown state as ready. For compatibility reasons, ready should never be \"true\" for terminating endpoints.", - "serving": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition.", - "terminating": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating.", + "serving": "serving is identical to ready except that it is set regardless of the terminating state of endpoints. This condition should be set to true for a ready endpoint that is terminating. If nil, consumers should defer to the ready condition. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", + "terminating": "terminating indicates that this endpoint is terminating. A nil value indicates an unknown state. Consumers should interpret this unknown state to mean that the endpoint is not terminating. This field can be enabled with the EndpointSliceTerminatingCondition feature gate.", } func (EndpointConditions) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/discovery/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/discovery/v1beta1/zz_generated.deepcopy.go index 65c3a017311..7076553d291 100644 --- a/staging/src/k8s.io/api/discovery/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/discovery/v1beta1/zz_generated.deepcopy.go @@ -51,6 +51,11 @@ func (in *Endpoint) DeepCopyInto(out *Endpoint) { (*out)[key] = val } } + if in.NodeName != nil { + in, out := &in.NodeName, &out.NodeName + *out = new(string) + **out = **in + } return }