Repository: go-to-k/delstack
Pull request #120 (2023-03-07 00:13:52)

chore(deps): bump github.com/urfave/cli/v2 from 2.24.3 to 2.25.0
Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.24.3 to 2.25.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/urfave/cli/releases">github.com/urfave/cli/v2's releases</a>.</em></p>
<blockquote>
<h2>v2.25.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Drop support for Go versions before 1.18 by <a href="https://github.com/meatballhat"><code>@​meatballhat</code></a> in <a href="https://github-redirect.dependabot.com/urfave/cli/pull/1667">urfave/cli#1667</a></li>
<li>add Integer type casting when loading yaml file by <a href="https://github.com/kjeom"><code>@​kjeom</code></a> in <a href="https://github-redirect.dependabot.com/urfave/cli/pull/1669">urfave/cli#1669</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/kjeom"><code>@​kjeom</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/urfave/cli/pull/1669">urfave/cli#1669</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/urfave/cli/compare/v2.24.4...v2.25.0">https://github.com/urfave/cli/compare/v2.24.4...v2.25.0</a></p>
<h2>v2.24.4</h2>
<h2>What's Changed</h2>
<ul>
<li>Deprecation of package ioutil in Go 1.16 by <a href="https://github.com/ArangoGutierrez"><code>@​ArangoGutierrez</code></a> in <a href="https://github-redirect.dependabot.com/urfave/cli/pull/1678">urfave/cli#1678</a></li>
<li>Backport [v2]:  Fix some issues in bash autocompletion by <a href="https://github.com/MrNaif2018"><code>@​MrNaif2018</code></a> in <a href="https://github-redirect.dependabot.com/urfave/cli/pull/1676">urfave/cli#1676</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/ArangoGutierrez"><code>@​ArangoGutierrez</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/urfave/cli/pull/1678">urfave/cli#1678</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/urfave/cli/compare/v2.24.3...v2.24.4">https://github.com/urfave/cli/compare/v2.24.3...v2.24.4</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/urfave/cli/commit/ce617c1af0effcbc314c5631b21d75c6dd67898c"><code>ce617c1</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/urfave/cli/issues/1669">#1669</a> from kjeom/integerTypeCasting</li>
<li><a href="https://github.com/urfave/cli/commit/963fab77367a5502834eca6da866b1bb70828c62"><code>963fab7</code></a> Merge branch 'integerTypeCasting' of <a href="https://github.com/kjeom/cli">https://github.com/kjeom/cli</a> into intege...</li>
<li><a href="https://github.com/urfave/cli/commit/f8fe5e8769bcf52dcca74897610983eaa56cfa29"><code>f8fe5e8</code></a> rollback package name from altsrc to altsrc_test</li>
<li><a href="https://github.com/urfave/cli/commit/2bd631912491cdd5c40009d981e764c228914059"><code>2bd6319</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/urfave/cli/issues/1667">#1667</a> from urfave/v2-go1.18-up</li>
<li><a href="https://github.com/urfave/cli/commit/cf80db26ee4869a680cb99e5f8be98b3a6e6af65"><code>cf80db2</code></a> Merge branch 'v2-maint' into v2-go1.18-up</li>
<li><a href="https://github.com/urfave/cli/commit/afcb85a3c3598c9322fdfd04050bc44d6d2c569a"><code>afcb85a</code></a> Merge branch 'v2-maint' into integerTypeCasting</li>
<li><a href="https://github.com/urfave/cli/commit/a105e805814b57aa53b8f31c20b3f390d2d108ee"><code>a105e80</code></a> make casting function private</li>
<li><a href="https://github.com/urfave/cli/commit/bebf9b7037dc3d4fa8b6e07d7ac32a065682a16c"><code>bebf9b7</code></a> fix testcase</li>
<li><a href="https://github.com/urfave/cli/commit/588cd92cc84a18997e22f2ce2d6c7ed7ba30b328"><code>588cd92</code></a> resolve testcase error</li>
<li><a href="https://github.com/urfave/cli/commit/4423ae419ad5f1be5232beed15e5249a697e215d"><code>4423ae4</code></a> added testcase</li>
<li>Additional commits viewable in <a href="https://github.com/urfave/cli/compare/v2.24.3...v2.25.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/urfave/cli/v2&package-manager=go_modules&previous-version=2.24.3&new-version=2.25.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/go.mod b/go.mod
index caed13e..9ec49e6 100644
--- a/go.mod
+++ b/go.mod
@@ -15,7 +15,7 @@ require (
 	github.com/golang/mock v1.6.0
 	github.com/olekukonko/tablewriter v0.0.5
 	github.com/rs/zerolog v1.29.0
-	github.com/urfave/cli/v2 v2.24.3
+	github.com/urfave/cli/v2 v2.25.0
 	golang.org/x/sync v0.1.0
 )
 
