Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug fixes, codeclimate, and featureflags #32

Merged
merged 3 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
checks:
return-statements:
enabled: false
plugins:
duplication:
enabled: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
go mod download
- name: run go tests
run: |
go test -timeout 60s -race -coverprofile=coverage.txt -covermode=atomic ./...
go test -timeout 60s -race -coverprofile=coverage.txt -covermode=atomic ./...
35 changes: 35 additions & 0 deletions docs/cli-feature-flags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Feature Flags

## Overview

These are the feature flags that are currently available in aws-nuke. They are all disabled by default. These are
switches that changes the actual behavior of the tool itself. Changing the behavior of a resource is done via resource
settings.

!!! note
The original tool had configuration options called `feature-flags` which were used to enable/disable certain
behaviors with resources, those are now called settings and `feature-flags` have been deprecated in the config.

## Usage

```console
aws-nuke run --feature-flag "wait-on-dependencies"
```

**Note:** other CLI arguments are omitted for brevity.

## Available Feature Flags

- `wait-on-dependencies` - This feature flag will cause aws-nuke to wait for all resource type dependencies to be
deleted before deleting the next resource type.

### wait-on-dependencies

This feature flag will cause aws-nuke to wait for all resource type dependencies to be deleted before deleting the next
resource type. This is useful for resources that have dependencies on other resources. For example, an IAM Role that has
an attached policy.

The problem is that if you delete the IAM Role first, it will fail because it has a dependency on the policy.

This feature flag will cause aws-nuke to wait for all resources of a given type to be deleted before deleting the next
resource type. This will reduce the number of errors and unnecessary API calls.
52 changes: 52 additions & 0 deletions docs/cli-usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Usage

## aws-nuke

```console
NAME:
aws-nuke - remove everything from an aws account

USAGE:
aws-nuke [global options] command [command options]

VERSION:
3.0.0-beta.2

AUTHOR:
Erik Kristensen <[email protected]>

COMMANDS:
run, nuke run nuke against an aws account and remove everything from it
resource-types, list-resources list available resources to nuke
help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version
```

## aws-nuke run

```console
NAME:
aws-nuke run - run nuke against an aws account and remove everything from it

USAGE:
aws-nuke run [command options] [arguments...]

OPTIONS:
--config value path to config file (default: "config.yaml")
--force disable prompting for verification to run (default: false)
--force-sleep value seconds to sleep (default: 10)
--quiet hide filtered messages (default: false)
--no-dry-run actually run the removal of the resources after discovery (default: false)
--only-resource value, --target value, --include value, --include-resource value [ --only-resource value, --target value, --include value, --include-resource value ] only run against these resource types
--exclude-resource value, --exclude value [ --exclude-resource value, --exclude value ] exclude these resource types
--cloud-control value [ --cloud-control value ] use these resource types with the Cloud Control API instead of the default
--feature-flag value [ --feature-flag value ] enable experimental behaviors that may not be fully tested or supported
--log-level value, -l value Log Level (default: "info") [$LOGLEVEL]
--log-caller log the caller (aka line number and file) (default: false)
--log-disable-color disable log coloring (default: false)
--log-full-timestamp force log output to always show full timestamp (default: false)
--help, -h show help
```
22 changes: 19 additions & 3 deletions docs/config-filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,32 @@ IAMUser:

### DateOlderThan

