Skip to content

Commit

Permalink
add ability for targetGroupBinding to change to nil networking (kuber…
Browse files Browse the repository at this point in the history
  • Loading branch information
M00nF1sh authored Oct 15, 2020
1 parent cdc8f71 commit a0c1562
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 50 deletions.
17 changes: 17 additions & 0 deletions controllers/elbv2/targetgroupbinding_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package controllers

import (
"context"
"github.com/aws/aws-sdk-go/aws"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/aws-load-balancer-controller/controllers/elbv2/eventhandlers"
"sigs.k8s.io/aws-load-balancer-controller/pkg/config"
Expand Down Expand Up @@ -98,6 +100,9 @@ func (r *targetGroupBindingReconciler) reconcileTargetGroupBinding(ctx context.C
if err := r.tgbResourceManager.Reconcile(ctx, tgb); err != nil {
return err
}
if err := r.updateTargetGroupBindingStatus(ctx, tgb); err != nil {
return err
}
return nil
}

Expand All @@ -113,6 +118,18 @@ func (r *targetGroupBindingReconciler) cleanupTargetGroupBinding(ctx context.Con
return nil
}

func (r *targetGroupBindingReconciler) updateTargetGroupBindingStatus(ctx context.Context, tgb *elbv2api.TargetGroupBinding) error {
if aws.Int64Value(tgb.Status.ObservedGeneration) == tgb.Generation {
return nil
}
tgbOld := tgb.DeepCopy()
tgb.Status.ObservedGeneration = aws.Int64(tgb.Generation)
if err := r.k8sClient.Status().Patch(ctx, tgb, client.MergeFrom(tgbOld)); err != nil {
return errors.Wrapf(err, "failed to update targetGroupBinding status: %v", k8s.NamespacedName(tgb))
}
return nil
}

func (r *targetGroupBindingReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
if err := r.setupIndexes(ctx, mgr.GetFieldIndexer()); err != nil {
return err
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ require (
go.uber.org/zap v1.10.0
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
gomodules.xyz/jsonpatch/v2 v2.0.1
k8s.io/api v0.18.4
k8s.io/apimachinery v0.18.4
k8s.io/client-go v0.18.4
sigs.k8s.io/controller-runtime v0.6.1
k8s.io/api v0.18.6
k8s.io/apimachinery v0.18.6
k8s.io/client-go v0.18.6
sigs.k8s.io/controller-runtime v0.6.3
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e // indirect
)
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ github.com/aws/aws-sdk-go v1.33.14/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve
github.com/aws/aws-sdk-go v1.35.4 h1:GG0sdhmzQSe4/UcF9iuQP9i+58bPRyU4OpujyzMlVjo=
github.com/aws/aws-sdk-go v1.35.4/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
Expand Down Expand Up @@ -67,6 +68,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
Expand Down Expand Up @@ -452,15 +455,26 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.18.4 h1:8x49nBRxuXGUlDlwlWd3RMY1SayZrzFfxea3UZSkFw4=
k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4=
k8s.io/api v0.18.6 h1:osqrAXbOQjkKIWDTjrqxWQ3w0GkKb1KA1XkUGHHYpeE=
k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI=
k8s.io/apiextensions-apiserver v0.18.4 h1:Y3HGERmS8t9u12YNUFoOISqefaoGRuTc43AYCLzWmWE=
k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrqOzaMo=
k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M=
k8s.io/apimachinery v0.18.4 h1:ST2beySjhqwJoIFk6p7Hp5v5O0hYY6Gngq/gUYXTPIA=
k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag=
k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg=
k8s.io/client-go v0.18.4 h1:un55V1Q/B3JO3A76eS0kUSywgGK/WR3BQ8fHQjNa6Zc=
k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g=
k8s.io/client-go v0.18.6 h1:I+oWqJbibLSGsZj8Xs8F0aWVXJVIoUHWaaJV3kUN/Zw=
k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q=
k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk=
k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
Expand All @@ -477,6 +491,8 @@ k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
sigs.k8s.io/controller-runtime v0.6.1 h1:LcK2+nk0kmaOnKGN+vBcWHqY5WDJNJNB/c5pW+sU8fc=
sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE=
sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
Expand Down
102 changes: 74 additions & 28 deletions pkg/deploy/elbv2/target_group_binding_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package elbv2

import (
"context"
awssdk "github.com/aws/aws-sdk-go/aws"
"github.com/go-logr/logr"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
elbv2api "sigs.k8s.io/aws-load-balancer-controller/apis/elbv2/v1beta1"
"sigs.k8s.io/aws-load-balancer-controller/pkg/deploy/tracking"
Expand All @@ -17,6 +19,8 @@ import (
)

const (
defaultWaitTGBObservedPollInterval = 200 * time.Millisecond
defaultWaitTGBObservedTimeout = 60 * time.Second
defaultWaitTGBDeletionPollInterval = 200 * time.Millisecond
defaultWaitTGBDeletionTimeout = 60 * time.Second
)
Expand All @@ -37,78 +41,81 @@ func NewDefaultTargetGroupBindingManager(k8sClient client.Client, trackingProvid
trackingProvider: trackingProvider,
logger: logger,

waitTGBObservedPollInterval: defaultWaitTGBObservedPollInterval,
waitTGBObservedTimout: defaultWaitTGBObservedTimeout,
waitTGBDeletionPollInterval: defaultWaitTGBDeletionPollInterval,
waitTGBDeletionTimeout: defaultWaitTGBDeletionTimeout,
}
}

var _ TargetGroupBindingManager = &defaultTargetGroupBindingManager{}

// default implementation for TargetGroupBindingManager.
type defaultTargetGroupBindingManager struct {
k8sClient client.Client
trackingProvider tracking.Provider
logger logr.Logger

waitTGBObservedPollInterval time.Duration
waitTGBObservedTimout time.Duration
waitTGBDeletionPollInterval time.Duration
waitTGBDeletionTimeout time.Duration
}

func (m *defaultTargetGroupBindingManager) Create(ctx context.Context, resTGB *elbv2model.TargetGroupBindingResource) (elbv2model.TargetGroupBindingResourceStatus, error) {
tgARN, err := resTGB.Spec.Template.Spec.TargetGroupARN.Resolve(ctx)
k8sTGBSpec, err := buildK8sTargetGroupBindingSpec(ctx, resTGB)
if err != nil {
return elbv2model.TargetGroupBindingResourceStatus{}, err
}
stackLabels := m.trackingProvider.StackLabels(resTGB.Stack())
k8sTGBSpec := elbv2api.TargetGroupBindingSpec{
TargetGroupARN: tgARN,
TargetType: resTGB.Spec.Template.Spec.TargetType,
ServiceRef: resTGB.Spec.Template.Spec.ServiceRef,
}
if resTGB.Spec.Template.Spec.Networking != nil {
k8sTGBNetworking, err := buildK8sTargetGroupBindingNetworking(ctx, *resTGB.Spec.Template.Spec.Networking)
if err != nil {
return elbv2model.TargetGroupBindingResourceStatus{}, err
}
k8sTGBSpec.Networking = &k8sTGBNetworking
}

stackLabels := m.trackingProvider.StackLabels(resTGB.Stack())
k8sTGB := &elbv2api.TargetGroupBinding{
ObjectMeta: v1.ObjectMeta{
ObjectMeta: metav1.ObjectMeta{
Namespace: resTGB.Spec.Template.Namespace,
Name: resTGB.Spec.Template.Name,
Labels: stackLabels,
},
Spec: k8sTGBSpec,
}

m.logger.Info("creating targetGroupBinding",
"stackID", resTGB.Stack().StackID(),
"resourceID", resTGB.ID())
if err := m.k8sClient.Create(ctx, k8sTGB); err != nil {
return elbv2model.TargetGroupBindingResourceStatus{}, err
}
m.logger.Info("created targetGroupBinding",
"stackID", resTGB.Stack().StackID(),
"resourceID", resTGB.ID(),
"targetGroupBinding", k8s.NamespacedName(k8sTGB))
return buildResTargetGroupBindingStatus(k8sTGB), nil
}

func (m *defaultTargetGroupBindingManager) Update(ctx context.Context, resTGB *elbv2model.TargetGroupBindingResource, k8sTGB *elbv2api.TargetGroupBinding) (elbv2model.TargetGroupBindingResourceStatus, error) {
tgARN, err := resTGB.Spec.Template.Spec.TargetGroupARN.Resolve(ctx)
k8sTGBSpec, err := buildK8sTargetGroupBindingSpec(ctx, resTGB)
if err != nil {
return elbv2model.TargetGroupBindingResourceStatus{}, err
}
k8sTGBSpec := elbv2api.TargetGroupBindingSpec{
TargetGroupARN: tgARN,
TargetType: resTGB.Spec.Template.Spec.TargetType,
ServiceRef: resTGB.Spec.Template.Spec.ServiceRef,
}
if resTGB.Spec.Template.Spec.Networking != nil {
k8sTGBNetworking, err := buildK8sTargetGroupBindingNetworking(ctx, *resTGB.Spec.Template.Spec.Networking)
if err != nil {
return elbv2model.TargetGroupBindingResourceStatus{}, err
}
k8sTGBSpec.Networking = &k8sTGBNetworking
if equality.Semantic.DeepEqual(k8sTGB.Spec, k8sTGBSpec) {
return buildResTargetGroupBindingStatus(k8sTGB), nil
}

oldK8sTGB := k8sTGB.DeepCopy()
k8sTGB.Spec = k8sTGBSpec
m.logger.Info("modifying targetGroupBinding",
"stackID", resTGB.Stack().StackID(),
"resourceID", resTGB.ID(),
"targetGroupBinding", k8s.NamespacedName(k8sTGB))
if err := m.k8sClient.Patch(ctx, k8sTGB, client.MergeFrom(oldK8sTGB)); err != nil {
return elbv2model.TargetGroupBindingResourceStatus{}, err
}
if err := m.waitUntilTargetGroupBindingObserved(ctx, k8sTGB); err != nil {
return elbv2model.TargetGroupBindingResourceStatus{}, err
}
m.logger.Info("modified targetGroupBinding",
"stackID", resTGB.Stack().StackID(),
"resourceID", resTGB.ID(),
"targetGroupBinding", k8s.NamespacedName(k8sTGB))
return buildResTargetGroupBindingStatus(k8sTGB), nil
}

Expand All @@ -126,6 +133,23 @@ func (m *defaultTargetGroupBindingManager) Delete(ctx context.Context, tgb *elbv
return nil
}

func (m *defaultTargetGroupBindingManager) waitUntilTargetGroupBindingObserved(ctx context.Context, tgb *elbv2api.TargetGroupBinding) error {
ctx, cancel := context.WithTimeout(ctx, m.waitTGBObservedTimout)
defer cancel()

observedTGB := &elbv2api.TargetGroupBinding{}
return wait.PollImmediateUntil(m.waitTGBObservedPollInterval, func() (bool, error) {
if err := m.k8sClient.Get(ctx, k8s.NamespacedName(tgb), observedTGB); err != nil {
return false, err
}
if awssdk.Int64Value(observedTGB.Status.ObservedGeneration) >= tgb.Generation {
return true, nil
}

return false, nil
}, ctx.Done())
}

func (m *defaultTargetGroupBindingManager) waitUntilTargetGroupBindingDeleted(ctx context.Context, tgb *elbv2api.TargetGroupBinding) error {
ctx, cancel := context.WithTimeout(ctx, m.waitTGBDeletionTimeout)
defer cancel()
Expand All @@ -142,6 +166,28 @@ func (m *defaultTargetGroupBindingManager) waitUntilTargetGroupBindingDeleted(ct
}, ctx.Done())
}

func buildK8sTargetGroupBindingSpec(ctx context.Context, resTGB *elbv2model.TargetGroupBindingResource) (elbv2api.TargetGroupBindingSpec, error) {
tgARN, err := resTGB.Spec.Template.Spec.TargetGroupARN.Resolve(ctx)
if err != nil {
return elbv2api.TargetGroupBindingSpec{}, err
}

k8sTGBSpec := elbv2api.TargetGroupBindingSpec{
TargetGroupARN: tgARN,
TargetType: resTGB.Spec.Template.Spec.TargetType,
ServiceRef: resTGB.Spec.Template.Spec.ServiceRef,
}

if resTGB.Spec.Template.Spec.Networking != nil {
k8sTGBNetworking, err := buildK8sTargetGroupBindingNetworking(ctx, *resTGB.Spec.Template.Spec.Networking)
if err != nil {
return elbv2api.TargetGroupBindingSpec{}, err
}
k8sTGBSpec.Networking = &k8sTGBNetworking
}
return k8sTGBSpec, nil
}

func buildK8sTargetGroupBindingNetworking(ctx context.Context, resTGBNetworking elbv2model.TargetGroupBindingNetworking) (elbv2api.TargetGroupBindingNetworking, error) {
k8sIngress := make([]elbv2api.NetworkingIngressRule, 0, len(resTGBNetworking.Ingress))
for _, rule := range resTGBNetworking.Ingress {
Expand Down
31 changes: 14 additions & 17 deletions pkg/targetgroupbinding/networking_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,33 +90,30 @@ type defaultNetworkingManager struct {
}

func (m *defaultNetworkingManager) ReconcileForPodEndpoints(ctx context.Context, tgb *elbv2api.TargetGroupBinding, endpoints []backend.PodEndpoint) error {
if tgb.Spec.Networking == nil {
return nil
}

ingressPermissionsPerSG, err := m.computeIngressPermissionsPerSGWithPodEndpoints(ctx, *tgb.Spec.Networking, endpoints)
if err != nil {
return err
var ingressPermissionsPerSG map[string][]networking.IPPermissionInfo
if tgb.Spec.Networking != nil {
var err error
ingressPermissionsPerSG, err = m.computeIngressPermissionsPerSGWithPodEndpoints(ctx, *tgb.Spec.Networking, endpoints)
if err != nil {
return err
}
}
return m.reconcileWithIngressPermissionsPerSG(ctx, tgb, ingressPermissionsPerSG)
}

func (m *defaultNetworkingManager) ReconcileForNodePortEndpoints(ctx context.Context, tgb *elbv2api.TargetGroupBinding, endpoints []backend.NodePortEndpoint) error {
if tgb.Spec.Networking == nil {
return nil
}

ingressPermissionsPerSG, err := m.computeIngressPermissionsPerSGWithNodePortEndpoints(ctx, *tgb.Spec.Networking, endpoints)
if err != nil {
return err
var ingressPermissionsPerSG map[string][]networking.IPPermissionInfo
if tgb.Spec.Networking != nil {
var err error
ingressPermissionsPerSG, err = m.computeIngressPermissionsPerSGWithNodePortEndpoints(ctx, *tgb.Spec.Networking, endpoints)
if err != nil {
return err
}
}
return m.reconcileWithIngressPermissionsPerSG(ctx, tgb, ingressPermissionsPerSG)
}

func (m *defaultNetworkingManager) Cleanup(ctx context.Context, tgb *elbv2api.TargetGroupBinding) error {
if tgb.Spec.Networking == nil {
return nil
}
return m.reconcileWithIngressPermissionsPerSG(ctx, tgb, nil)
}

Expand Down
4 changes: 3 additions & 1 deletion pkg/targetgroupbinding/resource_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ func (m *defaultResourceManager) reconcileWithInstanceTargetType(ctx context.Con
if err != nil {
return err
}
_, unmatchedEndpoints, unmatchedTargets := matchNodePortEndpointWithTargets(endpoints, targets)
notDrainingTargets, drainingTargets := partitionTargetsByDrainingStatus(targets)
_, unmatchedEndpoints, unmatchedTargets := matchNodePortEndpointWithTargets(endpoints, notDrainingTargets)

if err := m.networkingManager.ReconcileForNodePortEndpoints(ctx, tgb, endpoints); err != nil {
return err
Expand All @@ -144,6 +145,7 @@ func (m *defaultResourceManager) reconcileWithInstanceTargetType(ctx context.Con
if err := m.registerNodePortEndpoints(ctx, tgARN, unmatchedEndpoints); err != nil {
return err
}
_ = drainingTargets
return nil
}

Expand Down

0 comments on commit a0c1562

Please sign in to comment.