Skip to content

Commit 75d27af

Browse files
authored
add event action config to Terminator (#628)
1 parent b348906 commit 75d27af

File tree

14 files changed

+734
-65
lines changed

14 files changed

+734
-65
lines changed

src/api/v1alpha1/terminator_logging.go

+10
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ func (t *TerminatorSpec) MarshalLogObject(enc zapcore.ObjectEncoder) error {
3131
}
3232
enc.AddObject("sqs", t.SQS)
3333
enc.AddObject("drain", t.Drain)
34+
enc.AddObject("events", t.Events)
3435
return nil
3536
}
3637

@@ -47,3 +48,12 @@ func (d DrainSpec) MarshalLogObject(enc zapcore.ObjectEncoder) error {
4748
enc.AddInt("timeoutSeconds", d.TimeoutSeconds)
4849
return nil
4950
}
51+
52+
func (e EventsSpec) MarshalLogObject(enc zapcore.ObjectEncoder) error {
53+
enc.AddString("autoScalingTermination", e.AutoScalingTermination)
54+
enc.AddString("rebalanceRecommendation", e.RebalanceRecommendation)
55+
enc.AddString("scheduledChange", e.ScheduledChange)
56+
enc.AddString("spotInterruption", e.SpotInterruption)
57+
enc.AddString("stateChange", e.StateChange)
58+
return nil
59+
}

src/api/v1alpha1/terminator_types.go

+22
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type TerminatorSpec struct {
3333
MatchLabels map[string]string `json:"matchLabels,omitempty"`
3434
SQS SQSSpec `json:"sqs,omitempty"`
3535
Drain DrainSpec `json:"drain,omitempty"`
36+
Events EventsSpec `json:"events,omitempty"`
3637
}
3738

3839
// SQSSpec defines inputs to SQS "receive messages" requests.
@@ -51,6 +52,27 @@ type DrainSpec struct {
5152
TimeoutSeconds int `json:"timeoutSeconds,omitempty"`
5253
}
5354

