Skip to content

Commit

Permalink
feat: add check node deleted action (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
anjmao authored May 18, 2022
1 parent 7d3815c commit 0d31d5c
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 0 deletions.
1 change: 1 addition & 0 deletions actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func NewService(
reflect.TypeOf(&castai.ActionChartUninstall{}): newChartUninstallHandler(log, helmClient),
reflect.TypeOf(&castai.ActionDisconnectCluster{}): newDisconnectClusterHandler(log, clientset),
reflect.TypeOf(&castai.ActionSendAKSInitData{}): newSendAKSInitDataHandler(log, castaiClient),
reflect.TypeOf(&castai.ActionCheckNodeDeleted{}): newCheckNodeDeletedHandler(log, clientset),
},
}
}
Expand Down
60 changes: 60 additions & 0 deletions actions/check_node_deleted.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package actions

import (
"context"
"errors"
"fmt"
"time"

"github.com/cenkalti/backoff/v4"
"github.com/sirupsen/logrus"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"

"github.com/castai/cluster-controller/castai"
)

type checkNodeDeletedConfig struct {
retries uint64
retryWait time.Duration
}

func newCheckNodeDeletedHandler(log logrus.FieldLogger, clientset kubernetes.Interface) ActionHandler {
return &checkNodeDeletedHandler{
log: log,
clientset: clientset,
cfg: checkNodeDeletedConfig{
retries: 5,
retryWait: 1 * time.Second,
},
}
}

type checkNodeDeletedHandler struct {
log logrus.FieldLogger
clientset kubernetes.Interface
cfg checkNodeDeletedConfig
}

func (h *checkNodeDeletedHandler) Handle(ctx context.Context, data interface{}) error {
req, ok := data.(*castai.ActionCheckNodeDeleted)
if !ok {
return fmt.Errorf("unexpected type %T for check node deleted handler", data)
}

log := h.log.WithField("node_name", req.NodeName)
log.Info("checking if node is deleted")

b := backoff.WithContext(backoff.WithMaxRetries(backoff.NewConstantBackOff(h.cfg.retryWait), h.cfg.retries), ctx)
return backoff.Retry(func() error {
n, err := h.clientset.CoreV1().Nodes().Get(ctx, req.NodeName, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
return nil
}
if n != nil {
return backoff.Permanent(errors.New("node is not deleted"))
}
return err
}, b)
}
61 changes: 61 additions & 0 deletions actions/check_node_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package actions

import (
"context"
"testing"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"

"github.com/castai/cluster-controller/castai"
)

func TestCheckNodeDeletedHandler(t *testing.T) {
r := require.New(t)

log := logrus.New()
log.SetLevel(logrus.DebugLevel)

t.Run("return error when node is not deleted", func(t *testing.T) {
nodeName := "node1"
node := &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: nodeName,
},
}
clientset := fake.NewSimpleClientset(node)

h := checkNodeDeletedHandler{
log: log,
clientset: clientset,
cfg: checkNodeDeletedConfig{},
}

req := &castai.ActionCheckNodeDeleted{
NodeName: "node1",
}

err := h.Handle(context.Background(), req)
r.EqualError(err, "node is not deleted")
})

t.Run("handle check successfully when node is not found", func(t *testing.T) {
clientset := fake.NewSimpleClientset()

h := checkNodeDeletedHandler{
log: log,
clientset: clientset,
cfg: checkNodeDeletedConfig{},
}

req := &castai.ActionCheckNodeDeleted{
NodeName: "node1",
}

err := h.Handle(context.Background(), req)
r.NoError(err)
})
}
8 changes: 8 additions & 0 deletions castai/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type ClusterAction struct {
ActionChartUninstall *ActionChartUninstall `json:"actionChartUninstall,omitempty"`
ActionDisconnectCluster *ActionDisconnectCluster `json:"actionDisconnectCluster,omitempty"`
ActionSendAKSInitData *ActionSendAKSInitData `json:"actionSendAksInitData,omitempty"`
ActionCheckNodeDeleted *ActionCheckNodeDeleted `json:"actionCheckNodeDeleted,omitempty"`
CreatedAt time.Time `json:"createdAt"`
DoneAt *time.Time `json:"doneAt,omitempty"`
Error *string `json:"error,omitempty"`
Expand Down Expand Up @@ -60,6 +61,9 @@ func (c *ClusterAction) Data() interface{} {
if c.ActionSendAKSInitData != nil {
return c.ActionSendAKSInitData
}
if c.ActionCheckNodeDeleted != nil {
return c.ActionCheckNodeDeleted
}
return nil
}

Expand Down Expand Up @@ -112,6 +116,10 @@ type ActionDisconnectCluster struct {
type ActionSendAKSInitData struct {
}

type ActionCheckNodeDeleted struct {
NodeName string `json:"nodeName"`
}

type ActionChartUpsert struct {
Namespace string `json:"namespace"`
ReleaseName string `json:"releaseName"`
Expand Down

0 comments on commit 0d31d5c

Please sign in to comment.