Skip to content

Commit

Permalink
Merge pull request #269 from ekristen/rebuy-1254-athena
Browse files Browse the repository at this point in the history
feat: add two resources, athena-data-catalog, athena-prepared-statment
  • Loading branch information
ekristen authored Aug 31, 2024
2 parents f3d5dda + 37f6f82 commit 960da21
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 41 deletions.
89 changes: 89 additions & 0 deletions resources/athena-data-catalog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package resources

import (
"context"
"fmt"

"github.com/aws/aws-sdk-go/aws"

"github.com/aws/aws-sdk-go/service/athena"

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

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

const AthenaDataCatalogResource = "AthenaDataCatalog"

func init() {
registry.Register(&registry.Registration{
Name: AthenaDataCatalogResource,
Scope: nuke.Account,
Lister: &AthenaDataCatalogLister{},
})
}

type AthenaDataCatalogLister struct{}

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

svc := athena.New(opts.Session)
resources := make([]resource.Resource, 0)

params := &athena.ListDataCatalogsInput{
MaxResults: aws.Int64(50),
}

for {
output, err := svc.ListDataCatalogs(params)
if err != nil {
return nil, err
}

for _, catalog := range output.DataCatalogsSummary {
resources = append(resources, &AthenaDataCatalog{
svc: svc,
Name: catalog.CatalogName,
})
}

if output.NextToken == nil {
break
}

params.NextToken = output.NextToken
}

return resources, nil
}

type AthenaDataCatalog struct {
svc *athena.Athena
Name *string
}

func (r *AthenaDataCatalog) Properties() types.Properties {
return types.NewPropertiesFromStruct(r)
}

func (r *AthenaDataCatalog) Remove(_ context.Context) error {
_, err := r.svc.DeleteDataCatalog(&athena.DeleteDataCatalogInput{
Name: r.Name,
})

return err
}

func (r *AthenaDataCatalog) Filter() error {
if *r.Name == "AwsDataCatalog" {
return fmt.Errorf("cannot delete default data source")
}
return nil
}

