-
Notifications
You must be signed in to change notification settings - Fork 1.5k
EndpointSlice support for IP target groups #2169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
a76dc5f
Add support for EndpointSlices in tgb controller, tgb resource manage…
harivall 063ffd0
remove unnecessary logs, change endpointslices flag name, clean up code
harivall 60d1056
clean up code
harivall 876dda0
fix flag description
harivall eaa723f
fix formatting
kishorj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ site | |
|
||
# editor and IDE paraphernalia | ||
.idea | ||
.vscode | ||
*.swp | ||
*.swo | ||
*~ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package eventhandlers | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/go-logr/logr" | ||
"github.com/pkg/errors" | ||
discv1 "k8s.io/api/discovery/v1beta1" | ||
"k8s.io/apimachinery/pkg/api/equality" | ||
"k8s.io/apimachinery/pkg/types" | ||
"k8s.io/client-go/util/workqueue" | ||
elbv2api "sigs.k8s.io/aws-load-balancer-controller/apis/elbv2/v1beta1" | ||
"sigs.k8s.io/aws-load-balancer-controller/pkg/k8s" | ||
"sigs.k8s.io/aws-load-balancer-controller/pkg/targetgroupbinding" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/event" | ||
"sigs.k8s.io/controller-runtime/pkg/handler" | ||
"sigs.k8s.io/controller-runtime/pkg/reconcile" | ||
) | ||
|
||
const svcNameLabel = "kubernetes.io/service-name" | ||
|
||
// NewEnqueueRequestsForEndpointSlicesEvent constructs new enqueueRequestsForEndpointSlicesEvent. | ||
func NewEnqueueRequestsForEndpointSlicesEvent(k8sClient client.Client, logger logr.Logger) handler.EventHandler { | ||
return &enqueueRequestsForEndpointSlicesEvent{ | ||
k8sClient: k8sClient, | ||
logger: logger, | ||
} | ||
} | ||
|
||
var _ handler.EventHandler = (*enqueueRequestsForEndpointSlicesEvent)(nil) | ||
|
||
type enqueueRequestsForEndpointSlicesEvent struct { | ||
k8sClient client.Client | ||
logger logr.Logger | ||
} | ||
|
||
// Create is called in response to an create event - e.g. EndpointSlice Creation. | ||
func (h *enqueueRequestsForEndpointSlicesEvent) Create(e event.CreateEvent, queue workqueue.RateLimitingInterface) { | ||
epNew := e.Object.(*discv1.EndpointSlice) | ||
h.logger.V(1).Info("Create event for EndpointSlices", "name", epNew.Name) | ||
h.enqueueImpactedTargetGroupBindings(queue, epNew) | ||
} | ||
|
||
// Update is called in response to an update event - e.g. EndpointSlice Updated. | ||
func (h *enqueueRequestsForEndpointSlicesEvent) Update(e event.UpdateEvent, queue workqueue.RateLimitingInterface) { | ||
epOld := e.ObjectOld.(*discv1.EndpointSlice) | ||
epNew := e.ObjectNew.(*discv1.EndpointSlice) | ||
h.logger.V(1).Info("Update event for EndpointSlices", "name", epNew.Name) | ||
if !equality.Semantic.DeepEqual(epOld.Ports, epNew.Ports) || !equality.Semantic.DeepEqual(epOld.Endpoints, epNew.Endpoints) { | ||
h.logger.V(1).Info("Enqueue EndpointSlice", "name", epNew.Name) | ||
h.enqueueImpactedTargetGroupBindings(queue, epNew) | ||
} | ||
} | ||
|
||
// Delete is called in response to a delete event - e.g. EndpointSlice Deleted. | ||
func (h *enqueueRequestsForEndpointSlicesEvent) Delete(e event.DeleteEvent, queue workqueue.RateLimitingInterface) { | ||
epOld := e.Object.(*discv1.EndpointSlice) | ||
h.logger.V(1).Info("Deletion event for EndpointSlices", "name", epOld.Name) | ||
h.enqueueImpactedTargetGroupBindings(queue, epOld) | ||
} | ||
|
||
// Generic is called in response to an event of an unknown type or a synthetic event triggered as a cron or | ||
// external trigger request - e.g. reconcile AutoScaling, or a WebHook. | ||
func (h *enqueueRequestsForEndpointSlicesEvent) Generic(event.GenericEvent, workqueue.RateLimitingInterface) { | ||
} | ||
|
||
func (h *enqueueRequestsForEndpointSlicesEvent) enqueueImpactedTargetGroupBindings(queue workqueue.RateLimitingInterface, epSlice *discv1.EndpointSlice) { | ||
tgbList := &elbv2api.TargetGroupBindingList{} | ||
svcName, present := epSlice.Labels[svcNameLabel] | ||
if !present { | ||
err := errors.Errorf("EndpointSlice does not have a %v label", svcNameLabel) | ||
h.logger.Error(err, "unable to find service name for endpointslice") | ||
return | ||
} | ||
if err := h.k8sClient.List(context.Background(), tgbList, | ||
client.InNamespace(epSlice.Namespace), | ||
client.MatchingFields{targetgroupbinding.IndexKeyServiceRefName: svcName}); err != nil { | ||
h.logger.Error(err, "failed to fetch targetGroupBindings") | ||
return | ||
} | ||
|
||
epSliceKey := k8s.NamespacedName(epSlice) | ||
for _, tgb := range tgbList.Items { | ||
if tgb.Spec.TargetType == nil || (*tgb.Spec.TargetType) != elbv2api.TargetTypeIP { | ||
continue | ||
} | ||
|
||
h.logger.V(1).Info("enqueue targetGroupBinding for endpointslices event", | ||
"endpointslices", epSliceKey, | ||
"targetGroupBinding", k8s.NamespacedName(&tgb), | ||
) | ||
queue.Add(reconcile.Request{ | ||
NamespacedName: types.NamespacedName{ | ||
Namespace: tgb.Namespace, | ||
Name: tgb.Name, | ||
}, | ||
}) | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
package eventhandlers | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/golang/mock/gomock" | ||
"github.com/google/go-cmp/cmp" | ||
"github.com/stretchr/testify/assert" | ||
discv1 "k8s.io/api/discovery/v1beta1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
"k8s.io/client-go/util/workqueue" | ||
elbv2api "sigs.k8s.io/aws-load-balancer-controller/apis/elbv2/v1beta1" | ||
mock_client "sigs.k8s.io/aws-load-balancer-controller/mocks/controller-runtime/client" | ||
"sigs.k8s.io/aws-load-balancer-controller/pkg/testutils" | ||
ctrl "sigs.k8s.io/controller-runtime" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/controller/controllertest" | ||
"sigs.k8s.io/controller-runtime/pkg/log" | ||
) | ||
|
||
func Test_enqueueRequestsForEndpointSlicesEvent_enqueueImpactedTargetGroupBindings(t *testing.T) { | ||
instanceTargetType := elbv2api.TargetTypeInstance | ||
ipTargetType := elbv2api.TargetTypeIP | ||
|
||
type tgbListCall struct { | ||
opts []client.ListOption | ||
tgbs []*elbv2api.TargetGroupBinding | ||
err error | ||
} | ||
type fields struct { | ||
tgbListCalls []tgbListCall | ||
} | ||
type args struct { | ||
epslice *discv1.EndpointSlice | ||
} | ||
tests := []struct { | ||
name string | ||
fields fields | ||
args args | ||
wantRequests []ctrl.Request | ||
}{ | ||
{ | ||
name: "service event should enqueue impacted ip TargetType TGBs", | ||
fields: fields{ | ||
tgbListCalls: []tgbListCall{ | ||
{ | ||
opts: []client.ListOption{ | ||
client.InNamespace("awesome-ns"), | ||
client.MatchingFields{"spec.serviceRef.name": "awesome-svc"}, | ||
}, | ||
tgbs: []*elbv2api.TargetGroupBinding{ | ||
{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "awesome-ns", | ||
Name: "tgb-1", | ||
}, | ||
Spec: elbv2api.TargetGroupBindingSpec{ | ||
TargetType: &ipTargetType, | ||
}, | ||
}, | ||
{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "awesome-ns", | ||
Name: "tgb-2", | ||
}, | ||
Spec: elbv2api.TargetGroupBindingSpec{ | ||
TargetType: &instanceTargetType, | ||
}, | ||
}, | ||
{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "awesome-ns", | ||
Name: "tgb-3", | ||
}, | ||
Spec: elbv2api.TargetGroupBindingSpec{ | ||
TargetType: &ipTargetType, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
args: args{ | ||
epslice: &discv1.EndpointSlice{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "awesome-ns", | ||
Name: "awesome-svc", | ||
Labels: map[string]string{"kubernetes.io/service-name": "awesome-svc"}, | ||
}, | ||
}, | ||
}, | ||
wantRequests: []ctrl.Request{ | ||
{ | ||
NamespacedName: types.NamespacedName{Namespace: "awesome-ns", Name: "tgb-1"}, | ||
}, | ||
{ | ||
NamespacedName: types.NamespacedName{Namespace: "awesome-ns", Name: "tgb-3"}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "service event should enqueue impacted ip TargetType TGBs - ignore nil TargetType", | ||
fields: fields{ | ||
tgbListCalls: []tgbListCall{ | ||
{ | ||
opts: []client.ListOption{ | ||
client.InNamespace("awesome-ns"), | ||
client.MatchingFields{"spec.serviceRef.name": "awesome-svc"}, | ||
}, | ||
tgbs: []*elbv2api.TargetGroupBinding{ | ||
{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "awesome-ns", | ||
Name: "tgb-1", | ||
}, | ||
Spec: elbv2api.TargetGroupBindingSpec{ | ||
TargetType: &ipTargetType, | ||
}, | ||
}, | ||
{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "awesome-ns", | ||
Name: "tgb-2", | ||
}, | ||
Spec: elbv2api.TargetGroupBindingSpec{ | ||
TargetType: nil, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
args: args{ | ||
epslice: &discv1.EndpointSlice{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "awesome-ns", | ||
Name: "awesome-svc", | ||
Labels: map[string]string{"kubernetes.io/service-name": "awesome-svc"}, | ||
}, | ||
}, | ||
}, | ||
wantRequests: []ctrl.Request{ | ||
{ | ||
NamespacedName: types.NamespacedName{Namespace: "awesome-ns", Name: "tgb-1"}, | ||
}, | ||
}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
ctrl := gomock.NewController(t) | ||
defer ctrl.Finish() | ||
|
||
k8sClient := mock_client.NewMockClient(ctrl) | ||
for _, call := range tt.fields.tgbListCalls { | ||
var extraMatchers []interface{} | ||
for _, opt := range call.opts { | ||
extraMatchers = append(extraMatchers, testutils.NewListOptionEquals(opt)) | ||
} | ||
k8sClient.EXPECT().List(gomock.Any(), gomock.Any(), extraMatchers...).DoAndReturn( | ||
func(ctx context.Context, tgbList *elbv2api.TargetGroupBindingList, opts ...client.ListOption) error { | ||
for _, tgb := range call.tgbs { | ||
tgbList.Items = append(tgbList.Items, *(tgb.DeepCopy())) | ||
} | ||
return call.err | ||
}, | ||
) | ||
} | ||
|
||
h := &enqueueRequestsForEndpointSlicesEvent{ | ||
k8sClient: k8sClient, | ||
logger: &log.NullLogger{}, | ||
} | ||
queue := controllertest.Queue{Interface: workqueue.New()} | ||
h.enqueueImpactedTargetGroupBindings(queue, tt.args.epslice) | ||
gotRequests := testutils.ExtractCTRLRequestsFromQueue(queue) | ||
assert.True(t, cmp.Equal(tt.wantRequests, gotRequests), | ||
"diff", cmp.Diff(tt.wantRequests, gotRequests)) | ||
}) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to specify this via the kube-builder annotation. Please refer to the following
aws-load-balancer-controller/controllers/elbv2/targetgroupbinding_controller.go
Line 83 in f861a8e
Once you specify the kubebuilder annotation, make generate will automatically generate this file