Skip to content
This repository has been archived by the owner on Aug 16, 2022. It is now read-only.

feat: Add tags for organizations.Account #942

Merged
merged 8 commits into from
May 25, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 20 additions & 0 deletions client/mocks/mock_organizations.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ type MQClient interface {
type OrganizationsClient interface {
ListAccountsForParent(ctx context.Context, params *organizations.ListAccountsForParentInput, optFns ...func(*organizations.Options)) (*organizations.ListAccountsForParentOutput, error)
ListAccounts(ctx context.Context, params *organizations.ListAccountsInput, optFns ...func(*organizations.Options)) (*organizations.ListAccountsOutput, error)
organizations.ListTagsForResourceAPIClient
}

//go:generate mockgen -package=mocks -destination=./mocks/mock_rds.go . RdsClient
Expand Down
2 changes: 1 addition & 1 deletion resources/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func Provider() *provider.Provider {
"lambda.layers": lambda.LambdaLayers(),
"lambda.runtimes": lambda.LambdaRuntimes(),
"mq.brokers": mq.Brokers(),
"organizations.accounts": organizations.OrganizationsAccounts(),
"organizations.accounts": organizations.Accounts(),
"qldb.ledgers": qldb.Ledgers(),
"rds.certificates": rds.RdsCertificates(),
"rds.cluster_parameter_groups": rds.RdsClusterParameterGroups(),
Expand Down
72 changes: 52 additions & 20 deletions resources/services/organizations/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,65 +4,73 @@ import (
"context"
"errors"

"github.com/aws/aws-sdk-go-v2/service/organizations/types"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/organizations"
"github.com/aws/smithy-go"
"github.com/cloudquery/cq-provider-aws/client"
"github.com/cloudquery/cq-provider-sdk/provider/diag"

"github.com/cloudquery/cq-provider-aws/client"
"github.com/cloudquery/cq-provider-sdk/provider/schema"
)

func OrganizationsAccounts() *schema.Table {
//go:generate cq-gen --resource accounts --config gen.hcl --output .
func Accounts() *schema.Table {
return &schema.Table{
Name: "aws_organizations_accounts",
Description: "Contains information about an AWS account that is a member of an organization.",
Resolver: fetchOrganizationsAccounts,
Multiplex: client.AccountMultiplex,
IgnoreError: client.IgnoreAccessDeniedServiceDisabled,
DeleteFilter: client.DeleteAccountFilter,
Options: schema.TableCreationOptions{PrimaryKeys: []string{"account_id", "id"}},
IgnoreInTests: true,
Name: "aws_organizations_accounts",
Description: "Contains information about an AWS account that is a member of an organization",
Resolver: fetchOrganizationsAccounts,
Multiplex: client.AccountMultiplex,
DeleteFilter: client.DeleteAccountFilter,
IgnoreError: client.IgnoreAccessDeniedServiceDisabled,
Options: schema.TableCreationOptions{PrimaryKeys: []string{"account_id", "id"}},
Columns: []schema.Column{
{
Name: "account_id",
Description: "The root/organizational unit AWS account",
Description: "The AWS Account ID of the resource.",
Type: schema.TypeString,
Resolver: client.ResolveAWSAccount,
},
{
Name: "tags",
Description: "The AWS tags of the resource.",
Type: schema.TypeJSON,
Resolver: ResolveOrganizationsAccountTags,
},
{
Name: "arn",
Description: "The Amazon Resource Name (ARN) of the account.",
Description: "The Amazon Resource Name (ARN) of the account",
Type: schema.TypeString,
},
{
Name: "email",
Description: "The email address associated with the AWS account.",
Description: "The email address associated with the AWS account",
Type: schema.TypeString,
},
{
Name: "id",
Description: "The unique identifier (ID) of the account.",
Description: "The unique identifier (ID) of the account",
Type: schema.TypeString,
Resolver: schema.PathResolver("Id"),
},
{
Name: "joined_method",
Description: "The method by which the account joined the organization.",
Description: "The method by which the account joined the organization",
Type: schema.TypeString,
},
{
Name: "joined_timestamp",
Description: "The date the account became a part of the organization.",
Description: "The date the account became a part of the organization",
Type: schema.TypeTimestamp,
},
{
Name: "name",
Description: "The friendly name of the account.",
Description: "The friendly name of the account",
Type: schema.TypeString,
},
{
Name: "status",
Description: "The status of the account in the organization.",
Description: "The status of the account in the organization",
Type: schema.TypeString,
},
},
Expand All @@ -72,7 +80,8 @@ func OrganizationsAccounts() *schema.Table {
// ====================================================================================================================
// Table Resolver Functions
// ====================================================================================================================
func fetchOrganizationsAccounts(ctx context.Context, meta schema.ClientMeta, parent *schema.Resource, res chan<- interface{}) error {

func fetchOrganizationsAccounts(ctx context.Context, meta schema.ClientMeta, _ *schema.Resource, res chan<- interface{}) error {
c := meta.(*client.Client)
svc := c.Services().Organizations
var input organizations.ListAccountsInput
Expand Down Expand Up @@ -100,3 +109,26 @@ func fetchOrganizationsAccounts(ctx context.Context, meta schema.ClientMeta, par
}
return nil
}
func ResolveOrganizationsAccountTags(ctx context.Context, meta schema.ClientMeta, resource *schema.Resource, _ schema.Column) error {
cl := meta.(*client.Client)
account := resource.Item.(types.Account)
allTags := make(map[string]*string)
input := organizations.ListTagsForResourceInput{
ResourceId: account.Id,
NextToken: nil,
}
for {
response, err := cl.Services().Organizations.ListTagsForResource(ctx, &input)
if err != nil {
return diag.WrapError(err)
}
for _, t := range response.Tags {
allTags[*t.Key] = t.Value
}
if response.NextToken == nil {
break
}
input.NextToken = response.NextToken
}
return resource.Set("tags", allTags)
}
12 changes: 11 additions & 1 deletion resources/services/organizations/accounts_mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,21 @@ func buildOrganizationsAccounts(t *testing.T, ctrl *gomock.Controller) client.Se
&organizations.ListAccountsOutput{
Accounts: []organizationsTypes.Account{g},
}, nil)

tt := make([]organizationsTypes.Tag, 3)
if err := faker.FakeData(&tt); err != nil {
t.Fatal(err)
}

m.EXPECT().ListTagsForResource(gomock.Any(), gomock.Any()).Return(
&organizations.ListTagsForResourceOutput{
Tags: tt,
}, nil)
return client.Services{
Organizations: m,
}
}

func TestOrganizationsAccounts(t *testing.T) {
client.AwsMockTestHelper(t, OrganizationsAccounts(), buildOrganizationsAccounts, client.TestOptions{})
client.AwsMockTestHelper(t, Accounts(), buildOrganizationsAccounts, client.TestOptions{})
}
40 changes: 40 additions & 0 deletions resources/services/organizations/gen.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
service = "aws"
output_directory = "."
add_generate = true

description_modifier "remove_read_only" {
words = [" This member is required."]
}

resource "aws" "organizations" "accounts" {
path = "github.com/aws/aws-sdk-go-v2/service/organizations/types.Account"
ignoreError "IgnoreAccessDenied" {
path = "github.com/cloudquery/cq-provider-aws/client.IgnoreAccessDeniedServiceDisabled"
}

multiplex "AccountMultiplexer" {
path = "github.com/cloudquery/cq-provider-aws/client.AccountMultiplex"
}

deleteFilter "DeleteAccountFilter" {
path = "github.com/cloudquery/cq-provider-aws/client.DeleteAccountFilter"
}

options {
primary_keys = ["account_id", "id"]
}

userDefinedColumn "account_id" {
type = "string"
description = "The AWS Account ID of the resource."
resolver "resolveAWSAccount" {
path = "github.com/cloudquery/cq-provider-aws/client.ResolveAWSAccount"
}
}

userDefinedColumn "tags" {
type = "json"
description = "The AWS tags of the resource."
generate_resolver = true
}
}