Skip to content

Commit

Permalink
Issue wallix#157. implemet CloudFormation RollbackTriggers.
Browse files Browse the repository at this point in the history
  • Loading branch information
taraspos committed Jan 30, 2018
1 parent 4d41e2e commit e686712
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 49 deletions.
28 changes: 16 additions & 12 deletions aws/doc/paramsdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,14 @@ var manualParamsDoc = map[string]map[string]string{
"adjustment-scaling": "The amount by which to scale, based on the specified adjustment type (e.g. '-2', '3')",
},
"create.stack": {
"capabilities": "A list of values that you must specify before AWS CloudFormation can create certain stacks",
"on-failure": "Determines what action will be taken if stack creation fails",
"parameters": "A list of Parameters that specify input parameters for the stack given using this format: [key1:val1,key2:val2,...]",
"policy-file": "The path to the file containing the stack policy body",
"template-file": "The path to the file containing the template body with a minimum size of 1 byte and a maximum size of 51,200 bytes",
"stack-file": "The path to the file containing Parameters/Tags/StackPolices definition (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-cfn-artifacts.html#w2ab2c13c15c15). Values passed via CLI has higher priority than ones defined in StackFile",
"capabilities": "A list of values that you must specify before AWS CloudFormation can create certain stacks",
"on-failure": "Determines what action will be taken if stack creation fails",
"parameters": "A list of Parameters that specify input parameters for the stack given using this format: [key1:val1,key2:val2,...]",
"policy-file": "The path to the file containing the stack policy body",
"template-file": "The path to the file containing the template body with a minimum size of 1 byte and a maximum size of 51,200 bytes",
"stack-file": "The path to the file containing Parameters/Tags/StackPolices definition (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-cfn-artifacts.html#w2ab2c13c15c15). Values passed via CLI has higher priority than ones defined in StackFile",
"rollback-triggers": "List of ClodwatchAlarm Arns to monitor during and after creation",
"rollback-monitoring-min": "Time to monitor rollback-triggers during and after creation",
},
"create.subnet": {
"name": "The 'Name' Tag for the subnet to create",
Expand Down Expand Up @@ -531,12 +533,14 @@ var manualParamsDoc = map[string]map[string]string{
"portrange": "The portrange for the rule to update: any, 80, 22-23...",
},
"update.stack": {
"capabilities": "A list of values that you must specify before AWS CloudFormation can update certain stacks",
"parameters": "A list of Parameters that specify input parameters for the stack given using this format: [key1:val1,key2:val2,...]",
"policy-file": "The path to the file containing the stack policy body",
"policy-update-file": "The path to the file containing the temporary overriding stack policy",
"template-file": "The path to the file containing the template body with a minimum size of 1 byte and a maximum size of 51,200 bytes",
"stack-file": "The path to the file containing Parameters/Tags/StackPolices definition (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-cfn-artifacts.html#w2ab2c13c15c15). Values passed via CLI has higher priority than ones defined in StackFile",
"capabilities": "A list of values that you must specify before AWS CloudFormation can update certain stacks",
"parameters": "A list of Parameters that specify input parameters for the stack given using this format: [key1:val1,key2:val2,...]",
"policy-file": "The path to the file containing the stack policy body",
"policy-update-file": "The path to the file containing the temporary overriding stack policy",
"template-file": "The path to the file containing the template body with a minimum size of 1 byte and a maximum size of 51,200 bytes",
"stack-file": "The path to the file containing Parameters/Tags/StackPolices definition (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-cfn-artifacts.html#w2ab2c13c15c15). Values passed via CLI has higher priority than ones defined in StackFile",
"rollback-triggers": "List of ClodwatchAlarm Arns to monitor during and after update",
"rollback-monitoring-min": "Time to monitor rollback-triggers during and after update",
},
"update.targetgroup": {
"id": "The Amazon Resource Name (ARN) of the target group",
Expand Down
3 changes: 3 additions & 0 deletions aws/spec/setters.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const (
aws6digitsstring = "aws6digitsstring"
awsbyteslice = "awsbyteslice"
awstagslice = "awstagslice"
awsrollbackconfig = "awsrollbackconfig"
)

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

v = tags
case awsrollbackconfig:
// do nothing since we did all job in BeforeRun
}
awsutil.SetValueAtPath(i, fieldPath, v)
return nil
Expand Down
105 changes: 68 additions & 37 deletions aws/spec/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,40 @@ 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"`
_ 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"`
}

func (cmd *CreateStack) ParamsSpec() params.Spec {
return params.NewSpec(
params.AllOf(params.Key("name"), params.Key("template-file"), params.Opt("capabilities", "disable-rollback", "notifications", "on-failure", "parameters", "policy-file", "resource-types", "role", "stack-file", "tags", "timeout")),
params.AllOf(params.Key("name"), params.Key("template-file"), params.Opt("capabilities", "disable-rollback", "notifications", "on-failure", "parameters", "policy-file", "resource-types", "role", "stack-file", "tags", "timeout", "rollback-triggers", "rollback-monitoring-min")),
params.Validators{"template-file": params.IsFilepath},
)
}
Expand All @@ -71,32 +75,38 @@ func (cmd *CreateStack) ExtractResult(i interface{}) string {
func (cmd *CreateStack) BeforeRun(renv env.Running) error {
var 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
}

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"`
_ 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"`
}

func (cmd *UpdateStack) ParamsSpec() params.Spec {
return params.NewSpec(params.AllOf(params.Key("name"),
params.Opt("capabilities", "notifications", "parameters", "policy-file", "policy-update-file", "resource-types", "role", "stack-file", "tags", "template-file", "use-previous-template"),
params.Opt("capabilities", "notifications", "parameters", "policy-file", "policy-update-file", "resource-types", "role", "stack-file", "tags", "template-file", "use-previous-template", "rollback-triggers", "rollback-monitoring-min"),
))
}

Expand All @@ -110,9 +120,30 @@ func (cmd *UpdateStack) ExtractResult(i interface{}) string {
func (cmd *UpdateStack) BeforeRun(renv env.Running) error {
var 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
}

type stackFile struct {
Parameters map[string]string `yaml:"Parameters"`
Tags map[string]string `yaml:"Tags"`
Expand Down

0 comments on commit e686712

Please sign in to comment.