func (r *AthenaDataCatalog) String() string {
return *r.Name
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ func init() {

type AthenaNamedQueryLister struct{}

type AthenaNamedQuery struct {
svc *athena.Athena
id *string
}

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

Expand Down Expand Up @@ -76,19 +71,24 @@ func (l *AthenaNamedQueryLister) List(_ context.Context, o interface{}) ([]resou
return resources, err
}

func (a *AthenaNamedQuery) Remove(_ context.Context) error {
_, err := a.svc.DeleteNamedQuery(&athena.DeleteNamedQueryInput{
NamedQueryId: a.id,
type AthenaNamedQuery struct {
svc *athena.Athena
id *string
}

func (r *AthenaNamedQuery) Remove(_ context.Context) error {
_, err := r.svc.DeleteNamedQuery(&athena.DeleteNamedQueryInput{
NamedQueryId: r.id,
})

return err
}

func (a *AthenaNamedQuery) Properties() types.Properties {
func (r *AthenaNamedQuery) Properties() types.Properties {
return types.NewProperties().
Set("Id", *a.id)
Set("Id", *r.id)
}

func (a *AthenaNamedQuery) String() string {
return *a.id
func (r *AthenaNamedQuery) String() string {
return *r.id
}
92 changes: 92 additions & 0 deletions resources/athena-prepared-statement.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package resources

import (
"context"

"github.com/aws/aws-sdk-go/aws"

"github.com/aws/aws-sdk-go/service/athena"

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

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

const AthenaPreparedStatementResource = "AthenaPreparedStatement"

func init() {
registry.Register(&registry.Registration{
Name: AthenaPreparedStatementResource,
Scope: nuke.Account,
Lister: &AthenaPreparedStatementLister{},
})
}

type AthenaPreparedStatementLister struct{}

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

svc := athena.New(opts.Session)
resources := make([]resource.Resource, 0)

workgroups, err := svc.ListWorkGroups(&athena.ListWorkGroupsInput{})
if err != nil {
return nil, err
}

for _, workgroup := range workgroups.WorkGroups {
params := &athena.ListPreparedStatementsInput{
WorkGroup: workgroup.Name,
MaxResults: aws.Int64(50),
}

for {
output, err := svc.ListPreparedStatements(params)
if err != nil {
return nil, err
}

for _, statement := range output.PreparedStatements {
resources = append(resources, &AthenaPreparedStatement{
svc: svc,
Name: statement.StatementName,
WorkGroup: workgroup.Name,
})
}

if output.NextToken == nil {
break
}

params.NextToken = output.NextToken
}
}

return resources, nil
}

type AthenaPreparedStatement struct {
svc *athena.Athena
Name *string
WorkGroup *string
}

func (r *AthenaPreparedStatement) Properties() types.Properties {
return types.NewPropertiesFromStruct(r)
}

func (r *AthenaPreparedStatement) Remove(_ context.Context) error {
_, err := r.svc.DeletePreparedStatement(&athena.DeletePreparedStatementInput{
StatementName: r.Name,
WorkGroup: r.WorkGroup,
})

return err
}

func (r *AthenaPreparedStatement) String() string {
return *r.Name
}
58 changes: 29 additions & 29 deletions resources/athena-work-groups.go → resources/athena-work-group.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ func init() {

type AthenaWorkGroupLister struct{}

type AthenaWorkGroup struct {
svc *athena.Athena
name *string
arn *string
}

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

Expand Down Expand Up @@ -84,15 +78,21 @@ func (l *AthenaWorkGroupLister) List(_ context.Context, o interface{}) ([]resour
return resources, err
}

func (a *AthenaWorkGroup) Remove(_ context.Context) error {
type AthenaWorkGroup struct {
svc *athena.Athena
name *string
arn *string
}

func (r *AthenaWorkGroup) Remove(_ context.Context) error {
// Primary WorkGroup cannot be deleted,
// but we can reset it to a clean state
if *a.name == "primary" {
// but we can reset it to r clean state
if *r.name == "primary" {
// TODO: pass logger via ListerOpts instead of using global
logrus.Info("Primary Athena WorkGroup may not be deleted. Resetting configuration only.")

// Reset the configuration to its default state
_, err := a.svc.UpdateWorkGroup(&athena.UpdateWorkGroupInput{
_, err := r.svc.UpdateWorkGroup(&athena.UpdateWorkGroupInput{
// See https://docs.aws.amazon.com/athena/latest/APIReference/API_WorkGroupConfigurationUpdates.html
// for documented defaults
ConfigurationUpdates: &athena.WorkGroupConfigurationUpdates{
Expand All @@ -106,15 +106,15 @@ func (a *AthenaWorkGroup) Remove(_ context.Context) error {
},
},
Description: aws.String(""),
WorkGroup: a.name,
WorkGroup: r.name,
})
if err != nil {
return err
}

// Remove any tags
wgTagsRes, err := a.svc.ListTagsForResource(&athena.ListTagsForResourceInput{
ResourceARN: a.arn,
wgTagsRes, err := r.svc.ListTagsForResource(&athena.ListTagsForResourceInput{
ResourceARN: r.arn,
})
if err != nil {
return err
Expand All @@ -125,8 +125,8 @@ func (a *AthenaWorkGroup) Remove(_ context.Context) error {
tagKeys = append(tagKeys, tag.Key)
}

_, err = a.svc.UntagResource(&athena.UntagResourceInput{
ResourceARN: a.arn,
_, err = r.svc.UntagResource(&athena.UntagResourceInput{
ResourceARN: r.arn,
TagKeys: tagKeys,
})
if err != nil {
Expand All @@ -136,35 +136,35 @@ func (a *AthenaWorkGroup) Remove(_ context.Context) error {
return nil
}

_, err := a.svc.DeleteWorkGroup(&athena.DeleteWorkGroupInput{
_, err := r.svc.DeleteWorkGroup(&athena.DeleteWorkGroupInput{
RecursiveDeleteOption: aws.Bool(true),
WorkGroup: a.name,
WorkGroup: r.name,
})

return err
}

func (a *AthenaWorkGroup) Filter() error {
func (r *AthenaWorkGroup) Filter() error {
// If this is the primary work group,
// check if it's already had its configuration reset
if *a.name == "primary" {
if *r.name == "primary" {
// Get workgroup configuration
wgConfigRes, err := a.svc.GetWorkGroup(&athena.GetWorkGroupInput{
WorkGroup: a.name,
wgConfigRes, err := r.svc.GetWorkGroup(&athena.GetWorkGroupInput{
WorkGroup: r.name,
})
if err != nil {
return err
}

// Get workgroup tags
wgTagsRes, err := a.svc.ListTagsForResource(&athena.ListTagsForResourceInput{
ResourceARN: a.arn,
wgTagsRes, err := r.svc.ListTagsForResource(&athena.ListTagsForResourceInput{
ResourceARN: r.arn,
})
if err != nil {
return err
}

// If the workgroup is already in a "clean" state, then
// If the workgroup is already in r "clean" state, then
// don't add it to our plan
wgConfig := wgConfigRes.WorkGroup.Configuration
isCleanConfig := wgConfig.BytesScannedCutoffPerQuery == nil &&
Expand All @@ -181,12 +181,12 @@ func (a *AthenaWorkGroup) Filter() error {
return nil
}

func (a *AthenaWorkGroup) Properties() types.Properties {
func (r *AthenaWorkGroup) Properties() types.Properties {
return types.NewProperties().
Set("Name", *a.name).
Set("ARN", *a.arn)
Set("Name", *r.name).
Set("ARN", *r.arn)
}

func (a *AthenaWorkGroup) String() string {
return *a.name
func (r *AthenaWorkGroup) String() string {
return *r.name
}

0 comments on commit 960da21

Please sign in to comment.