Skip to content

Commit

Permalink
feat: disconnect cluster action (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
anjmao authored Dec 9, 2021
1 parent 79c0a65 commit d4e07ba
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 19 deletions.
15 changes: 8 additions & 7 deletions actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import (
"reflect"
"time"

"github.com/castai/cluster-controller/helm"
"github.com/cenkalti/backoff/v4"
"github.com/sirupsen/logrus"
"k8s.io/client-go/kubernetes"

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

type Config struct {
Expand Down Expand Up @@ -44,12 +44,13 @@ func NewService(
cfg: cfg,
castaiClient: castaiClient,
actionHandlers: map[reflect.Type]ActionHandler{
reflect.TypeOf(&castai.ActionDeleteNode{}): newDeleteNodeHandler(log, clientset),
reflect.TypeOf(&castai.ActionDrainNode{}): newDrainNodeHandler(log, clientset),
reflect.TypeOf(&castai.ActionPatchNode{}): newPatchNodeHandler(log, clientset),
reflect.TypeOf(&castai.ActionCreateEvent{}): newCreateEventHandler(log, clientset),
reflect.TypeOf(&castai.ActionApproveCSR{}): newApproveCSRHandler(log, clientset),
reflect.TypeOf(&castai.ActionChartUpsert{}): newChartUpsertHandler(log, helmClient),
reflect.TypeOf(&castai.ActionDeleteNode{}): newDeleteNodeHandler(log, clientset),
reflect.TypeOf(&castai.ActionDrainNode{}): newDrainNodeHandler(log, clientset),
reflect.TypeOf(&castai.ActionPatchNode{}): newPatchNodeHandler(log, clientset),
reflect.TypeOf(&castai.ActionCreateEvent{}): newCreateEventHandler(log, clientset),
reflect.TypeOf(&castai.ActionApproveCSR{}): newApproveCSRHandler(log, clientset),
reflect.TypeOf(&castai.ActionChartUpsert{}): newChartUpsertHandler(log, helmClient),
reflect.TypeOf(&castai.ActionDisconnectCluster{}): newDisconnectClusterHandler(log, clientset),
},
}
}
Expand Down
47 changes: 47 additions & 0 deletions actions/disconnect_cluster_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package actions

import (
"context"
"fmt"

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

func newDisconnectClusterHandler(log logrus.FieldLogger, client kubernetes.Interface) ActionHandler {
return &disconnectClusterHandler{
log: log,
client: client,
}
}

type disconnectClusterHandler struct {
log logrus.FieldLogger
client kubernetes.Interface
}

func (c *disconnectClusterHandler) Handle(ctx context.Context, data interface{}) error {
ns := "castai-agent"
_, err := c.client.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return nil
}

// Skip if unauthorized. We either deleted access in previous reconcile loop or we never had it.
if apierrors.IsUnauthorized(err) {
return nil
}

return err
}

c.log.Infof("deleting namespace %q", ns)
if err := c.client.CoreV1().Namespaces().Delete(ctx, ns, metav1.DeleteOptions{}); err != nil {
return fmt.Errorf("deleting namespace %q: %v", ns, err)
}

return nil
}
37 changes: 37 additions & 0 deletions actions/disconnect_cluster_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package actions

import (
"context"
"testing"

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

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

func TestDisconnectClusterHandler(t *testing.T) {
r := require.New(t)
ctx := context.Background()

ns := "castai-agent"
node := &v1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: ns,
},
}
clientset := fake.NewSimpleClientset(node)

handler := newDisconnectClusterHandler(logrus.New(), clientset)

err := handler.Handle(ctx, &castai.ActionDisconnectCluster{})
r.NoError(err)

_, err = clientset.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{})
r.Error(err)
r.True(apierrors.IsNotFound(err))
}
28 changes: 17 additions & 11 deletions castai/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ type AckClusterActionRequest struct {
}

