Skip to content

Commit 617fa9d

Browse files
authored
refactor: reorganize commands directory for better code organization (#958)
* refactor: reorganize commands directory for better code organization This commit refactors the commands directory by: - Extracting AWS command handlers to aws_commands.go - Extracting GCP command handlers to gcp_commands.go - Creating reusable flag helpers in flags.go - Creating shared helper functions in helpers.go - Adding new error types to errors.go for better error handling - Simplifying cli.go to use the new modular structure Minimal supporting change: - Added config.ApplyTimeFilters() helper method (10 lines) These changes improve code organization and maintainability without changing functionality. All telemetry event names remain as string literals to keep changes minimal and focused on commands directory structure. * docs: document GCP resource-type limitation and add timeout validation Address code review feedback: - Add documentation noting that GCP --resource-type and --exclude-resource-type flags are currently ignored (will be implemented in future PR) - Add validation to ensure timeout parameter is positive - Prevents confusing behavior where users expect filtering but get none * refactor: consolidate telemetry tracking and parseLogLevel usage - Add TrackCommandLifecycle helper to reduce telemetry boilerplate - Update all command handlers (awsNuke, awsDefaults, awsInspect, gcpNuke, gcpInspect) to use new helper - Consolidate parseLogLevel usage in awsDefaults for consistent error handling - Remove unused logging import from aws_commands.go This refactoring reduces code duplication and improves maintainability, making it easier to integrate with OpenTelemetry in the future.
1 parent ac93000 commit 617fa9d

File tree

9 files changed

+955
-754
lines changed

9 files changed

+955
-754
lines changed

commands/aws_commands.go

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
package commands
2+
3+
import (
4+
"github.com/gruntwork-io/cloud-nuke/aws"
5+
"github.com/gruntwork-io/cloud-nuke/config"
6+
"github.com/gruntwork-io/cloud-nuke/telemetry"
7+
"github.com/gruntwork-io/cloud-nuke/ui"
8+
"github.com/gruntwork-io/go-commons/errors"
9+
commonTelemetry "github.com/gruntwork-io/go-commons/telemetry"
10+
"github.com/pterm/pterm"
11+
"github.com/urfave/cli/v2"
12+
)
13+
14+
// AWS Command Handlers
15+
// These functions implement the CLI commands for AWS operations
16+
17+
// awsNuke is the main command handler for nuking (deleting) AWS resources.
18+
// It supports resource filtering, time-based filtering, and config file overrides.
19+
func awsNuke(c *cli.Context) error {
20+
defer telemetry.TrackCommandLifecycle("aws")()
21+
22+
// Handle the --list-resource-types flag
23+
if c.Bool(FlagListResourceTypes) {
24+
return handleListResourceTypes()
25+
}
26+
27+
// Parse and set log level
28+
if err := parseLogLevel(c); err != nil {
29+
return err
30+
}
31+
32+
// Load config file if provided
33+
configObj, err := loadConfigFile(c.String(FlagConfig))
34+
if err != nil {
35+
return errors.WithStackTrace(err)
36+
}
37+
38+
// Apply timeout to config (consistent with GCP behavior)
39+
if err = parseAndApplyTimeout(c, &configObj); err != nil {
40+
return err
41+
}
42+
43+
// Build AWS query from CLI flags
44+
query, err := generateQuery(c, c.Bool(FlagDeleteUnaliasedKMSKeys), nil, false)
45+
if err != nil {
46+
return errors.WithStackTrace(err)
47+
}
48+
49+
// Get output preferences
50+
outputFormat := c.String(FlagOutputFormat)
51+
outputFile := c.String(FlagOutputFile)
52+
53+
return awsNukeHelper(c, configObj, query, outputFormat, outputFile)
54+
}
55+
56+
// awsDefaults is the command handler for nuking AWS default VPCs and security groups.
57+
// This is a specialized version of awsNuke that targets only default resources.
58+
func awsDefaults(c *cli.Context) error {
59+
defer telemetry.TrackCommandLifecycle("aws-defaults")()
60+
61+
// Parse and set log level
62+
if err := parseLogLevel(c); err != nil {
63+
return err
64+
}
65+
66+
// Determine which default resources to target based on flags
67+
resourceTypes := []string{"vpc"} // VPC deletion will remove attached default security groups
68+
if c.Bool(FlagSGOnly) {
69+
resourceTypes = []string{"security-group"} // Only target default security groups
70+
}
71+
72+
// Build query for default resources only
73+
query, err := generateQuery(c, false, resourceTypes, true)
74+
if err != nil {
75+
return errors.WithStackTrace(err)
76+
}
77+
78+
// Note: Config file feature is only available for the 'aws' command
79+
// The 'defaults-aws' command always uses table format output to stdout
80+
return awsNukeHelper(c, config.Config{}, query, DefaultOutputFormat, "")
81+
}
82+
83+
// awsInspect is the command handler for non-destructive inspection of AWS resources.
84+
// It lists resources that would be deleted without actually deleting them.
85+
func awsInspect(c *cli.Context) error {
86+
defer telemetry.TrackCommandLifecycle("aws-inspect")()
87+
88+
// Handle the --list-resource-types flag
89+
if c.Bool(FlagListResourceTypes) {
90+
return handleListResourceTypes()
91+
}
92+
93+
// Build AWS query from CLI flags
94+
query, err := generateQuery(c, c.Bool(FlagListUnaliasedKMSKeys), nil, false)
95+
if err != nil {
96+
return errors.WithStackTrace(err)
97+
}
98+
99+
// Get output preferences
100+
outputFormat := c.String(FlagOutputFormat)
101+
outputFile := c.String(FlagOutputFile)
102+
103+
// Retrieve and display resources without deleting them
104+
_, err = handleGetResourcesWithFormat(c, config.Config{}, query, outputFormat, outputFile)
105+
return err
106+
}
107+
108+
// Helper Functions
109+
// These functions contain shared logic used by multiple command handlers
110+
111+
// awsNukeHelper is the core logic for nuking AWS resources.
112+
// It retrieves resources, confirms deletion with the user, and executes the nuke operation.
113+
func awsNukeHelper(c *cli.Context, configObj config.Config, query *aws.Query, outputFormat string, outputFile string) error {
114+
// Retrieve all matching resources
115+
account, err := handleGetResourcesWithFormat(c, configObj, query, outputFormat, outputFile)
116+
if err != nil {
117+
telemetry.TrackEvent(commonTelemetry.EventContext{
118+
EventName: "Error getting resources",
119+
}, map[string]interface{}{})
120+
return errors.WithStackTrace(err)
121+
}
122+
123+
// Confirm with user before proceeding (unless --force or --dry-run is set)
124+
shouldProceed, err := confirmNuke(c, len(account.Resources) > 0)
125+
if err != nil {
126+
return err
127+
}
128+
129+
// Execute the nuke operation if confirmed
130+
if shouldProceed {
131+
if err := aws.NukeAllResources(account, query.Regions); err != nil {
132+
return err
133+
}
134+
ui.RenderRunReportWithFormat(outputFormat, outputFile)
135+
}
136+
137+
return nil
138+
}
139+
140+
// generateQuery builds an AWS Query object from CLI context and flags.
141+
// The query determines which AWS resources will be targeted for inspection or deletion.
142+
func generateQuery(c *cli.Context, includeUnaliasedKmsKeys bool, overridingResourceTypes []string, onlyDefault bool) (*aws.Query, error) {
143+
// Parse time-based filters
144+
excludeAfter, err := parseDurationParam(FlagOlderThan, c.String(FlagOlderThan))
145+
if err != nil {
146+
return nil, errors.WithStackTrace(err)
147+
}
148+
149+
includeAfter, err := parseDurationParam(FlagNewerThan, c.String(FlagNewerThan))
150+
if err != nil {
151+
return nil, errors.WithStackTrace(err)
152+
}
153+
154+
// Parse timeout
155+
timeout, err := parseTimeoutDurationParam(FlagTimeout, c.String(FlagTimeout))
156+
if err != nil {
157+
return nil, errors.WithStackTrace(err)
158+
}
159+
160+
// Determine which resource types to target
161+
resourceTypes := c.StringSlice(FlagResourceType)
162+
if overridingResourceTypes != nil {
163+
resourceTypes = overridingResourceTypes
164+
}
165+
166+
// Build and return the query
167+
return aws.NewQuery(
168+
c.StringSlice(FlagRegion),
169+
c.StringSlice(FlagExcludeRegion),
170+
resourceTypes,
171+
c.StringSlice(FlagExcludeResourceType),
172+
excludeAfter,
173+
includeAfter,
174+
includeUnaliasedKmsKeys,
175+
timeout,
176+
onlyDefault,
177+
c.Bool(FlagExcludeFirstSeen),
178+
)
179+
}
180+
181+
// handleGetResourcesWithFormat retrieves all AWS resources matching the query and renders them
182+
// in the specified output format. This is used for both inspect and nuke operations.
183+
func handleGetResourcesWithFormat(c *cli.Context, configObj config.Config, query *aws.Query, outputFormat string, outputFile string) (
184+
*aws.AwsAccountResources, error) {
185+
// Display query parameters (only for table format to avoid cluttering JSON output)
186+
if !ui.ShouldSuppressProgressOutput(outputFormat) {
187+
pterm.DefaultSection.WithTopPadding(1).WithBottomPadding(0).Println("AWS Resource Query Parameters")
188+
err := ui.RenderQueryAsBulletList(query)
189+
if err != nil {
190+
return nil, errors.WithStackTrace(err)
191+
}
192+
pterm.Println()
193+
}
194+
195+
// Retrieve all resources matching the query
196+
accountResources, err := aws.GetAllResources(c.Context, query, configObj)
197+
if err != nil {
198+
telemetry.TrackEvent(commonTelemetry.EventContext{
199+
EventName: "Error inspecting resources",
200+
}, map[string]interface{}{})
201+
return nil, errors.WithStackTrace(aws.ResourceInspectionError{Underlying: err})
202+
}
203+
204+
// Display found resources header (only for table format)
205+
if !ui.ShouldSuppressProgressOutput(outputFormat) {
206+
pterm.DefaultSection.WithTopPadding(1).WithBottomPadding(0).Println("Found AWS Resources")
207+
}
208+
209+
// Render the resources in the requested format (table or JSON)
210+
err = ui.RenderResourcesAsTableWithFormat(accountResources, query, outputFormat, outputFile)
211+
212+
return accountResources, err
213+
}
214+
215+
// handleListResourceTypes displays all available AWS resource types that can be targeted.
216+
func handleListResourceTypes() error {
217+
pterm.DefaultSection.WithTopPadding(1).WithBottomPadding(0).Println("AWS Resource Types")
218+
return ui.RenderResourceTypesAsBulletList(aws.ListResourceTypes())
219+
}

0 commit comments

Comments
 (0)