Skip to content
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

add event action config to Terminator #628

Merged
merged 6 commits into from
Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/api/v1alpha1/terminator_logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func (t *TerminatorSpec) MarshalLogObject(enc zapcore.ObjectEncoder) error {
}
enc.AddObject("sqs", t.SQS)
enc.AddObject("drain", t.Drain)
enc.AddObject("events", t.Events)
return nil
}

Expand All @@ -47,3 +48,12 @@ func (d DrainSpec) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddInt("timeoutSeconds", d.TimeoutSeconds)
return nil
}

func (e EventsSpec) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddString("autoScalingTermination", e.AutoScalingTermination)
enc.AddString("rebalanceRecommendation", e.RebalanceRecommendation)
enc.AddString("scheduledChange", e.ScheduledChange)
enc.AddString("spotInterruption", e.SpotInterruption)
enc.AddString("stateChange", e.StateChange)
return nil
}
22 changes: 22 additions & 0 deletions src/api/v1alpha1/terminator_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type TerminatorSpec struct {
MatchLabels map[string]string `json:"matchLabels,omitempty"`
SQS SQSSpec `json:"sqs,omitempty"`
Drain DrainSpec `json:"drain,omitempty"`
Events EventsSpec `json:"events,omitempty"`
}

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

type Action = string

var Actions = struct {
CordonAndDrain,
Cordon,
NoAction Action
}{
CordonAndDrain: Action("CordonAndDrain"),
Cordon: Action("Cordon"),
NoAction: Action("NoAction"),
}

// EventsSpec defines the action(s) that should be performed in response to a particular event.
type EventsSpec struct {
AutoScalingTermination Action `json:"autoScalingTermination,omitempty"`
RebalanceRecommendation Action `json:"rebalanceRecommendation,omitempty"`
ScheduledChange Action `json:"scheduledChange,omitempty"`
SpotInterruption Action `json:"spotInterruption,omitempty"`
StateChange Action `json:"stateChange,omitempty"`
}

// TerminatorStatus defines the observed state of Terminator
type TerminatorStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
Expand Down
27 changes: 22 additions & 5 deletions src/api/v1alpha1/terminator_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ package v1alpha1

import (
"context"
"fmt"
"net/url"

"github.com/aws/aws-sdk-go/service/sqs"

"k8s.io/apimachinery/pkg/util/sets"

"knative.dev/pkg/apis"
)

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

func (t *Terminator) Validate(_ context.Context) (errs *apis.FieldError) {
Expand All @@ -43,6 +43,7 @@ func (t *TerminatorSpec) validate() (errs *apis.FieldError) {
return errs.Also(
t.validateMatchLabels().ViaField("matchLabels"),
t.SQS.validate().ViaField("sqs"),
t.Events.validate().ViaField("events"),
)
}

Expand All @@ -61,3 +62,19 @@ func (s *SQSSpec) validate() (errs *apis.FieldError) {
}
return errs
}