type ClusterAction struct {
ID string `json:"id"`
ActionDeleteNode *ActionDeleteNode `json:"actionDeleteNode,omitempty"`
ActionDrainNode *ActionDrainNode `json:"actionDrainNode,omitempty"`
ActionPatchNode *ActionPatchNode `json:"actionPatchNode,omitempty"`
ActionCreateEvent *ActionCreateEvent `json:"actionCreateEvent,omitempty"`
ActionApproveCSR *ActionApproveCSR `json:"actionApproveCsr,omitempty"`
ActionChartUpsert *ActionChartUpsert `json:"actionChartUpsert,omitempty"`
CreatedAt time.Time `json:"createdAt"`
DoneAt *time.Time `json:"doneAt,omitempty"`
Error *string `json:"error,omitempty"`
ID string `json:"id"`
ActionDeleteNode *ActionDeleteNode `json:"actionDeleteNode,omitempty"`
ActionDrainNode *ActionDrainNode `json:"actionDrainNode,omitempty"`
ActionPatchNode *ActionPatchNode `json:"actionPatchNode,omitempty"`
ActionCreateEvent *ActionCreateEvent `json:"actionCreateEvent,omitempty"`
ActionApproveCSR *ActionApproveCSR `json:"actionApproveCsr,omitempty"`
ActionChartUpsert *ActionChartUpsert `json:"actionChartUpsert,omitempty"`
ActionDisconnectCluster *ActionDisconnectCluster `json:"actionDisconnectCluster,omitempty"`
CreatedAt time.Time `json:"createdAt"`
DoneAt *time.Time `json:"doneAt,omitempty"`
Error *string `json:"error,omitempty"`
}

func (c *ClusterAction) Data() interface{} {
Expand All @@ -48,7 +49,9 @@ func (c *ClusterAction) Data() interface{} {
if c.ActionChartUpsert != nil {
return c.ActionChartUpsert
}

if c.ActionDisconnectCluster != nil {
return c.ActionDisconnectCluster
}
return nil
}

Expand Down Expand Up @@ -95,6 +98,9 @@ type ActionCreateEvent struct {
Message string `json:"message"`
}

type ActionDisconnectCluster struct {
}

type ActionChartUpsert struct {
Namespace string `json:"namespace"`
ReleaseName string `json:"releaseName"`
Expand Down
20 changes: 20 additions & 0 deletions helm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ type InstallOptions struct {
ValuesOverrides map[string]string
}

type UninstallOptions struct {
Namespace string
ReleaseName string
}

type UpgradeOptions struct {
ChartSource *castai.ChartSource
Release *release.Release
Expand Down Expand Up @@ -62,6 +67,7 @@ func NewClient(log logrus.FieldLogger, loader ChartLoader, restConfig *rest.Conf

type Client interface {
Install(ctx context.Context, opts InstallOptions) (*release.Release, error)
Uninstall(opts UninstallOptions) (*release.UninstallReleaseResponse, error)
Upgrade(ctx context.Context, opts UpgradeOptions) (*release.Release, error)
Rollback(opts RollbackOptions) error
GetRelease(opts GetReleaseOptions) (*release.Release, error)
Expand Down Expand Up @@ -111,6 +117,20 @@ func (c *client) Install(ctx context.Context, opts InstallOptions) (*release.Rel
return res, err
}

func (c *client) Uninstall(opts UninstallOptions) (*release.UninstallReleaseResponse, error) {
cfg, err := c.configurationGetter.Get(opts.Namespace)
if err != nil {
return nil, err
}

uninstall := action.NewUninstall(cfg)
res, err := uninstall.Run(opts.ReleaseName)
if err != nil {
return nil, fmt.Errorf("chart uninstall failed, name=%s, namespace=%s: %w", opts.ReleaseName, opts.Namespace, err)
}
return res, nil
}

func (c *client) Upgrade(ctx context.Context, opts UpgradeOptions) (*release.Release, error) {
ch, err := c.chartLoader.Load(ctx, opts.ChartSource)
if err != nil {
Expand Down
23 changes: 22 additions & 1 deletion helm/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"io/ioutil"
"testing"

"github.com/castai/cluster-controller/castai"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
"helm.sh/helm/v3/pkg/action"
Expand All @@ -16,6 +15,8 @@ import (
"helm.sh/helm/v3/pkg/storage"
"helm.sh/helm/v3/pkg/storage/driver"
"helm.sh/helm/v3/pkg/time"

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

func TestClientInstall(t *testing.T) {
Expand Down Expand Up @@ -74,6 +75,26 @@ func TestClientUpdate(t *testing.T) {
r.Equal("noop", rel.Config["random"])
}

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

currentRelease := buildNginxIngressRelease(release.StatusDeployed)
client := &client{
log: logrus.New(),
chartLoader: &testChartLoader{chart: buildNginxIngressChart()},
configurationGetter: &testConfigurationGetter{
t: t,
currentRelease: currentRelease,
},
}

_, err := client.Uninstall(UninstallOptions{
ReleaseName: currentRelease.Name,
Namespace: currentRelease.Namespace,
})
r.NoError(err)
}

type testConfigurationGetter struct {
t *testing.T
currentRelease *release.Release
Expand Down
15 changes: 15 additions & 0 deletions helm/mock/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d4e07ba

Please sign in to comment.