diff --git a/go.sum b/go.sum
index 1255be8..0b9e104 100644
--- a/go.sum
+++ b/go.sum
@@ -95,8 +95,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/urfave/cli/v2 v2.24.3 h1:7Q1w8VN8yE0MJEHP06bv89PjYsN4IHWED2s1v/Zlfm0=
-github.com/urfave/cli/v2 v2.24.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
+github.com/urfave/cli/v2 v2.25.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8=
+github.com/urfave/cli/v2 v2.25.0/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
 github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
 github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
diff --git a/internal/app/app.go b/internal/app/app.go
index 87f7170..4aa9a8f 100644
--- a/internal/app/app.go
+++ b/internal/app/app.go
@@ -118,6 +118,7 @@ func (a *App) getAction() func(c *cli.Context) error {
 		operatorManager := operation.NewOperatorManager(operatorCollection)
 
 		io.Logger.Info().Msgf("Start deletion, %v", a.StackName)
+		io.Logger.Info().Msg("Please wait a few minutes...")
 
 		if err := cloudformationStackOperator.DeleteCloudFormationStack(c.Context, aws.String(a.StackName), isRootStack, operatorManager); err != nil {
 			return err
@@ -147,8 +148,13 @@ func (a *App) doInteractiveMode() ([]string, string, bool) {
 		checkboxes = io.GetCheckboxes(label, opts)
 
 		if len(checkboxes) == 0 {
-			io.Logger.Warn().Msg("Select ResourceTypes!")
-			ok := io.GetYesNo("Do you want to finish?")
+			ok := io.GetYesNo("No selection?")
+			if ok {
+				return checkboxes, keyword, true
+			}
+
+			// The case for interruption(Ctrl + C)
+			ok = io.GetYesNo("Do you want to finish?")
 			if ok {
 				io.Logger.Info().Msg("Finished...")
 				return checkboxes, keyword, false
diff --git a/internal/operation/cloudformation_stack.go b/internal/operation/cloudformation_stack.go
index e533cc1..150098f 100644
--- a/internal/operation/cloudformation_stack.go
+++ b/internal/operation/cloudformation_stack.go
@@ -102,19 +102,19 @@ func (o *CloudFormationStackOperator) DeleteCloudFormationStack(ctx context.Cont
 }
 
 func (o *CloudFormationStackOperator) deleteStackNormally(ctx context.Context, stackName *string, isRootStack bool) (bool, error) {
-	stackOutputBeforeDelete, stackExistsBeforeDelete, err := o.client.DescribeStacks(ctx, stackName)
+	stacksBeforeDelete, err := o.client.DescribeStacks(ctx, stackName)
 	if err != nil {
 		return false, err
 	}
-	if !stackExistsBeforeDelete && isRootStack {
+	if len(stacksBeforeDelete) == 0 && isRootStack {
 		errMsg := fmt.Sprintf("%s stack not found.", *stackName)
 		return false, fmt.Errorf("NotExistsError: %v", errMsg)
 	}
-	if !stackExistsBeforeDelete {
+	if len(stacksBeforeDelete) == 0 {
 		return true, nil
 	}
 
-	if *stackOutputBeforeDelete.Stacks[0].EnableTerminationProtection {
+	if stacksBeforeDelete[0].EnableTerminationProtection != nil && *stacksBeforeDelete[0].EnableTerminationProtection {
 		return false, fmt.Errorf("TerminationProtectionIsEnabled: %v", *stackName)
 	}
 
@@ -122,16 +122,16 @@ func (o *CloudFormationStackOperator) deleteStackNormally(ctx context.Context, s
 		return false, err
 	}
 
-	stackOutputAfterDelete, stackExistsAfterDelete, err := o.client.DescribeStacks(ctx, stackName)
+	stacksAfterDelete, err := o.client.DescribeStacks(ctx, stackName)
 	if err != nil {
 		return false, err
 	}
-	if !stackExistsAfterDelete {
+	if len(stacksAfterDelete) == 0 {
 		io.Logger.Info().Msg("No resources were DELETE_FAILED.")
 		return true, nil
 	}
-	if stackOutputAfterDelete.Stacks[0].StackStatus != "DELETE_FAILED" {
-		return false, fmt.Errorf("StackStatusError: StackStatus is expected to be DELETE_FAILED, but %v: %v", stackOutputAfterDelete.Stacks[0].StackStatus, *stackName)
+	if stacksAfterDelete[0].StackStatus != "DELETE_FAILED" {
+		return false, fmt.Errorf("StackStatusError: StackStatus is expected to be DELETE_FAILED, but %v: %v", stacksAfterDelete[0].StackStatus, *stackName)
 	}
 
 	return false, nil
@@ -146,6 +146,11 @@ func (o *CloudFormationStackOperator) ListStacksFilteredByKeyword(ctx context.Co
 	}
 
 	for _, stackSummary := range stackSummaries {
+		// pass the nested child stacks
+		if stackSummary.RootId != nil {
+			continue
+		}
+
 		// for case-insensitive
 		lowerStackName := strings.ToLower(*stackSummary.StackName)
 		lowerKeyword := strings.ToLower(*keyword)
diff --git a/pkg/client/cloudformation.go b/pkg/client/cloudformation.go
index 144ee8f..36691f8 100644
--- a/pkg/client/cloudformation.go
+++ b/pkg/client/cloudformation.go
@@ -14,7 +14,7 @@ const CloudFormationWaitNanoSecTime = time.Duration(4500000000000)
 
 type ICloudFormation interface {
 	DeleteStack(ctx context.Context, stackName *string, retainResources []string) error
-	DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error)
+	DescribeStacks(ctx context.Context, stackName *string) ([]types.Stack, error)
 	ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error)
 	ListStacks(ctx context.Context) ([]types.StackSummary, error)
 }
@@ -56,22 +56,48 @@ func (c *CloudFormation) DeleteStack(ctx context.Context, stackName *string, ret
 	return nil
 }
 
-func (c *CloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	input := &cloudformation.DescribeStacksInput{
-		StackName: stackName,
-	}
+func (c *CloudFormation) DescribeStacks(ctx context.Context, stackName *string) ([]types.Stack, error) {
+	var nextToken *string
+	stacks := []types.Stack{}
 
-	output, err := c.client.DescribeStacks(ctx, input)
-	if err != nil && strings.Contains(err.Error(), "does not exist") {
-		return output, false, nil
-	}
-	if err != nil {
-		return output, true, &ClientError{
-			ResourceName: stackName,
-			Err:          err,
+	for {
+		select {
+		case <-ctx.Done():
+			return stacks, &ClientError{
+				ResourceName: stackName,
+				Err:          ctx.Err(),
+			}
+		default:
+		}
+
+		// If a stackName is nil, then return all stacks
+		input := &cloudformation.DescribeStacksInput{
+			NextToken: nextToken,
+			StackName: stackName,
+		}
+
+		output, err := c.client.DescribeStacks(ctx, input)
+		if err != nil && strings.Contains(err.Error(), "does not exist") {
+			return stacks, nil
+		}
+		if err != nil {
+			return stacks, &ClientError{
+				ResourceName: stackName,
+				Err:          err,
+			}
+		}
+
+		if len(stacks) == 0 && len(output.Stacks) == 0 {
+			return stacks, nil
+		}
+		stacks = append(stacks, output.Stacks...)
+
+		nextToken = output.NextToken
+		if nextToken == nil {
+			break
 		}
 	}
-	return output, true, nil
+	return stacks, nil
 }
 
 func (c *CloudFormation) waitDeleteStack(ctx context.Context, stackName *string) error {
@@ -139,6 +165,7 @@ func (c *CloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary,
 		}
 
 		input := &cloudformation.ListStacksInput{
+			// Except StackStatusDeleteComplete
 			StackStatusFilter: []types.StackStatus{
 				types.StackStatusCreateInProgress,
 				types.StackStatusCreateFailed,
@@ -173,6 +200,10 @@ func (c *CloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary,
 			}
 		}
 
+		if len(stackSummaries) == 0 && len(output.StackSummaries) == 0 {
+			return stackSummaries, nil
+		}
+
 		stackSummaries = append(stackSummaries, output.StackSummaries...)
 		nextToken = output.NextToken
 
diff --git a/pkg/client/cloudformation_mock.go b/pkg/client/cloudformation_mock.go
index e825901..4adbba2 100644
--- a/pkg/client/cloudformation_mock.go
+++ b/pkg/client/cloudformation_mock.go
@@ -8,7 +8,6 @@ import (
 	context "context"
 	reflect "reflect"
 
-	cloudformation "github.com/aws/aws-sdk-go-v2/service/cloudformation"
 	types "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
 	gomock "github.com/golang/mock/gomock"
 )
@@ -51,13 +50,12 @@ func (mr *MockICloudFormationMockRecorder) DeleteStack(ctx, stackName, retainRes
 }
 
 // DescribeStacks mocks base method.
-func (m *MockICloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
+func (m *MockICloudFormation) DescribeStacks(ctx context.Context, stackName *string) ([]types.Stack, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DescribeStacks", ctx, stackName)
-	ret0, _ := ret[0].(*cloudformation.DescribeStacksOutput)
-	ret1, _ := ret[1].(bool)
-	ret2, _ := ret[2].(error)
-	return ret0, ret1, ret2
+	ret0, _ := ret[0].([]types.Stack)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
 // DescribeStacks indicates an expected call of DescribeStacks.


Test patch:
diff --git a/internal/operation/cloudformation_stack_test.go b/internal/operation/cloudformation_stack_test.go
index e353f5b..6b07659 100644
--- a/internal/operation/cloudformation_stack_test.go
+++ b/internal/operation/cloudformation_stack_test.go
@@ -7,7 +7,6 @@ import (
 	"testing"
 
 	"github.com/aws/aws-sdk-go-v2/aws"
-	"github.com/aws/aws-sdk-go-v2/service/cloudformation"
 	"github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
 	"github.com/go-to-k/delstack/internal/io"
 	"github.com/go-to-k/delstack/pkg/client"
@@ -44,32 +43,20 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
-						},
-					},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -86,32 +73,20 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
-						},
-					},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -128,16 +103,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "CREATE_COMPLETE",
-								EnableTerminationProtection: aws.Bool(true),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "CREATE_COMPLETE",
+							EnableTerminationProtection: aws.Bool(true),
 						},
 					},
-					true,
 					nil,
 				)
 			},
@@ -154,16 +126,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "CREATE_COMPLETE",
-								EnableTerminationProtection: aws.Bool(true),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "CREATE_COMPLETE",
+							EnableTerminationProtection: aws.Bool(true),
 						},
 					},
-					true,
 					nil,
 				)
 			},
@@ -180,16 +149,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -208,16 +174,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -236,16 +199,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
@@ -264,16 +224,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
@@ -292,8 +249,7 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					true,
+					[]types.Stack{},
 					fmt.Errorf("DescribeStacksError"),
 				)
 			},
@@ -310,8 +266,7 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					true,
+					[]types.Stack{},
 					fmt.Errorf("DescribeStacksError"),
 				)
 			},
@@ -328,8 +283,7 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -346,8 +300,7 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -364,24 +317,20 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					true,
+					[]types.Stack{},
 					fmt.Errorf("DescribeStacksError"),
 				)
 			},
