Skip to content

Commit b348906

Browse files
authored
add node label selector to Terminator (#625)
1 parent 395ae09 commit b348906

File tree

10 files changed

+251
-39
lines changed

10 files changed

+251
-39
lines changed

src/api/v1alpha1/terminator_logging.go

+8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ import (
2121
)
2222

2323
func (t *TerminatorSpec) MarshalLogObject(enc zapcore.ObjectEncoder) error {
24+
if len(t.MatchLabels) > 0 {
25+
enc.AddObject("matchLabels", zapcore.ObjectMarshalerFunc(func(enc zapcore.ObjectEncoder) error {
26+
for name, value := range t.MatchLabels {
27+
enc.AddString(name, value)
28+
}
29+
return nil
30+
}))
31+
}
2432
enc.AddObject("sqs", t.SQS)
2533
enc.AddObject("drain", t.Drain)
2634
return nil

src/api/v1alpha1/terminator_types.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ type TerminatorSpec struct {
3030
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
3131
// Important: Run "make" to regenerate code after modifying this file
3232

33-
SQS SQSSpec `json:"sqs,omitempty"`
34-
Drain DrainSpec `json:"drain,omitempty"`
33+
MatchLabels map[string]string `json:"matchLabels,omitempty"`
34+
SQS SQSSpec `json:"sqs,omitempty"`
35+
Drain DrainSpec `json:"drain,omitempty"`
3536
}
3637

3738
// SQSSpec defines inputs to SQS "receive messages" requests.

src/api/v1alpha1/terminator_validation.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,19 @@ func (t *Terminator) Validate(_ context.Context) (errs *apis.FieldError) {
4040
}
4141

4242
func (t *TerminatorSpec) validate() (errs *apis.FieldError) {
43-
return t.SQS.validate().ViaField("sqs")
43+
return errs.Also(
44+
t.validateMatchLabels().ViaField("matchLabels"),
45+
t.SQS.validate().ViaField("sqs"),
46+
)
47+
}
48+
49+
func (t *TerminatorSpec) validateMatchLabels() (errs *apis.FieldError) {
50+
for name, value := range t.MatchLabels {
51+
if value == "" {
52+
errs = errs.Also(apis.ErrInvalidValue(value, name, "label value cannot be empty"))
53+
}
54+
}
55+
return errs
4456
}
4557

4658
func (s *SQSSpec) validate() (errs *apis.FieldError) {

src/charts/aws-node-termination-handler-2/templates/node.k8s.aws_terminators.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,16 @@ spec:
3636
description: TerminatorSpec defines the desired state of Terminator
3737
type: object
3838
properties:
39+
matchLabels:
40+
description: Filter nodes by label that will be acted upon.
41+
type: object
42+
additionalProperties:
43+
type: string
3944
sqs:
4045
description: AWS SQS queue configuration.
4146
type: object
47+
required:
48+
- queueURL
4249
properties:
4350
queueURL:
4451
description: |

src/cmd/controller/main.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,10 @@ func main() {
156156
rec := terminator.Reconciler{
157157
Name: "terminator",
158158
RequeueInterval: time.Duration(10) * time.Second,
159-
NodeGetter: node.Getter{KubeGetter: kubeClient},
160-
NodeNameGetter: nodename.Getter{EC2InstancesDescriber: ec2Client},
159+
NodeGetterBuilder: terminatoradapter.NodeGetterBuilder{
160+
NodeGetter: node.Getter{KubeGetter: kubeClient},
161+
},
162+
NodeNameGetter: nodename.Getter{EC2InstancesDescriber: ec2Client},
161163
SQSClientBuilder: terminatoradapter.SQSMessageClientBuilder{
162164
SQSMessageClient: sqsmessage.Client{SQSClient: sqsClient},
163165
},

src/pkg/event/noop.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (n noop) EC2InstanceIDs() []string {
3030
}
3131

3232
func (n noop) Done(_ context.Context) (bool, error) {
33-
return false, nil
33+
return true, nil
3434
}
3535

3636
func (n noop) MarshalLogObject(enc zapcore.ObjectEncoder) error {

src/pkg/node/getter.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type (
3636
}
3737
)
3838

39-
func (g Getter) GetNode(ctx context.Context, nodeName string) (*v1.Node, error) {
39+
func (g Getter) GetNode(ctx context.Context, nodeName string, labels map[string]string) (*v1.Node, error) {
4040
ctx = logging.WithLogger(ctx, logging.FromContext(ctx).Named("node"))
4141

4242
node := &v1.Node{}
@@ -47,5 +47,11 @@ func (g Getter) GetNode(ctx context.Context, nodeName string) (*v1.Node, error)
4747
return nil, err
4848
}
4949

50+
for name, value := range labels {
51+
if v, ok := node.Labels[name]; !ok || v != value {
52+
return nil, nil
53+
}
54+
}
55+
5056
return node, nil
5157
}
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
Copyright 2022 Amazon.com, Inc. or its affiliates. All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package adapter
18+
19+
import (
20+
"context"
21+
22+
"github.com/aws/aws-node-termination-handler/api/v1alpha1"
23+
"github.com/aws/aws-node-termination-handler/pkg/terminator"
24+
v1 "k8s.io/api/core/v1"
25+
)
26+
27+
type (
28+
NodeGetter interface {
29+
GetNode(context.Context, string, map[string]string) (*v1.Node, error)
30+
}
31+
32+
NodeGetterBuilder struct {
33+
NodeGetter
34+
}
35+
36+
nodeGetter struct {
37+
NodeGetter
38+
39+
Labels map[string]string
40+
}
41+
)
42+
43+
func (n NodeGetterBuilder) NewNodeGetter(terminator *v1alpha1.Terminator) terminator.NodeGetter {
44+
return nodeGetter{
45+
NodeGetter: n.NodeGetter,
46+
Labels: terminator.Spec.MatchLabels,
47+
}
48+
}
49+
50+
func (n nodeGetter) GetNode(ctx context.Context, nodeName string) (*v1.Node, error) {
51+
return n.NodeGetter.GetNode(ctx, nodeName, n.Labels)
52+
}

src/pkg/terminator/reconciler.go

+18-5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ type (
6161
GetNode(context.Context, string) (*v1.Node, error)
6262
}
6363

64+
NodeGetterBuilder interface {
65+
NewNodeGetter(*v1alpha1.Terminator) NodeGetter
66+
}
67+
6468
NodeNameGetter interface {
6569
GetNodeName(context.Context, string) (string, error)
6670
}
@@ -79,7 +83,7 @@ type (
7983
}
8084

8185
Reconciler struct {
82-
NodeGetter
86+
NodeGetterBuilder
8387
NodeNameGetter
8488
SQSClientBuilder
8589
SQSMessageParser
@@ -102,6 +106,8 @@ func (r Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (recon
102106
return reconcile.Result{}, nil
103107
}
104108

109+
nodeGetter := r.NewNodeGetter(terminator)
110+
105111
cordondrainer, err := r.NewCordonDrainer(terminator)
106112
if err != nil {
107113
return reconcile.Result{}, err
@@ -126,6 +132,7 @@ func (r Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (recon
126132
evt := r.Parse(ctx, msg)
127133
ctx = logging.WithLogger(ctx, logging.FromContext(ctx).With("event", evt))
128134

135+
allInstancesHandled := true
129136
savedCtx := ctx
130137
for _, ec2InstanceID := range evt.EC2InstanceIDs() {
131138
ctx = logging.WithLogger(savedCtx, logging.FromContext(savedCtx).
@@ -135,14 +142,20 @@ func (r Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (recon
135142
nodeName, e := r.GetNodeName(ctx, ec2InstanceID)
136143
if e != nil {
137144
err = multierr.Append(err, e)
145+
allInstancesHandled = false
138146
continue
139147
}
140148

141149
ctx = logging.WithLogger(ctx, logging.FromContext(ctx).With("node", nodeName))
142150

143-
node, e := r.GetNode(ctx, nodeName)
144-
if e != nil {
145-
err = multierr.Append(err, e)
151+
node, e := nodeGetter.GetNode(ctx, nodeName)
152+
if node == nil {
153+
logger := logging.FromContext(ctx)
154+
if e != nil {
155+
logger = logger.With("error", e)
156+
}
157+
logger.Warn("no matching node found")
158+
allInstancesHandled = false
146159
continue
147160
}
148161

@@ -163,7 +176,7 @@ func (r Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (recon
163176
err = multierr.Append(err, e)
164177
}
165178

166-
if tryAgain {
179+
if tryAgain || !allInstancesHandled {
167180
continue
168181
}
169182

0 commit comments

Comments
 (0)