mirror of
https://github.com/docker/compose.git
synced 2025-07-07 05:44:25 +02:00
up
can update an existing stack using CloudFormation Changeset
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
efeded2670
commit
2d931dab9d
@ -26,14 +26,6 @@ func (b *Backend) Up(ctx context.Context, options cli.ProjectOptions) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
update, err := b.api.StackExists(ctx, project.Name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if update {
|
|
||||||
return fmt.Errorf("we do not (yet) support updating an existing CloudFormation stack")
|
|
||||||
}
|
|
||||||
|
|
||||||
template, err := b.Convert(project)
|
template, err := b.Convert(project)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -62,17 +54,34 @@ func (b *Backend) Up(ctx context.Context, options cli.ProjectOptions) error {
|
|||||||
ParameterLoadBalancerARN: lb,
|
ParameterLoadBalancerARN: lb,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.api.CreateStack(ctx, project.Name, template, parameters)
|
update, err := b.api.StackExists(ctx, project.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
operation := compose.StackCreate
|
||||||
|
if update {
|
||||||
|
operation = compose.StackUpdate
|
||||||
|
changeset, err := b.api.CreateChangeSet(ctx, project.Name, template, parameters)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = b.api.UpdateStack(ctx, changeset)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = b.api.CreateStack(ctx, project.Name, template, parameters)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
w := console.NewProgressWriter()
|
w := console.NewProgressWriter()
|
||||||
for k := range template.Resources {
|
for k := range template.Resources {
|
||||||
w.ResourceEvent(k, "PENDING", "")
|
w.ResourceEvent(k, "PENDING", "")
|
||||||
}
|
}
|
||||||
return b.WaitStackCompletion(ctx, project.Name, compose.StackCreate, w)
|
return b.WaitStackCompletion(ctx, project.Name, operation, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Backend) GetVPC(ctx context.Context, project *types.Project) (string, error) {
|
func (b Backend) GetVPC(ctx context.Context, project *types.Project) (string, error) {
|
||||||
|
@ -23,6 +23,8 @@ type API interface {
|
|||||||
GetStackID(ctx context.Context, name string) (string, error)
|
GetStackID(ctx context.Context, name string) (string, error)
|
||||||
WaitStackComplete(ctx context.Context, name string, operation int) error
|
WaitStackComplete(ctx context.Context, name string, operation int) error
|
||||||
DescribeStackEvents(ctx context.Context, stackID string) ([]*cf.StackEvent, error)
|
DescribeStackEvents(ctx context.Context, stackID string) ([]*cf.StackEvent, error)
|
||||||
|
CreateChangeSet(ctx context.Context, name string, template *cloudformation.Template, parameters map[string]string) (string, error)
|
||||||
|
UpdateStack(ctx context.Context, changeset string) error
|
||||||
|
|
||||||
DescribeServices(ctx context.Context, cluster string, arns []string) ([]compose.ServiceStatus, error)
|
DescribeServices(ctx context.Context, cluster string, arns []string) ([]compose.ServiceStatus, error)
|
||||||
|
|
||||||
|
@ -175,9 +175,8 @@ func (s sdk) CreateStack(ctx context.Context, name string, template *cf.Template
|
|||||||
param := []*cloudformation.Parameter{}
|
param := []*cloudformation.Parameter{}
|
||||||
for name, value := range parameters {
|
for name, value := range parameters {
|
||||||
param = append(param, &cloudformation.Parameter{
|
param = append(param, &cloudformation.Parameter{
|
||||||
ParameterKey: aws.String(name),
|
ParameterKey: aws.String(name),
|
||||||
ParameterValue: aws.String(value),
|
ParameterValue: aws.String(value),
|
||||||
UsePreviousValue: aws.Bool(true),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +193,60 @@ func (s sdk) CreateStack(ctx context.Context, name string, template *cf.Template
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s sdk) CreateChangeSet(ctx context.Context, name string, template *cf.Template, parameters map[string]string) (string, error) {
|
||||||
|
logrus.Debug("Create CloudFormation Changeset")
|
||||||
|
json, err := template.JSON()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
param := []*cloudformation.Parameter{}
|
||||||
|
for name := range parameters {
|
||||||
|
param = append(param, &cloudformation.Parameter{
|
||||||
|
ParameterKey: aws.String(name),
|
||||||
|
UsePreviousValue: aws.Bool(true),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
update := fmt.Sprintf("Update%s", time.Now().Format("2006-01-02-15-04-05"))
|
||||||
|
changeset, err := s.CF.CreateChangeSetWithContext(ctx, &cloudformation.CreateChangeSetInput{
|
||||||
|
ChangeSetName: aws.String(update),
|
||||||
|
ChangeSetType: aws.String(cloudformation.ChangeSetTypeUpdate),
|
||||||
|
StackName: aws.String(name),
|
||||||
|
TemplateBody: aws.String(string(json)),
|
||||||
|
Parameters: param,
|
||||||
|
Capabilities: []*string{
|
||||||
|
aws.String(cloudformation.CapabilityCapabilityIam),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.CF.WaitUntilChangeSetCreateCompleteWithContext(ctx, &cloudformation.DescribeChangeSetInput{
|
||||||
|
ChangeSetName: changeset.Id,
|
||||||
|
})
|
||||||
|
return *changeset.Id, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sdk) UpdateStack(ctx context.Context, changeset string) error {
|
||||||
|
desc, err := s.CF.DescribeChangeSetWithContext(ctx, &cloudformation.DescribeChangeSetInput{
|
||||||
|
ChangeSetName: aws.String(changeset),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(aws.StringValue(desc.StatusReason), "The submitted information didn't contain changes.") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.CF.ExecuteChangeSet(&cloudformation.ExecuteChangeSetInput{
|
||||||
|
ChangeSetName: aws.String(changeset),
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (s sdk) WaitStackComplete(ctx context.Context, name string, operation int) error {
|
func (s sdk) WaitStackComplete(ctx context.Context, name string, operation int) error {
|
||||||
input := &cloudformation.DescribeStacksInput{
|
input := &cloudformation.DescribeStacksInput{
|
||||||
StackName: aws.String(name),
|
StackName: aws.String(name),
|
||||||
|
@ -19,6 +19,7 @@ type ServiceStatus struct {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
StackCreate = iota
|
StackCreate = iota
|
||||||
|
StackUpdate
|
||||||
StackDelete
|
StackDelete
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user