Example #1
0
// waitForState will spin in a loop forever waiting for state to
// reach a certain target.
func waitForState(errCh chan<- error, target string, refresh stateRefreshFunc) error {
	err := common.Retry(2, 2, 0, func() (bool, error) {
		state, err := refresh()
		if err != nil {
			return false, err
		} else if state == target {
			return true, nil
		}
		return false, nil
	})
	errCh <- err
	return err
}
// Run reads the instance metadata and looks for the log entry
// indicating the startup script finished.
func (s *StepWaitInstanceStartup) Run(state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(*Config)
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)
	instanceName := state.Get("instance_name").(string)

	ui.Say("Waiting for any running startup script to finish...")

	// Keep checking the serial port output to see if the startup script is done.
	err := common.Retry(10, 60, 0, func() (bool, error) {
		status, err := driver.GetInstanceMetadata(config.Zone,
			instanceName, StartupScriptStatusKey)

		if err != nil {
			err := fmt.Errorf("Error getting startup script status: %s", err)
			return false, err
		}

		if status == StartupScriptStatusError {
			err = errors.New("Startup script error.")
			return false, err
		}

		done := status == StartupScriptStatusDone
		if !done {
			ui.Say("Startup script not finished yet. Waiting...")
		}

		return done, nil
	})

	if err != nil {
		err := fmt.Errorf("Error waiting for startup script to finish: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}
	ui.Say("Startup script, if any, has finished running.")
	return multistep.ActionContinue
}
func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction {
	ec2conn := state.Get("ec2").(*ec2.EC2)
	ui := state.Get("ui").(packer.Ui)
	amis := state.Get("amis").(map[string]string)

	if len(s.Tags) > 0 {
		for region, ami := range amis {
			ui.Say(fmt.Sprintf("Adding tags to AMI (%s)...", ami))

			var ec2Tags []*ec2.Tag
			for key, value := range s.Tags {
				ui.Message(fmt.Sprintf("Adding tag: \"%s\": \"%s\"", key, value))
				ec2Tags = append(ec2Tags, &ec2.Tag{
					Key:   aws.String(key),
					Value: aws.String(value),
				})
			}

			// Declare list of resources to tag
			resourceIds := []*string{&ami}
			awsConfig := aws.Config{
				Credentials: ec2conn.Config.Credentials,
				Region:      aws.String(region),
			}
			session := session.New(&awsConfig)

			regionconn := ec2.New(session)

			// Retrieve image list for given AMI
			imageResp, err := regionconn.DescribeImages(&ec2.DescribeImagesInput{
				ImageIds: resourceIds,
			})

			if err != nil {
				err := fmt.Errorf("Error retrieving details for AMI (%s): %s", ami, err)
				state.Put("error", err)
				ui.Error(err.Error())
				return multistep.ActionHalt
			}

			if len(imageResp.Images) == 0 {
				err := fmt.Errorf("Error retrieving details for AMI (%s), no images found", ami)
				state.Put("error", err)
				ui.Error(err.Error())
				return multistep.ActionHalt
			}

			image := imageResp.Images[0]

			// Add only those with a Snapshot ID, i.e. not Ephemeral
			for _, device := range image.BlockDeviceMappings {
				if device.Ebs != nil && device.Ebs.SnapshotId != nil {
					ui.Say(fmt.Sprintf("Tagging snapshot: %s", *device.Ebs.SnapshotId))
					resourceIds = append(resourceIds, device.Ebs.SnapshotId)
				}
			}

			// Retry creating tags for about 2.5 minutes
			err = retry.Retry(0.2, 30, 11, func() (bool, error) {
				_, err := regionconn.CreateTags(&ec2.CreateTagsInput{
					Resources: resourceIds,
					Tags:      ec2Tags,
				})
				if err == nil {
					return true, nil
				}
				if awsErr, ok := err.(awserr.Error); ok {
					if awsErr.Code() == "InvalidAMIID.NotFound" ||
						awsErr.Code() == "InvalidSnapshot.NotFound" {
						return false, nil
					}
				}
				return true, err
			})

			if err != nil {
				err := fmt.Errorf("Error adding tags to Resources (%#v): %s", resourceIds, err)
				state.Put("error", err)
				ui.Error(err.Error())
				return multistep.ActionHalt
			}
		}
	}

	return multistep.ActionContinue
}