@@ -398,24 +347,20 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					true,
+					[]types.Stack{},
 					fmt.Errorf("DescribeStacksError"),
 				)
 			},
@@ -432,24 +377,20 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -466,24 +407,20 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -500,16 +437,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -533,16 +467,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -566,16 +497,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -617,16 +545,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -668,16 +593,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -720,16 +642,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -772,16 +691,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -827,16 +743,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -882,16 +795,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -937,16 +847,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -1048,32 +955,26 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 			},
@@ -1092,32 +993,26 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 			},
@@ -1136,16 +1031,13 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "CREATE_COMPLETE",
-								EnableTerminationProtection: aws.Bool(true),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "CREATE_COMPLETE",
+							EnableTerminationProtection: aws.Bool(true),
 						},
 					},
-					true,
 					nil,
 				)
 			},
@@ -1164,16 +1056,13 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "CREATE_COMPLETE",
-								EnableTerminationProtection: aws.Bool(true),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "CREATE_COMPLETE",
+							EnableTerminationProtection: aws.Bool(true),
 						},
 					},
-					true,
 					nil,
 				)
 			},
@@ -1192,16 +1081,13 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -1222,16 +1108,13 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				).AnyTimes()
 
@@ -1252,16 +1135,13 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
@@ -1282,16 +1162,13 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
@@ -1312,8 +1189,7 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					true,
+					[]types.Stack{},
 					fmt.Errorf("DescribeStacksError"),
 				)
 			},