func (e *EventsSpec) validate() (errs *apis.FieldError) {
errMsg := fmt.Sprintf("must be one of %s", knownActions.List())
for name, value := range map[string]string{
"autoScalingTermination": e.AutoScalingTermination,
"rebalanceRecommendation": e.RebalanceRecommendation,
"scheduledChange": e.ScheduledChange,
"spotInterruption": e.SpotInterruption,
"stateChange": e.StateChange,
} {
if !knownActions.Has(value) {
errs = errs.Also(apis.ErrInvalidValue(value, name, errMsg))
}
}
return errs
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,45 @@ spec:
{{- with .Values.terminator.defaults.drain.timeoutSeconds }}
default: {{ . }}
{{- end }}
events:
description: Specify what action should be taken when a particular message type is received.
type: object
properties:
autoScalingTermination:
type: string
enum:
- CordonAndDrain
- Cordon
- NoAction
default: CordonAndDrain
rebalanceRecommendation:
type: string
enum:
- CordonAndDrain
- Cordon
- NoAction
default: CordonAndDrain
scheduledChange:
type: string
enum:
- CordonAndDrain
- Cordon
- NoAction
default: CordonAndDrain
spotInterruption:
type: string
enum:
- CordonAndDrain
- Cordon
- NoAction
default: CordonAndDrain
stateChange:
type: string
enum:
- CordonAndDrain
- Cordon
- NoAction
default: CordonAndDrain
status:
description: TerminatorStatus defines the observed state of Terminator
type: object
Expand Down
5 changes: 5 additions & 0 deletions src/pkg/event/asgterminate/v1/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"

"github.com/aws/aws-node-termination-handler/pkg/event/asgterminate/lifecycleaction"
"github.com/aws/aws-node-termination-handler/pkg/terminator"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
Expand All @@ -30,6 +31,10 @@ type EC2InstanceTerminateLifecycleAction struct {
AWSEvent
}

func (EC2InstanceTerminateLifecycleAction) Kind() terminator.EventKind {
return terminator.EventKinds.AutoScalingTermination
}

func (e EC2InstanceTerminateLifecycleAction) EC2InstanceIDs() []string {
return []string{e.Detail.EC2InstanceID}
}
Expand Down
5 changes: 5 additions & 0 deletions src/pkg/event/asgterminate/v2/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"

"github.com/aws/aws-node-termination-handler/pkg/event/asgterminate/lifecycleaction"
"github.com/aws/aws-node-termination-handler/pkg/terminator"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
Expand All @@ -30,6 +31,10 @@ type EC2InstanceTerminateLifecycleAction struct {
AWSEvent
}

func (EC2InstanceTerminateLifecycleAction) Kind() terminator.EventKind {
return terminator.EventKinds.AutoScalingTermination
}

func (e EC2InstanceTerminateLifecycleAction) EC2InstanceIDs() []string {
return []string{e.Detail.EC2InstanceID}
}
Expand Down
10 changes: 8 additions & 2 deletions src/pkg/event/noop.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,23 @@ package event
import (
"context"

"github.com/aws/aws-node-termination-handler/pkg/terminator"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

type noop AWSMetadata

func (n noop) EC2InstanceIDs() []string {
func (noop) Kind() terminator.EventKind {
return terminator.EventKinds.Noop
}

func (noop) EC2InstanceIDs() []string {
return []string{}
}

func (n noop) Done(_ context.Context) (bool, error) {
func (noop) Done(_ context.Context) (bool, error) {
return true, nil
}

Expand Down
8 changes: 7 additions & 1 deletion src/pkg/event/rebalancerecommendation/v0/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,23 @@ package v0
import (
"context"

"github.com/aws/aws-node-termination-handler/pkg/terminator"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

type EC2InstanceRebalanceRecommendation AWSEvent

func (EC2InstanceRebalanceRecommendation) Kind() terminator.EventKind {
return terminator.EventKinds.RebalanceRecommendation
}

func (e EC2InstanceRebalanceRecommendation) EC2InstanceIDs() []string {
return []string{e.Detail.InstanceID}
}

func (e EC2InstanceRebalanceRecommendation) Done(_ context.Context) (bool, error) {
func (EC2InstanceRebalanceRecommendation) Done(_ context.Context) (bool, error) {
return false, nil
}

Expand Down
8 changes: 7 additions & 1 deletion src/pkg/event/scheduledchange/v1/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@ package v1
import (
"context"

"github.com/aws/aws-node-termination-handler/pkg/terminator"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

type AWSHealthEvent AWSEvent

func (AWSHealthEvent) Kind() terminator.EventKind {
return terminator.EventKinds.ScheduledChange
}

func (e AWSHealthEvent) EC2InstanceIDs() []string {
ids := make([]string, len(e.Detail.AffectedEntities))
for i, entity := range e.Detail.AffectedEntities {
Expand All @@ -33,7 +39,7 @@ func (e AWSHealthEvent) EC2InstanceIDs() []string {
return ids
}

func (e AWSHealthEvent) Done(_ context.Context) (bool, error) {
func (AWSHealthEvent) Done(_ context.Context) (bool, error) {
return false, nil
}

Expand Down
8 changes: 7 additions & 1 deletion src/pkg/event/spotinterruption/v1/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,23 @@ package v1
import (
"context"

"github.com/aws/aws-node-termination-handler/pkg/terminator"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

type EC2SpotInstanceInterruptionWarning AWSEvent

func (EC2SpotInstanceInterruptionWarning) Kind() terminator.EventKind {
return terminator.EventKinds.SpotInterruption
}

func (e EC2SpotInstanceInterruptionWarning) EC2InstanceIDs() []string {
return []string{e.Detail.InstanceID}
}

func (e EC2SpotInstanceInterruptionWarning) Done(_ context.Context) (bool, error) {
func (EC2SpotInstanceInterruptionWarning) Done(_ context.Context) (bool, error) {
return false, nil
}

Expand Down
8 changes: 7 additions & 1 deletion src/pkg/event/statechange/v1/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,23 @@ package v1
import (
"context"

"github.com/aws/aws-node-termination-handler/pkg/terminator"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

type EC2InstanceStateChangeNotification AWSEvent

func (EC2InstanceStateChangeNotification) Kind() terminator.EventKind {
return terminator.EventKinds.StateChange
}

func (e EC2InstanceStateChangeNotification) EC2InstanceIDs() []string {
return []string{e.Detail.InstanceID}
}

func (e EC2InstanceStateChangeNotification) Done(_ context.Context) (bool, error) {
func (EC2InstanceStateChangeNotification) Done(_ context.Context) (bool, error) {
return false, nil
}

Expand Down
39 changes: 39 additions & 0 deletions src/pkg/terminator/eventkind.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
Copyright 2022 Amazon.com, Inc. or its affiliates. All rights reserved.

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 terminator

type EventKind string

var EventKinds = struct {
AutoScalingTermination,
RebalanceRecommendation,
ScheduledChange,
SpotInterruption,
StateChange,
Noop EventKind
}{
AutoScalingTermination: EventKind("autoScalingTermination"),
RebalanceRecommendation: EventKind("rebalanceRecommendation"),
ScheduledChange: EventKind("scheduledChange"),
SpotInterruption: EventKind("spotInterruption"),
StateChange: EventKind("stateChange"),
Noop: EventKind("noop"),
}

func (e EventKind) String() string {
return string(e)
}
Loading