Skip to content

Commit

Permalink
feat: apps remove tear down app completely + apps deploy tears down r…
Browse files Browse the repository at this point in the history
…esources when failed (#311)

* feat: apps remove tear down app completely + apps deploy tears down resources when failed
  • Loading branch information
raulb authored Apr 15, 2022
1 parent ac91128 commit 2a08bba
Show file tree
Hide file tree
Showing 14 changed files with 233 additions and 37 deletions.
26 changes: 25 additions & 1 deletion cmd/meroxa/root/apps/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const (
type deployApplicationClient interface {
CreateApplication(ctx context.Context, input *meroxa.CreateApplicationInput) (*meroxa.Application, error)
GetApplication(ctx context.Context, nameOrUUID string) (*meroxa.Application, error)
DeleteApplicationEntities(ctx context.Context, name string) (*http.Response, error)
CreateBuild(ctx context.Context, input *meroxa.CreateBuildInput) (*meroxa.Build, error)
CreateSource(ctx context.Context) (*meroxa.Source, error)
GetBuild(ctx context.Context, uuid string) (*meroxa.Build, error)
Expand Down Expand Up @@ -410,7 +411,9 @@ func (d *Deploy) deployApp(ctx context.Context, imageName string) (string, error
func (d *Deploy) buildApp(ctx context.Context) error {
var err error

d.logger.StartSpinner("\t", "Building application...")
// Without the " " at the beginning of `suffix`, spinner looks next to word (only on this occurrence)
// TODO: Fix this (not having to add that extra blank space at the beginning)
d.logger.StartSpinner("\t", " Building application...")

switch d.lang {
case GoLang:
Expand Down Expand Up @@ -536,12 +539,33 @@ func (d *Deploy) prepareAppForDeployment(ctx context.Context) error {
return err
}

func (d *Deploy) tearDownExistingResources(ctx context.Context) error {
app, _ := d.client.GetApplication(ctx, d.appName)

if app != nil && app.Status.State == meroxa.ApplicationStateRunning {
appIsReady := fmt.Sprintf("application %q is already %s", d.appName, app.Status.State)
msg := fmt.Sprintf("%s\n\t. Use `meroxa apps remove %s` if you want to redeploy to this application", appIsReady, d.appName)
return errors.New(msg)
}
resp, _ := d.client.DeleteApplicationEntities(ctx, d.appName)
if resp.Body != nil {
defer resp.Body.Close()
}
return nil
}

func (d *Deploy) Execute(ctx context.Context) error {
err := d.validate(ctx)
if err != nil {
return err
}

// ⚠️ This is only until we re-deploy applications applying only the changes made
err = d.tearDownExistingResources(ctx)
if err != nil {
return err
}

err = d.prepareAppForDeployment(ctx)
if err != nil {
return err
Expand Down
96 changes: 96 additions & 0 deletions cmd/meroxa/root/apps/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"reflect"
"testing"
Expand Down Expand Up @@ -288,6 +289,101 @@ func TestCreateApplication(t *testing.T) {
}
}

func TestTearDownExistingResourcesWithAppRunning(t *testing.T) {
ctx := context.Background()
ctrl := gomock.NewController(t)
client := mock.NewMockClient(ctrl)
logger := log.NewTestLogger()

d := &Deploy{
client: client,
logger: logger,
}

app := utils.GenerateApplication("")
d.appName = app.Name

client.
EXPECT().
GetApplication(ctx, app.Name).
Return(&app, nil)

err := d.tearDownExistingResources(ctx)

expectedError := fmt.Sprintf("application %q is already %s", app.Name, app.Status.State)
expectedError = fmt.Sprintf("%s\n\t. Use `meroxa apps remove %s` if you want to redeploy to this application", expectedError, app.Name)
if err.Error() != expectedError {
t.Fatalf("expected %s error, got \"%s\"", expectedError, err.Error())
}
}

func TestTearDownExistingResourcesWithAppDegraded(t *testing.T) {
ctx := context.Background()
ctrl := gomock.NewController(t)
client := mock.NewMockClient(ctrl)
logger := log.NewTestLogger()

d := &Deploy{
client: client,
logger: logger,
}

app := utils.GenerateApplication(meroxa.ApplicationStateDegraded)
d.appName = app.Name

client.
EXPECT().
GetApplication(ctx, app.Name).
Return(&app, nil)

res := &http.Response{
StatusCode: http.StatusNoContent,
}
client.
EXPECT().
DeleteApplicationEntities(ctx, d.appName).
Return(res, nil)

err := d.tearDownExistingResources(ctx)

if err != nil {
t.Fatalf("not expected error, got %q", err.Error())
}
}

func TestTearDownExistingResourcesWithAppNotFound(t *testing.T) {
ctx := context.Background()
ctrl := gomock.NewController(t)
client := mock.NewMockClient(ctrl)
logger := log.NewTestLogger()

d := &Deploy{
client: client,
logger: logger,
}

d.appName = "test"

client.
EXPECT().
GetApplication(ctx, d.appName).
Return(nil, nil)

res := &http.Response{
StatusCode: http.StatusNoContent,
}
client.
EXPECT().
DeleteApplicationEntities(ctx, d.appName).
Return(res, nil)

err := d.tearDownExistingResources(ctx)

if err != nil {
t.Fatalf("not expected error, got %q", err.Error())
}
}

func initLocalApp(name string) (string, error) {
if err := os.Mkdir(tempAppDir, 0700); err != nil {
return "", err
Expand Down
4 changes: 2 additions & 2 deletions cmd/meroxa/root/apps/describe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestDescribeApplicationExecution(t *testing.T) {

appName := "my-env"

a := utils.GenerateApplication()
a := utils.GenerateApplication("")
a.Name = appName

client.
Expand Down Expand Up @@ -114,7 +114,7 @@ func TestDescribeApplicationExecutionWithFunctions(t *testing.T) {

appName := "my-app-with-funcs"

a := utils.GenerateApplication()
a := utils.GenerateApplication("")
a.Name = appName
a.Functions = []meroxa.EntityIdentifier{
{Name: null.StringFrom("fun1")},
Expand Down
2 changes: 1 addition & 1 deletion cmd/meroxa/root/apps/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestListAppsExecution(t *testing.T) {
Name: "my-app",
UUID: "531428f7-4e86-4094-8514-d397d49026f7",
Language: GoLang,
Status: meroxa.ApplicationStatus{State: meroxa.ApplicationStateReady},
Status: meroxa.ApplicationStatus{State: meroxa.ApplicationStateRunning},
}

apps := []*meroxa.Application{aa}
Expand Down
13 changes: 5 additions & 8 deletions cmd/meroxa/root/apps/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ package apps
import (
"context"
"errors"
"net/http"

"github.com/meroxa/cli/cmd/meroxa/builder"
"github.com/meroxa/cli/log"
"github.com/meroxa/meroxa-go/pkg/meroxa"
)

type removeAppClient interface {
GetApplication(ctx context.Context, nameOrUUID string) (*meroxa.Application, error)
DeleteApplication(ctx context.Context, nameOrUUID string) error
DeleteApplicationEntities(ctx context.Context, name string) (*http.Response, error)
}

type Remove struct {
Expand Down Expand Up @@ -56,15 +56,12 @@ func (r *Remove) ValueToConfirm(_ context.Context) (wantInput string) {
func (r *Remove) Execute(ctx context.Context) error {
r.logger.Infof(ctx, "Removing application %q...", r.args.NameOrUUID)

res, err := r.client.GetApplication(ctx, r.args.NameOrUUID)
res, err := r.client.DeleteApplicationEntities(ctx, r.args.NameOrUUID)
if err != nil {
return err
}

err = r.client.DeleteApplication(ctx, r.args.NameOrUUID)

if err != nil {
return err
if res.Body != nil {
defer res.Body.Close()
}

r.logger.Infof(ctx, "Application %q successfully removed", r.args.NameOrUUID)
Expand Down
28 changes: 14 additions & 14 deletions cmd/meroxa/root/apps/remove_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ import (
"encoding/json"
"errors"
"fmt"
"net/http"
"reflect"
"testing"

"github.com/golang/mock/gomock"

"github.com/meroxa/cli/log"
"github.com/meroxa/cli/utils"
"github.com/meroxa/meroxa-go/pkg/meroxa"
"github.com/meroxa/meroxa-go/pkg/mock"
)

Expand Down Expand Up @@ -67,18 +67,17 @@ func TestRemoveAppExecution(t *testing.T) {
logger: logger,
}

res := utils.GenerateApplication()
r.args.NameOrUUID = res.Name
app := utils.GenerateApplication("")
r.args.NameOrUUID = app.Name

client.
EXPECT().
GetApplication(ctx, r.args.NameOrUUID).
Return(&res, nil)
res := &http.Response{
StatusCode: http.StatusNoContent,
}

client.
EXPECT().
DeleteApplication(ctx, r.args.NameOrUUID).
Return(nil)
DeleteApplicationEntities(ctx, r.args.NameOrUUID).
Return(res, nil)

err := r.Execute(ctx)

Expand All @@ -89,20 +88,21 @@ func TestRemoveAppExecution(t *testing.T) {
gotLeveledOutput := logger.LeveledOutput()
wantLeveledOutput := fmt.Sprintf(`Removing application %q...
Application %q successfully removed
`, res.Name, res.Name)
`, app.Name, app.Name)

if gotLeveledOutput != wantLeveledOutput {
t.Fatalf("expected output:\n%s\ngot:\n%s", wantLeveledOutput, gotLeveledOutput)
}

gotJSONOutput := logger.JSONOutput()
var gotApplication meroxa.Application
err = json.Unmarshal([]byte(gotJSONOutput), &gotApplication)

var gotResponse *http.Response
err = json.Unmarshal([]byte(gotJSONOutput), &gotResponse)
if err != nil {
t.Fatalf("not expected error, got %q", err.Error())
}

if !reflect.DeepEqual(gotApplication, res) {
t.Fatalf("expected \"%v\", got \"%v\"", res, gotApplication)
if !reflect.DeepEqual(gotResponse, res) {
t.Fatalf("expected \"%v\", got \"%v\"", gotResponse, res)
}
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/manifoldco/promptui v0.8.0
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-runewidth v0.0.10 // indirect
github.com/meroxa/meroxa-go v0.0.0-20220404191043-2fff202066b1
github.com/meroxa/meroxa-go v0.0.0-20220415204845-92b08f71390e
github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20170819232839-0fbfe93532da
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4
github.com/rivo/uniseg v0.2.0 // indirect
Expand All @@ -28,7 +28,7 @@ require (
github.com/briandowns/spinner v1.18.1
github.com/docker/docker v20.10.12+incompatible
github.com/mattn/go-shellwords v1.0.12
github.com/meroxa/turbine-go v0.0.0-20220415162617-7cd06570b49b
github.com/meroxa/turbine-go v0.0.0-20220415203703-5ab9fcaf547d
github.com/volatiletech/null/v8 v8.1.2
)

Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -574,10 +574,10 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182aff
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
github.com/meroxa/funtime v0.0.0-20220113012133-85e6e898fc73/go.mod h1:K2y2GvcA4Cg3dJtckcwYWnwnJzF63FDdtAQI0fToU0Q=
github.com/meroxa/meroxa-go v0.0.0-20220208195203-71ddc3133fab/go.mod h1:HDFszURCM1cOpKE699o5Hs0T2tEIXqY+vFcsur3RiwY=
github.com/meroxa/meroxa-go v0.0.0-20220404191043-2fff202066b1 h1:RXAOz9J0QeJS4w62qOkBc1bYRxMq8FwsV0L7BoAkvJU=
github.com/meroxa/meroxa-go v0.0.0-20220404191043-2fff202066b1/go.mod h1:BsqYa9jqfyGOAgfkggfK567b2Ahkb+RCH3lXDQGgrh8=
github.com/meroxa/turbine-go v0.0.0-20220415162617-7cd06570b49b h1:Elj6aOiV+ZQaWA8CfsozVIlBKEzQQKgbYncCbXNv7TU=
github.com/meroxa/turbine-go v0.0.0-20220415162617-7cd06570b49b/go.mod h1:F4ODyjX+tn5dYFRc1bQlHLUnTtlJIxs09AKHqfCD5Cg=
github.com/meroxa/meroxa-go v0.0.0-20220415204845-92b08f71390e h1:Gkv7fU8Bc2sBbNoJu1K5ElHyJ3HsYb7k43ikJpaE4uM=
github.com/meroxa/meroxa-go v0.0.0-20220415204845-92b08f71390e/go.mod h1:BsqYa9jqfyGOAgfkggfK567b2Ahkb+RCH3lXDQGgrh8=
github.com/meroxa/turbine-go v0.0.0-20220415203703-5ab9fcaf547d h1:JWJ0rrFmm9zV3WMMm3hIXS0Ebegm129SVs3zPcFi2Kk=
github.com/meroxa/turbine-go v0.0.0-20220415203703-5ab9fcaf547d/go.mod h1:F4ODyjX+tn5dYFRc1bQlHLUnTtlJIxs09AKHqfCD5Cg=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
Expand Down
8 changes: 7 additions & 1 deletion utils/tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,16 @@ func GenerateEnvironment(environmentName string) meroxa.Environment {
}
}

func GenerateApplication() meroxa.Application {
func GenerateApplication(state meroxa.ApplicationState) meroxa.Application {
if state == "" {
state = meroxa.ApplicationStateRunning
}
return meroxa.Application{
Name: "application-name",
Language: "golang",
Status: meroxa.ApplicationStatus{
State: state,
},
}
}

Expand Down
Loading

0 comments on commit 2a08bba

Please sign in to comment.