Skip to content

Commit

Permalink
Refactor generator (#22)
Browse files Browse the repository at this point in the history
* Set default region and profile for generator

* Refactor generate list

* Discard TRACE logs of Terraform provider

* Refactor GetResourceID into method

* Refactor a lot

* Add some new resources via manual map
  • Loading branch information
jckuester authored Dec 19, 2020
1 parent 0209252 commit 196ade0
Show file tree
Hide file tree
Showing 27 changed files with 838 additions and 609 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A list command for AWS resources.
[![Travis](https://img.shields.io/travis/jckuester/awsls/master.svg?style=for-the-badge)](https://travis-ci.org/jckuester/awsls)

awsls supports listing of [over 200 types of resources](#supported-resources)
across 83 different AWS services. The goal is to code-generate a list function for
across 84 different AWS services. The goal is to code-generate a list function for
every AWS resource that is covered by the Terraform AWS Provider (currently over 500). If you want to contribute,
[the generator is here](./gen).

Expand Down Expand Up @@ -96,7 +96,7 @@ The `--all-profiles` flag will use all profiles from `~/.aws/config`, or if `AWS

## Supported resources

Currently, all 234 resource types across 83 services in the table below can be listed with awsls. The `Tags` column shows if a resource
Currently, all 237 resource types across 84 services in the table below can be listed with awsls. The `Tags` column shows if a resource
supports displaying tags, the `Creation Time` column if a resource has a creation timestamp, and the `Owner` column if
resources are pre-filtered belonging to the account owner.

Expand Down Expand Up @@ -141,6 +141,8 @@ Note: the prefix `aws_` for resource types is now optional. This means, for exam
| aws_cloudformation_stack_set | x | |
| **cloudhsmv2** |
| aws_cloudhsm_v2_cluster | x | |
| **cloudtrail** |
| aws_cloudtrail | x | |
| **cloudwatch** |
| aws_cloudwatch_dashboard | | |
| **cloudwatchevents** |
Expand Down Expand Up @@ -209,7 +211,7 @@ Note: the prefix `aws_` for resource types is now optional. This means, for exam
| aws_ec2_transit_gateway_vpc_attachment | x | x |
| aws_egress_only_internet_gateway | x | |
| aws_eip | x | |
| aws_instance | x | x | x |
| aws_instance | x | x | x |
| aws_internet_gateway | x | | x |
| aws_key_pair | x | |
| aws_launch_template | x | x |
Expand Down Expand Up @@ -419,6 +421,8 @@ Note: the prefix `aws_` for resource types is now optional. This means, for exam
| **worklink** |
| aws_worklink_fleet | | x |
| **workspaces** |
| aws_workspaces_directory | x | |
| aws_workspaces_ip_group | x | |
| aws_workspaces_workspace | x | |
| **xray** |
| aws_xray_group | x | |
35 changes: 35 additions & 0 deletions aws/aws_cloudtrail.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Code is generated. DO NOT EDIT.

package aws

import (
"context"

"github.com/aws/aws-sdk-go-v2/service/cloudtrail"
)

func ListCloudtrail(client *Client) ([]Resource, error) {
req := client.Cloudtrailconn.DescribeTrailsRequest(&cloudtrail.DescribeTrailsInput{})

var result []Resource

resp, err := req.Send(context.Background())
if err != nil {
return nil, err
}

if len(resp.TrailList) > 0 {
for _, r := range resp.TrailList {

result = append(result, Resource{
Type: "aws_cloudtrail",
ID: *r.Name,
Profile: client.Profile,
Region: client.Region,
AccountID: client.AccountID,
})
}
}

return result, nil
}
4 changes: 2 additions & 2 deletions aws/aws_instance.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// TODO this resource is currently manually added, because the pattern of how
// it's code must be generated differs from all other resources (nested for-loop
// This resource is currently manually added, because the pattern of how
// it's code must be generated differs from other resources (nested for-loop
// of instances inside reservations)

package aws
Expand Down
37 changes: 37 additions & 0 deletions aws/aws_workspaces_directory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Code is generated. DO NOT EDIT.

package aws

import (
"context"

"github.com/aws/aws-sdk-go-v2/service/workspaces"
)

func ListWorkspacesDirectory(client *Client) ([]Resource, error) {
req := client.Workspacesconn.DescribeWorkspaceDirectoriesRequest(&workspaces.DescribeWorkspaceDirectoriesInput{})

var result []Resource

p := workspaces.NewDescribeWorkspaceDirectoriesPaginator(req)
for p.Next(context.Background()) {
page := p.CurrentPage()

for _, r := range page.Directories {

result = append(result, Resource{
Type: "aws_workspaces_directory",
ID: *r.DirectoryId,
Profile: client.Profile,
Region: client.Region,
AccountID: client.AccountID,
})
}
}

if err := p.Err(); err != nil {
return nil, err
}

return result, nil
}
14 changes: 7 additions & 7 deletions aws/aws_kms_alias.go → aws/aws_workspaces_workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ package aws
import (
"context"

"github.com/aws/aws-sdk-go-v2/service/kms"
"github.com/aws/aws-sdk-go-v2/service/workspaces"
)

func ListKmsAlias(client *Client) ([]Resource, error) {
req := client.Kmsconn.ListAliasesRequest(&kms.ListAliasesInput{})
func ListWorkspacesWorkspace(client *Client) ([]Resource, error) {
req := client.Workspacesconn.DescribeWorkspacesRequest(&workspaces.DescribeWorkspacesInput{})

var result []Resource

p := kms.NewListAliasesPaginator(req)
p := workspaces.NewDescribeWorkspacesPaginator(req)
for p.Next(context.Background()) {
page := p.CurrentPage()

for _, r := range page.Aliases {
for _, r := range page.Workspaces {

result = append(result, Resource{
Type: "aws_kms_alias",
ID: *r.AliasName,
Type: "aws_workspaces_workspace",
ID: *r.WorkspaceId,
Profile: client.Profile,
Region: client.Region,
AccountID: client.AccountID,
Expand Down
1 change: 1 addition & 0 deletions aws/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package aws
import (
"context"
"fmt"

"github.com/apex/log"
"github.com/aws/aws-sdk-go-v2/aws/external"
"github.com/aws/aws-sdk-go-v2/service/accessanalyzer"
Expand Down
6 changes: 6 additions & 0 deletions aws/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ func ListResourcesByType(client *Client, resourceType string) ([]Resource, error
return ListCloudformationStackSet(client)
case "aws_cloudhsm_v2_cluster":
return ListCloudhsmV2Cluster(client)
case "aws_cloudtrail":
return ListCloudtrail(client)
case "aws_cloudwatch_dashboard":
return ListCloudwatchDashboard(client)
case "aws_cloudwatch_event_bus":
Expand Down Expand Up @@ -486,8 +488,12 @@ func ListResourcesByType(client *Client, resourceType string) ([]Resource, error
return ListWafv2WebAclLoggingConfiguration(client)
case "aws_worklink_fleet":
return ListWorklinkFleet(client)
case "aws_workspaces_directory":
return ListWorkspacesDirectory(client)
case "aws_workspaces_ip_group":
return ListWorkspacesIpGroup(client)
case "aws_workspaces_workspace":
return ListWorkspacesWorkspace(client)
case "aws_xray_group":
return ListXrayGroup(client)
default:
Expand Down
112 changes: 112 additions & 0 deletions gen/aws/README.tpl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# awsls

A list command for AWS resources.

[![Release](https://img.shields.io/github/release/jckuester/awsls.svg?style=for-the-badge)](https://github.com/jckuester/awsls/releases/latest)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=for-the-badge)](/LICENSE.md)
[![Travis](https://img.shields.io/travis/jckuester/awsls/master.svg?style=for-the-badge)](https://travis-ci.org/jckuester/awsls)

awsls supports listing of [over 200 types of resources](#supported-resources)
across {{ len .Services }} different AWS services. The goal is to code-generate a list function for
every AWS resource that is covered by the Terraform AWS Provider (currently over 500). If you want to contribute,
[the generator is here](./gen).

If you encounter any issue with `awsls` or have a feature request,
please open an issue or write me on [Twitter](https://twitter.com/jckuester).

Happy listing!

**Note:** If you're also looking for an easy but powerful way to delete AWS resources, pipe the output of `awsls` into its new sibling
[`awsrm`](https://github.com/jckuester/awsrm) via Unix-pipes and use well-known standard tooling such as `grep` for filtering.

## Features

* List multiple types of resources at once by using glob patterns
(e.g., `"aws_iam_*"` lists all IAM resources and `"*"` all resources in your account)
* **New:** List resources across multiple accounts and regions by using the `--profiles` and `--regions` flag
(e.g., `-p account1,account2 -r us-east-1,us-west-2`)
* Show any resource attribute documented in the [Terraform AWS Provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)
(e.g., `-a private_ip,tags` lists the IP and tags for resources of type [`aws_instance`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#attributes-reference))

## Examples

### List various resource attributes

Use Terraform resource types to tell `awsls` which resources to list. For example, `awsls aws_instance` shows
all EC2 instances. In addition to the default attributes `TYPE`, `ID`, `REGION`, and `CREATED` timestamp, additional attributes
can be displayed via the `--attributes <comma-separated list>` flag. Every attribute in the Terraform documentation
([here](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#attributes-reference) are the attributes for `aws_instance`) is a valid one:

![](img/instance.gif)

### List multiple resource types at once (via glob patterns)

For example, `awsls "aws_iam_*` lists all IAM resources:

![](img/iam.gif)

### List across multiple accounts and regions

To use specific profiles and/or regions, use the `-p (--profiles)` or `-r (--regions)` flags. For example,
`-p myaccount1,myaccount2 -r us-east-1,us-west-2` lists resources in every permutation of the given profiles and regions,
i.e., resources in region `us-west-2` and `us-east-1` for account `myaccount1` as well as `myaccount2`:

![](img/multi-profiles-and-regions.gif)

## Usage

awsls [flags] <resource_type glob pattern>

To see options available run `awsls --help`.

## Installation

### Binary Releases

You can download a specific version of awsls on the [releases page](https://github.com/jckuester/awsls/releases) or
install it the following way to `./bin/`:

```bash
curl -sSfL https://raw.githubusercontent.com/jckuester/awsls/master/install.sh | sh -s v0.6.1
```

### Homebrew

Homebrew users can install by:

```bash
brew install jckuester/tap/awsls
```

For more information on Homebrew taps please see the [tap documentation](https://docs.brew.sh/Taps).

## Credentials, profiles and regions

If the `--profiles` and/or `--regions` flag is unset, `awsls` will follow the usual
[AWS CLI precedence](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-precedence)
of first trying to find credentials, profiles and/or regions via [environment variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html),
and so on.

For example, if using `--profiles foo,bar`, but not setting the regions flag,
`awsls` will first try to use the region from an environment variable (e.g., `AWS_DEFAULT_REGION`)
and second will try to use the default region for each profile from `~/.aws/config`.

The `--all-profiles` flag will use all profiles from `~/.aws/config`, or if `AWS_CONFIG_FILE=/my/config` is set, from
`/my/config` otherwise.

## Supported resources

Currently, all {{ .SupportedResourceTypeCount }} resource types across {{ len .Services }} services in the table below can be listed with awsls. The `Tags` column shows if a resource
supports displaying tags, the `Creation Time` column if a resource has a creation timestamp, and the `Owner` column if
resources are pre-filtered belonging to the account owner.

Note: the prefix `aws_` for resource types is now optional. This means, for example,
`awsls aws_instance` and `awsls instance` are both valid commands.

| Service / Type | Tags | Creation Time | Owner
| :------------- | :--: | :-----------: | :---:
{{ range $service := .Services }}| **{{ $service.Name }}** |
{{ range $rType := $service.TerraformResourceTypes -}}
| {{ $rType.Name }} | {{ if $rType.Tags }} x {{ end }} | {{ if $rType.CreationTime }} x {{ end }} |{{ if $rType.Owner }} x |{{ end }}
{{ end }}
{{- end }}
17 changes: 4 additions & 13 deletions gen/aws/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,16 @@ package aws

import (
"bytes"
"fmt"
"os"
"path/filepath"
"strings"
"text/template"

"github.com/jckuester/awsls/gen/util"
)

// GenerateClient writes Go code to initialize all AWS API Clients.
func GenerateClient(outputPath string, services []string) error {
err := os.MkdirAll(outputPath, 0775)
if err != nil {
return fmt.Errorf("failed to create directory: %s", err)
}

err = util.WriteGoFile(
// GenerateClient returns Go code that initializes all AWS API clients.
func GenerateClient(outputPath string, services []string) {
err := util.WriteGoFile(
filepath.Join(outputPath, "client.go"),
util.CodeLayout,
"",
Expand All @@ -29,10 +22,8 @@ func GenerateClient(outputPath string, services []string) error {
)

if err != nil {
return fmt.Errorf("failed to write Go code to file: %s", err)
panic(err)
}

return nil
}

func clientGoCode(services []string) string {
Expand Down
Loading

0 comments on commit 196ade0

Please sign in to comment.