mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +00:00
Merge pull request #92968 from andrewsykim/endpointslice-termination
Add Terminating Condition to EndpointSlice
This commit is contained in:
commit
cccd77bd3a
10
api/openapi-spec/swagger.json
generated
10
api/openapi-spec/swagger.json
generated
@ -10914,7 +10914,15 @@
|
|||||||
"description": "EndpointConditions represents the current condition of an endpoint.",
|
"description": "EndpointConditions represents the current condition of an endpoint.",
|
||||||
"properties": {
|
"properties": {
|
||||||
"ready": {
|
"ready": {
|
||||||
"description": "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.",
|
"description": "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.",
|
||||||
|
"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.",
|
||||||
|
"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.",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -114,8 +114,21 @@ type EndpointConditions struct {
|
|||||||
// ready indicates that this endpoint is prepared to receive traffic,
|
// ready indicates that this endpoint is prepared to receive traffic,
|
||||||
// according to whatever system is managing the endpoint. A nil value
|
// according to whatever system is managing the endpoint. A nil value
|
||||||
// indicates an unknown state. In most cases consumers should interpret this
|
// indicates an unknown state. In most cases consumers should interpret this
|
||||||
// unknown state as ready.
|
// unknown state as ready. For compatibility reasons, ready should never be
|
||||||
|
// "true" for terminating endpoints.
|
||||||
Ready *bool
|
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.
|
||||||
|
// +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.
|
||||||
|
// +optional
|
||||||
|
Terminating *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointPort represents a Port used by an EndpointSlice.
|
// EndpointPort represents a Port used by an EndpointSlice.
|
||||||
|
@ -125,6 +125,8 @@ func Convert_discovery_Endpoint_To_v1alpha1_Endpoint(in *discovery.Endpoint, out
|
|||||||
|
|
||||||
func autoConvert_v1alpha1_EndpointConditions_To_discovery_EndpointConditions(in *v1alpha1.EndpointConditions, out *discovery.EndpointConditions, s conversion.Scope) error {
|
func autoConvert_v1alpha1_EndpointConditions_To_discovery_EndpointConditions(in *v1alpha1.EndpointConditions, out *discovery.EndpointConditions, s conversion.Scope) error {
|
||||||
out.Ready = (*bool)(unsafe.Pointer(in.Ready))
|
out.Ready = (*bool)(unsafe.Pointer(in.Ready))
|
||||||
|
out.Serving = (*bool)(unsafe.Pointer(in.Serving))
|
||||||
|
out.Terminating = (*bool)(unsafe.Pointer(in.Terminating))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +137,8 @@ func Convert_v1alpha1_EndpointConditions_To_discovery_EndpointConditions(in *v1a
|
|||||||
|
|
||||||
func autoConvert_discovery_EndpointConditions_To_v1alpha1_EndpointConditions(in *discovery.EndpointConditions, out *v1alpha1.EndpointConditions, s conversion.Scope) error {
|
func autoConvert_discovery_EndpointConditions_To_v1alpha1_EndpointConditions(in *discovery.EndpointConditions, out *v1alpha1.EndpointConditions, s conversion.Scope) error {
|
||||||
out.Ready = (*bool)(unsafe.Pointer(in.Ready))
|
out.Ready = (*bool)(unsafe.Pointer(in.Ready))
|
||||||
|
out.Serving = (*bool)(unsafe.Pointer(in.Serving))
|
||||||
|
out.Terminating = (*bool)(unsafe.Pointer(in.Terminating))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +125,8 @@ func Convert_discovery_Endpoint_To_v1beta1_Endpoint(in *discovery.Endpoint, out
|
|||||||
|
|
||||||
func autoConvert_v1beta1_EndpointConditions_To_discovery_EndpointConditions(in *v1beta1.EndpointConditions, out *discovery.EndpointConditions, s conversion.Scope) error {
|
func autoConvert_v1beta1_EndpointConditions_To_discovery_EndpointConditions(in *v1beta1.EndpointConditions, out *discovery.EndpointConditions, s conversion.Scope) error {
|
||||||
out.Ready = (*bool)(unsafe.Pointer(in.Ready))
|
out.Ready = (*bool)(unsafe.Pointer(in.Ready))
|
||||||
|
out.Serving = (*bool)(unsafe.Pointer(in.Serving))
|
||||||
|
out.Terminating = (*bool)(unsafe.Pointer(in.Terminating))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +137,8 @@ func Convert_v1beta1_EndpointConditions_To_discovery_EndpointConditions(in *v1be
|
|||||||
|
|
||||||
func autoConvert_discovery_EndpointConditions_To_v1beta1_EndpointConditions(in *discovery.EndpointConditions, out *v1beta1.EndpointConditions, s conversion.Scope) error {
|
func autoConvert_discovery_EndpointConditions_To_v1beta1_EndpointConditions(in *discovery.EndpointConditions, out *v1beta1.EndpointConditions, s conversion.Scope) error {
|
||||||
out.Ready = (*bool)(unsafe.Pointer(in.Ready))
|
out.Ready = (*bool)(unsafe.Pointer(in.Ready))
|
||||||
|
out.Serving = (*bool)(unsafe.Pointer(in.Serving))
|
||||||
|
out.Terminating = (*bool)(unsafe.Pointer(in.Terminating))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
pkg/apis/discovery/zz_generated.deepcopy.go
generated
10
pkg/apis/discovery/zz_generated.deepcopy.go
generated
@ -72,6 +72,16 @@ func (in *EndpointConditions) DeepCopyInto(out *EndpointConditions) {
|
|||||||
*out = new(bool)
|
*out = new(bool)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
|
if in.Serving != nil {
|
||||||
|
in, out := &in.Serving, &out.Serving
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.Terminating != nil {
|
||||||
|
in, out := &in.Terminating, &out.Terminating
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ go_library(
|
|||||||
"//pkg/controller:go_default_library",
|
"//pkg/controller:go_default_library",
|
||||||
"//pkg/controller/endpointslice/metrics:go_default_library",
|
"//pkg/controller/endpointslice/metrics:go_default_library",
|
||||||
"//pkg/controller/util/endpoint: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/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/discovery/v1beta1:go_default_library",
|
"//staging/src/k8s.io/api/discovery/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||||
@ -31,6 +32,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait: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/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/informers/discovery/v1beta1: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",
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
@ -61,6 +63,7 @@ go_test(
|
|||||||
"//pkg/controller:go_default_library",
|
"//pkg/controller:go_default_library",
|
||||||
"//pkg/controller/endpointslice/metrics:go_default_library",
|
"//pkg/controller/endpointslice/metrics:go_default_library",
|
||||||
"//pkg/controller/util/endpoint: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/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/discovery/v1beta1:go_default_library",
|
"//staging/src/k8s.io/api/discovery/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||||
@ -71,11 +74,13 @@ go_test(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/rand: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/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/informers:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/cache: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",
|
"//staging/src/k8s.io/component-base/metrics/testutil:go_default_library",
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
"//vendor/k8s.io/utils/pointer:go_default_library",
|
||||||
|
@ -33,12 +33,15 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
k8stesting "k8s.io/client-go/testing"
|
k8stesting "k8s.io/client-go/testing"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint"
|
endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
utilpointer "k8s.io/utils/pointer"
|
utilpointer "k8s.io/utils/pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -186,11 +189,11 @@ func TestSyncServicePodSelection(t *testing.T) {
|
|||||||
client, esController := newController([]string{"node-1"}, time.Duration(0))
|
client, esController := newController([]string{"node-1"}, time.Duration(0))
|
||||||
ns := metav1.NamespaceDefault
|
ns := metav1.NamespaceDefault
|
||||||
|
|
||||||
pod1 := newPod(1, ns, true, 0)
|
pod1 := newPod(1, ns, true, 0, false)
|
||||||
esController.podStore.Add(pod1)
|
esController.podStore.Add(pod1)
|
||||||
|
|
||||||
// ensure this pod will not match the selector
|
// ensure this pod will not match the selector
|
||||||
pod2 := newPod(2, ns, true, 0)
|
pod2 := newPod(2, ns, true, 0, false)
|
||||||
pod2.Labels["foo"] = "boo"
|
pod2.Labels["foo"] = "boo"
|
||||||
esController.podStore.Add(pod2)
|
esController.podStore.Add(pod2)
|
||||||
|
|
||||||
@ -335,27 +338,138 @@ func TestOnEndpointSliceUpdate(t *testing.T) {
|
|||||||
assert.Equal(t, 1, esController.queue.Len())
|
assert.Equal(t, 1, esController.queue.Len())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure SyncService handles a variety of protocols and IPs appropriately.
|
func TestSyncService(t *testing.T) {
|
||||||
func TestSyncServiceFull(t *testing.T) {
|
creationTimestamp := metav1.Now()
|
||||||
client, esController := newController([]string{"node-1"}, time.Duration(0))
|
deletionTimestamp := metav1.Now()
|
||||||
namespace := metav1.NamespaceDefault
|
|
||||||
serviceName := "all-the-protocols"
|
|
||||||
|
|
||||||
pod1 := newPod(1, namespace, true, 0)
|
testcases := []struct {
|
||||||
pod1.Status.PodIPs = []v1.PodIP{{IP: "1.2.3.4"}}
|
name string
|
||||||
esController.podStore.Add(pod1)
|
service *v1.Service
|
||||||
|
pods []*v1.Pod
|
||||||
pod2 := newPod(2, namespace, true, 0)
|
expectedEndpointPorts []discovery.EndpointPort
|
||||||
pod2.Status.PodIPs = []v1.PodIP{{IP: "1.2.3.5"}, {IP: "1234::5678:0000:0000:9abc:def0"}}
|
expectedEndpoints []discovery.Endpoint
|
||||||
esController.podStore.Add(pod2)
|
terminatingGateEnabled bool
|
||||||
|
}{
|
||||||
// create service with all protocols and multiple ports
|
{
|
||||||
serviceCreateTime := time.Now()
|
name: "pods with multiple IPs and Service with ipFamilies=ipv4",
|
||||||
service := &v1.Service{
|
service: &v1.Service{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: serviceName,
|
Name: "foobar",
|
||||||
Namespace: namespace,
|
Namespace: "default",
|
||||||
CreationTimestamp: metav1.NewTime(serviceCreateTime),
|
CreationTimestamp: creationTimestamp,
|
||||||
|
},
|
||||||
|
Spec: v1.ServiceSpec{
|
||||||
|
Ports: []v1.ServicePort{
|
||||||
|
{Name: "tcp-example", TargetPort: intstr.FromInt(80), Protocol: v1.ProtocolTCP},
|
||||||
|
{Name: "udp-example", TargetPort: intstr.FromInt(161), Protocol: v1.ProtocolUDP},
|
||||||
|
{Name: "sctp-example", TargetPort: intstr.FromInt(3456), Protocol: v1.ProtocolSCTP},
|
||||||
|
},
|
||||||
|
Selector: map[string]string{"foo": "bar"},
|
||||||
|
IPFamilies: []v1.IPFamily{v1.IPv4Protocol},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod0",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: nil,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.1",
|
||||||
|
PodIPs: []v1.PodIP{{
|
||||||
|
IP: "10.0.0.1",
|
||||||
|
}},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod1",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: nil,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.2",
|
||||||
|
PodIPs: []v1.PodIP{
|
||||||
|
{
|
||||||
|
IP: "10.0.0.2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
IP: "fd08::5678:0000:0000:9abc:def0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpointPorts: []discovery.EndpointPort{
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("sctp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolSCTP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(3456)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("udp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolUDP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(161)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("tcp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolTCP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(80)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Addresses: []string{"10.0.0.1"},
|
||||||
|
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod0"},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Addresses: []string{"10.0.0.2"},
|
||||||
|
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod1"},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pods with multiple IPs and Service with ipFamilies=ipv6",
|
||||||
|
service: &v1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: "default",
|
||||||
|
CreationTimestamp: creationTimestamp,
|
||||||
},
|
},
|
||||||
Spec: v1.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
Ports: []v1.ServicePort{
|
Ports: []v1.ServicePort{
|
||||||
@ -366,45 +480,566 @@ func TestSyncServiceFull(t *testing.T) {
|
|||||||
Selector: map[string]string{"foo": "bar"},
|
Selector: map[string]string{"foo": "bar"},
|
||||||
IPFamilies: []v1.IPFamily{v1.IPv6Protocol},
|
IPFamilies: []v1.IPFamily{v1.IPv6Protocol},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod0",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: nil,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.1",
|
||||||
|
PodIPs: []v1.PodIP{{
|
||||||
|
IP: "10.0.0.1",
|
||||||
|
}},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod1",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: nil,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.2",
|
||||||
|
PodIPs: []v1.PodIP{
|
||||||
|
{
|
||||||
|
IP: "10.0.0.2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
IP: "fd08::5678:0000:0000:9abc:def0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpointPorts: []discovery.EndpointPort{
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("sctp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolSCTP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(3456)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("udp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolUDP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(161)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("tcp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolTCP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(80)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Addresses: []string{"fd08::5678:0000:0000:9abc:def0"},
|
||||||
|
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod1"},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Terminating pods with EndpointSliceTerminatingCondition enabled",
|
||||||
|
service: &v1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: "default",
|
||||||
|
CreationTimestamp: creationTimestamp,
|
||||||
|
},
|
||||||
|
Spec: v1.ServiceSpec{
|
||||||
|
Ports: []v1.ServicePort{
|
||||||
|
{Name: "tcp-example", TargetPort: intstr.FromInt(80), Protocol: v1.ProtocolTCP},
|
||||||
|
{Name: "udp-example", TargetPort: intstr.FromInt(161), Protocol: v1.ProtocolUDP},
|
||||||
|
{Name: "sctp-example", TargetPort: intstr.FromInt(3456), Protocol: v1.ProtocolSCTP},
|
||||||
|
},
|
||||||
|
Selector: map[string]string{"foo": "bar"},
|
||||||
|
IPFamilies: []v1.IPFamily{v1.IPv4Protocol},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{
|
||||||
|
{
|
||||||
|
// one ready pod for comparison
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod0",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: nil,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.1",
|
||||||
|
PodIPs: []v1.PodIP{{
|
||||||
|
IP: "10.0.0.1",
|
||||||
|
}},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod1",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: &deletionTimestamp,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.2",
|
||||||
|
PodIPs: []v1.PodIP{
|
||||||
|
{
|
||||||
|
IP: "10.0.0.2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpointPorts: []discovery.EndpointPort{
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("sctp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolSCTP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(3456)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("udp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolUDP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(161)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("tcp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolTCP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(80)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(true),
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
Addresses: []string{"10.0.0.1"},
|
||||||
|
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod0"},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(false),
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Addresses: []string{"10.0.0.2"},
|
||||||
|
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod1"},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Terminating pods with EndpointSliceTerminatingCondition disabled",
|
||||||
|
service: &v1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: "default",
|
||||||
|
CreationTimestamp: creationTimestamp,
|
||||||
|
},
|
||||||
|
Spec: v1.ServiceSpec{
|
||||||
|
Ports: []v1.ServicePort{
|
||||||
|
{Name: "tcp-example", TargetPort: intstr.FromInt(80), Protocol: v1.ProtocolTCP},
|
||||||
|
{Name: "udp-example", TargetPort: intstr.FromInt(161), Protocol: v1.ProtocolUDP},
|
||||||
|
{Name: "sctp-example", TargetPort: intstr.FromInt(3456), Protocol: v1.ProtocolSCTP},
|
||||||
|
},
|
||||||
|
Selector: map[string]string{"foo": "bar"},
|
||||||
|
IPFamilies: []v1.IPFamily{v1.IPv4Protocol},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{
|
||||||
|
{
|
||||||
|
// one ready pod for comparison
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod0",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: nil,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.1",
|
||||||
|
PodIPs: []v1.PodIP{{
|
||||||
|
IP: "10.0.0.1",
|
||||||
|
}},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod1",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: &deletionTimestamp,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.2",
|
||||||
|
PodIPs: []v1.PodIP{
|
||||||
|
{
|
||||||
|
IP: "10.0.0.2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpointPorts: []discovery.EndpointPort{
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("sctp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolSCTP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(3456)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("udp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolUDP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(161)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("tcp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolTCP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(80)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Addresses: []string{"10.0.0.1"},
|
||||||
|
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod0"},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Not ready terminating pods with EndpointSliceTerminatingCondition enabled",
|
||||||
|
service: &v1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: "default",
|
||||||
|
CreationTimestamp: creationTimestamp,
|
||||||
|
},
|
||||||
|
Spec: v1.ServiceSpec{
|
||||||
|
Ports: []v1.ServicePort{
|
||||||
|
{Name: "tcp-example", TargetPort: intstr.FromInt(80), Protocol: v1.ProtocolTCP},
|
||||||
|
{Name: "udp-example", TargetPort: intstr.FromInt(161), Protocol: v1.ProtocolUDP},
|
||||||
|
{Name: "sctp-example", TargetPort: intstr.FromInt(3456), Protocol: v1.ProtocolSCTP},
|
||||||
|
},
|
||||||
|
Selector: map[string]string{"foo": "bar"},
|
||||||
|
IPFamilies: []v1.IPFamily{v1.IPv4Protocol},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{
|
||||||
|
{
|
||||||
|
// one ready pod for comparison
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod0",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: nil,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.1",
|
||||||
|
PodIPs: []v1.PodIP{{
|
||||||
|
IP: "10.0.0.1",
|
||||||
|
}},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod1",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: &deletionTimestamp,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.2",
|
||||||
|
PodIPs: []v1.PodIP{
|
||||||
|
{
|
||||||
|
IP: "10.0.0.2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionFalse,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpointPorts: []discovery.EndpointPort{
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("sctp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolSCTP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(3456)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("udp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolUDP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(161)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("tcp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolTCP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(80)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(true),
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
Addresses: []string{"10.0.0.1"},
|
||||||
|
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod0"},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(false),
|
||||||
|
Serving: utilpointer.BoolPtr(false),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Addresses: []string{"10.0.0.2"},
|
||||||
|
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod1"},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Not ready terminating pods with EndpointSliceTerminatingCondition disabled",
|
||||||
|
service: &v1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foobar",
|
||||||
|
Namespace: "default",
|
||||||
|
CreationTimestamp: creationTimestamp,
|
||||||
|
},
|
||||||
|
Spec: v1.ServiceSpec{
|
||||||
|
Ports: []v1.ServicePort{
|
||||||
|
{Name: "tcp-example", TargetPort: intstr.FromInt(80), Protocol: v1.ProtocolTCP},
|
||||||
|
{Name: "udp-example", TargetPort: intstr.FromInt(161), Protocol: v1.ProtocolUDP},
|
||||||
|
{Name: "sctp-example", TargetPort: intstr.FromInt(3456), Protocol: v1.ProtocolSCTP},
|
||||||
|
},
|
||||||
|
Selector: map[string]string{"foo": "bar"},
|
||||||
|
IPFamilies: []v1.IPFamily{v1.IPv4Protocol},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pods: []*v1.Pod{
|
||||||
|
{
|
||||||
|
// one ready pod for comparison
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod0",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: nil,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.1",
|
||||||
|
PodIPs: []v1.PodIP{{
|
||||||
|
IP: "10.0.0.1",
|
||||||
|
}},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "pod1",
|
||||||
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: &deletionTimestamp,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{{
|
||||||
|
Name: "container-1",
|
||||||
|
}},
|
||||||
|
NodeName: "node-1",
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
PodIP: "10.0.0.2",
|
||||||
|
PodIPs: []v1.PodIP{
|
||||||
|
{
|
||||||
|
IP: "10.0.0.2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{
|
||||||
|
Type: v1.PodReady,
|
||||||
|
Status: v1.ConditionFalse,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpointPorts: []discovery.EndpointPort{
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("sctp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolSCTP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(3456)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("udp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolUDP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(161)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: utilpointer.StringPtr("tcp-example"),
|
||||||
|
Protocol: protoPtr(v1.ProtocolTCP),
|
||||||
|
Port: utilpointer.Int32Ptr(int32(80)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEndpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Addresses: []string{"10.0.0.1"},
|
||||||
|
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: "default", Name: "pod0"},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
esController.serviceStore.Add(service)
|
|
||||||
_, err := esController.client.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{})
|
for _, testcase := range testcases {
|
||||||
|
t.Run(testcase.name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testcase.terminatingGateEnabled)()
|
||||||
|
|
||||||
|
client, esController := newController([]string{"node-1"}, time.Duration(0))
|
||||||
|
|
||||||
|
for _, pod := range testcase.pods {
|
||||||
|
esController.podStore.Add(pod)
|
||||||
|
}
|
||||||
|
esController.serviceStore.Add(testcase.service)
|
||||||
|
|
||||||
|
_, err := esController.client.CoreV1().Services(testcase.service.Namespace).Create(context.TODO(), testcase.service, metav1.CreateOptions{})
|
||||||
assert.Nil(t, err, "Expected no error creating service")
|
assert.Nil(t, err, "Expected no error creating service")
|
||||||
|
|
||||||
// run through full sync service loop
|
err = esController.syncService(fmt.Sprintf("%s/%s", testcase.service.Namespace, testcase.service.Name))
|
||||||
err = esController.syncService(fmt.Sprintf("%s/%s", namespace, serviceName))
|
assert.Nil(t, err)
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// last action should be to create endpoint slice
|
// last action should be to create endpoint slice
|
||||||
expectActions(t, client.Actions(), 1, "create", "endpointslices")
|
expectActions(t, client.Actions(), 1, "create", "endpointslices")
|
||||||
sliceList, err := client.DiscoveryV1beta1().EndpointSlices(namespace).List(context.TODO(), metav1.ListOptions{})
|
sliceList, err := client.DiscoveryV1beta1().EndpointSlices(testcase.service.Namespace).List(context.TODO(), metav1.ListOptions{})
|
||||||
assert.Nil(t, err, "Expected no error fetching endpoint slices")
|
assert.Nil(t, err, "Expected no error fetching endpoint slices")
|
||||||
assert.Len(t, sliceList.Items, 1, "Expected 1 endpoint slices")
|
assert.Len(t, sliceList.Items, 1, "Expected 1 endpoint slices")
|
||||||
|
|
||||||
// ensure all attributes of endpoint slice match expected state
|
// ensure all attributes of endpoint slice match expected state
|
||||||
slice := sliceList.Items[0]
|
slice := sliceList.Items[0]
|
||||||
assert.Len(t, slice.Endpoints, 1, "Expected 1 endpoints in first slice")
|
assert.Equal(t, slice.Annotations["endpoints.kubernetes.io/last-change-trigger-time"], creationTimestamp.Format(time.RFC3339Nano))
|
||||||
assert.Equal(t, slice.Annotations["endpoints.kubernetes.io/last-change-trigger-time"], serviceCreateTime.Format(time.RFC3339Nano))
|
assert.EqualValues(t, testcase.expectedEndpointPorts, slice.Ports)
|
||||||
assert.EqualValues(t, []discovery.EndpointPort{{
|
assert.ElementsMatch(t, testcase.expectedEndpoints, slice.Endpoints)
|
||||||
Name: utilpointer.StringPtr("sctp-example"),
|
})
|
||||||
Protocol: protoPtr(v1.ProtocolSCTP),
|
}
|
||||||
Port: utilpointer.Int32Ptr(int32(3456)),
|
|
||||||
}, {
|
|
||||||
Name: utilpointer.StringPtr("udp-example"),
|
|
||||||
Protocol: protoPtr(v1.ProtocolUDP),
|
|
||||||
Port: utilpointer.Int32Ptr(int32(161)),
|
|
||||||
}, {
|
|
||||||
Name: utilpointer.StringPtr("tcp-example"),
|
|
||||||
Protocol: protoPtr(v1.ProtocolTCP),
|
|
||||||
Port: utilpointer.Int32Ptr(int32(80)),
|
|
||||||
}}, slice.Ports)
|
|
||||||
|
|
||||||
assert.ElementsMatch(t, []discovery.Endpoint{{
|
|
||||||
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
|
|
||||||
Addresses: []string{"1234::5678:0000:0000:9abc:def0"},
|
|
||||||
TargetRef: &v1.ObjectReference{Kind: "Pod", Namespace: namespace, Name: pod2.Name},
|
|
||||||
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
|
||||||
}}, slice.Endpoints)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestPodAddsBatching verifies that endpoint updates caused by pod addition are batched together.
|
// TestPodAddsBatching verifies that endpoint updates caused by pod addition are batched together.
|
||||||
@ -499,7 +1134,7 @@ func TestPodAddsBatching(t *testing.T) {
|
|||||||
for i, add := range tc.adds {
|
for i, add := range tc.adds {
|
||||||
time.Sleep(add.delay)
|
time.Sleep(add.delay)
|
||||||
|
|
||||||
p := newPod(i, ns, true, 0)
|
p := newPod(i, ns, true, 0, false)
|
||||||
esController.podStore.Add(p)
|
esController.podStore.Add(p)
|
||||||
esController.addPod(p)
|
esController.addPod(p)
|
||||||
}
|
}
|
||||||
@ -789,7 +1424,7 @@ func TestPodDeleteBatching(t *testing.T) {
|
|||||||
func addPods(t *testing.T, esController *endpointSliceController, namespace string, podsCount int) {
|
func addPods(t *testing.T, esController *endpointSliceController, namespace string, podsCount int) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
for i := 0; i < podsCount; i++ {
|
for i := 0; i < podsCount; i++ {
|
||||||
pod := newPod(i, namespace, true, 0)
|
pod := newPod(i, namespace, true, 0, false)
|
||||||
esController.podStore.Add(pod)
|
esController.podStore.Add(pod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,12 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
corelisters "k8s.io/client-go/listers/core/v1"
|
corelisters "k8s.io/client-go/listers/core/v1"
|
||||||
"k8s.io/kubernetes/pkg/controller/endpointslice/metrics"
|
"k8s.io/kubernetes/pkg/controller/endpointslice/metrics"
|
||||||
endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint"
|
endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
// reconciler is responsible for transforming current EndpointSlice state into
|
// reconciler is responsible for transforming current EndpointSlice state into
|
||||||
@ -136,7 +138,8 @@ func (r *reconciler) reconcileByAddressType(service *corev1.Service, pods []*cor
|
|||||||
numDesiredEndpoints := 0
|
numDesiredEndpoints := 0
|
||||||
|
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
if !endpointutil.ShouldPodBeInEndpoints(pod, service.Spec.PublishNotReadyAddresses) {
|
includeTerminating := service.Spec.PublishNotReadyAddresses || utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition)
|
||||||
|
if !endpointutil.ShouldPodBeInEndpointSlice(pod, includeTerminating) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,13 +32,16 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
corelisters "k8s.io/client-go/listers/core/v1"
|
corelisters "k8s.io/client-go/listers/core/v1"
|
||||||
k8stesting "k8s.io/client-go/testing"
|
k8stesting "k8s.io/client-go/testing"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/component-base/metrics/testutil"
|
"k8s.io/component-base/metrics/testutil"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/controller/endpointslice/metrics"
|
"k8s.io/kubernetes/pkg/controller/endpointslice/metrics"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
utilpointer "k8s.io/utils/pointer"
|
utilpointer "k8s.io/utils/pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -95,7 +98,7 @@ func TestReconcile1Pod(t *testing.T) {
|
|||||||
dualStackSvc.Spec.ClusterIP = "10.0.0.10"
|
dualStackSvc.Spec.ClusterIP = "10.0.0.10"
|
||||||
dualStackSvc.Spec.ClusterIPs = []string{"10.0.0.10", "2000::1"}
|
dualStackSvc.Spec.ClusterIPs = []string{"10.0.0.10", "2000::1"}
|
||||||
|
|
||||||
pod1 := newPod(1, namespace, true, 1)
|
pod1 := newPod(1, namespace, true, 1, false)
|
||||||
pod1.Status.PodIPs = []corev1.PodIP{{IP: "1.2.3.4"}, {IP: "1234::5678:0000:0000:9abc:def0"}}
|
pod1.Status.PodIPs = []corev1.PodIP{{IP: "1.2.3.4"}, {IP: "1234::5678:0000:0000:9abc:def0"}}
|
||||||
pod1.Spec.Hostname = "example-hostname"
|
pod1.Spec.Hostname = "example-hostname"
|
||||||
node1 := &corev1.Node{
|
node1 := &corev1.Node{
|
||||||
@ -114,6 +117,7 @@ func TestReconcile1Pod(t *testing.T) {
|
|||||||
expectedEndpoint discovery.Endpoint
|
expectedEndpoint discovery.Endpoint
|
||||||
expectedLabels map[string]string
|
expectedLabels map[string]string
|
||||||
expectedEndpointPerSlice map[discovery.AddressType][]discovery.Endpoint
|
expectedEndpointPerSlice map[discovery.AddressType][]discovery.Endpoint
|
||||||
|
terminatingGateEnabled bool
|
||||||
}{
|
}{
|
||||||
"no-family-service": {
|
"no-family-service": {
|
||||||
service: noFamilyService,
|
service: noFamilyService,
|
||||||
@ -140,7 +144,6 @@ func TestReconcile1Pod(t *testing.T) {
|
|||||||
discovery.LabelServiceName: "foo",
|
discovery.LabelServiceName: "foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"ipv4": {
|
"ipv4": {
|
||||||
service: svcv4,
|
service: svcv4,
|
||||||
expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{
|
expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{
|
||||||
@ -167,6 +170,37 @@ func TestReconcile1Pod(t *testing.T) {
|
|||||||
corev1.IsHeadlessService: "",
|
corev1.IsHeadlessService: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"ipv4-with-terminating-gate-enabled": {
|
||||||
|
service: svcv4,
|
||||||
|
expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{
|
||||||
|
discovery.AddressTypeIPv4: {
|
||||||
|
{
|
||||||
|
Addresses: []string{"1.2.3.4"},
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(true),
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
Topology: map[string]string{
|
||||||
|
"kubernetes.io/hostname": "node-1",
|
||||||
|
"topology.kubernetes.io/zone": "us-central1-a",
|
||||||
|
"topology.kubernetes.io/region": "us-central1",
|
||||||
|
},
|
||||||
|
TargetRef: &corev1.ObjectReference{
|
||||||
|
Kind: "Pod",
|
||||||
|
Namespace: namespace,
|
||||||
|
Name: "pod1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedLabels: map[string]string{
|
||||||
|
discovery.LabelManagedBy: controllerName,
|
||||||
|
discovery.LabelServiceName: "foo",
|
||||||
|
corev1.IsHeadlessService: "",
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: true,
|
||||||
|
},
|
||||||
"ipv4-clusterip": {
|
"ipv4-clusterip": {
|
||||||
service: svcv4ClusterIP,
|
service: svcv4ClusterIP,
|
||||||
expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{
|
expectedEndpointPerSlice: map[discovery.AddressType][]discovery.Endpoint{
|
||||||
@ -389,6 +423,8 @@ func TestReconcile1Pod(t *testing.T) {
|
|||||||
|
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testCase.terminatingGateEnabled)()
|
||||||
|
|
||||||
client := newClientset()
|
client := newClientset()
|
||||||
setupMetrics()
|
setupMetrics()
|
||||||
triggerTime := time.Now()
|
triggerTime := time.Now()
|
||||||
@ -496,7 +532,7 @@ func TestReconcile1EndpointSlicePublishNotReadyAddresses(t *testing.T) {
|
|||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 50; i++ {
|
for i := 0; i < 50; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
pods = append(pods, newPod(i, namespace, ready, 1))
|
pods = append(pods, newPod(i, namespace, ready, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
||||||
@ -530,7 +566,7 @@ func TestReconcileManyPods(t *testing.T) {
|
|||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 250; i++ {
|
for i := 0; i < 250; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
pods = append(pods, newPod(i, namespace, ready, 1))
|
pods = append(pods, newPod(i, namespace, ready, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
||||||
@ -563,7 +599,7 @@ func TestReconcileEndpointSlicesSomePreexisting(t *testing.T) {
|
|||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 250; i++ {
|
for i := 0; i < 250; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
pods = append(pods, newPod(i, namespace, ready, 1))
|
pods = append(pods, newPod(i, namespace, ready, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
// have approximately 1/4 in first slice
|
// have approximately 1/4 in first slice
|
||||||
@ -619,7 +655,7 @@ func TestReconcileEndpointSlicesSomePreexistingWorseAllocation(t *testing.T) {
|
|||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 300; i++ {
|
for i := 0; i < 300; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
pods = append(pods, newPod(i, namespace, ready, 1))
|
pods = append(pods, newPod(i, namespace, ready, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
// have approximately 1/4 in first slice
|
// have approximately 1/4 in first slice
|
||||||
@ -665,7 +701,7 @@ func TestReconcileEndpointSlicesUpdating(t *testing.T) {
|
|||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 250; i++ {
|
for i := 0; i < 250; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
pods = append(pods, newPod(i, namespace, ready, 1))
|
pods = append(pods, newPod(i, namespace, ready, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
||||||
@ -698,7 +734,7 @@ func TestReconcileEndpointSlicesServicesLabelsUpdating(t *testing.T) {
|
|||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 250; i++ {
|
for i := 0; i < 250; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
pods = append(pods, newPod(i, namespace, ready, 1))
|
pods = append(pods, newPod(i, namespace, ready, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
||||||
@ -742,7 +778,7 @@ func TestReconcileEndpointSlicesServicesReservedLabels(t *testing.T) {
|
|||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 250; i++ {
|
for i := 0; i < 250; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
pods = append(pods, newPod(i, namespace, ready, 1))
|
pods = append(pods, newPod(i, namespace, ready, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
||||||
@ -776,7 +812,7 @@ func TestReconcileEndpointSlicesRecycling(t *testing.T) {
|
|||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 300; i++ {
|
for i := 0; i < 300; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
pods = append(pods, newPod(i, namespace, ready, 1))
|
pods = append(pods, newPod(i, namespace, ready, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate 10 existing slices with 30 pods/endpoints each
|
// generate 10 existing slices with 30 pods/endpoints each
|
||||||
@ -827,7 +863,7 @@ func TestReconcileEndpointSlicesUpdatePacking(t *testing.T) {
|
|||||||
|
|
||||||
slice1 := newEmptyEndpointSlice(1, namespace, endpointMeta, svc)
|
slice1 := newEmptyEndpointSlice(1, namespace, endpointMeta, svc)
|
||||||
for i := 0; i < 80; i++ {
|
for i := 0; i < 80; i++ {
|
||||||
pod := newPod(i, namespace, true, 1)
|
pod := newPod(i, namespace, true, 1, false)
|
||||||
slice1.Endpoints = append(slice1.Endpoints, podToEndpoint(pod, &corev1.Node{}, &svc, discovery.AddressTypeIPv4))
|
slice1.Endpoints = append(slice1.Endpoints, podToEndpoint(pod, &corev1.Node{}, &svc, discovery.AddressTypeIPv4))
|
||||||
pods = append(pods, pod)
|
pods = append(pods, pod)
|
||||||
}
|
}
|
||||||
@ -835,7 +871,7 @@ func TestReconcileEndpointSlicesUpdatePacking(t *testing.T) {
|
|||||||
|
|
||||||
slice2 := newEmptyEndpointSlice(2, namespace, endpointMeta, svc)
|
slice2 := newEmptyEndpointSlice(2, namespace, endpointMeta, svc)
|
||||||
for i := 100; i < 120; i++ {
|
for i := 100; i < 120; i++ {
|
||||||
pod := newPod(i, namespace, true, 1)
|
pod := newPod(i, namespace, true, 1, false)
|
||||||
slice2.Endpoints = append(slice2.Endpoints, podToEndpoint(pod, &corev1.Node{}, &svc, discovery.AddressTypeIPv4))
|
slice2.Endpoints = append(slice2.Endpoints, podToEndpoint(pod, &corev1.Node{}, &svc, discovery.AddressTypeIPv4))
|
||||||
pods = append(pods, pod)
|
pods = append(pods, pod)
|
||||||
}
|
}
|
||||||
@ -856,7 +892,7 @@ func TestReconcileEndpointSlicesUpdatePacking(t *testing.T) {
|
|||||||
|
|
||||||
// add a few additional endpoints - no more than could fit in either slice.
|
// add a few additional endpoints - no more than could fit in either slice.
|
||||||
for i := 200; i < 215; i++ {
|
for i := 200; i < 215; i++ {
|
||||||
pods = append(pods, newPod(i, namespace, true, 1))
|
pods = append(pods, newPod(i, namespace, true, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
||||||
@ -888,7 +924,7 @@ func TestReconcileEndpointSlicesReplaceDeprecated(t *testing.T) {
|
|||||||
|
|
||||||
slice1 := newEmptyEndpointSlice(1, namespace, endpointMeta, svc)
|
slice1 := newEmptyEndpointSlice(1, namespace, endpointMeta, svc)
|
||||||
for i := 0; i < 80; i++ {
|
for i := 0; i < 80; i++ {
|
||||||
pod := newPod(i, namespace, true, 1)
|
pod := newPod(i, namespace, true, 1, false)
|
||||||
slice1.Endpoints = append(slice1.Endpoints, podToEndpoint(pod, &corev1.Node{}, &corev1.Service{Spec: corev1.ServiceSpec{}}, discovery.AddressTypeIPv4))
|
slice1.Endpoints = append(slice1.Endpoints, podToEndpoint(pod, &corev1.Node{}, &corev1.Service{Spec: corev1.ServiceSpec{}}, discovery.AddressTypeIPv4))
|
||||||
pods = append(pods, pod)
|
pods = append(pods, pod)
|
||||||
}
|
}
|
||||||
@ -896,7 +932,7 @@ func TestReconcileEndpointSlicesReplaceDeprecated(t *testing.T) {
|
|||||||
|
|
||||||
slice2 := newEmptyEndpointSlice(2, namespace, endpointMeta, svc)
|
slice2 := newEmptyEndpointSlice(2, namespace, endpointMeta, svc)
|
||||||
for i := 100; i < 150; i++ {
|
for i := 100; i < 150; i++ {
|
||||||
pod := newPod(i, namespace, true, 1)
|
pod := newPod(i, namespace, true, 1, false)
|
||||||
slice2.Endpoints = append(slice2.Endpoints, podToEndpoint(pod, &corev1.Node{}, &corev1.Service{Spec: corev1.ServiceSpec{}}, discovery.AddressTypeIPv4))
|
slice2.Endpoints = append(slice2.Endpoints, podToEndpoint(pod, &corev1.Node{}, &corev1.Service{Spec: corev1.ServiceSpec{}}, discovery.AddressTypeIPv4))
|
||||||
pods = append(pods, pod)
|
pods = append(pods, pod)
|
||||||
}
|
}
|
||||||
@ -955,7 +991,7 @@ func TestReconcileEndpointSlicesRecreation(t *testing.T) {
|
|||||||
svc, endpointMeta := newServiceAndEndpointMeta("foo", namespace)
|
svc, endpointMeta := newServiceAndEndpointMeta("foo", namespace)
|
||||||
slice := newEmptyEndpointSlice(1, namespace, endpointMeta, svc)
|
slice := newEmptyEndpointSlice(1, namespace, endpointMeta, svc)
|
||||||
|
|
||||||
pod := newPod(1, namespace, true, 1)
|
pod := newPod(1, namespace, true, 1, false)
|
||||||
slice.Endpoints = append(slice.Endpoints, podToEndpoint(pod, &corev1.Node{}, &corev1.Service{Spec: corev1.ServiceSpec{}}, discovery.AddressTypeIPv4))
|
slice.Endpoints = append(slice.Endpoints, podToEndpoint(pod, &corev1.Node{}, &corev1.Service{Spec: corev1.ServiceSpec{}}, discovery.AddressTypeIPv4))
|
||||||
|
|
||||||
if !tc.ownedByService {
|
if !tc.ownedByService {
|
||||||
@ -1023,7 +1059,7 @@ func TestReconcileEndpointSlicesNamedPorts(t *testing.T) {
|
|||||||
for i := 0; i < 300; i++ {
|
for i := 0; i < 300; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
portOffset := i % 5
|
portOffset := i % 5
|
||||||
pod := newPod(i, namespace, ready, 1)
|
pod := newPod(i, namespace, ready, 1, false)
|
||||||
pod.Spec.Containers[0].Ports = []corev1.ContainerPort{{
|
pod.Spec.Containers[0].Ports = []corev1.ContainerPort{{
|
||||||
Name: portNameIntStr.StrVal,
|
Name: portNameIntStr.StrVal,
|
||||||
ContainerPort: int32(8080 + portOffset),
|
ContainerPort: int32(8080 + portOffset),
|
||||||
@ -1073,7 +1109,7 @@ func TestReconcileMaxEndpointsPerSlice(t *testing.T) {
|
|||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 250; i++ {
|
for i := 0; i < 250; i++ {
|
||||||
ready := !(i%3 == 0)
|
ready := !(i%3 == 0)
|
||||||
pods = append(pods, newPod(i, namespace, ready, 1))
|
pods = append(pods, newPod(i, namespace, ready, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
@ -1125,7 +1161,7 @@ func TestReconcileEndpointSlicesMetrics(t *testing.T) {
|
|||||||
// start with 20 pods
|
// start with 20 pods
|
||||||
pods := []*corev1.Pod{}
|
pods := []*corev1.Pod{}
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
pods = append(pods, newPod(i, namespace, true, 1))
|
pods = append(pods, newPod(i, namespace, true, 1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
r := newReconciler(client, []*corev1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "node-1"}}}, defaultMaxEndpointsPerSlice)
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
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/cache"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
@ -34,6 +35,7 @@ import (
|
|||||||
helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
"k8s.io/kubernetes/pkg/apis/discovery/validation"
|
"k8s.io/kubernetes/pkg/apis/discovery/validation"
|
||||||
endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint"
|
endpointutil "k8s.io/kubernetes/pkg/controller/util/endpoint"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
utilnet "k8s.io/utils/net"
|
utilnet "k8s.io/utils/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -60,7 +62,11 @@ func podToEndpoint(pod *corev1.Pod, node *corev1.Node, service *corev1.Service,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ready := service.Spec.PublishNotReadyAddresses || podutil.IsPodReady(pod)
|
serving := podutil.IsPodReady(pod)
|
||||||
|
terminating := pod.DeletionTimestamp != nil
|
||||||
|
// For compatibility reasons, "ready" should never be "true" if a pod is terminatng, unless
|
||||||
|
// publishNotReadyAddresses was set.
|
||||||
|
ready := service.Spec.PublishNotReadyAddresses || (serving && !terminating)
|
||||||
ep := discovery.Endpoint{
|
ep := discovery.Endpoint{
|
||||||
Addresses: getEndpointAddresses(pod.Status, service, addressType),
|
Addresses: getEndpointAddresses(pod.Status, service, addressType),
|
||||||
Conditions: discovery.EndpointConditions{
|
Conditions: discovery.EndpointConditions{
|
||||||
@ -76,6 +82,11 @@ func podToEndpoint(pod *corev1.Pod, node *corev1.Node, service *corev1.Service,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(features.EndpointSliceTerminatingCondition) {
|
||||||
|
ep.Conditions.Serving = &serving
|
||||||
|
ep.Conditions.Terminating = &terminating
|
||||||
|
}
|
||||||
|
|
||||||
if endpointutil.ShouldSetHostname(pod, service) {
|
if endpointutil.ShouldSetHostname(pod, service) {
|
||||||
ep.Hostname = &pod.Spec.Hostname
|
ep.Hostname = &pod.Spec.Hostname
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
@ -30,8 +31,11 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/apimachinery/pkg/util/rand"
|
"k8s.io/apimachinery/pkg/util/rand"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
k8stesting "k8s.io/client-go/testing"
|
k8stesting "k8s.io/client-go/testing"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
utilpointer "k8s.io/utils/pointer"
|
utilpointer "k8s.io/utils/pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -219,13 +223,15 @@ func TestPodToEndpoint(t *testing.T) {
|
|||||||
svcPublishNotReady, _ := newServiceAndEndpointMeta("publishnotready", ns)
|
svcPublishNotReady, _ := newServiceAndEndpointMeta("publishnotready", ns)
|
||||||
svcPublishNotReady.Spec.PublishNotReadyAddresses = true
|
svcPublishNotReady.Spec.PublishNotReadyAddresses = true
|
||||||
|
|
||||||
readyPod := newPod(1, ns, true, 1)
|
readyPod := newPod(1, ns, true, 1, false)
|
||||||
readyPodHostname := newPod(1, ns, true, 1)
|
readyTerminatingPod := newPod(1, ns, true, 1, true)
|
||||||
|
readyPodHostname := newPod(1, ns, true, 1, false)
|
||||||
readyPodHostname.Spec.Subdomain = svc.Name
|
readyPodHostname.Spec.Subdomain = svc.Name
|
||||||
readyPodHostname.Spec.Hostname = "example-hostname"
|
readyPodHostname.Spec.Hostname = "example-hostname"
|
||||||
|
|
||||||
unreadyPod := newPod(1, ns, false, 1)
|
unreadyPod := newPod(1, ns, false, 1, false)
|
||||||
multiIPPod := newPod(1, ns, true, 1)
|
unreadyTerminatingPod := newPod(1, ns, false, 1, true)
|
||||||
|
multiIPPod := newPod(1, ns, true, 1, false)
|
||||||
multiIPPod.Status.PodIPs = []v1.PodIP{{IP: "1.2.3.4"}, {IP: "1234::5678:0000:0000:9abc:def0"}}
|
multiIPPod.Status.PodIPs = []v1.PodIP{{IP: "1.2.3.4"}, {IP: "1234::5678:0000:0000:9abc:def0"}}
|
||||||
|
|
||||||
node1 := &v1.Node{
|
node1 := &v1.Node{
|
||||||
@ -245,6 +251,7 @@ func TestPodToEndpoint(t *testing.T) {
|
|||||||
svc *v1.Service
|
svc *v1.Service
|
||||||
expectedEndpoint discovery.Endpoint
|
expectedEndpoint discovery.Endpoint
|
||||||
publishNotReadyAddresses bool
|
publishNotReadyAddresses bool
|
||||||
|
terminatingGateEnabled bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Ready pod",
|
name: "Ready pod",
|
||||||
@ -381,13 +388,121 @@ func TestPodToEndpoint(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Ready pod, terminating gate enabled",
|
||||||
|
pod: readyPod,
|
||||||
|
svc: &svc,
|
||||||
|
expectedEndpoint: discovery.Endpoint{
|
||||||
|
Addresses: []string{"1.2.3.5"},
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(true),
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
TargetRef: &v1.ObjectReference{
|
||||||
|
Kind: "Pod",
|
||||||
|
Namespace: ns,
|
||||||
|
Name: readyPod.Name,
|
||||||
|
UID: readyPod.UID,
|
||||||
|
ResourceVersion: readyPod.ResourceVersion,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ready terminating pod, terminating gate disabled",
|
||||||
|
pod: readyTerminatingPod,
|
||||||
|
svc: &svc,
|
||||||
|
expectedEndpoint: discovery.Endpoint{
|
||||||
|
Addresses: []string{"1.2.3.5"},
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
TargetRef: &v1.ObjectReference{
|
||||||
|
Kind: "Pod",
|
||||||
|
Namespace: ns,
|
||||||
|
Name: readyPod.Name,
|
||||||
|
UID: readyPod.UID,
|
||||||
|
ResourceVersion: readyPod.ResourceVersion,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ready terminating pod, terminating gate enabled",
|
||||||
|
pod: readyTerminatingPod,
|
||||||
|
svc: &svc,
|
||||||
|
expectedEndpoint: discovery.Endpoint{
|
||||||
|
Addresses: []string{"1.2.3.5"},
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(false),
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
TargetRef: &v1.ObjectReference{
|
||||||
|
Kind: "Pod",
|
||||||
|
Namespace: ns,
|
||||||
|
Name: readyPod.Name,
|
||||||
|
UID: readyPod.UID,
|
||||||
|
ResourceVersion: readyPod.ResourceVersion,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Not ready terminating pod, terminating gate disabled",
|
||||||
|
pod: unreadyTerminatingPod,
|
||||||
|
svc: &svc,
|
||||||
|
expectedEndpoint: discovery.Endpoint{
|
||||||
|
Addresses: []string{"1.2.3.5"},
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
TargetRef: &v1.ObjectReference{
|
||||||
|
Kind: "Pod",
|
||||||
|
Namespace: ns,
|
||||||
|
Name: readyPod.Name,
|
||||||
|
UID: readyPod.UID,
|
||||||
|
ResourceVersion: readyPod.ResourceVersion,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Not ready terminating pod, terminating gate enabled",
|
||||||
|
pod: unreadyTerminatingPod,
|
||||||
|
svc: &svc,
|
||||||
|
expectedEndpoint: discovery.Endpoint{
|
||||||
|
Addresses: []string{"1.2.3.5"},
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Ready: utilpointer.BoolPtr(false),
|
||||||
|
Serving: utilpointer.BoolPtr(false),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Topology: map[string]string{"kubernetes.io/hostname": "node-1"},
|
||||||
|
TargetRef: &v1.ObjectReference{
|
||||||
|
Kind: "Pod",
|
||||||
|
Namespace: ns,
|
||||||
|
Name: readyPod.Name,
|
||||||
|
UID: readyPod.UID,
|
||||||
|
ResourceVersion: readyPod.ResourceVersion,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
terminatingGateEnabled: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testCase.terminatingGateEnabled)()
|
||||||
|
|
||||||
endpoint := podToEndpoint(testCase.pod, testCase.node, testCase.svc, discovery.AddressTypeIPv4)
|
endpoint := podToEndpoint(testCase.pod, testCase.node, testCase.svc, discovery.AddressTypeIPv4)
|
||||||
if !reflect.DeepEqual(testCase.expectedEndpoint, endpoint) {
|
if !reflect.DeepEqual(testCase.expectedEndpoint, endpoint) {
|
||||||
t.Errorf("Expected endpoint: %v, got: %v", testCase.expectedEndpoint, endpoint)
|
t.Errorf("Expected endpoint: %+v, got: %+v", testCase.expectedEndpoint, endpoint)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -811,18 +926,26 @@ func TestSetEndpointSliceLabels(t *testing.T) {
|
|||||||
|
|
||||||
// Test helpers
|
// Test helpers
|
||||||
|
|
||||||
func newPod(n int, namespace string, ready bool, nPorts int) *v1.Pod {
|
func newPod(n int, namespace string, ready bool, nPorts int, terminating bool) *v1.Pod {
|
||||||
status := v1.ConditionTrue
|
status := v1.ConditionTrue
|
||||||
if !ready {
|
if !ready {
|
||||||
status = v1.ConditionFalse
|
status = v1.ConditionFalse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var deletionTimestamp *metav1.Time
|
||||||
|
if terminating {
|
||||||
|
deletionTimestamp = &metav1.Time{
|
||||||
|
Time: time.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p := &v1.Pod{
|
p := &v1.Pod{
|
||||||
TypeMeta: metav1.TypeMeta{APIVersion: "v1"},
|
TypeMeta: metav1.TypeMeta{APIVersion: "v1"},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Name: fmt.Sprintf("pod%d", n),
|
Name: fmt.Sprintf("pod%d", n),
|
||||||
Labels: map[string]string{"foo": "bar"},
|
Labels: map[string]string{"foo": "bar"},
|
||||||
|
DeletionTimestamp: deletionTimestamp,
|
||||||
},
|
},
|
||||||
Spec: v1.PodSpec{
|
Spec: v1.PodSpec{
|
||||||
Containers: []v1.Container{{
|
Containers: []v1.Container{{
|
||||||
|
@ -122,14 +122,14 @@ func DeepHashObjectToString(objectToWrite interface{}) string {
|
|||||||
return hex.EncodeToString(hasher.Sum(nil)[0:])
|
return hex.EncodeToString(hasher.Sum(nil)[0:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShouldPodBeInEndpoints returns true if a specified pod should be in an
|
// ShouldPodBeInEndpointSlice returns true if a specified pod should be in an EndpointSlice object.
|
||||||
// endpoints object. Terminating pods are only included if publishNotReady is true.
|
// Terminating pods are only included if includeTerminating is true
|
||||||
func ShouldPodBeInEndpoints(pod *v1.Pod, publishNotReady bool) bool {
|
func ShouldPodBeInEndpointSlice(pod *v1.Pod, includeTerminating bool) bool {
|
||||||
if len(pod.Status.PodIP) == 0 && len(pod.Status.PodIPs) == 0 {
|
if len(pod.Status.PodIP) == 0 && len(pod.Status.PodIPs) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !publishNotReady && pod.DeletionTimestamp != nil {
|
if !includeTerminating && pod.DeletionTimestamp != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,12 +100,12 @@ func TestDetermineNeededServiceUpdates(t *testing.T) {
|
|||||||
// There are 3*5 possibilities(3 types of RestartPolicy by 5 types of PodPhase).
|
// There are 3*5 possibilities(3 types of RestartPolicy by 5 types of PodPhase).
|
||||||
// Not listing them all here. Just listing all of the 3 false cases and 3 of the
|
// Not listing them all here. Just listing all of the 3 false cases and 3 of the
|
||||||
// 12 true cases.
|
// 12 true cases.
|
||||||
func TestShouldPodBeInEndpoints(t *testing.T) {
|
func TestShouldPodBeInEndpointSlice(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
pod *v1.Pod
|
pod *v1.Pod
|
||||||
publishNotReady bool
|
|
||||||
expected bool
|
expected bool
|
||||||
|
includeTerminating bool
|
||||||
}{
|
}{
|
||||||
// Pod should not be in endpoints:
|
// Pod should not be in endpoints:
|
||||||
{
|
{
|
||||||
@ -162,7 +162,7 @@ func TestShouldPodBeInEndpoints(t *testing.T) {
|
|||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Terminating Pod",
|
name: "Terminating Pod with includeTerminating=false",
|
||||||
pod: &v1.Pod{
|
pod: &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
DeletionTimestamp: &metav1.Time{
|
DeletionTimestamp: &metav1.Time{
|
||||||
@ -175,7 +175,6 @@ func TestShouldPodBeInEndpoints(t *testing.T) {
|
|||||||
PodIP: "1.2.3.4",
|
PodIP: "1.2.3.4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
publishNotReady: false,
|
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
// Pod should be in endpoints:
|
// Pod should be in endpoints:
|
||||||
@ -245,7 +244,7 @@ func TestShouldPodBeInEndpoints(t *testing.T) {
|
|||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Terminating Pod with publish not ready",
|
name: "Terminating Pod with includeTerminating=true",
|
||||||
pod: &v1.Pod{
|
pod: &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
DeletionTimestamp: &metav1.Time{
|
DeletionTimestamp: &metav1.Time{
|
||||||
@ -258,14 +257,14 @@ func TestShouldPodBeInEndpoints(t *testing.T) {
|
|||||||
PodIP: "1.2.3.4",
|
PodIP: "1.2.3.4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
publishNotReady: true,
|
|
||||||
expected: true,
|
expected: true,
|
||||||
|
includeTerminating: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
result := ShouldPodBeInEndpoints(test.pod, test.publishNotReady)
|
result := ShouldPodBeInEndpointSlice(test.pod, test.includeTerminating)
|
||||||
if result != test.expected {
|
if result != test.expected {
|
||||||
t.Errorf("expected: %t, got: %t", test.expected, result)
|
t.Errorf("expected: %t, got: %t", test.expected, result)
|
||||||
}
|
}
|
||||||
|
@ -651,6 +651,12 @@ const (
|
|||||||
// Allows kube-controller-manager to publish kube-root-ca.crt configmap to
|
// Allows kube-controller-manager to publish kube-root-ca.crt configmap to
|
||||||
// every namespace. This feature is a prerequisite of BoundServiceAccountTokenVolume.
|
// every namespace. This feature is a prerequisite of BoundServiceAccountTokenVolume.
|
||||||
RootCAConfigMap featuregate.Feature = "RootCAConfigMap"
|
RootCAConfigMap featuregate.Feature = "RootCAConfigMap"
|
||||||
|
|
||||||
|
// owner: @andrewsykim
|
||||||
|
// alpha: v1.20
|
||||||
|
//
|
||||||
|
// Enable Terminating condition in Endpoint Slices.
|
||||||
|
EndpointSliceTerminatingCondition featuregate.Feature = "EndpointSliceTerminatingCondition"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -731,6 +737,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
IPv6DualStack: {Default: false, PreRelease: featuregate.Alpha},
|
IPv6DualStack: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
EndpointSlice: {Default: true, PreRelease: featuregate.Beta},
|
EndpointSlice: {Default: true, PreRelease: featuregate.Beta},
|
||||||
EndpointSliceProxying: {Default: true, PreRelease: featuregate.Beta},
|
EndpointSliceProxying: {Default: true, PreRelease: featuregate.Beta},
|
||||||
|
EndpointSliceTerminatingCondition: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
WindowsEndpointSliceProxying: {Default: false, PreRelease: featuregate.Alpha},
|
WindowsEndpointSliceProxying: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
EvenPodsSpread: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.21
|
EvenPodsSpread: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.21
|
||||||
StartupProbe: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.21
|
StartupProbe: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.21
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
@ -12,11 +12,13 @@ go_library(
|
|||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/discovery:go_default_library",
|
"//pkg/apis/discovery:go_default_library",
|
||||||
"//pkg/apis/discovery/validation:go_default_library",
|
"//pkg/apis/discovery/validation:go_default_library",
|
||||||
|
"//pkg/features:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,3 +38,17 @@ filegroup(
|
|||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "go_default_test",
|
||||||
|
srcs = ["strategy_test.go"],
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
deps = [
|
||||||
|
"//pkg/apis/discovery:go_default_library",
|
||||||
|
"//pkg/features:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
|
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/pointer:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@ -24,9 +24,11 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
"k8s.io/apiserver/pkg/storage/names"
|
"k8s.io/apiserver/pkg/storage/names"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
"k8s.io/kubernetes/pkg/apis/discovery"
|
"k8s.io/kubernetes/pkg/apis/discovery"
|
||||||
"k8s.io/kubernetes/pkg/apis/discovery/validation"
|
"k8s.io/kubernetes/pkg/apis/discovery/validation"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
// endpointSliceStrategy implements verification logic for Replication.
|
// endpointSliceStrategy implements verification logic for Replication.
|
||||||
@ -47,6 +49,8 @@ func (endpointSliceStrategy) NamespaceScoped() bool {
|
|||||||
func (endpointSliceStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
func (endpointSliceStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||||
endpointSlice := obj.(*discovery.EndpointSlice)
|
endpointSlice := obj.(*discovery.EndpointSlice)
|
||||||
endpointSlice.Generation = 1
|
endpointSlice.Generation = 1
|
||||||
|
|
||||||
|
dropDisabledConditionsOnCreate(endpointSlice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||||
@ -67,6 +71,8 @@ func (endpointSliceStrategy) PrepareForUpdate(ctx context.Context, obj, old runt
|
|||||||
|
|
||||||
newEPS.ObjectMeta = ogNewMeta
|
newEPS.ObjectMeta = ogNewMeta
|
||||||
oldEPS.ObjectMeta = ogOldMeta
|
oldEPS.ObjectMeta = ogOldMeta
|
||||||
|
|
||||||
|
dropDisabledConditionsOnUpdate(oldEPS, newEPS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates a new EndpointSlice.
|
// Validate validates a new EndpointSlice.
|
||||||
@ -96,3 +102,42 @@ func (endpointSliceStrategy) ValidateUpdate(ctx context.Context, new, old runtim
|
|||||||
func (endpointSliceStrategy) AllowUnconditionalUpdate() bool {
|
func (endpointSliceStrategy) AllowUnconditionalUpdate() bool {
|
||||||
return true
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dropConditions {
|
||||||
|
for i := range newEPS.Endpoints {
|
||||||
|
newEPS.Endpoints[i].Conditions.Serving = nil
|
||||||
|
newEPS.Endpoints[i].Conditions.Terminating = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
448
pkg/registry/discovery/endpointslice/strategy_test.go
Normal file
448
pkg/registry/discovery/endpointslice/strategy_test.go
Normal file
@ -0,0 +1,448 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package endpointslice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/discovery"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
|
utilpointer "k8s.io/utils/pointer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_dropConditionsOnCreate(t *testing.T) {
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
terminatingGateEnabled bool
|
||||||
|
eps *discovery.EndpointSlice
|
||||||
|
expectedEPS *discovery.EndpointSlice
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "gate enabled, field should be allowed",
|
||||||
|
terminatingGateEnabled: true,
|
||||||
|
eps: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gate disabled, field should be set to nil",
|
||||||
|
terminatingGateEnabled: false,
|
||||||
|
eps: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testcase := range testcases {
|
||||||
|
t.Run(testcase.name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testcase.terminatingGateEnabled)()
|
||||||
|
|
||||||
|
dropDisabledConditionsOnCreate(testcase.eps)
|
||||||
|
if !apiequality.Semantic.DeepEqual(testcase.eps, testcase.expectedEPS) {
|
||||||
|
t.Logf("actual endpointslice: %v", testcase.eps)
|
||||||
|
t.Logf("expected endpointslice: %v", testcase.expectedEPS)
|
||||||
|
t.Errorf("unexpected EndpointSlice on create API strategy")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_dropTerminatingConditionOnUpdate(t *testing.T) {
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
terminatingGateEnabled bool
|
||||||
|
oldEPS *discovery.EndpointSlice
|
||||||
|
newEPS *discovery.EndpointSlice
|
||||||
|
expectedEPS *discovery.EndpointSlice
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "gate enabled, field should be allowed",
|
||||||
|
terminatingGateEnabled: true,
|
||||||
|
oldEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gate disabled, and not set on existing EPS",
|
||||||
|
terminatingGateEnabled: false,
|
||||||
|
oldEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gate disabled, and set on existing EPS",
|
||||||
|
terminatingGateEnabled: false,
|
||||||
|
oldEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: nil,
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gate disabled, and set on existing EPS with new values",
|
||||||
|
terminatingGateEnabled: false,
|
||||||
|
oldEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(false),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Terminating: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(false),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedEPS: &discovery.EndpointSlice{
|
||||||
|
Endpoints: []discovery.Endpoint{
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(true),
|
||||||
|
Terminating: utilpointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Serving: utilpointer.BoolPtr(false),
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: discovery.EndpointConditions{
|
||||||
|
Terminating: utilpointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testcase := range testcases {
|
||||||
|
t.Run(testcase.name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EndpointSliceTerminatingCondition, testcase.terminatingGateEnabled)()
|
||||||
|
|
||||||
|
dropDisabledConditionsOnUpdate(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)
|
||||||
|
t.Errorf("unexpected EndpointSlice from update API strategy")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -200,54 +200,57 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_772f83c5b34e07a5 = []byte{
|
var fileDescriptor_772f83c5b34e07a5 = []byte{
|
||||||
// 746 bytes of a gzipped FileDescriptorProto
|
// 787 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x4b, 0x6f, 0xd3, 0x4a,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x4d, 0x8f, 0xe3, 0x44,
|
||||||
0x14, 0x8e, 0x9b, 0x5a, 0xb2, 0x27, 0x8d, 0x6e, 0x3b, 0xba, 0x8b, 0x28, 0xf7, 0x5e, 0x3b, 0xca,
|
0x10, 0x8d, 0x27, 0x13, 0xad, 0xdd, 0xd9, 0x11, 0xbb, 0x2d, 0x0e, 0xd1, 0x00, 0xf6, 0x28, 0x08,
|
||||||
0x5d, 0x10, 0xa9, 0x30, 0x26, 0x15, 0x45, 0x15, 0xac, 0x6a, 0x28, 0x0f, 0x89, 0x47, 0x18, 0xba,
|
0x11, 0x69, 0xa0, 0x4d, 0x46, 0x80, 0x56, 0x70, 0x1a, 0xc3, 0xf2, 0x21, 0xf1, 0x31, 0xf4, 0xce,
|
||||||
0x40, 0x88, 0x05, 0x13, 0x7b, 0xea, 0x98, 0x24, 0x1e, 0xcb, 0x9e, 0x44, 0xca, 0x8e, 0x9f, 0xc0,
|
0x01, 0x21, 0x0e, 0xf4, 0xd8, 0xb5, 0x8e, 0x49, 0xec, 0xb6, 0xba, 0x3b, 0x91, 0x72, 0xe3, 0x1f,
|
||||||
0x0f, 0x62, 0x89, 0x50, 0x97, 0x5d, 0x76, 0x65, 0x51, 0xf7, 0x5f, 0x74, 0x85, 0x66, 0xfc, 0x4a,
|
0xc0, 0x0f, 0xe2, 0x88, 0xd0, 0x1c, 0xf7, 0xb8, 0x27, 0x8b, 0xf1, 0xfe, 0x8b, 0x39, 0xa1, 0x6e,
|
||||||
0x09, 0x8f, 0xec, 0x66, 0xbe, 0x39, 0xdf, 0x77, 0xce, 0xf9, 0xe6, 0x1c, 0xf0, 0x68, 0x7c, 0x10,
|
0x7f, 0x0e, 0x01, 0x36, 0x37, 0xf7, 0xab, 0x7a, 0xaf, 0xea, 0x95, 0xab, 0xd0, 0x67, 0xcb, 0x47,
|
||||||
0x23, 0x9f, 0x59, 0xe3, 0xd9, 0x90, 0x46, 0x01, 0xe5, 0x34, 0xb6, 0xe6, 0x34, 0x70, 0x59, 0x64,
|
0x92, 0x24, 0xdc, 0x5f, 0xae, 0xaf, 0x40, 0x64, 0xa0, 0x40, 0xfa, 0x1b, 0xc8, 0x22, 0x2e, 0xfc,
|
||||||
0xe5, 0x0f, 0x24, 0xf4, 0x2d, 0xd7, 0x8f, 0x1d, 0x36, 0xa7, 0xd1, 0xc2, 0x9a, 0xf7, 0xc9, 0x24,
|
0x3a, 0xc0, 0xf2, 0xc4, 0x8f, 0x12, 0x19, 0xf2, 0x0d, 0x88, 0xad, 0xbf, 0x99, 0xb3, 0x55, 0xbe,
|
||||||
0x1c, 0x91, 0xbe, 0xe5, 0xd1, 0x80, 0x46, 0x84, 0x53, 0x17, 0x85, 0x11, 0xe3, 0x0c, 0xfe, 0x97,
|
0x60, 0x73, 0x3f, 0x86, 0x0c, 0x04, 0x53, 0x10, 0x91, 0x5c, 0x70, 0xc5, 0xf1, 0x1b, 0x55, 0x3a,
|
||||||
0x85, 0x23, 0x12, 0xfa, 0xa8, 0x0c, 0x47, 0x45, 0x78, 0xfb, 0x96, 0xe7, 0xf3, 0xd1, 0x6c, 0x88,
|
0x61, 0x79, 0x42, 0xda, 0x74, 0xd2, 0xa4, 0x1f, 0xbf, 0x1b, 0x27, 0x6a, 0xb1, 0xbe, 0x22, 0x21,
|
||||||
0x1c, 0x36, 0xb5, 0x3c, 0xe6, 0x31, 0x4b, 0xb2, 0x86, 0xb3, 0x13, 0x79, 0x93, 0x17, 0x79, 0xca,
|
0x4f, 0xfd, 0x98, 0xc7, 0xdc, 0x37, 0xac, 0xab, 0xf5, 0x53, 0xf3, 0x32, 0x0f, 0xf3, 0x55, 0xa9,
|
||||||
0xd4, 0xda, 0xdd, 0xa5, 0xe4, 0x0e, 0x8b, 0xa8, 0x35, 0x5f, 0xc9, 0xd8, 0xbe, 0x53, 0xc5, 0x4c,
|
0x1d, 0x4f, 0x7b, 0xc5, 0x43, 0x2e, 0xc0, 0xdf, 0xec, 0x54, 0x3c, 0x7e, 0xbf, 0xcb, 0x49, 0x59,
|
||||||
0x89, 0x33, 0xf2, 0x03, 0x51, 0x5f, 0x38, 0xf6, 0x04, 0x10, 0x5b, 0x53, 0xca, 0xc9, 0xcf, 0x58,
|
0xb8, 0x48, 0x32, 0xdd, 0x5f, 0xbe, 0x8c, 0x35, 0x20, 0xfd, 0x14, 0x14, 0xfb, 0x37, 0x96, 0xff,
|
||||||
0xd6, 0xaf, 0x58, 0xd1, 0x2c, 0xe0, 0xfe, 0x94, 0xae, 0x10, 0xee, 0xfe, 0x89, 0x10, 0x3b, 0x23,
|
0x5f, 0x2c, 0xb1, 0xce, 0x54, 0x92, 0xc2, 0x0e, 0xe1, 0xc3, 0x97, 0x11, 0x64, 0xb8, 0x80, 0x94,
|
||||||
0x3a, 0x25, 0x3f, 0xf2, 0xba, 0x9f, 0xeb, 0x40, 0x3b, 0x0a, 0xdc, 0x90, 0xf9, 0x01, 0x87, 0xbb,
|
0xfd, 0x93, 0x37, 0xfd, 0x7d, 0x88, 0xec, 0xc7, 0x59, 0x94, 0xf3, 0x24, 0x53, 0xf8, 0x14, 0x39,
|
||||||
0x40, 0x27, 0xae, 0x1b, 0xd1, 0x38, 0xa6, 0x71, 0x4b, 0xe9, 0xd4, 0x7b, 0xba, 0xdd, 0x4c, 0x13,
|
0x2c, 0x8a, 0x04, 0x48, 0x09, 0x72, 0x62, 0x9d, 0x0c, 0x67, 0x4e, 0x70, 0x54, 0x16, 0x9e, 0x73,
|
||||||
0x53, 0x3f, 0x2c, 0x40, 0x5c, 0xbd, 0x43, 0x0a, 0x80, 0xc3, 0x02, 0xd7, 0xe7, 0x3e, 0x0b, 0xe2,
|
0xde, 0x80, 0xb4, 0x8b, 0x63, 0x40, 0x28, 0xe4, 0x59, 0x94, 0xa8, 0x84, 0x67, 0x72, 0x72, 0x70,
|
||||||
0xd6, 0x46, 0x47, 0xe9, 0x35, 0xf6, 0xfa, 0xe8, 0xb7, 0xfe, 0xa2, 0x22, 0xd3, 0x83, 0x92, 0x68,
|
0x62, 0xcd, 0xc6, 0x67, 0x73, 0xf2, 0xbf, 0xf3, 0x25, 0x4d, 0xa5, 0x4f, 0x5a, 0x62, 0x80, 0xaf,
|
||||||
0xc3, 0xd3, 0xc4, 0xac, 0xa5, 0x89, 0x09, 0x2a, 0x0c, 0x2f, 0x09, 0xc3, 0x1e, 0xd0, 0x46, 0x2c,
|
0x0b, 0x6f, 0x50, 0x16, 0x1e, 0xea, 0x30, 0xda, 0x13, 0xc6, 0x33, 0x64, 0x2f, 0xb8, 0x54, 0x19,
|
||||||
0xe6, 0x01, 0x99, 0xd2, 0x56, 0xbd, 0xa3, 0xf4, 0x74, 0x7b, 0x2b, 0x4d, 0x4c, 0xed, 0x49, 0x8e,
|
0x4b, 0x61, 0x32, 0x3c, 0xb1, 0x66, 0x4e, 0x70, 0xbf, 0x2c, 0x3c, 0xfb, 0x8b, 0x1a, 0xa3, 0x6d,
|
||||||
0xe1, 0xf2, 0x15, 0x0e, 0x80, 0xce, 0x49, 0xe4, 0x51, 0x8e, 0xe9, 0x49, 0x6b, 0x53, 0xd6, 0xf3,
|
0x14, 0x5f, 0x20, 0x47, 0x31, 0x11, 0x83, 0xa2, 0xf0, 0x74, 0x72, 0x68, 0xfa, 0x79, 0xb3, 0xdf,
|
||||||
0xff, 0x72, 0x3d, 0xe2, 0x87, 0xd0, 0xbc, 0x8f, 0x5e, 0x0e, 0x3f, 0x50, 0x47, 0x04, 0xd1, 0x88,
|
0x8f, 0xfe, 0x43, 0x64, 0x33, 0x27, 0xdf, 0x5e, 0xfd, 0x0c, 0xa1, 0x4e, 0x02, 0x01, 0x59, 0x08,
|
||||||
0x06, 0x0e, 0xcd, 0x5a, 0x3c, 0x2e, 0x98, 0xb8, 0x12, 0x81, 0x0e, 0xd0, 0x38, 0x0b, 0xd9, 0x84,
|
0x95, 0xc5, 0xcb, 0x86, 0x49, 0x3b, 0x11, 0x1c, 0x22, 0x5b, 0xf1, 0x9c, 0xaf, 0x78, 0xbc, 0x9d,
|
||||||
0x79, 0x8b, 0x96, 0xda, 0xa9, 0xf7, 0x1a, 0x7b, 0xfb, 0x6b, 0x36, 0x88, 0x8e, 0x73, 0xde, 0x51,
|
0x8c, 0x4e, 0x86, 0xb3, 0xf1, 0xd9, 0x07, 0x7b, 0x1a, 0x24, 0x97, 0x35, 0xef, 0x71, 0xa6, 0xc4,
|
||||||
0xc0, 0xa3, 0x85, 0xbd, 0x9d, 0x37, 0xa9, 0x15, 0x30, 0x2e, 0x85, 0xdb, 0xf7, 0x41, 0xf3, 0x5a,
|
0x36, 0x78, 0x50, 0x9b, 0xb4, 0x1b, 0x98, 0xb6, 0xc2, 0xc7, 0x1f, 0xa3, 0xa3, 0x3b, 0xc9, 0xf8,
|
||||||
0x30, 0xdc, 0x06, 0xf5, 0x31, 0x5d, 0xb4, 0x14, 0xd1, 0x2c, 0x16, 0x47, 0xf8, 0x37, 0x50, 0xe7,
|
0x01, 0x1a, 0x2e, 0x61, 0x3b, 0xb1, 0xb4, 0x59, 0xaa, 0x3f, 0xf1, 0xab, 0x68, 0xb4, 0x61, 0xab,
|
||||||
0x64, 0x32, 0xa3, 0xd2, 0x65, 0x1d, 0x67, 0x97, 0x7b, 0x1b, 0x07, 0x4a, 0x77, 0x1f, 0xc0, 0x55,
|
0x35, 0x98, 0x29, 0x3b, 0xb4, 0x7a, 0x7c, 0x74, 0xf0, 0xc8, 0x9a, 0xfe, 0x6a, 0x21, 0xbc, 0x3b,
|
||||||
0x4f, 0xa1, 0x09, 0xd4, 0x88, 0x12, 0x37, 0xd3, 0xd0, 0x6c, 0x3d, 0x4d, 0x4c, 0x15, 0x0b, 0x00,
|
0x54, 0xec, 0xa1, 0x91, 0x00, 0x16, 0x55, 0x22, 0x76, 0xe0, 0x94, 0x85, 0x37, 0xa2, 0x1a, 0xa0,
|
||||||
0x67, 0x78, 0xf7, 0xab, 0x02, 0xb6, 0x0a, 0xde, 0x80, 0x45, 0x1c, 0xfe, 0x0b, 0x36, 0xa5, 0xc3,
|
0x15, 0x8e, 0xdf, 0x42, 0xf7, 0x24, 0x88, 0x4d, 0x92, 0xc5, 0x46, 0xd3, 0x0e, 0xc6, 0x65, 0xe1,
|
||||||
0x32, 0xa9, 0xad, 0xa5, 0x89, 0xb9, 0xf9, 0x42, 0xb8, 0x2b, 0x51, 0xf8, 0x18, 0x68, 0x72, 0x5a,
|
0xdd, 0x7b, 0x52, 0x41, 0xb4, 0x89, 0xe1, 0x39, 0x1a, 0x2b, 0x10, 0x69, 0x92, 0x31, 0xa5, 0x53,
|
||||||
0x1c, 0x36, 0xc9, 0x4a, 0xb0, 0x77, 0x45, 0x33, 0x83, 0x1c, 0xbb, 0x4a, 0xcc, 0x7f, 0x56, 0x37,
|
0x87, 0x26, 0xf5, 0x95, 0xb2, 0xf0, 0xc6, 0x97, 0x1d, 0x4c, 0xfb, 0x39, 0xd3, 0x3f, 0x2d, 0x74,
|
||||||
0x01, 0x15, 0xcf, 0xb8, 0x24, 0x8b, 0x34, 0x21, 0x8b, 0xb8, 0xfc, 0x48, 0x35, 0x4b, 0x23, 0xd2,
|
0xbf, 0xe9, 0xe8, 0x82, 0x0b, 0x85, 0x5f, 0x47, 0x87, 0xe6, 0xe7, 0x19, 0x3f, 0x81, 0x5d, 0x16,
|
||||||
0x63, 0x89, 0xc2, 0x3e, 0x68, 0x90, 0x30, 0x2c, 0x68, 0xf2, 0x0b, 0x75, 0xfb, 0xaf, 0x34, 0x31,
|
0xde, 0xe1, 0x37, 0xfa, 0xc7, 0x19, 0x14, 0x7f, 0x8e, 0x6c, 0xb3, 0x88, 0x21, 0x5f, 0x55, 0xee,
|
||||||
0x1b, 0x87, 0x15, 0x8c, 0x97, 0x63, 0xba, 0x97, 0x1b, 0xa0, 0x59, 0x34, 0xf2, 0x7a, 0xe2, 0x3b,
|
0x82, 0x53, 0x3d, 0xa7, 0x8b, 0x1a, 0xbb, 0x2d, 0xbc, 0xd7, 0x76, 0x8f, 0x8c, 0x34, 0x61, 0xda,
|
||||||
0x14, 0xbe, 0x07, 0x9a, 0x58, 0x2a, 0x97, 0x70, 0x22, 0xbb, 0x69, 0xec, 0xdd, 0x5e, 0xfa, 0xb3,
|
0x92, 0x75, 0x99, 0x9c, 0x0b, 0x65, 0x7a, 0x1c, 0x55, 0x65, 0x74, 0x79, 0x6a, 0x50, 0x6d, 0x84,
|
||||||
0x72, 0x37, 0x50, 0x38, 0xf6, 0x04, 0x10, 0x23, 0x11, 0x5d, 0x8d, 0xc5, 0x73, 0xca, 0x49, 0x35,
|
0xe5, 0x79, 0x43, 0x33, 0xdb, 0xe1, 0x54, 0x46, 0xce, 0x3b, 0x98, 0xf6, 0x73, 0xa6, 0x2f, 0x0e,
|
||||||
0x93, 0x15, 0x86, 0x4b, 0x55, 0xf8, 0x10, 0x34, 0xf2, 0x2d, 0x38, 0x5e, 0x84, 0x34, 0x2f, 0xb3,
|
0xd0, 0x51, 0x63, 0xe4, 0xc9, 0x2a, 0x09, 0x01, 0xff, 0x84, 0x6c, 0x7d, 0xaf, 0x11, 0x53, 0xcc,
|
||||||
0x9b, 0x53, 0x1a, 0x87, 0xd5, 0xd3, 0xd5, 0xf5, 0x2b, 0x5e, 0xa6, 0xc1, 0x37, 0x40, 0xa7, 0x79,
|
0xb8, 0x19, 0x9f, 0xbd, 0xd7, 0x5b, 0x87, 0xf6, 0xec, 0x48, 0xbe, 0x8c, 0x35, 0x20, 0x89, 0xce,
|
||||||
0xe1, 0x62, 0x7b, 0xc4, 0x70, 0xdd, 0x58, 0x73, 0xb8, 0xec, 0x9d, 0x3c, 0x99, 0x5e, 0x20, 0x31,
|
0xee, 0x36, 0xee, 0x6b, 0x50, 0xac, 0x5b, 0xf7, 0x0e, 0xa3, 0xad, 0x2a, 0xfe, 0x14, 0x8d, 0xeb,
|
||||||
0xae, 0xc4, 0xe0, 0x00, 0xa8, 0xc2, 0xce, 0xb8, 0x55, 0x97, 0xaa, 0xbb, 0x6b, 0xaa, 0x8a, 0x8f,
|
0x03, 0xbb, 0xdc, 0xe6, 0x50, 0xb7, 0x39, 0xad, 0x29, 0xe3, 0xf3, 0x2e, 0x74, 0x7b, 0xf7, 0x49,
|
||||||
0xb0, 0x9b, 0xb9, 0xb2, 0x2a, 0x6e, 0x31, 0xce, 0x84, 0xba, 0x5f, 0x14, 0xb0, 0x73, 0xcd, 0xe5,
|
0xfb, 0x34, 0xfc, 0x3d, 0x72, 0xa0, 0x6e, 0x5c, 0x1f, 0xa6, 0xde, 0xdb, 0xb7, 0xf7, 0xdc, 0xdb,
|
||||||
0x67, 0x7e, 0xcc, 0xe1, 0xbb, 0x15, 0xa7, 0xd1, 0x7a, 0x4e, 0x0b, 0xb6, 0xf4, 0xb9, 0x5c, 0x8b,
|
0xe0, 0x61, 0x5d, 0xcc, 0x69, 0x10, 0x49, 0x3b, 0x31, 0x7c, 0x81, 0x46, 0x7a, 0x9c, 0x72, 0x32,
|
||||||
0x02, 0x59, 0x72, 0xf9, 0x15, 0x50, 0x7d, 0x4e, 0xa7, 0x85, 0x37, 0x37, 0xd7, 0xec, 0x42, 0x96,
|
0x34, 0xaa, 0xa7, 0x7b, 0xaa, 0xea, 0x1f, 0x11, 0x1c, 0xd5, 0xca, 0x23, 0xfd, 0x92, 0xb4, 0x12,
|
||||||
0x57, 0xb5, 0xf1, 0x54, 0x48, 0xe0, 0x4c, 0xc9, 0x46, 0xa7, 0x17, 0x46, 0xed, 0xec, 0xc2, 0xa8,
|
0x9a, 0xfe, 0x61, 0xa1, 0x87, 0x77, 0xa6, 0xfc, 0x55, 0x22, 0x15, 0xfe, 0x71, 0x67, 0xd2, 0x64,
|
||||||
0x9d, 0x5f, 0x18, 0xb5, 0x8f, 0xa9, 0xa1, 0x9c, 0xa6, 0x86, 0x72, 0x96, 0x1a, 0xca, 0x79, 0x6a,
|
0xbf, 0x49, 0x6b, 0xb6, 0x99, 0x73, 0x7b, 0x71, 0x0d, 0xd2, 0x9b, 0xf2, 0x77, 0x68, 0x94, 0x28,
|
||||||
0x28, 0xdf, 0x52, 0x43, 0xf9, 0x74, 0x69, 0xd4, 0xde, 0x6a, 0x85, 0xe6, 0xf7, 0x00, 0x00, 0x00,
|
0x48, 0x9b, 0xd9, 0xbc, 0xb3, 0xa7, 0x0b, 0xd3, 0x5e, 0x67, 0xe3, 0x4b, 0x2d, 0x41, 0x2b, 0xa5,
|
||||||
0xff, 0xff, 0x65, 0x85, 0x5a, 0x9b, 0x75, 0x06, 0x00, 0x00,
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Endpoint) Marshal() (dAtA []byte, err error) {
|
func (m *Endpoint) Marshal() (dAtA []byte, err error) {
|
||||||
@ -355,6 +358,26 @@ func (m *EndpointConditions) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
_ = l
|
_ = l
|
||||||
|
if m.Terminating != nil {
|
||||||
|
i--
|
||||||
|
if *m.Terminating {
|
||||||
|
dAtA[i] = 1
|
||||||
|
} else {
|
||||||
|
dAtA[i] = 0
|
||||||
|
}
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x18
|
||||||
|
}
|
||||||
|
if m.Serving != nil {
|
||||||
|
i--
|
||||||
|
if *m.Serving {
|
||||||
|
dAtA[i] = 1
|
||||||
|
} else {
|
||||||
|
dAtA[i] = 0
|
||||||
|
}
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x10
|
||||||
|
}
|
||||||
if m.Ready != nil {
|
if m.Ready != nil {
|
||||||
i--
|
i--
|
||||||
if *m.Ready {
|
if *m.Ready {
|
||||||
@ -583,6 +606,12 @@ func (m *EndpointConditions) Size() (n int) {
|
|||||||
if m.Ready != nil {
|
if m.Ready != nil {
|
||||||
n += 2
|
n += 2
|
||||||
}
|
}
|
||||||
|
if m.Serving != nil {
|
||||||
|
n += 2
|
||||||
|
}
|
||||||
|
if m.Terminating != nil {
|
||||||
|
n += 2
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,6 +717,8 @@ func (this *EndpointConditions) String() string {
|
|||||||
}
|
}
|
||||||
s := strings.Join([]string{`&EndpointConditions{`,
|
s := strings.Join([]string{`&EndpointConditions{`,
|
||||||
`Ready:` + valueToStringGenerated(this.Ready) + `,`,
|
`Ready:` + valueToStringGenerated(this.Ready) + `,`,
|
||||||
|
`Serving:` + valueToStringGenerated(this.Serving) + `,`,
|
||||||
|
`Terminating:` + valueToStringGenerated(this.Terminating) + `,`,
|
||||||
`}`,
|
`}`,
|
||||||
}, "")
|
}, "")
|
||||||
return s
|
return s
|
||||||
@ -1116,6 +1147,48 @@ func (m *EndpointConditions) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
b := bool(v != 0)
|
b := bool(v != 0)
|
||||||
m.Ready = &b
|
m.Ready = &b
|
||||||
|
case 2:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Serving", wireType)
|
||||||
|
}
|
||||||
|
var v int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowGenerated
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
v |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b := bool(v != 0)
|
||||||
|
m.Serving = &b
|
||||||
|
case 3:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Terminating", wireType)
|
||||||
|
}
|
||||||
|
var v int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowGenerated
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
v |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b := bool(v != 0)
|
||||||
|
m.Terminating = &b
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||||
|
@ -76,9 +76,22 @@ message EndpointConditions {
|
|||||||
// ready indicates that this endpoint is prepared to receive traffic,
|
// ready indicates that this endpoint is prepared to receive traffic,
|
||||||
// according to whatever system is managing the endpoint. A nil value
|
// according to whatever system is managing the endpoint. A nil value
|
||||||
// indicates an unknown state. In most cases consumers should interpret this
|
// indicates an unknown state. In most cases consumers should interpret this
|
||||||
// unknown state as ready.
|
// unknown state as ready. For compatibility reasons, ready should never be
|
||||||
|
// "true" for terminating endpoints.
|
||||||
// +optional
|
// +optional
|
||||||
optional bool ready = 1;
|
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.
|
||||||
|
// +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.
|
||||||
|
// +optional
|
||||||
|
optional bool terminating = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointPort represents a Port used by an EndpointSlice
|
// EndpointPort represents a Port used by an EndpointSlice
|
||||||
|
@ -115,9 +115,22 @@ type EndpointConditions struct {
|
|||||||
// ready indicates that this endpoint is prepared to receive traffic,
|
// ready indicates that this endpoint is prepared to receive traffic,
|
||||||
// according to whatever system is managing the endpoint. A nil value
|
// according to whatever system is managing the endpoint. A nil value
|
||||||
// indicates an unknown state. In most cases consumers should interpret this
|
// indicates an unknown state. In most cases consumers should interpret this
|
||||||
// unknown state as ready.
|
// unknown state as ready. For compatibility reasons, ready should never be
|
||||||
|
// "true" for terminating endpoints.
|
||||||
// +optional
|
// +optional
|
||||||
Ready *bool `json:"ready,omitempty" protobuf:"bytes,1,name=ready"`
|
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.
|
||||||
|
// +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.
|
||||||
|
// +optional
|
||||||
|
Terminating *bool `json:"terminating,omitempty" protobuf:"bytes,3,name=terminating"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointPort represents a Port used by an EndpointSlice
|
// EndpointPort represents a Port used by an EndpointSlice
|
||||||
|
@ -42,7 +42,9 @@ func (Endpoint) SwaggerDoc() map[string]string {
|
|||||||
|
|
||||||
var map_EndpointConditions = map[string]string{
|
var map_EndpointConditions = map[string]string{
|
||||||
"": "EndpointConditions represents the current condition of an endpoint.",
|
"": "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.",
|
"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.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EndpointConditions) SwaggerDoc() map[string]string {
|
func (EndpointConditions) SwaggerDoc() map[string]string {
|
||||||
|
@ -72,6 +72,16 @@ func (in *EndpointConditions) DeepCopyInto(out *EndpointConditions) {
|
|||||||
*out = new(bool)
|
*out = new(bool)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
|
if in.Serving != nil {
|
||||||
|
in, out := &in.Serving, &out.Serving
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.Terminating != nil {
|
||||||
|
in, out := &in.Terminating, &out.Terminating
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
168
staging/src/k8s.io/api/discovery/v1beta1/generated.pb.go
generated
168
staging/src/k8s.io/api/discovery/v1beta1/generated.pb.go
generated
@ -200,54 +200,56 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_ece80bbc872d519b = []byte{
|
var fileDescriptor_ece80bbc872d519b = []byte{
|
||||||
// 745 bytes of a gzipped FileDescriptorProto
|
// 784 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xcf, 0x6b, 0xdb, 0x48,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x4d, 0x8f, 0xe3, 0x44,
|
||||||
0x14, 0xb6, 0xe2, 0x88, 0x95, 0xc6, 0x31, 0x9b, 0x0c, 0x7b, 0x30, 0xde, 0x20, 0x19, 0x2f, 0x2c,
|
0x10, 0x8d, 0x27, 0x63, 0x8d, 0xdd, 0xd9, 0x11, 0xbb, 0x2d, 0x0e, 0xd1, 0xb0, 0xb2, 0x47, 0x41,
|
||||||
0x66, 0x43, 0xa4, 0x75, 0xc8, 0x2e, 0x61, 0xf7, 0x14, 0xed, 0x86, 0xb6, 0xd0, 0x36, 0x66, 0x1a,
|
0xa0, 0x88, 0xd1, 0xda, 0xcc, 0x6a, 0x85, 0x56, 0x70, 0x1a, 0xc3, 0x08, 0x90, 0x80, 0x8d, 0x7a,
|
||||||
0x28, 0x94, 0x1e, 0x3a, 0x96, 0x26, 0xb2, 0x6a, 0x5b, 0x23, 0x34, 0x63, 0x83, 0x6f, 0xfd, 0x13,
|
0x23, 0x21, 0x21, 0x0e, 0x74, 0xec, 0x5a, 0xc7, 0x24, 0x76, 0x5b, 0xdd, 0x9d, 0x48, 0xb9, 0xf1,
|
||||||
0xfa, 0xf7, 0xf4, 0x5a, 0x28, 0x39, 0xe6, 0x98, 0x93, 0xa8, 0xd5, 0xff, 0x22, 0xa7, 0x32, 0xa3,
|
0x0f, 0xe0, 0xf7, 0x70, 0x45, 0x42, 0x73, 0xdc, 0xe3, 0x9e, 0x2c, 0x62, 0xfe, 0xc5, 0x9c, 0x50,
|
||||||
0x5f, 0x76, 0xdd, 0x1f, 0xbe, 0xcd, 0x7c, 0xf3, 0xbe, 0xef, 0xbd, 0xf7, 0xcd, 0x7b, 0xe0, 0x62,
|
0xb7, 0xbf, 0x12, 0xc2, 0x47, 0x6e, 0xee, 0x57, 0xf5, 0x5e, 0xd5, 0x2b, 0x57, 0xa1, 0xdb, 0xc5,
|
||||||
0x7c, 0xc6, 0xac, 0x80, 0xda, 0xe3, 0xd9, 0x90, 0xc4, 0x21, 0xe1, 0x84, 0xd9, 0x73, 0x12, 0x7a,
|
0x73, 0xe1, 0x25, 0xcc, 0x5f, 0xac, 0x66, 0xc0, 0x33, 0x90, 0x20, 0xfc, 0x35, 0x64, 0x11, 0xe3,
|
||||||
0x34, 0xb6, 0xf3, 0x07, 0x1c, 0x05, 0xb6, 0x17, 0x30, 0x97, 0xce, 0x49, 0xbc, 0xb0, 0xe7, 0xfd,
|
0x7e, 0x1d, 0xa0, 0x79, 0xe2, 0x47, 0x89, 0x08, 0xd9, 0x1a, 0xf8, 0xc6, 0x5f, 0x5f, 0xcf, 0x40,
|
||||||
0x21, 0xe1, 0xb8, 0x6f, 0xfb, 0x24, 0x24, 0x31, 0xe6, 0xc4, 0xb3, 0xa2, 0x98, 0x72, 0x0a, 0x0f,
|
0xd2, 0x6b, 0x3f, 0x86, 0x0c, 0x38, 0x95, 0x10, 0x79, 0x39, 0x67, 0x92, 0xe1, 0xc7, 0x55, 0xb6,
|
||||||
0xb3, 0x68, 0x0b, 0x47, 0x81, 0x55, 0x46, 0x5b, 0x79, 0x74, 0xfb, 0xd8, 0x0f, 0xf8, 0x68, 0x36,
|
0x47, 0xf3, 0xc4, 0x6b, 0xb3, 0xbd, 0x3a, 0xfb, 0xe2, 0x49, 0x9c, 0xc8, 0xf9, 0x6a, 0xe6, 0x85,
|
||||||
0xb4, 0x5c, 0x3a, 0xb5, 0x7d, 0xea, 0x53, 0x5b, 0x92, 0x86, 0xb3, 0x6b, 0x79, 0x93, 0x17, 0x79,
|
0x2c, 0xf5, 0x63, 0x16, 0x33, 0x5f, 0x93, 0x66, 0xab, 0x57, 0xfa, 0xa5, 0x1f, 0xfa, 0xab, 0x12,
|
||||||
0xca, 0xc4, 0xda, 0xdd, 0x95, 0xd4, 0x2e, 0x8d, 0x89, 0x3d, 0xdf, 0x48, 0xd8, 0x3e, 0xad, 0x62,
|
0xbb, 0x18, 0xed, 0x94, 0x0e, 0x19, 0x07, 0x7f, 0x7d, 0x50, 0xf0, 0xe2, 0x59, 0x97, 0x93, 0xd2,
|
||||||
0xa6, 0xd8, 0x1d, 0x05, 0xa1, 0xa8, 0x2e, 0x1a, 0xfb, 0x02, 0x60, 0xf6, 0x94, 0x70, 0xfc, 0x35,
|
0x70, 0x9e, 0x64, 0xaa, 0xbb, 0x7c, 0x11, 0x2b, 0x40, 0xf8, 0x29, 0x48, 0xfa, 0x4f, 0x2c, 0xff,
|
||||||
0x96, 0xfd, 0x2d, 0x56, 0x3c, 0x0b, 0x79, 0x30, 0x25, 0x1b, 0x84, 0xbf, 0x7f, 0x44, 0x60, 0xee,
|
0xdf, 0x58, 0x7c, 0x95, 0xc9, 0x24, 0x85, 0x03, 0xc2, 0x47, 0xff, 0x47, 0x10, 0xe1, 0x1c, 0x52,
|
||||||
0x88, 0x4c, 0xf1, 0x97, 0xbc, 0xee, 0xbb, 0x3a, 0xd0, 0x2e, 0x42, 0x2f, 0xa2, 0x41, 0xc8, 0xe1,
|
0xfa, 0x77, 0xde, 0xe8, 0xd7, 0x3e, 0xb2, 0x6e, 0xb3, 0x28, 0x67, 0x49, 0x26, 0xf1, 0x15, 0xb2,
|
||||||
0x11, 0xd0, 0xb1, 0xe7, 0xc5, 0x84, 0x31, 0xc2, 0x5a, 0x4a, 0xa7, 0xde, 0xd3, 0x9d, 0x66, 0x9a,
|
0x69, 0x14, 0x71, 0x10, 0x02, 0xc4, 0xd0, 0xb8, 0xec, 0x8f, 0xed, 0xe0, 0xbc, 0x2c, 0x5c, 0xfb,
|
||||||
0x98, 0xfa, 0x79, 0x01, 0xa2, 0xea, 0x1d, 0x7a, 0x00, 0xb8, 0x34, 0xf4, 0x02, 0x1e, 0xd0, 0x90,
|
0xa6, 0x01, 0x49, 0x17, 0xc7, 0x11, 0x42, 0x21, 0xcb, 0xa2, 0x44, 0x26, 0x2c, 0x13, 0xc3, 0x93,
|
||||||
0xb5, 0x76, 0x3a, 0x4a, 0xaf, 0x71, 0xf2, 0xa7, 0xf5, 0x3d, 0x7b, 0xad, 0x22, 0xd1, 0x7f, 0x25,
|
0x4b, 0x63, 0x3c, 0x78, 0xfa, 0xa1, 0xf7, 0x5f, 0xe3, 0xf5, 0x9a, 0x42, 0x9f, 0xb6, 0xbc, 0x00,
|
||||||
0xcf, 0x81, 0x37, 0x89, 0x59, 0x4b, 0x13, 0x13, 0x54, 0x18, 0x5a, 0xd1, 0x85, 0x3d, 0xa0, 0x8d,
|
0xdf, 0x15, 0x6e, 0xaf, 0x2c, 0x5c, 0xd4, 0x61, 0x64, 0x47, 0x17, 0x8f, 0x91, 0x35, 0x67, 0x42,
|
||||||
0x28, 0xe3, 0x21, 0x9e, 0x92, 0x56, 0xbd, 0xa3, 0xf4, 0x74, 0x67, 0x2f, 0x4d, 0x4c, 0xed, 0x61,
|
0x66, 0x34, 0x85, 0x61, 0xff, 0xd2, 0x18, 0xdb, 0xc1, 0x83, 0xb2, 0x70, 0xad, 0x2f, 0x6a, 0x8c,
|
||||||
0x8e, 0xa1, 0xf2, 0x15, 0x0e, 0x80, 0xce, 0x71, 0xec, 0x13, 0x8e, 0xc8, 0x75, 0x6b, 0x57, 0x96,
|
0xb4, 0x51, 0x3c, 0x41, 0xb6, 0xa4, 0x3c, 0x06, 0x49, 0xe0, 0xd5, 0xf0, 0x54, 0xb7, 0xf3, 0xee,
|
||||||
0xf3, 0xdb, 0x6a, 0x39, 0xe2, 0x83, 0xac, 0x79, 0xdf, 0xba, 0x1c, 0xbe, 0x26, 0xae, 0x08, 0x22,
|
0x6e, 0x3b, 0xea, 0x07, 0x79, 0xeb, 0x6b, 0xef, 0xc5, 0xec, 0x47, 0x08, 0x55, 0x12, 0x70, 0xc8,
|
||||||
0x31, 0x09, 0x5d, 0x92, 0x75, 0x78, 0x55, 0x30, 0x51, 0x25, 0x02, 0x87, 0x40, 0xe3, 0x34, 0xa2,
|
0x42, 0xa8, 0x1c, 0x4e, 0x1b, 0x26, 0xe9, 0x44, 0xf0, 0x0c, 0x59, 0x92, 0xe5, 0x6c, 0xc9, 0xe2,
|
||||||
0x13, 0xea, 0x2f, 0x5a, 0x6a, 0xa7, 0xde, 0x6b, 0x9c, 0x9c, 0x6e, 0xd7, 0x9f, 0x75, 0x95, 0xd3,
|
0xcd, 0xd0, 0xbc, 0xec, 0x8f, 0x07, 0x4f, 0x9f, 0x1d, 0xe7, 0xcf, 0x9b, 0xd6, 0xb4, 0xdb, 0x4c,
|
||||||
0x2e, 0x42, 0x1e, 0x2f, 0x9c, 0xfd, 0xbc, 0x47, 0xad, 0x80, 0x51, 0xa9, 0xdb, 0xfe, 0x17, 0x34,
|
0xf2, 0x4d, 0xf0, 0xb0, 0xf6, 0x68, 0x35, 0x30, 0x69, 0x75, 0x2f, 0x3e, 0x41, 0xe7, 0x7b, 0xc9,
|
||||||
0xd7, 0x82, 0xe1, 0x3e, 0xa8, 0x8f, 0xc9, 0xa2, 0xa5, 0x88, 0x5e, 0x91, 0x38, 0xc2, 0x5f, 0x80,
|
0xf8, 0x21, 0xea, 0x2f, 0x60, 0x33, 0x34, 0x94, 0x57, 0xa2, 0x3e, 0xf1, 0xdb, 0xc8, 0x5c, 0xd3,
|
||||||
0x3a, 0xc7, 0x93, 0x19, 0x91, 0x1e, 0xeb, 0x28, 0xbb, 0xfc, 0xb3, 0x73, 0xa6, 0x74, 0xff, 0x02,
|
0xe5, 0x0a, 0xf4, 0x8c, 0x6d, 0x52, 0x3d, 0x3e, 0x3e, 0x79, 0x6e, 0x8c, 0x7e, 0x36, 0x10, 0x3e,
|
||||||
0x70, 0xd3, 0x52, 0x68, 0x02, 0x35, 0x26, 0xd8, 0xcb, 0x34, 0x34, 0x47, 0x4f, 0x13, 0x53, 0x45,
|
0x9c, 0x29, 0x76, 0x91, 0xc9, 0x81, 0x46, 0x95, 0x88, 0x15, 0xd8, 0x65, 0xe1, 0x9a, 0x44, 0x01,
|
||||||
0x02, 0x40, 0x19, 0xde, 0xfd, 0xa0, 0x80, 0xbd, 0x82, 0x37, 0xa0, 0x31, 0x87, 0x87, 0x60, 0x57,
|
0xa4, 0xc2, 0xf1, 0x7b, 0xe8, 0x4c, 0x00, 0x5f, 0x27, 0x59, 0xac, 0x35, 0xad, 0x60, 0x50, 0x16,
|
||||||
0x1a, 0x2c, 0x93, 0x3a, 0x5a, 0x9a, 0x98, 0xbb, 0x4f, 0x85, 0xb9, 0x12, 0x85, 0x0f, 0x80, 0x26,
|
0xee, 0xd9, 0xcb, 0x0a, 0x22, 0x4d, 0x0c, 0x5f, 0xa3, 0x81, 0x04, 0x9e, 0x26, 0x19, 0x95, 0x2a,
|
||||||
0x67, 0xc5, 0xa5, 0x93, 0xac, 0x04, 0xe7, 0x48, 0x34, 0x33, 0xc8, 0xb1, 0xfb, 0xc4, 0xfc, 0x75,
|
0xb5, 0xaf, 0x53, 0xdf, 0x2a, 0x0b, 0x77, 0x30, 0xed, 0x60, 0xb2, 0x9b, 0x33, 0xfa, 0xdd, 0x40,
|
||||||
0x73, 0x0f, 0xac, 0xe2, 0x19, 0x95, 0x64, 0x91, 0x26, 0xa2, 0x31, 0x97, 0xff, 0xa8, 0x66, 0x69,
|
0x0f, 0x9a, 0x8e, 0x26, 0x8c, 0x4b, 0xfc, 0x18, 0x9d, 0xea, 0x7f, 0xa7, 0xfd, 0x04, 0x56, 0x59,
|
||||||
0x44, 0x7a, 0x24, 0x51, 0xd8, 0x07, 0x0d, 0x1c, 0x45, 0x05, 0x4d, 0xfe, 0xa0, 0xee, 0xfc, 0x9c,
|
0xb8, 0xa7, 0xdf, 0xa8, 0xff, 0xa6, 0x51, 0xfc, 0x39, 0xb2, 0xf4, 0x1a, 0x86, 0x6c, 0x59, 0xb9,
|
||||||
0x26, 0x66, 0xe3, 0xbc, 0x82, 0xd1, 0x6a, 0x4c, 0x77, 0xb9, 0x03, 0x9a, 0x45, 0x23, 0xcf, 0x26,
|
0x0b, 0xae, 0xd4, 0x9c, 0x26, 0x35, 0x76, 0x5f, 0xb8, 0xef, 0x1c, 0x9e, 0x98, 0xd7, 0x84, 0x49,
|
||||||
0x81, 0x4b, 0xe0, 0x2b, 0xa0, 0x89, 0x95, 0xf2, 0x30, 0xc7, 0xb2, 0x9b, 0xf5, 0x91, 0x2c, 0x37,
|
0x4b, 0x56, 0x65, 0x72, 0xc6, 0xa5, 0xee, 0xd1, 0xac, 0xca, 0xa8, 0xf2, 0x44, 0xa3, 0xca, 0x08,
|
||||||
0xc3, 0x8a, 0xc6, 0xbe, 0x00, 0x98, 0x25, 0xa2, 0xab, 0xa9, 0x78, 0x42, 0x38, 0xae, 0x46, 0xb2,
|
0xcd, 0xf3, 0x86, 0xa6, 0x97, 0xc3, 0xae, 0x8c, 0xdc, 0x74, 0x30, 0xd9, 0xcd, 0x19, 0x6d, 0x4f,
|
||||||
0xc2, 0x50, 0xa9, 0x0a, 0xff, 0x07, 0x8d, 0x7c, 0x07, 0xae, 0x16, 0x11, 0xc9, 0xcb, 0xec, 0xe6,
|
0xd0, 0x79, 0x63, 0xe4, 0xe5, 0x32, 0x09, 0x01, 0xff, 0x80, 0x2c, 0x75, 0xad, 0x11, 0x95, 0x54,
|
||||||
0x94, 0xc6, 0x79, 0xf5, 0x74, 0xbf, 0x7e, 0x45, 0xab, 0x34, 0xf8, 0x1c, 0xe8, 0x24, 0x2f, 0x5c,
|
0xbb, 0xd9, 0xdf, 0xf6, 0xf6, 0xe8, 0xbc, 0x7c, 0x11, 0x2b, 0x40, 0x78, 0x2a, 0xbb, 0x5b, 0xb8,
|
||||||
0xec, 0x8e, 0x98, 0xad, 0xdf, 0xb7, 0x9b, 0x2d, 0xe7, 0x20, 0xcf, 0xa5, 0x17, 0x08, 0x43, 0x95,
|
0xaf, 0x41, 0xd2, 0x6e, 0xdb, 0x3b, 0x8c, 0xb4, 0xaa, 0xf8, 0x33, 0x34, 0xa8, 0xcf, 0x6b, 0xba,
|
||||||
0x16, 0xbc, 0x04, 0xaa, 0x70, 0x93, 0xb5, 0xea, 0x52, 0xf4, 0x8f, 0xed, 0x44, 0xc5, 0x37, 0x38,
|
0xc9, 0xa1, 0x6e, 0x73, 0x54, 0x53, 0x06, 0x37, 0x5d, 0xe8, 0x7e, 0xff, 0x49, 0x76, 0x69, 0xf8,
|
||||||
0xcd, 0x5c, 0x58, 0x15, 0x37, 0x86, 0x32, 0x9d, 0xee, 0x7b, 0x05, 0x1c, 0xac, 0x79, 0xfc, 0x38,
|
0x5b, 0x64, 0x43, 0xdd, 0xb8, 0x3a, 0x4b, 0xb5, 0xb6, 0xef, 0x1f, 0xb7, 0xb6, 0xc1, 0xa3, 0xba,
|
||||||
0x60, 0x1c, 0xbe, 0xdc, 0xf0, 0xd9, 0xda, 0xce, 0x67, 0xc1, 0x96, 0x2e, 0x97, 0x4b, 0x51, 0x20,
|
0x96, 0xdd, 0x20, 0x82, 0x74, 0x5a, 0xf8, 0x05, 0x32, 0xd5, 0x34, 0xc5, 0xb0, 0xaf, 0x45, 0x3f,
|
||||||
0x2b, 0x1e, 0x0f, 0x80, 0x1a, 0x70, 0x32, 0x2d, 0x9c, 0x39, 0xda, 0xae, 0x09, 0x59, 0x5d, 0xd5,
|
0x38, 0x4e, 0x54, 0xfd, 0x86, 0xe0, 0xbc, 0x16, 0x36, 0xd5, 0x4b, 0x90, 0x4a, 0x67, 0xf4, 0x9b,
|
||||||
0xc5, 0x23, 0xa1, 0x80, 0x32, 0x21, 0xe7, 0xf8, 0x66, 0x69, 0xd4, 0x6e, 0x97, 0x46, 0xed, 0x6e,
|
0x81, 0x1e, 0xed, 0xcd, 0xf8, 0xab, 0x44, 0x48, 0xfc, 0xfd, 0xc1, 0x9c, 0xbd, 0xe3, 0xe6, 0xac,
|
||||||
0x69, 0xd4, 0xde, 0xa4, 0x86, 0x72, 0x93, 0x1a, 0xca, 0x6d, 0x6a, 0x28, 0x77, 0xa9, 0xa1, 0x7c,
|
0xd8, 0x7a, 0xca, 0xed, 0xbd, 0x35, 0xc8, 0xce, 0x8c, 0x27, 0xc8, 0x4c, 0x24, 0xa4, 0xcd, 0x64,
|
||||||
0x4c, 0x0d, 0xe5, 0xed, 0x27, 0xa3, 0xf6, 0xe2, 0xa7, 0x5c, 0xf2, 0x73, 0x00, 0x00, 0x00, 0xff,
|
0xae, 0x8e, 0x33, 0xa1, 0xbb, 0xeb, 0x5c, 0x7c, 0xa9, 0x14, 0x48, 0x25, 0x14, 0x3c, 0xb9, 0xdb,
|
||||||
0xff, 0x29, 0x1a, 0xa2, 0x6f, 0x6d, 0x06, 0x00, 0x00,
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Endpoint) Marshal() (dAtA []byte, err error) {
|
func (m *Endpoint) Marshal() (dAtA []byte, err error) {
|
||||||
@ -355,6 +357,26 @@ func (m *EndpointConditions) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
_ = l
|
_ = l
|
||||||
|
if m.Terminating != nil {
|
||||||
|
i--
|
||||||
|
if *m.Terminating {
|
||||||
|
dAtA[i] = 1
|
||||||
|
} else {
|
||||||
|
dAtA[i] = 0
|
||||||
|
}
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x18
|
||||||
|
}
|
||||||
|
if m.Serving != nil {
|
||||||
|
i--
|
||||||
|
if *m.Serving {
|
||||||
|
dAtA[i] = 1
|
||||||
|
} else {
|
||||||
|
dAtA[i] = 0
|
||||||
|
}
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x10
|
||||||
|
}
|
||||||
if m.Ready != nil {
|
if m.Ready != nil {
|
||||||
i--
|
i--
|
||||||
if *m.Ready {
|
if *m.Ready {
|
||||||
@ -583,6 +605,12 @@ func (m *EndpointConditions) Size() (n int) {
|
|||||||
if m.Ready != nil {
|
if m.Ready != nil {
|
||||||
n += 2
|
n += 2
|
||||||
}
|
}
|
||||||
|
if m.Serving != nil {
|
||||||
|
n += 2
|
||||||
|
}
|
||||||
|
if m.Terminating != nil {
|
||||||
|
n += 2
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,6 +716,8 @@ func (this *EndpointConditions) String() string {
|
|||||||
}
|
}
|
||||||
s := strings.Join([]string{`&EndpointConditions{`,
|
s := strings.Join([]string{`&EndpointConditions{`,
|
||||||
`Ready:` + valueToStringGenerated(this.Ready) + `,`,
|
`Ready:` + valueToStringGenerated(this.Ready) + `,`,
|
||||||
|
`Serving:` + valueToStringGenerated(this.Serving) + `,`,
|
||||||
|
`Terminating:` + valueToStringGenerated(this.Terminating) + `,`,
|
||||||
`}`,
|
`}`,
|
||||||
}, "")
|
}, "")
|
||||||
return s
|
return s
|
||||||
@ -1116,6 +1146,48 @@ func (m *EndpointConditions) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
b := bool(v != 0)
|
b := bool(v != 0)
|
||||||
m.Ready = &b
|
m.Ready = &b
|
||||||
|
case 2:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Serving", wireType)
|
||||||
|
}
|
||||||
|
var v int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowGenerated
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
v |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b := bool(v != 0)
|
||||||
|
m.Serving = &b
|
||||||
|
case 3:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Terminating", wireType)
|
||||||
|
}
|
||||||
|
var v int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowGenerated
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
v |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b := bool(v != 0)
|
||||||
|
m.Terminating = &b
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||||
|
@ -76,9 +76,22 @@ message EndpointConditions {
|
|||||||
// ready indicates that this endpoint is prepared to receive traffic,
|
// ready indicates that this endpoint is prepared to receive traffic,
|
||||||
// according to whatever system is managing the endpoint. A nil value
|
// according to whatever system is managing the endpoint. A nil value
|
||||||
// indicates an unknown state. In most cases consumers should interpret this
|
// indicates an unknown state. In most cases consumers should interpret this
|
||||||
// unknown state as ready.
|
// unknown state as ready. For compatibility reasons, ready should never be
|
||||||
|
// "true" for terminating endpoints.
|
||||||
// +optional
|
// +optional
|
||||||
optional bool ready = 1;
|
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.
|
||||||
|
// +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.
|
||||||
|
// +optional
|
||||||
|
optional bool terminating = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointPort represents a Port used by an EndpointSlice
|
// EndpointPort represents a Port used by an EndpointSlice
|
||||||
|
@ -117,9 +117,22 @@ type EndpointConditions struct {
|
|||||||
// ready indicates that this endpoint is prepared to receive traffic,
|
// ready indicates that this endpoint is prepared to receive traffic,
|
||||||
// according to whatever system is managing the endpoint. A nil value
|
// according to whatever system is managing the endpoint. A nil value
|
||||||
// indicates an unknown state. In most cases consumers should interpret this
|
// indicates an unknown state. In most cases consumers should interpret this
|
||||||
// unknown state as ready.
|
// unknown state as ready. For compatibility reasons, ready should never be
|
||||||
|
// "true" for terminating endpoints.
|
||||||
// +optional
|
// +optional
|
||||||
Ready *bool `json:"ready,omitempty" protobuf:"bytes,1,name=ready"`
|
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.
|
||||||
|
// +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.
|
||||||
|
// +optional
|
||||||
|
Terminating *bool `json:"terminating,omitempty" protobuf:"bytes,3,name=terminating"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointPort represents a Port used by an EndpointSlice
|
// EndpointPort represents a Port used by an EndpointSlice
|
||||||
|
@ -42,7 +42,9 @@ func (Endpoint) SwaggerDoc() map[string]string {
|
|||||||
|
|
||||||
var map_EndpointConditions = map[string]string{
|
var map_EndpointConditions = map[string]string{
|
||||||
"": "EndpointConditions represents the current condition of an endpoint.",
|
"": "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.",
|
"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.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EndpointConditions) SwaggerDoc() map[string]string {
|
func (EndpointConditions) SwaggerDoc() map[string]string {
|
||||||
|
@ -72,6 +72,16 @@ func (in *EndpointConditions) DeepCopyInto(out *EndpointConditions) {
|
|||||||
*out = new(bool)
|
*out = new(bool)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
|
if in.Serving != nil {
|
||||||
|
in, out := &in.Serving, &out.Serving
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.Terminating != nil {
|
||||||
|
in, out := &in.Terminating, &out.Terminating
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user