@@ -1332,8 +1208,7 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					true,
+					[]types.Stack{},
 					fmt.Errorf("DescribeStacksError"),
 				)
 			},
@@ -1352,8 +1227,7 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -1372,8 +1246,7 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -1392,24 +1265,20 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					true,
+					[]types.Stack{},
 					fmt.Errorf("DescribeStacksError"),
 				)
 			},
@@ -1428,24 +1297,20 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					true,
+					[]types.Stack{},
 					fmt.Errorf("DescribeStacksError"),
 				)
 			},
@@ -1464,24 +1329,20 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -1500,24 +1361,20 @@ func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 			},
 			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{
-						Stacks: []types.Stack{
-							{
-								StackName:                   aws.String("test"),
-								StackStatus:                 "DELETE_FAILED",
-								EnableTerminationProtection: aws.Bool(false),
-							},
+					[]types.Stack{
+						{
+							StackName:                   aws.String("test"),
+							StackStatus:                 "DELETE_FAILED",
+							EnableTerminationProtection: aws.Bool(false),
 						},
 					},
-					true,
 					nil,
 				)
 
 				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 
 				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
-					&cloudformation.DescribeStacksOutput{},
-					false,
+					[]types.Stack{},
 					nil,
 				)
 			},
@@ -1613,6 +1470,65 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 			},
 			wantErr: false,
 		},
