Skip to content

Commit

Permalink
Stack: Rollback config: injecting values properly
Browse files Browse the repository at this point in the history
from template at the injection step instead of the
BeforeRun step.
See #188
  • Loading branch information
simcap committed Apr 12, 2018
1 parent 3ae9272 commit 8cc604d
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 103 deletions.
12 changes: 9 additions & 3 deletions acceptance/aws/stack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ func TestStack(t *testing.T) {
defer polClean()

t.Run("create", func(t *testing.T) {

Template("create stack name=new-stack template-file="+tplFilePath+" capabilities=one,two disable-rollback=true notifications=none,ntwo on-failure=done parameters=1:pone,2:ptwo resource-types=rone,rtwo role=donjuan policy-file="+polFilePath+" rollback-triggers=[arn1,arn2] rollback-monitoring-min=2 timeout=180").Mock(&cloudformationMock{
Template("create stack name=new-stack template-file="+tplFilePath+" capabilities=one,two disable-rollback=true notifications=none,ntwo on-failure=done parameters=1:pone,2:ptwo resource-types=rone,rtwo role=donjuan policy-file="+polFilePath+" rollback-monitoring-min=2 rollback-triggers=[arn1,arn2] timeout=180").Mock(&cloudformationMock{
CreateStackFunc: func(input *cloudformation.CreateStackInput) (*cloudformation.CreateStackOutput, error) {
return &cloudformation.CreateStackOutput{StackId: String("new-stack-id")}, nil
}}).ExpectInput("CreateStack", &cloudformation.CreateStackInput{
Expand Down Expand Up @@ -48,7 +47,7 @@ func TestStack(t *testing.T) {
_, polUpdateFilePath, clean := generateTmpFile("update policy content")
defer clean()

Template("update stack name=other-name template-file="+tplFilePath+" use-previous-template=true capabilities=one,two notifications=none,ntwo parameters=1:pone,2:ptwo resource-types=rone,rtwo role=donjuan policy-file="+polFilePath+" policy-update-file="+polUpdateFilePath).Mock(&cloudformationMock{
Template("update stack name=other-name template-file="+tplFilePath+" use-previous-template=true capabilities=one,two notifications=none,ntwo parameters=1:pone,2:ptwo resource-types=rone,rtwo role=donjuan policy-file="+polFilePath+" policy-update-file="+polUpdateFilePath+" rollback-monitoring-min=2 rollback-triggers=[arn1,arn2]").Mock(&cloudformationMock{
UpdateStackFunc: func(input *cloudformation.UpdateStackInput) (*cloudformation.UpdateStackOutput, error) {
return &cloudformation.UpdateStackOutput{StackId: String("any-stack-id")}, nil
}}).ExpectInput("UpdateStack", &cloudformation.UpdateStackInput{
Expand All @@ -62,6 +61,13 @@ func TestStack(t *testing.T) {
StackPolicyBody: String("policy content"),
StackPolicyDuringUpdateBody: String("update policy content"),
UsePreviousTemplate: Bool(true),
RollbackConfiguration: &cloudformation.RollbackConfiguration{
MonitoringTimeInMinutes: Int64(2),
RollbackTriggers: []*cloudformation.RollbackTrigger{
{Arn: String("arn1"), Type: aws.String("AWS::CloudWatch::Alarm")},
{Arn: String("arn2"), Type: aws.String("AWS::CloudWatch::Alarm")},
},
},
}).ExpectCommandResult("any-stack-id").ExpectCalls("UpdateStack").Run(t)
})

Expand Down
66 changes: 38 additions & 28 deletions aws/spec/setters.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,32 @@ import (
)

const (
awsstr = "awsstr"
awsint = "awsint"
awsint64 = "awsint64"
awsfloat = "awsfloat"
awsbool = "awsbool"
awsboolattribute = "awsboolattribute"
awsstringattribute = "awsstringattribute"
awsint64slice = "awsint64slice"
awsstringslice = "awsstringslice"
awsstringpointermap = "awsstringpointermap"
awsslicestruct = "awsslicestruct"
awsslicestructint64 = "awsslicestructint64"
awsuserdatatobase64 = "awsuserdatatobase64"
awsfiletobyteslice = "awsfiletobyteslice"
awsfiletostring = "awsfiletostring"
awsdimensionslice = "awsdimensionslice"
awsparameterslice = "awsparameterslice"
awsecskeyvalue = "awsecskeyvalue"
awsportmappings = "awsportmappings"
awssubnetmappings = "awssubnetmappings"
awsstepadjustments = "awsstepadjustments"
awscsvstr = "awscsvstr"
aws6digitsstring = "aws6digitsstring"
awsbyteslice = "awsbyteslice"
awstagslice = "awstagslice"
awsrollbackconfig = "awsrollbackconfig"
awsstr = "awsstr"
awsint = "awsint"
awsint64 = "awsint64"
awsfloat = "awsfloat"
awsbool = "awsbool"
awsboolattribute = "awsboolattribute"
awsstringattribute = "awsstringattribute"
awsint64slice = "awsint64slice"
awsstringslice = "awsstringslice"
awsstringpointermap = "awsstringpointermap"
awsslicestruct = "awsslicestruct"
awsslicestructint64 = "awsslicestructint64"
awsuserdatatobase64 = "awsuserdatatobase64"
awsfiletobyteslice = "awsfiletobyteslice"
awsfiletostring = "awsfiletostring"
awsdimensionslice = "awsdimensionslice"
awsparameterslice = "awsparameterslice"
awsecskeyvalue = "awsecskeyvalue"
awsportmappings = "awsportmappings"
awssubnetmappings = "awssubnetmappings"
awsstepadjustments = "awsstepadjustments"
awscsvstr = "awscsvstr"
aws6digitsstring = "aws6digitsstring"
awsbyteslice = "awsbyteslice"
awstagslice = "awstagslice"
awsalarmrollbacktriggers = "awsalarmrollbacktriggers"
)

var (
Expand Down Expand Up @@ -360,9 +360,19 @@ func setFieldWithType(v, i interface{}, fieldPath string, destType string, inter
}

v = tags
case awsrollbackconfig:
// do nothing since we did all job in BeforeRun
case awsalarmrollbacktriggers:
var triggers []*cloudformation.RollbackTrigger
if list := castStringSlice(v); len(list) > 0 {
for _, t := range list {
triggers = append(triggers, &cloudformation.RollbackTrigger{
Arn: aws.String(t),
Type: aws.String("AWS::CloudWatch::Alarm"),
})
}
}
v = triggers
}

awsutil.SetValueAtPath(i, fieldPath, v)
return nil
}
Expand Down
115 changes: 43 additions & 72 deletions aws/spec/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,33 @@ import (
"github.com/wallix/awless/template/env"
"github.com/wallix/awless/template/params"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/aws/aws-sdk-go/service/cloudformation/cloudformationiface"
"github.com/wallix/awless/logger"
"gopkg.in/yaml.v2"
)

type CreateStack struct {
_ string `action:"create" entity:"stack" awsAPI:"cloudformation" awsCall:"CreateStack" awsInput:"cloudformation.CreateStackInput" awsOutput:"cloudformation.CreateStackOutput"`
logger *logger.Logger
graph cloud.GraphAPI
api cloudformationiface.CloudFormationAPI
Name *string `awsName:"StackName" awsType:"awsstr" templateName:"name"`
TemplateFile *string `awsName:"TemplateBody" awsType:"awsfiletostring" templateName:"template-file"`
Capabilities []*string `awsName:"Capabilities" awsType:"awsstringslice" templateName:"capabilities"`
DisableRollback *bool `awsName:"DisableRollback" awsType:"awsbool" templateName:"disable-rollback"`
Notifications []*string `awsName:"NotificationARNs" awsType:"awsstringslice" templateName:"notifications"`
OnFailure *string `awsName:"OnFailure" awsType:"awsstr" templateName:"on-failure"`
Parameters []*string `awsName:"Parameters" awsType:"awsparameterslice" templateName:"parameters"`
ResourceTypes []*string `awsName:"ResourceTypes" awsType:"awsstringslice" templateName:"resource-types"`
Role *string `awsName:"RoleARN" awsType:"awsstr" templateName:"role"`
PolicyFile *string `awsName:"StackPolicyBody" awsType:"awsfiletostring" templateName:"policy-file"`
Timeout *int64 `awsName:"TimeoutInMinutes" awsType:"awsint64" templateName:"timeout"`
Tags []*string `awsName:"Tags" awsType:"awstagslice" templateName:"tags"`
PolicyBody *string `awsName:"StackPolicyBody" awsType:"awsstr"`
StackFile *string `templateName:"stack-file"`
RollbackConfigurations *cloudformation.RollbackConfiguration `awsName:"RollbackConfiguration" awsType:"awsrollbackconfig"`
RollbackTriggers []*string `templateName:"rollback-triggers"`
RollbackMonitoringMin *int64 `templateName:"rollback-monitoring-min"`
_ string `action:"create" entity:"stack" awsAPI:"cloudformation" awsCall:"CreateStack" awsInput:"cloudformation.CreateStackInput" awsOutput:"cloudformation.CreateStackOutput"`
logger *logger.Logger
graph cloud.GraphAPI
api cloudformationiface.CloudFormationAPI
Name *string `awsName:"StackName" awsType:"awsstr" templateName:"name"`
TemplateFile *string `awsName:"TemplateBody" awsType:"awsfiletostring" templateName:"template-file"`
Capabilities []*string `awsName:"Capabilities" awsType:"awsstringslice" templateName:"capabilities"`
DisableRollback *bool `awsName:"DisableRollback" awsType:"awsbool" templateName:"disable-rollback"`
Notifications []*string `awsName:"NotificationARNs" awsType:"awsstringslice" templateName:"notifications"`
OnFailure *string `awsName:"OnFailure" awsType:"awsstr" templateName:"on-failure"`
Parameters []*string `awsName:"Parameters" awsType:"awsparameterslice" templateName:"parameters"`
ResourceTypes []*string `awsName:"ResourceTypes" awsType:"awsstringslice" templateName:"resource-types"`
Role *string `awsName:"RoleARN" awsType:"awsstr" templateName:"role"`
PolicyFile *string `awsName:"StackPolicyBody" awsType:"awsfiletostring" templateName:"policy-file"`
Timeout *int64 `awsName:"TimeoutInMinutes" awsType:"awsint64" templateName:"timeout"`
Tags []*string `awsName:"Tags" awsType:"awstagslice" templateName:"tags"`
PolicyBody *string `awsName:"StackPolicyBody" awsType:"awsstr"`
StackFile *string `templateName:"stack-file"`
RollbackTriggers []*string `awsName:"RollbackConfiguration.RollbackTriggers" awsType:"awsalarmrollbacktriggers" templateName:"rollback-triggers"`
RollbackMonitoringMin *int64 `awsName:"RollbackConfiguration.MonitoringTimeInMinutes" awsType:"awsint64" templateName:"rollback-monitoring-min"`
}

func (cmd *CreateStack) ParamsSpec() params.Spec {
Expand All @@ -72,36 +70,31 @@ func (cmd *CreateStack) ExtractResult(i interface{}) string {
// Add StackFile support via BeforeRun hook
// https://github.com/wallix/awless/issues/145
// http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-cfn-artifacts.html
func (cmd *CreateStack) BeforeRun(renv env.Running) error {
var err error
func (cmd *CreateStack) BeforeRun(renv env.Running) (err error) {
cmd.Parameters, cmd.Tags, cmd.PolicyBody, err = processStackFile(cmd.StackFile, cmd.PolicyFile, cmd.Parameters, cmd.Tags)
if len(cmd.RollbackTriggers) > 0 || cmd.RollbackMonitoringMin != nil {
cmd.RollbackConfigurations = newRollBackConfig(cmd.RollbackTriggers, cmd.RollbackMonitoringMin)
}
return err
return
}

type UpdateStack struct {
_ string `action:"update" entity:"stack" awsAPI:"cloudformation" awsCall:"UpdateStack" awsInput:"cloudformation.UpdateStackInput" awsOutput:"cloudformation.UpdateStackOutput"`
logger *logger.Logger
graph cloud.GraphAPI
api cloudformationiface.CloudFormationAPI
Name *string `awsName:"StackName" awsType:"awsstr" templateName:"name"`
Capabilities []*string `awsName:"Capabilities" awsType:"awsstringslice" templateName:"capabilities"`
Notifications []*string `awsName:"NotificationARNs" awsType:"awsstringslice" templateName:"notifications"`
Parameters []*string `awsName:"Parameters" awsType:"awsparameterslice" templateName:"parameters"`
ResourceTypes []*string `awsName:"ResourceTypes" awsType:"awsstringslice" templateName:"resource-types"`
Role *string `awsName:"RoleARN" awsType:"awsstr" templateName:"role"`
PolicyFile *string `awsName:"StackPolicyBody" awsType:"awsfiletostring" templateName:"policy-file"`
PolicyUpdateFile *string `awsName:"StackPolicyDuringUpdateBody" awsType:"awsfiletostring" templateName:"policy-update-file"`
TemplateFile *string `awsName:"TemplateBody" awsType:"awsfiletostring" templateName:"template-file"`
UsePreviousTemplate *bool `awsName:"UsePreviousTemplate" awsType:"awsbool" templateName:"use-previous-template"`
Tags []*string `awsName:"Tags" awsType:"awstagslice" templateName:"tags"`
PolicyBody *string `awsName:"StackPolicyBody" awsType:"awsstr"`
StackFile *string `templateName:"stack-file"`
RollbackConfigurations *cloudformation.RollbackConfiguration `awsName:"RollbackConfiguration" awsType:"awsrollbackconfig"`
RollbackTriggers []*string `templateName:"rollback-triggers"`
RollbackMonitoringMin *int64 `templateName:"rollback-monitoring-min"`
_ string `action:"update" entity:"stack" awsAPI:"cloudformation" awsCall:"UpdateStack" awsInput:"cloudformation.UpdateStackInput" awsOutput:"cloudformation.UpdateStackOutput"`
logger *logger.Logger
graph cloud.GraphAPI
api cloudformationiface.CloudFormationAPI
Name *string `awsName:"StackName" awsType:"awsstr" templateName:"name"`
Capabilities []*string `awsName:"Capabilities" awsType:"awsstringslice" templateName:"capabilities"`
Notifications []*string `awsName:"NotificationARNs" awsType:"awsstringslice" templateName:"notifications"`
Parameters []*string `awsName:"Parameters" awsType:"awsparameterslice" templateName:"parameters"`
ResourceTypes []*string `awsName:"ResourceTypes" awsType:"awsstringslice" templateName:"resource-types"`
Role *string `awsName:"RoleARN" awsType:"awsstr" templateName:"role"`
PolicyFile *string `awsName:"StackPolicyBody" awsType:"awsfiletostring" templateName:"policy-file"`
PolicyUpdateFile *string `awsName:"StackPolicyDuringUpdateBody" awsType:"awsfiletostring" templateName:"policy-update-file"`
TemplateFile *string `awsName:"TemplateBody" awsType:"awsfiletostring" templateName:"template-file"`
UsePreviousTemplate *bool `awsName:"UsePreviousTemplate" awsType:"awsbool" templateName:"use-previous-template"`
Tags []*string `awsName:"Tags" awsType:"awstagslice" templateName:"tags"`
PolicyBody *string `awsName:"StackPolicyBody" awsType:"awsstr"`
StackFile *string `templateName:"stack-file"`
RollbackTriggers []*string `awsName:"RollbackConfiguration.RollbackTriggers" awsType:"awsalarmrollbacktriggers" templateName:"rollback-triggers"`
RollbackMonitoringMin *int64 `awsName:"RollbackConfiguration.MonitoringTimeInMinutes" awsType:"awsint64" templateName:"rollback-monitoring-min"`
}

func (cmd *UpdateStack) ParamsSpec() params.Spec {
Expand All @@ -117,31 +110,9 @@ func (cmd *UpdateStack) ExtractResult(i interface{}) string {
// Add StackFile support via BeforeRun hook
// https://github.com/wallix/awless/issues/145
// http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-cfn-artifacts.html
func (cmd *UpdateStack) BeforeRun(renv env.Running) error {
var err error
func (cmd *UpdateStack) BeforeRun(renv env.Running) (err error) {
cmd.Parameters, cmd.Tags, cmd.PolicyBody, err = processStackFile(cmd.StackFile, cmd.PolicyFile, cmd.Parameters, cmd.Tags)
if len(cmd.RollbackTriggers) > 0 || cmd.RollbackMonitoringMin != nil {
cmd.RollbackConfigurations = newRollBackConfig(cmd.RollbackTriggers, cmd.RollbackMonitoringMin)
}

return err
}

func newRollBackConfig(rollbackTriggers []*string, monitoringTime *int64) *cloudformation.RollbackConfiguration {
rc := &cloudformation.RollbackConfiguration{
MonitoringTimeInMinutes: monitoringTime,
}

if len(rollbackTriggers) > 0 {
for _, rt := range rollbackTriggers {
rc.RollbackTriggers = append(rc.RollbackTriggers, &cloudformation.RollbackTrigger{
Arn: rt,
Type: aws.String("AWS::CloudWatch::Alarm"),
})
}
}

return rc
return
}

type stackFile struct {
Expand Down

0 comments on commit 8cc604d

Please sign in to comment.