55+
type Action = string
56+
57+
var Actions = struct {
58+
CordonAndDrain,
59+
Cordon,
60+
NoAction Action
61+
}{
62+
CordonAndDrain: Action("CordonAndDrain"),
63+
Cordon: Action("Cordon"),
64+
NoAction: Action("NoAction"),
65+
}
66+
67+
// EventsSpec defines the action(s) that should be performed in response to a particular event.
68+
type EventsSpec struct {
69+
AutoScalingTermination Action `json:"autoScalingTermination,omitempty"`
70+
RebalanceRecommendation Action `json:"rebalanceRecommendation,omitempty"`
71+
ScheduledChange Action `json:"scheduledChange,omitempty"`
72+
SpotInterruption Action `json:"spotInterruption,omitempty"`
73+
StateChange Action `json:"stateChange,omitempty"`
74+
}
75+
5476
// TerminatorStatus defines the observed state of Terminator
5577
type TerminatorStatus struct {
5678
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster

src/api/v1alpha1/terminator_validation.go

+22-5
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ package v1alpha1
1818

1919
import (
2020
"context"
21+
"fmt"
2122
"net/url"
2223

23-
"github.com/aws/aws-sdk-go/service/sqs"
24-
2524
"k8s.io/apimachinery/pkg/util/sets"
2625

2726
"knative.dev/pkg/apis"
2827
)
2928

30-
var (
31-
// https://github.com/aws/aws-sdk-go/blob/v1.38.55/service/sqs/api.go#L3966-L3994
32-
knownSQSAttributeNames = sets.NewString(sqs.MessageSystemAttributeName_Values()...)
29+
var knownActions = sets.NewString(
30+
Actions.CordonAndDrain,
31+
Actions.Cordon,
32+
Actions.NoAction,
3333
)
3434

3535
func (t *Terminator) Validate(_ context.Context) (errs *apis.FieldError) {
@@ -43,6 +43,7 @@ func (t *TerminatorSpec) validate() (errs *apis.FieldError) {
4343
return errs.Also(
4444
t.validateMatchLabels().ViaField("matchLabels"),
4545
t.SQS.validate().ViaField("sqs"),
46+
t.Events.validate().ViaField("events"),
4647
)
4748
}
4849

@@ -61,3 +62,19 @@ func (s *SQSSpec) validate() (errs *apis.FieldError) {
6162
}
6263
return errs
6364
}
65+
66+
func (e *EventsSpec) validate() (errs *apis.FieldError) {
67+
errMsg := fmt.Sprintf("must be one of %s", knownActions.List())
68+
for name, value := range map[string]string{
69+
"autoScalingTermination": e.AutoScalingTermination,
70+
"rebalanceRecommendation": e.RebalanceRecommendation,
71+
"scheduledChange": e.ScheduledChange,
72+
"spotInterruption": e.SpotInterruption,
73+
"stateChange": e.StateChange,
74+
} {
75+
if !knownActions.Has(value) {
76+
errs = errs.Also(apis.ErrInvalidValue(value, name, errMsg))
77+
}
78+
}
79+
return errs
80+
}

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

+39
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,45 @@ spec:
9797
{{- with .Values.terminator.defaults.drain.timeoutSeconds }}
9898
default: {{ . }}
9999
{{- end }}
100+
events:
101+
description: Specify what action should be taken when a particular message type is received.
102+
type: object
103+
properties:
104+
autoScalingTermination:
105+
type: string
106+
enum:
107+
- CordonAndDrain
108+
- Cordon
109+
- NoAction
110+
default: CordonAndDrain
111+
rebalanceRecommendation:
112+
type: string
113+
enum:
114+
- CordonAndDrain
115+
- Cordon
116+
- NoAction
117+
default: CordonAndDrain
118+
scheduledChange:
119+
type: string
120+
enum:
121+
- CordonAndDrain
122+
- Cordon
123+
- NoAction
124+
default: CordonAndDrain
125+
spotInterruption:
126+
type: string
127+
enum:
128+
- CordonAndDrain
129+
- Cordon
130+
- NoAction
131+
default: CordonAndDrain
132+
stateChange:
133+
type: string
134+
enum:
135+
- CordonAndDrain
136+
- Cordon
137+
- NoAction
138+
default: CordonAndDrain
100139
status:
101140
description: TerminatorStatus defines the observed state of Terminator
102141
type: object

src/pkg/event/asgterminate/v1/handler.go

+5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121

2222
"github.com/aws/aws-node-termination-handler/pkg/event/asgterminate/lifecycleaction"
23+
"github.com/aws/aws-node-termination-handler/pkg/terminator"
2324

2425
"go.uber.org/zap"
2526
"go.uber.org/zap/zapcore"
@@ -30,6 +31,10 @@ type EC2InstanceTerminateLifecycleAction struct {
3031
AWSEvent
3132
}
3233

34+
func (EC2InstanceTerminateLifecycleAction) Kind() terminator.EventKind {
35+
return terminator.EventKinds.AutoScalingTermination
36+
}
37+
3338
func (e EC2InstanceTerminateLifecycleAction) EC2InstanceIDs() []string {
3439
return []string{e.Detail.EC2InstanceID}
3540
}

src/pkg/event/asgterminate/v2/handler.go

+5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121

2222
"github.com/aws/aws-node-termination-handler/pkg/event/asgterminate/lifecycleaction"
23+
"github.com/aws/aws-node-termination-handler/pkg/terminator"
2324

2425
"go.uber.org/zap"
2526
"go.uber.org/zap/zapcore"
@@ -30,6 +31,10 @@ type EC2InstanceTerminateLifecycleAction struct {
3031
AWSEvent
3132
}
3233

34+
func (EC2InstanceTerminateLifecycleAction) Kind() terminator.EventKind {
35+
return terminator.EventKinds.AutoScalingTermination
36+
}
37+
3338
func (e EC2InstanceTerminateLifecycleAction) EC2InstanceIDs() []string {
3439
return []string{e.Detail.EC2InstanceID}
3540
}

src/pkg/event/noop.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,23 @@ package event
1919
import (
2020
"context"
2121

22+
"github.com/aws/aws-node-termination-handler/pkg/terminator"
23+
2224
"go.uber.org/zap"
2325
"go.uber.org/zap/zapcore"
2426
)
2527

2628
type noop AWSMetadata
2729

28-
func (n noop) EC2InstanceIDs() []string {
30+
func (noop) Kind() terminator.EventKind {
31+
return terminator.EventKinds.Noop
32+
}
33+
34+
func (noop) EC2InstanceIDs() []string {
2935
return []string{}
3036
}
3137

32-
func (n noop) Done(_ context.Context) (bool, error) {
38+
func (noop) Done(_ context.Context) (bool, error) {
3339
return true, nil
3440
}
3541

src/pkg/event/rebalancerecommendation/v0/handler.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,23 @@ package v0
1919
import (
2020
"context"
2121

22+
"github.com/aws/aws-node-termination-handler/pkg/terminator"
23+
2224
"go.uber.org/zap"
2325
"go.uber.org/zap/zapcore"
2426
)
2527

2628
type EC2InstanceRebalanceRecommendation AWSEvent
2729

30+
func (EC2InstanceRebalanceRecommendation) Kind() terminator.EventKind {
31+
return terminator.EventKinds.RebalanceRecommendation
32+
}
33+
2834
func (e EC2InstanceRebalanceRecommendation) EC2InstanceIDs() []string {
2935
return []string{e.Detail.InstanceID}
3036
}
3137

32-
func (e EC2InstanceRebalanceRecommendation) Done(_ context.Context) (bool, error) {
38+
func (EC2InstanceRebalanceRecommendation) Done(_ context.Context) (bool, error) {
3339
return false, nil
3440
}
3541

src/pkg/event/scheduledchange/v1/handler.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@ package v1
1919
import (
2020
"context"
2121

22+
"github.com/aws/aws-node-termination-handler/pkg/terminator"
23+
2224
"go.uber.org/zap"
2325
"go.uber.org/zap/zapcore"
2426
)
2527

2628
type AWSHealthEvent AWSEvent
2729

30+
func (AWSHealthEvent) Kind() terminator.EventKind {
31+
return terminator.EventKinds.ScheduledChange
32+
}
33+
2834
func (e AWSHealthEvent) EC2InstanceIDs() []string {
2935
ids := make([]string, len(e.Detail.AffectedEntities))
3036
for i, entity := range e.Detail.AffectedEntities {
@@ -33,7 +39,7 @@ func (e AWSHealthEvent) EC2InstanceIDs() []string {
3339
return ids
3440
}
3541

36-
func (e AWSHealthEvent) Done(_ context.Context) (bool, error) {
42+
func (AWSHealthEvent) Done(_ context.Context) (bool, error) {
3743
return false, nil
3844
}
3945

src/pkg/event/spotinterruption/v1/handler.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,23 @@ package v1
1919
import (
2020
"context"
2121

22+
"github.com/aws/aws-node-termination-handler/pkg/terminator"
23+
2224
"go.uber.org/zap"
2325
"go.uber.org/zap/zapcore"
2426
)
2527

2628
type EC2SpotInstanceInterruptionWarning AWSEvent
2729

30+
func (EC2SpotInstanceInterruptionWarning) Kind() terminator.EventKind {
31+
return terminator.EventKinds.SpotInterruption
32+
}
33+
2834
func (e EC2SpotInstanceInterruptionWarning) EC2InstanceIDs() []string {
2935
return []string{e.Detail.InstanceID}
3036
}
3137

32-
func (e EC2SpotInstanceInterruptionWarning) Done(_ context.Context) (bool, error) {
38+
func (EC2SpotInstanceInterruptionWarning) Done(_ context.Context) (bool, error) {
3339
return false, nil
3440
}
3541

src/pkg/event/statechange/v1/handler.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,23 @@ package v1
1919
import (
2020
"context"
2121

22+
"github.com/aws/aws-node-termination-handler/pkg/terminator"
23+
2224
"go.uber.org/zap"
2325
"go.uber.org/zap/zapcore"
2426
)
2527

2628
type EC2InstanceStateChangeNotification AWSEvent
2729

30+
func (EC2InstanceStateChangeNotification) Kind() terminator.EventKind {
31+
return terminator.EventKinds.StateChange
32+
}
33+
2834
func (e EC2InstanceStateChangeNotification) EC2InstanceIDs() []string {
2935
return []string{e.Detail.InstanceID}
3036
}
3137

32-
func (e EC2InstanceStateChangeNotification) Done(_ context.Context) (bool, error) {
38+
func (EC2InstanceStateChangeNotification) Done(_ context.Context) (bool, error) {
3339
return false, nil
3440
}
3541

src/pkg/terminator/eventkind.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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 terminator
18+
19+
type EventKind string
20+
21+
var EventKinds = struct {
22+
AutoScalingTermination,
23+
RebalanceRecommendation,
24+
ScheduledChange,
25+
SpotInterruption,
26+
StateChange,
27+
Noop EventKind
28+
}{
29+
AutoScalingTermination: EventKind("autoScalingTermination"),
30+
RebalanceRecommendation: EventKind("rebalanceRecommendation"),
31+
ScheduledChange: EventKind("scheduledChange"),
32+
SpotInterruption: EventKind("spotInterruption"),
33+
StateChange: EventKind("stateChange"),
34+
Noop: EventKind("noop"),
35+
}
36+
37+
func (e EventKind) String() string {
38+
return string(e)
39+
}

0 commit comments

Comments
 (0)