Skip to content

Commit

Permalink
Add warning when deleting an environment with existing applications (#…
Browse files Browse the repository at this point in the history
…7786)

# Description
Add additional warning for deleting environments with existing applications.

## Type of change

- This pull request adds or changes features of Radius and has an
approved issue (issue link required).

Fixes: #7529

---------

Signed-off-by: SoTrx <[email protected]>
Signed-off-by: SoTrxII <[email protected]>
  • Loading branch information
SoTrx authored Aug 13, 2024
1 parent 255c6d8 commit d01ecf9
Show file tree
Hide file tree
Showing 2 changed files with 203 additions and 14 deletions.
32 changes: 26 additions & 6 deletions pkg/cli/cmd/env/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package delete
import (
"context"
"fmt"
"strings"

"github.com/radius-project/radius/pkg/cli"
"github.com/radius-project/radius/pkg/cli/cmd/commonflags"
Expand All @@ -31,6 +32,7 @@ import (
)

const (
warnDependencies = "There are currently application(s) or resource(s) associated with this environment."
deleteConfirmation = "Are you sure you want to delete environment '%v'?"
)

Expand Down Expand Up @@ -140,9 +142,32 @@ func (r *Runner) Validate(cmd *cobra.Command, args []string) error {
// Run prompts the user to confirm the deletion of an environment, creates an applications management client, and
// deletes the environment if confirmed. It returns an error if the prompt or client creation fails.
func (r *Runner) Run(ctx context.Context) error {
client, err := r.ConnectionFactory.CreateApplicationsManagementClient(ctx, *r.Workspace)
if err != nil {
return err
}

// Prompt user to confirm deletion
if !r.Confirm {
confirmed, err := prompt.YesOrNoPrompt(fmt.Sprintf(deleteConfirmation, r.EnvironmentName), prompt.ConfirmNo, r.InputPrompter)
// Doesn't list applications
resourcesInEnvironment, err := client.ListResourcesInEnvironment(ctx, r.EnvironmentName)
if err != nil {
return err
}

appsInEnvironment, err := client.ListResourcesOfTypeInEnvironment(ctx, r.EnvironmentName, "Applications.Core/applications")
if err != nil {
return err
}

var promptBuilder strings.Builder
if len(appsInEnvironment) > 0 || len(resourcesInEnvironment) > 0 {
promptBuilder.WriteString(warnDependencies)
promptBuilder.WriteString(" ")
}
promptBuilder.WriteString(fmt.Sprintf(deleteConfirmation, r.EnvironmentName))

confirmed, err := prompt.YesOrNoPrompt(promptBuilder.String(), prompt.ConfirmNo, r.InputPrompter)
if err != nil {
return err
}
Expand All @@ -151,11 +176,6 @@ func (r *Runner) Run(ctx context.Context) error {
}
}

client, err := r.ConnectionFactory.CreateApplicationsManagementClient(ctx, *r.Workspace)
if err != nil {
return err
}

deleted, err := client.DeleteEnvironment(ctx, r.EnvironmentName)
if err != nil {
return err
Expand Down
185 changes: 177 additions & 8 deletions pkg/cli/cmd/env/delete/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package delete
import (
"context"
"fmt"
"github.com/radius-project/radius/pkg/cli/clients_new/generated"
"strings"
"testing"

"github.com/radius-project/radius/pkg/cli/clients"
Expand Down Expand Up @@ -150,6 +152,79 @@ func Test_Show(t *testing.T) {
Times(1)

appManagementClient := clients.NewMockApplicationsManagementClient(ctrl)

appManagementClient.EXPECT().
ListResourcesInEnvironment(gomock.Any(), "test-env").
Return([]generated.GenericResource{}, nil).
Times(1)

appManagementClient.EXPECT().
ListResourcesOfTypeInEnvironment(gomock.Any(), "test-env", "Applications.Core/applications").
Return([]generated.GenericResource{}, nil).
Times(1)

appManagementClient.EXPECT().
DeleteEnvironment(gomock.Any(), "test-env").
Return(true, nil).
Times(1)

workspace := &workspaces.Workspace{
Connection: map[string]any{
"kind": "kubernetes",
"context": "kind-kind",
},
Name: "kind-kind",
Scope: "/planes/radius/local/resourceGroups/test-group",
}
outputSink := &output.MockOutput{}
runner := &Runner{
ConnectionFactory: &connections.MockFactory{ApplicationsManagementClient: appManagementClient},
InputPrompter: promptMock,
Workspace: workspace,
Format: "table",
Output: outputSink,
EnvironmentName: "test-env",
}

err := runner.Run(context.Background())
require.NoError(t, err)

expected := []any{
output.LogOutput{
Format: "Environment deleted",
},
}

require.Equal(t, expected, outputSink.Writes)
})
t.Run("Success: Prompt Confirmed, existing applications", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

expectedPrompt := strings.Join([]string{
warnDependencies,
fmt.Sprintf(deleteConfirmation, "test-env"),
}, " ")
promptMock := prompt.NewMockInterface(ctrl)
promptMock.EXPECT().
GetListInput([]string{prompt.ConfirmNo, prompt.ConfirmYes}, expectedPrompt).
Return(prompt.ConfirmYes, nil).
Times(1)

appManagementClient := clients.NewMockApplicationsManagementClient(ctrl)

appManagementClient.EXPECT().
ListResourcesInEnvironment(gomock.Any(), "test-env").
Return([]generated.GenericResource{}, nil).
Times(1)

appManagementClient.EXPECT().
ListResourcesOfTypeInEnvironment(gomock.Any(), "test-env", "Applications.Core/applications").
Return([]generated.GenericResource{
{},
}, nil).
Times(1)

appManagementClient.EXPECT().
DeleteEnvironment(gomock.Any(), "test-env").
Return(true, nil).
Expand Down Expand Up @@ -184,7 +259,68 @@ func Test_Show(t *testing.T) {

require.Equal(t, expected, outputSink.Writes)
})
t.Run("Success: Prompt Confirmed, existing resources", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

expectedPrompt := strings.Join([]string{
warnDependencies,
fmt.Sprintf(deleteConfirmation, "test-env"),
}, " ")
promptMock := prompt.NewMockInterface(ctrl)
promptMock.EXPECT().
GetListInput([]string{prompt.ConfirmNo, prompt.ConfirmYes}, expectedPrompt).
Return(prompt.ConfirmYes, nil).
Times(1)

appManagementClient := clients.NewMockApplicationsManagementClient(ctrl)

appManagementClient.EXPECT().
ListResourcesInEnvironment(gomock.Any(), "test-env").
Return([]generated.GenericResource{
{},
}, nil).
Times(1)

appManagementClient.EXPECT().
ListResourcesOfTypeInEnvironment(gomock.Any(), "test-env", "Applications.Core/applications").
Return([]generated.GenericResource{}, nil).
Times(1)

appManagementClient.EXPECT().
DeleteEnvironment(gomock.Any(), "test-env").
Return(true, nil).
Times(1)

workspace := &workspaces.Workspace{
Connection: map[string]any{
"kind": "kubernetes",
"context": "kind-kind",
},
Name: "kind-kind",
Scope: "/planes/radius/local/resourceGroups/test-group",
}
outputSink := &output.MockOutput{}
runner := &Runner{
ConnectionFactory: &connections.MockFactory{ApplicationsManagementClient: appManagementClient},
InputPrompter: promptMock,
Workspace: workspace,
Format: "table",
Output: outputSink,
EnvironmentName: "test-env",
}

err := runner.Run(context.Background())
require.NoError(t, err)

expected := []any{
output.LogOutput{
Format: "Environment deleted",
},
}

require.Equal(t, expected, outputSink.Writes)
})
t.Run("Success: Prompt Cancelled", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
Expand All @@ -195,6 +331,18 @@ func Test_Show(t *testing.T) {
Return(prompt.ConfirmNo, nil).
Times(1)

appManagementClient := clients.NewMockApplicationsManagementClient(ctrl)

appManagementClient.EXPECT().
ListResourcesInEnvironment(gomock.Any(), "test-env").
Return([]generated.GenericResource{}, nil).
Times(1)

appManagementClient.EXPECT().
ListResourcesOfTypeInEnvironment(gomock.Any(), "test-env", "Applications.Core/applications").
Return([]generated.GenericResource{}, nil).
Times(1)

workspace := &workspaces.Workspace{
Connection: map[string]any{
"kind": "kubernetes",
Expand All @@ -205,11 +353,12 @@ func Test_Show(t *testing.T) {
}
outputSink := &output.MockOutput{}
runner := &Runner{
InputPrompter: promptMock,
Workspace: workspace,
Format: "table",
Output: outputSink,
EnvironmentName: "test-env",
ConnectionFactory: &connections.MockFactory{ApplicationsManagementClient: appManagementClient},
InputPrompter: promptMock,
Workspace: workspace,
Format: "table",
Output: outputSink,
EnvironmentName: "test-env",
}

err := runner.Run(context.Background())
Expand Down Expand Up @@ -273,11 +422,31 @@ func Test_Show(t *testing.T) {
Return("", &prompt.ErrExitConsole{}).
Times(1)

appManagementClient := clients.NewMockApplicationsManagementClient(ctrl)
appManagementClient.EXPECT().
ListResourcesInEnvironment(gomock.Any(), "test-env").
Return([]generated.GenericResource{}, nil).
Times(1)
appManagementClient.EXPECT().
ListResourcesOfTypeInEnvironment(gomock.Any(), "test-env", "Applications.Core/applications").
Return([]generated.GenericResource{}, nil).
Times(1)

outputSink := &output.MockOutput{}
workspace := &workspaces.Workspace{
Connection: map[string]any{
"kind": "kubernetes",
"context": "kind-kind",
},
Name: "kind-kind",
Scope: "/planes/radius/local/resourceGroups/test-group",
}
runner := &Runner{
InputPrompter: promptMock,
Output: outputSink,
EnvironmentName: "test-env",
ConnectionFactory: &connections.MockFactory{ApplicationsManagementClient: appManagementClient},
Workspace: workspace,
InputPrompter: promptMock,
Output: outputSink,
EnvironmentName: "test-env",
}

err := runner.Run(context.Background())
Expand Down

0 comments on commit d01ecf9

Please sign in to comment.