+		{
+			name: "list stacks with RootId filtered by keyword successfully",
+			args: args{
+				ctx:     ctx,
+				keyword: "TestStack",
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().ListStacks(gomock.Any()).Return(
+					[]types.StackSummary{
+						{
+							StackName:   aws.String("TestStack1"),
+							StackStatus: types.StackStatusCreateComplete,
+							RootId:      aws.String("test-stack-root"),
+						},
+						{
+							StackName:   aws.String("TestStack2"),
+							StackStatus: types.StackStatusCreateComplete,
+						},
+					},
+					nil,
+				)
+			},
+			want: want{
+				filteredStacks: []string{
+					"TestStack2",
+				},
+				err: nil,
+			},
+			wantErr: false,
+		},
+		{
+			name: "list stacks with RootId filtered by keyword and no stacks do not have RootId found successfully",
+			args: args{
+				ctx:     ctx,
+				keyword: "TestStack",
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().ListStacks(gomock.Any()).Return(
+					[]types.StackSummary{
+						{
+							StackName:   aws.String("TestStack1"),
+							StackStatus: types.StackStatusCreateComplete,
+							RootId:      aws.String("test-stack-root"),
+						},
+						{
+							StackName:   aws.String("TestStack2"),
+							StackStatus: types.StackStatusCreateComplete,
+							RootId:      aws.String("test-stack-root"),
+						},
+					},
+					nil,
+				)
+			},
+			want: want{
+				filteredStacks: []string{},
+				err:            nil,
+			},
+			wantErr: false,
+		},
 		{
 			name: "list stacks filtered by lower keyword successfully",
 			args: args{
diff --git a/pkg/client/cloudformation_test.go b/pkg/client/cloudformation_test.go
index 85d9407..658b341 100644
--- a/pkg/client/cloudformation_test.go
+++ b/pkg/client/cloudformation_test.go
@@ -22,6 +22,8 @@ func getNextTokenForCloudFormationInitialize(
 	out middleware.InitializeOutput, metadata middleware.Metadata, err error,
 ) {
 	switch v := in.Parameters.(type) {
+	case *cloudformation.DescribeStacksInput:
+		ctx = middleware.WithStackValue(ctx, tokenKeyForCloudFormation{}, v.NextToken)
 	case *cloudformation.ListStackResourcesInput:
 		ctx = middleware.WithStackValue(ctx, tokenKeyForCloudFormation{}, v.NextToken)
 	case *cloudformation.ListStacksInput:
@@ -259,8 +261,7 @@ func TestCloudFormation_DescribeStacks(t *testing.T) {
 	}
 
 	type want struct {
-		output *cloudformation.DescribeStacksOutput
-		exists bool
+		output []types.Stack
 		err    error
 	}
 
@@ -297,16 +298,87 @@ func TestCloudFormation_DescribeStacks(t *testing.T) {
 				},
 			},
 			want: want{
-				output: &cloudformation.DescribeStacksOutput{
-					Stacks: []types.Stack{
-						{
-							StackName:   aws.String("StackName"),
-							StackStatus: "DELETE_FAILED",
-						},
+				output: []types.Stack{
+					{
+						StackName:   aws.String("StackName"),
+						StackStatus: "DELETE_FAILED",
 					},
 				},
-				exists: true,
-				err:    nil,
+				err: nil,
+			},
+			wantErr: false,
+		},
+		{
+			name: "describe stacks with next token successfully",
+			args: args{
+				ctx:       context.Background(),
+				stackName: aws.String("test"),
+				withAPIOptionsFunc: func(stack *middleware.Stack) error {
+					err := stack.Initialize.Add(
+						middleware.InitializeMiddlewareFunc(
+							"GetNextToken",
+							getNextTokenForCloudFormationInitialize,
+						), middleware.Before,
+					)
+					if err != nil {
+						return err
+					}
+
+					err = stack.Finalize.Add(
+						middleware.FinalizeMiddlewareFunc(
+							"DescribeStacksWithNextTokenMock",
+							func(ctx context.Context, input middleware.FinalizeInput, handler middleware.FinalizeHandler) (middleware.FinalizeOutput, middleware.Metadata, error) {
+								token := middleware.GetStackValue(ctx, tokenKeyForCloudFormation{}).(*string)
+
+								var nextToken *string
+								var stacks []types.Stack
+								if token == nil {
+									nextToken = aws.String("NextToken")
+									stacks = []types.Stack{
+										{
+											StackName:   aws.String("StackName1"),
+											StackStatus: "DELETE_FAILED",
+										},
+									}
+									return middleware.FinalizeOutput{
+										Result: &cloudformation.DescribeStacksOutput{
+											NextToken: nextToken,
+											Stacks:    stacks,
+										},
+									}, middleware.Metadata{}, nil
+								} else {
+									stacks = []types.Stack{
+										{
+											StackName:   aws.String("StackName2"),
+											StackStatus: "DELETE_FAILED",
+										},
+									}
+									return middleware.FinalizeOutput{
+										Result: &cloudformation.DescribeStacksOutput{
+											NextToken: nextToken,
+											Stacks:    stacks,
+										},
+									}, middleware.Metadata{}, nil
+								}
+							},
+						),
+						middleware.Before,
+					)
+					return err
+				},
+			},
+			want: want{
+				output: []types.Stack{
+					{
+						StackName:   aws.String("StackName1"),
+						StackStatus: "DELETE_FAILED",
+					},
+					{
+						StackName:   aws.String("StackName2"),
+						StackStatus: "DELETE_FAILED",
+					},
+				},
+				err: nil,
 			},
 			wantErr: false,
 		},
@@ -330,8 +402,75 @@ func TestCloudFormation_DescribeStacks(t *testing.T) {
 				},
 			},
 			want: want{
-				output: &cloudformation.DescribeStacksOutput{},
-				exists: true,
+				output: []types.Stack{},
+				err: &ClientError{
+					ResourceName: aws.String("test"),
+					Err:          fmt.Errorf("operation error CloudFormation: DescribeStacks, DescribeStacksError"),
+				},
+			},
+			wantErr: true,
+		},
+		{
+			name: "describe stacks with next token failure",
+			args: args{
+				ctx:       context.Background(),
+				stackName: aws.String("test"),
+				withAPIOptionsFunc: func(stack *middleware.Stack) error {
+					err := stack.Initialize.Add(
+						middleware.InitializeMiddlewareFunc(
+							"GetNextToken",
+							getNextTokenForCloudFormationInitialize,
+						), middleware.Before,
+					)
+					if err != nil {
+						return err
+					}
+
+					err = stack.Finalize.Add(
+						middleware.FinalizeMiddlewareFunc(
+							"DescribeStacksWithNextTokenErrorMock",
+							func(ctx context.Context, input middleware.FinalizeInput, handler middleware.FinalizeHandler) (middleware.FinalizeOutput, middleware.Metadata, error) {
+								token := middleware.GetStackValue(ctx, tokenKeyForCloudFormation{}).(*string)
+
+								var nextToken *string
+								var stacks []types.Stack
+								if token == nil {
+									nextToken = aws.String("NextToken")
+									stacks = []types.Stack{
+										{
+											StackName:   aws.String("StackName1"),
+											StackStatus: "DELETE_FAILED",
+										},
+									}
+									return middleware.FinalizeOutput{
+										Result: &cloudformation.DescribeStacksOutput{
+											NextToken: nextToken,
+											Stacks:    stacks,
+										},
+									}, middleware.Metadata{}, nil
+								} else {
+									stacks = []types.Stack{}
+									return middleware.FinalizeOutput{
+										Result: &cloudformation.DescribeStacksOutput{
+											NextToken: nextToken,
+											Stacks:    stacks,
+										},
+									}, middleware.Metadata{}, fmt.Errorf("DescribeStacksError")
+								}
+							},
+						),
+						middleware.Before,
+					)
+					return err
+				},
+			},
+			want: want{
+				output: []types.Stack{
+					{
+						StackName:   aws.String("StackName1"),
+						StackStatus: "DELETE_FAILED",
+					},
+				},
 				err: &ClientError{
 					ResourceName: aws.String("test"),
 					Err:          fmt.Errorf("operation error CloudFormation: DescribeStacks, DescribeStacksError"),
@@ -359,8 +498,7 @@ func TestCloudFormation_DescribeStacks(t *testing.T) {
 				},
 			},
 			want: want{
-				output: &cloudformation.DescribeStacksOutput{},
-				exists: false,
+				output: []types.Stack{},
 				err:    nil,
 			},
 			wantErr: false,
@@ -385,7 +523,7 @@ func TestCloudFormation_DescribeStacks(t *testing.T) {
 				cfnWaiter,
 			)
 
-			output, exists, err := cfnClient.DescribeStacks(tt.args.ctx, tt.args.stackName)
+			output, err := cfnClient.DescribeStacks(tt.args.ctx, tt.args.stackName)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("error = %#v, wantErr %#v", err, tt.wantErr)
 				return
@@ -394,10 +532,7 @@ func TestCloudFormation_DescribeStacks(t *testing.T) {
 				t.Errorf("err = %#v, want %#v", err, tt.want)
 				return
 			}
-			if !tt.wantErr && exists != tt.want.exists {
-				t.Errorf("exists = %#v, want %#v", exists, tt.want.exists)
-			}
-			if !tt.wantErr && exists && !reflect.DeepEqual(output, tt.want.output) {
+			if !tt.wantErr && !reflect.DeepEqual(output, tt.want.output) {
 				t.Errorf("output = %#v, want %#v", output, tt.want.output)
 				return
 			}
@@ -622,6 +757,33 @@ func TestCloudFormation_ListStackResources(t *testing.T) {
 			},
 			wantErr: true,
 		},
+		{
+			name: "list stack resources but not exist",
+			args: args{
+				ctx:       context.Background(),
+				stackName: aws.String("test"),
+				withAPIOptionsFunc: func(stack *middleware.Stack) error {
+					return stack.Finalize.Add(
+						middleware.FinalizeMiddlewareFunc(
+							"ListStackResourcesMock",
+							func(context.Context, middleware.FinalizeInput, middleware.FinalizeHandler) (middleware.FinalizeOutput, middleware.Metadata, error) {
+								return middleware.FinalizeOutput{
+									Result: &cloudformation.ListStackResourcesOutput{
+										StackResourceSummaries: []types.StackResourceSummary{},
+									},
+								}, middleware.Metadata{}, nil
+							},
+						),
+						middleware.Before,
+					)
+				},
+			},
+			want: want{
+				output: []types.StackResourceSummary{},
+				err:    nil,
+			},
+			wantErr: false,
+		},
 		{
 			name: "list stack resources with next token successfully",
 			args: args{