Example #1
0
// Service Update takes a map of CF Parameter changes and applies on top of
// the existing parameters and the newest template.
// The CLI / Client / Server delegates everything to CloudFormation, and
// makes no guarantees of service uptime during update. In fact, most datastore
// updates guarantee resource replacement which will cause database downtime.
func (s *Service) Update(changes map[string]string) error {
	var req *cloudformation.UpdateStackInput
	var err error

	switch s.Type {
	case "papertrail":
		return fmt.Errorf("can not update papertrail")
	case "webhook":
		return fmt.Errorf("can not update webhook")
	case "s3", "sns", "sqs":
		req, err = s.UpdateIAMService()
	default:
		req, err = s.UpdateDatastore()
	}

	if err != nil {
		return err
	}

	params := map[string]string{}

	// copy existing parameters
	for key, value := range s.Parameters {
		params[key] = value
	}

	// update changes
	for key, value := range changes {
		params[key] = value
	}

	fp, err := formationParameters(*req.TemplateBody)

	if err != nil {
		return err
	}

	// remove params that don't exist in the template
	for key := range params {
		if _, ok := fp[key]; !ok {
			delete(params, key)
		}
	}

	// pass through service parameters as Cloudformation Parameters
	for key, value := range params {
		req.Parameters = append(req.Parameters, &cloudformation.Parameter{
			ParameterKey:   aws.String(key),
			ParameterValue: aws.String(value),
		})
	}

	_, err = CloudFormation().UpdateStack(req)

	return err
}
Example #2
0
// executeStackUpdate performs a stack update.
func (s *Scheduler) executeStackUpdate(input *cloudformation.UpdateStackInput) error {
	stack, err := s.stack(input.StackName)
	if err != nil {
		return err
	}

	// If we're updating a stack, without changing the template, merge in
	// existing parameters with their previous value.
	if input.UsePreviousTemplate != nil && *input.UsePreviousTemplate == true {
		// The parameters that the stack defines. We need to make sure that we
		// provide all parameters in the update (lame).
		definedParams := make(map[string]bool)
		for _, p := range stack.Parameters {
			definedParams[*p.ParameterKey] = true
		}

		// The parameters that are provided in this update.
		providedParams := make(map[string]bool)
		for _, p := range input.Parameters {
			providedParams[*p.ParameterKey] = true
		}

		// Fill in any parameters that weren't provided with their default
		// value.
		for k := range definedParams {
			if !providedParams[k] {
				input.Parameters = append(input.Parameters, &cloudformation.Parameter{
					ParameterKey:     aws.String(k),
					UsePreviousValue: aws.Bool(true),
				})
			}
		}
	}

	_, err = s.cloudformation.UpdateStack(input)
	if err != nil {
		if err, ok := err.(awserr.Error); ok {
			if err.Code() == "ValidationError" && err.Message() == "No updates are to be performed." {
				return nil
			}
		}

		return fmt.Errorf("error updating stack: %v", err)
	}

	return nil
}
Example #3
0
// UsePreviousTemplate sets the use previous tempalte on a UpdateStackInput
func UsePreviousTemplate(params *cfn.UpdateStackInput) {
	params.UsePreviousTemplate = aws.Bool(true)
}
					createStackError = awserr.New("code", "message", errors.New("operation failed"))
				})

				It("returns the proper error", func() {
					err := stack.Create(stackName, stackDetails)
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(Equal("code: message"))
				})
			})
		})
	})

	var _ = Describe("Modify", func() {
		var (
			stackDetails StackDetails

			updateStackInput *cloudformation.UpdateStackInput
			updateStackError error
		)

		BeforeEach(func() {
			stackDetails = StackDetails{
				StackName:   stackName,
				TemplateURL: "test-template-url",
			}

			updateStackInput = &cloudformation.UpdateStackInput{
				StackName:   aws.String(stackName),
				TemplateURL: aws.String("test-template-url"),
			}
			updateStackError = nil
		})