The identifier is parsed as a timestamp. After the offset is added to it (specified in the `value` field), the resulting
timestamp must be AFTER the current time. Details on offset syntax can be found in the [library documentation](https://golang.org/pkg/time/#ParseDuration).
Supported date formats are epoch time:
This works by parsing the specified property into a timestamp and comparing it to the current time minus the specified
duration. The duration is specified in the `value` field. The duration syntax is based on golang's duration syntax.

> ParseDuration parses a duration string. A duration string is a possibly signed sequence of decimal numbers, each with
> optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"),
> "ms", "s", "m", "h".

Full details on duration syntax can be found in the [time library documentation](https://golang.org/pkg/time/#ParseDuration).

The value from the property is parsed as a timestamp and the following are the supported formats:

- `2006-01-02`
- `2006/01/02`
- `2006-01-02T15:04:05Z`
- `2006-01-02T15:04:05.999999999Z07:00`
- `2006-01-02T15:04:05Z07:00`

In the follow example we are filtering EC2 Images that have a `CreationDate` older than 1 hour.

```yaml
EC2Image:
- type: dateOlderThan
property: CreationDate
value: 1h
```

## Properties

By default, when writing a filter if you do not specify a property, it will use the `Name` property. However, resources
Expand Down
66 changes: 66 additions & 0 deletions docs/resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ The anatomy of a resource is fairly simple, it's broken down into a few parts:
- `Resource` - This is the base resource type that is used to define the resource.
- `Lister` - This is the type that is used to list the resources.

### Resource

The resource must have the `func Remove() error` method defined on it, this is what is used to remove the resource.

It can optionally have the following methods defined:
Expand All @@ -21,6 +23,70 @@ It can optionally have the following methods defined:
- `func String() string` - This is used to print the resource in a human-readable format.
- `func Properties() types.Properties` - This is used to print the resource in a human-readable format.

```go
package resources

import (
"context"

"github.com/ekristen/libnuke/pkg/resource"
"github.com/ekristen/libnuke/pkg/types"

"github.com/ekristen/aws-nuke/pkg/nuke"
)

type ExampleResource struct {
ID *string
}

func (r *ExampleResource) Remove(_ context.Context) error {
// remove the resource, an error will put the resource in failed state
// resources in failed state are retried a number of times
return nil
}

func (r *ExampleResource) Filter() error {
// filter the resource, this is useful for built-in resources that cannot
// be removed, like an AWS managed resource, return an error here to filter
// it before it even gets to the user supplied filters.
return nil
}

func (r *ExampleResource) String() string {
// return a string representation of the resource, this is legacy, but still
// used for a number of reasons.
return *r.ID
}
```

## Lister

The lister must have the `func List(ctx context.Context, o interface{}) ([]resource.Resource, error)` method defined on it.

```go
package resources

import (
"context"

"github.com/ekristen/libnuke/pkg/resource"

"github.com/ekristen/aws-nuke/pkg/nuke"
)

type ExampleResourceLister struct{}

func (l *ExampleResourceLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) {
opts := o.(*nuke.ListerOpts)

var resources []resource.Resource

// list the resources and add to resources slice

return resources, nil
}
```

### Example

```go
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.21.6

require (
github.com/aws/aws-sdk-go v1.49.21
github.com/ekristen/libnuke v0.0.0-20240122232527-922a9af6ba13
github.com/ekristen/libnuke v0.0.0-20240123221700-d8899f33f580
github.com/fatih/color v1.16.0
github.com/golang/mock v1.6.0
github.com/google/uuid v1.5.0
Expand All @@ -24,7 +24,6 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mb0/glob v0.0.0-20160210091149-1eb79d2de6c4 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stevenle/topsort v0.2.0 // indirect
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ekristen/libnuke v0.0.0-20240122232527-922a9af6ba13 h1:d8d42BTmJkuO+cS8c+xitkNFC0ik9xAbqbZ+pJ76j3M=
github.com/ekristen/libnuke v0.0.0-20240122232527-922a9af6ba13/go.mod h1:GgNcRFHihQza4zWLoun9hEXzVfGTk+nKTwCwo6xAyDg=
github.com/ekristen/libnuke v0.0.0-20240123221700-d8899f33f580 h1:7F4+KkJLtwDC5STusCTGIcnIjBmOOP7mUOpCzS2KoCU=
github.com/ekristen/libnuke v0.0.0-20240123221700-d8899f33f580/go.mod h1:BqHpyOLHEgCwAi82WbM+1fjGRgdDDG4a8W4ivjfHMP8=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
Expand All @@ -34,8 +34,6 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mb0/glob v0.0.0-20160210091149-1eb79d2de6c4 h1:NK3O7S5FRD/wj7ORQ5C3Mx1STpyEMuFe+/F0Lakd1Nk=
github.com/mb0/glob v0.0.0-20160210091149-1eb79d2de6c4/go.mod h1:FqD3ES5hx6zpzDainDaHgkTIqrPaI9uX4CVWqYZoQjY=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ nav:
- Install: installation.md
- Authentication: auth.md
- Quick Start: quick-start.md
- CLI:
- Usage: cli-usage.md
- Feature Flags: cli-feature-flags.md
- Config:
- Overview: config.md
- Filtering: config-filtering.md
Expand Down
21 changes: 17 additions & 4 deletions pkg/commands/nuke/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"os"
"slices"

"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
Expand Down Expand Up @@ -52,6 +53,12 @@ func execute(c *cli.Context) error {
Alternatives: c.StringSlice("cloud-control"),
}

if len(c.StringSlice("feature-flag")) > 0 {
if slices.Contains(c.StringSlice("feature-flag"), "wait-on-dependencies") {
params.WaitOnDependencies = true
}
}

// Parse the user supplied configuration file to pass in part to configure the nuke process.
parsedConfig, err := config.New(libconfig.Options{
Path: c.Path("config"),
Expand Down Expand Up @@ -94,6 +101,8 @@ func execute(c *cli.Context) error {
// Instantiate libnuke
n := libnuke.New(params, filters, parsedConfig.Settings)

n.RegisterVersion(common.AppVersion.Summary)

// Register our custom validate handler that validates the account and AWS nuke unique alias checks
n.RegisterValidateHandler(func() error {
return parsedConfig.ValidateAccount(account.ID(), account.Aliases())
Expand All @@ -112,8 +121,8 @@ func execute(c *cli.Context) error {
resource.GetNames(),
[]types.Collection{
n.Parameters.Includes,
parsedConfig.ResourceTypes.Targets,
accountConfig.ResourceTypes.Targets,
parsedConfig.ResourceTypes.GetIncludes(),
accountConfig.ResourceTypes.GetIncludes(),
},
[]types.Collection{
n.Parameters.Excludes,
Expand All @@ -122,8 +131,8 @@ func execute(c *cli.Context) error {
},
[]types.Collection{
n.Parameters.Alternatives,
parsedConfig.ResourceTypes.CloudControl,
accountConfig.ResourceTypes.CloudControl,
parsedConfig.ResourceTypes.GetAlternatives(),
accountConfig.ResourceTypes.GetAlternatives(),
},
resource.GetAlternativeResourceTypeMapping(),
)
Expand Down Expand Up @@ -194,6 +203,10 @@ func init() {
Name: "cloud-control",
Usage: "use these resource types with the Cloud Control API instead of the default",
},
&cli.StringSliceFlag{
Name: "feature-flag",
Usage: "enable experimental behaviors that may not be fully tested or supported",
},
}

cmd := &cli.Command{
Expand Down
3 changes: 3 additions & 0 deletions resources/ec2-snapshots.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ func init() {
Name: EC2SnapshotResource,
Scope: nuke.Account,
Lister: &EC2SnapshotLister{},
DependsOn: []string{
EC2ImageResource,
},
})
}

Expand Down