Skip to content

Commit

Permalink
add CloudFormationStackLister method
Browse files Browse the repository at this point in the history
  • Loading branch information
nao1215 committed Jan 11, 2024
1 parent 5d80d93 commit 046c5e7
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
86 changes: 86 additions & 0 deletions app/domain/model/cloudformation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package model

import "time"

const (
// CloudFormationRetryMaxAttempts is the maximum number of retries for CloudFormation.
CloudFormationRetryMaxAttempts int = 2
)

// StackStatus is the status of a CloudFormation stack.
type StackStatus string

// StackDriftInformationSummary contains information about whether the stack's
// actual configuration differs, or has drifted, from its expected configuration,
// as defined in the stack template and any values specified as template parameters.
// A stack is considered to have drifted if one or more of its resources have drifted.
type StackDriftInformationSummary struct {
// StackDriftStatus is status of the stack's actual configuration compared to its expected template
// configuration.
StackDriftStatus StackDriftStatus
// LastCheckTimestamp is most recent time when a drift detection operation was
// initiated on the stack, or any of its individual resources that support drift detection.
LastCheckTimestamp *time.Time
}

// StackDriftStatus is the status of a stack's actual configuration compared to
// its expected template configuration.
type StackDriftStatus string

const (
// StackDriftStatusDrifted is the stack differs from its expected template configuration.
// A stack is considered to have drifted if one or more of its resources have drifted.
StackDriftStatusDrifted StackDriftStatus = "DRIFTED"
// StackDriftStatusInSync is the stack's actual configuration matches its expected template
// configuration.
StackDriftStatusInSync StackDriftStatus = "IN_SYNC"
// StackDriftStatusNotChecked is CloudFormation hasn't checked if the stack differs from its
// expected template configuration.
StackDriftStatusNotChecked StackDriftStatus = "NOT_CHECKED"
// StackDriftStatusUnknown is this value is reserved for future use.
StackDriftStatusUnknown StackDriftStatus = "UNKNOWN"
)

// Values returns all known values for StackDriftStatus. Note that this can be
// expanded in the future, and so it is only as up to date as the client. The
// ordering of this slice is not guaranteed to be stable across updates.
func (StackDriftStatus) Values() []StackDriftStatus {
return []StackDriftStatus{
"DRIFTED",
"IN_SYNC",
"UNKNOWN",
"NOT_CHECKED",
}
}

// Stack is a CloudFormation stack. It is same as types.StackSummary.
type Stack struct {
// CreationTime is the time the stack was created.
CreationTime *time.Time
// StackName is the name associated with the stack.
StackName *string
// StackStatus is the current status of the stack.
StackStatus StackStatus
// DeletionTime is the time the stack was deleted.
DeletionTime *time.Time
// DriftInformation is summarizes information about whether a stack's actual
// configuration differs, or has drifted, from its expected configuration,
// as defined in the stack template and any values specified as template parameters.
DriftInformation *StackDriftInformationSummary
// LastUpdatedTime is the time the stack was last updated.
LastUpdatedTime *time.Time
// ParentID is used for nested stacks --stacks created as resources for
// another stack-- the stack ID of the direct parent of this stack.
// For the first level of nested stacks, the root stack is also the parent stack.
ParentID *string
// RootID id used for nested stacks --stacks created as resources for
// another stack--the stack ID of the top-level stack to which the nested stack
// ultimately belongs.
RootID *string
// StackID is unique stack identifier.
StackID *string
// StackStatusReason is Success/Failure message associated with the stack status.
StackStatusReason *string
// TemplateDescription is the template description of the template used to create the stack.
TemplateDescription *string
}
21 changes: 21 additions & 0 deletions app/domain/service/cloudformation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package service

import (
"context"

"github.com/nao1215/rainbow/app/domain/model"
)

// CloudFormationStackListerInput is the input of the CloudFormationStackLister method.
type CloudFormationStackListerInput struct{}

// CloudFormationStackListerOutput is the output of the CloudFormationStackLister method.
type CloudFormationStackListerOutput struct {
// Stacks is a list of CloudFormation stacks.
Stacks []*model.Stack
}

// CloudFormationStackLister is the interface that wraps the basic CloudFormationStackLister method.
type CloudFormationStackLister interface {
CloudFormationStackLister(ctx context.Context, input *CloudFormationStackListerInput) (*CloudFormationStackListerOutput, error)
}
90 changes: 90 additions & 0 deletions app/external/cloudformation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package external

import (
"context"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudformation"
"github.com/google/wire"
"github.com/nao1215/rainbow/app/domain/model"
"github.com/nao1215/rainbow/app/domain/service"
)

// NewCloudFormationClient returns a new CloudFormation client.
func NewCloudFormationClient(cfg *model.AWSConfig) *cloudformation.Client {
return cloudformation.NewFromConfig(
*cfg.Config,
func(o *cloudformation.Options) {
o.RetryMaxAttempts = model.CloudFormationRetryMaxAttempts
o.RetryMode = aws.RetryModeStandard
})
}

// CloudFormationStackLister implements the CloudFormationStackLister interface.
type CloudFormationStackLister struct {
client *cloudformation.Client
}

// CloudFormationStackListerSet is a set of CloudFormationStackLister.
//
//nolint:gochecknoglobals
var CloudFormationStackListerSet = wire.NewSet(
NewCloudFormationStackLister,
wire.Bind(new(service.CloudFormationStackLister), new(*CloudFormationStackLister)),
)

var _ service.CloudFormationStackLister = (*CloudFormationStackLister)(nil)

// NewCloudFormationStackLister returns a new CloudFormationStackLister.
func NewCloudFormationStackLister(client *cloudformation.Client) *CloudFormationStackLister {
return &CloudFormationStackLister{client: client}
}

// CloudFormationStackLister returns a list of CloudFormation stacks.
func (l *CloudFormationStackLister) CloudFormationStackLister(ctx context.Context, input *service.CloudFormationStackListerInput) (*service.CloudFormationStackListerOutput, error) {
in := &cloudformation.ListStacksInput{}
stacks := make([]*model.Stack, 0, 100)

for {
select {
case <-ctx.Done():
return &service.CloudFormationStackListerOutput{
Stacks: stacks,
}, ctx.Err()
default:
}

out, err := l.client.ListStacks(ctx, in)
if err != nil {
return nil, err
}

for _, stack := range out.StackSummaries {
stacks = append(stacks, &model.Stack{
CreationTime: stack.CreationTime,
StackName: stack.StackName,
StackStatus: model.StackStatus(stack.StackStatus),
DeletionTime: stack.DeletionTime,
DriftInformation: &model.StackDriftInformationSummary{
StackDriftStatus: model.StackDriftStatus(stack.DriftInformation.StackDriftStatus),
LastCheckTimestamp: stack.DriftInformation.LastCheckTimestamp,
},
LastUpdatedTime: stack.LastUpdatedTime,
ParentID: stack.ParentId,
RootID: stack.RootId,
StackID: stack.StackId,
StackStatusReason: stack.StackStatusReason,
TemplateDescription: stack.TemplateDescription,
})
}

if out.NextToken == nil {
break
}
in.NextToken = out.NextToken
}

return &service.CloudFormationStackListerOutput{
Stacks: stacks,
}, nil
}

0 comments on commit 046c5e7

Please sign in to comment.