예제 #1
0
func (p *Provisioner) ProvisionUpload(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Uploading %s => %s", p.config.Source, p.config.Destination))
	info, err := os.Stat(p.config.Source)
	if err != nil {
		return err
	}

	// If we're uploading a directory, short circuit and do that
	if info.IsDir() {
		return comm.UploadDir(p.config.Destination, p.config.Source, nil)
	}

	// We're uploading a file...
	f, err := os.Open(p.config.Source)
	if err != nil {
		return err
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return err
	}

	err = comm.Upload(p.config.Destination, f, &fi)
	if err != nil {
		ui.Error(fmt.Sprintf("Upload failed: %s", err))
	}
	return err
}
예제 #2
0
func (p *Provisioner) ProvisionDownload(ui packer.Ui, comm packer.Communicator) error {
	for _, src := range p.config.Sources {
		ui.Say(fmt.Sprintf("Downloading %s => %s", src, p.config.Destination))

		if strings.HasSuffix(p.config.Destination, "/") {
			err := os.MkdirAll(p.config.Destination, os.FileMode(0755))
			if err != nil {
				return err
			}
			return comm.DownloadDir(src, p.config.Destination, nil)
		}

		f, err := os.OpenFile(p.config.Destination, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
		if err != nil {
			return err
		}
		defer f.Close()

		err = comm.Download(src, f)
		if err != nil {
			ui.Error(fmt.Sprintf("Download failed: %s", err))
			return err
		}
	}
	return nil
}
예제 #3
0
func (p *Provisioner) ProvisionDownload(ui packer.Ui, comm packer.Communicator) error {
	for _, src := range p.config.Sources {
		ui.Say(fmt.Sprintf("Downloading %s => %s", src, p.config.Destination))
		// ensure destination dir exists.  p.config.Destination may either be a file or a dir.
		dir := p.config.Destination
		// if it doesn't end with a /, set dir as the parent dir
		if !strings.HasSuffix(p.config.Destination, "/") {
			dir = filepath.Dir(dir)
		}
		if dir != "" {
			err := os.MkdirAll(dir, os.FileMode(0755))
			if err != nil {
				return err
			}
		}
		// if the config.Destination was a dir, download the dir
		if strings.HasSuffix(p.config.Destination, "/") {
			return comm.DownloadDir(src, p.config.Destination, nil)
		}

		f, err := os.OpenFile(p.config.Destination, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
		if err != nil {
			return err
		}
		defer f.Close()

		err = comm.Download(src, f)
		if err != nil {
			ui.Error(fmt.Sprintf("Download failed: %s", err))
			return err
		}
	}
	return nil
}
예제 #4
0
func (t *tunnel) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say("Starting tunnel")
	t.server.comm = comm
	errc := make(chan error, 1)
	go func() {
		errc <- t.server.serveOne()
	}()

	stdout := &lineWriter{output: ui.Say}
	stderr := &lineWriter{output: ui.Error}

	cmd := exec.Command(t.Exec, t.Args...)
	cmd.Env = append(os.Environ(),
		"PACKER_TUNNEL_USERNAME="******"PACKER_TUNNEL_PASSWORD="******"PACKER_TUNNEL_PORT="+strconv.Itoa(t.server.port),
	)
	cmd.Stdout = stdout
	cmd.Stderr = stderr

	log.Println("Command", cmd.Args, "env", cmd.Env)

	ui.Say("Running command " + strings.Join(cmd.Args, " "))

	err := cmd.Run()
	stdout.Flush()
	stderr.Flush()
	if err != nil {
		ui.Error(fmt.Sprintf("Error running command %s", err))
		return err
	}

	return <-errc
}
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	if artifact.BuilderId() != dockerimport.BuilderId {
		err := fmt.Errorf(
			"Unknown artifact type: %s\nCan only tag from Docker builder artifacts.",
			artifact.BuilderId())
		return nil, false, err
	}

	dockerfile, template_err := p.render_template(trim_artifact_id(artifact.Id()))
	if template_err != nil { // could not render template
		return nil, false, template_err
	}

	log.Printf("[DEBUG] Dockerfile: %s\n", dockerfile.String())

	if image_id, err := p.docker_build_fn(dockerfile); err != nil { // docker build command failed
		ui.Error("docker build command failed: " + err.Error())
		return nil, false, err
	} else {
		ui.Message("Built image: " + image_id)
		new_artifact := &docker.ImportArtifact{
			BuilderIdValue: dockerimport.BuilderId,
			Driver:         &docker.DockerDriver{Ui: ui, Tpl: nil},
			IdValue:        image_id,
		}
		log.Printf("[DEBUG] artifact: %#v\n", new_artifact)
		return new_artifact, true, nil
	}
}
예제 #6
0
파일: signal.go 프로젝트: c12simple/packer
// Prepares the signal handlers so that we handle interrupts properly.
// The signal handler exists in a goroutine.
func setupSignalHandlers(ui packer.Ui) {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt)
	signal.Notify(ch, syscall.SIGTERM)

	go func() {
		// First interrupt. We mostly ignore this because it allows the
		// plugins time to cleanup.
		<-ch
		log.Println("First interrupt. Ignoring to allow plugins to clean up.")

		ui.Error("Interrupt signal received. Cleaning up...")

		// Second interrupt. Go down hard.
		<-ch
		log.Println("Second interrupt. Exiting now.")

		ui.Error("Interrupt signal received twice. Forcefully exiting now.")

		// Force kill all the plugins, but mark that we're killing them
		// first so that we don't get panics everywhere.
		plugin.CleanupClients()
		os.Exit(1)
	}()
}
예제 #7
0
func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator, privKeyFile string, checkHostKey bool) error {
	playbook, _ := filepath.Abs(p.config.PlaybookFile)
	inventory := p.config.inventoryFile
	var envvars []string

	args := []string{playbook, "-i", inventory}
	if len(privKeyFile) > 0 {
		args = append(args, "--private-key", privKeyFile)
	}
	args = append(args, p.config.ExtraArguments...)
	if len(p.config.AnsibleEnvVars) > 0 {
		envvars = append(envvars, p.config.AnsibleEnvVars...)
	}

	cmd := exec.Command(p.config.Command, args...)

	cmd.Env = os.Environ()
	if len(envvars) > 0 {
		cmd.Env = append(cmd.Env, envvars...)
	}

	if !checkHostKey {
		cmd.Env = append(cmd.Env, "ANSIBLE_HOST_KEY_CHECKING=False")
	}

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}

	wg := sync.WaitGroup{}
	repeat := func(r io.ReadCloser) {
		scanner := bufio.NewScanner(r)
		for scanner.Scan() {
			ui.Message(scanner.Text())
		}
		if err := scanner.Err(); err != nil {
			ui.Error(err.Error())
		}
		wg.Done()
	}
	wg.Add(2)
	go repeat(stdout)
	go repeat(stderr)

	ui.Say(fmt.Sprintf("Executing Ansible: %s", strings.Join(cmd.Args, " ")))
	cmd.Start()
	wg.Wait()
	err = cmd.Wait()
	if err != nil {
		return fmt.Errorf("Non-zero exit status: %s", err)
	}

	return nil
}
예제 #8
0
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	if artifact.BuilderId() != dockerimport.BuilderId &&
		artifact.BuilderId() != dockertag.BuilderId {
		err := fmt.Errorf(
			"Unknown artifact type: %s\nCan only import from docker-import and docker-tag artifacts.",
			artifact.BuilderId())
		return nil, false, err
	}

	driver := p.Driver
	if driver == nil {
		// If no driver is set, then we use the real driver
		driver = &docker.DockerDriver{Ctx: &p.config.ctx, Ui: ui}
	}

	if p.config.EcrLogin {
		ui.Message("Fetching ECR credentials...")

		username, password, err := p.config.EcrGetLogin(p.config.LoginServer)
		if err != nil {
			return nil, false, err
		}

		p.config.LoginUsername = username
		p.config.LoginPassword = password
	}

	if p.config.Login || p.config.EcrLogin {
		ui.Message("Logging in...")
		err := driver.Login(
			p.config.LoginServer,
			p.config.LoginEmail,
			p.config.LoginUsername,
			p.config.LoginPassword)
		if err != nil {
			return nil, false, fmt.Errorf(
				"Error logging in to Docker: %s", err)
		}

		defer func() {
			ui.Message("Logging out...")
			if err := driver.Logout(p.config.LoginServer); err != nil {
				ui.Error(fmt.Sprintf("Error logging out: %s", err))
			}
		}()
	}

	// Get the name.
	name := artifact.Id()

	ui.Message("Pushing: " + name)
	if err := driver.Push(name); err != nil {
		return nil, false, err
	}

	return nil, false, nil
}
예제 #9
0
func NewStepSetCertificate(config *Config, ui packer.Ui) *StepSetCertificate {
	var step = &StepSetCertificate{
		config: config,
		say:    func(message string) { ui.Say(message) },
		error:  func(e error) { ui.Error(e.Error()) },
	}

	return step
}
예제 #10
0
func NewStepGetIPAddress(client *AzureClient, ui packer.Ui) *StepGetIPAddress {
	var step = &StepGetIPAddress{
		client: client,
		say:    func(message string) { ui.Say(message) },
		error:  func(e error) { ui.Error(e.Error()) },
	}

	step.get = step.getIPAddress
	return step
}
예제 #11
0
func NewStepPowerOffCompute(client *AzureClient, ui packer.Ui) *StepPowerOffCompute {
	var step = &StepPowerOffCompute{
		client: client,
		say:    func(message string) { ui.Say(message) },
		error:  func(e error) { ui.Error(e.Error()) },
	}

	step.powerOff = step.powerOffCompute
	return step
}
예제 #12
0
func NewStepDeleteOSDisk(client *AzureClient, ui packer.Ui) *StepDeleteOSDisk {
	var step = &StepDeleteOSDisk{
		client: client,
		say:    func(message string) { ui.Say(message) },
		error:  func(e error) { ui.Error(e.Error()) },
	}

	step.delete = step.deleteBlob
	return step
}
예제 #13
0
func NewStepGetOSDisk(client *AzureClient, ui packer.Ui) *StepGetOSDisk {
	var step = &StepGetOSDisk{
		client: client,
		say:    func(message string) { ui.Say(message) },
		error:  func(e error) { ui.Error(e.Error()) },
	}

	step.query = step.queryCompute
	return step
}
예제 #14
0
func NewStepCreateResourceGroup(client *AzureClient, ui packer.Ui) *StepCreateResourceGroup {
	var step = &StepCreateResourceGroup{
		client: client,
		say:    func(message string) { ui.Say(message) },
		error:  func(e error) { ui.Error(e.Error()) },
	}

	step.create = step.createResourceGroup
	return step
}
예제 #15
0
func NewStepCaptureImage(client *AzureClient, ui packer.Ui) *StepCaptureImage {
	var step = &StepCaptureImage{
		client: client,
		say:    func(message string) { ui.Say(message) },
		error:  func(e error) { ui.Error(e.Error()) },
	}

	step.capture = step.captureImage
	return step
}
예제 #16
0
func NewStepDeployTemplate(client *AzureClient, ui packer.Ui) *StepDeployTemplate {
	var step = &StepDeployTemplate{
		client: client,
		say:    func(message string) { ui.Say(message) },
		error:  func(e error) { ui.Error(e.Error()) },
	}

	step.deploy = step.deployTemplate
	return step
}
func (p *Provisioner) ProvisionUpload(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Uploading %s => %s", p.config.Source, p.config.Destination))

	info, _ := os.Stat(p.config.Source)
	if info != nil {
		// If we're uploading a directory, short circuit and do that
		if info.IsDir() {
			return comm.UploadDir(p.config.Destination, p.config.Source, nil)
		}
	}

	pwd, err := os.Getwd()
	if err != nil {
		return fmt.Errorf("Couldn't get the current working directory")
	}

	det, err := gg.Detect(p.config.Source, pwd, gg.Detectors)
	if err != nil {
		return fmt.Errorf("Couldn't detect file source type: %v", err)
	}

	if len(det) == 0 {
		return errors.New("Don't recognise the source type")
	}

	dir, err := ioutil.TempDir("", "packer")
	if err != nil {
		return errors.New("Unable to create temp dir")
	}

	defer os.RemoveAll(dir)

	source := filepath.Join(dir, filepath.Base(p.config.Source))
	if err := gg.GetFile(source, p.config.Source); err != nil {
		return fmt.Errorf("There was a problem getting the file: %v", err)
	}

	// We're uploading a file...
	f, err := os.Open(source)
	if err != nil {
		return err
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return err
	}

	err = comm.Upload(p.config.Destination, f, &fi)
	if err != nil {
		ui.Error(fmt.Sprintf("Upload failed: %s", err))
	}
	return err
}
func NewStepValidateTemplate(client *AzureClient, ui packer.Ui, template string) *StepValidateTemplate {
	var step = &StepValidateTemplate{
		client:   client,
		template: template,
		say:      func(message string) { ui.Say(message) },
		error:    func(e error) { ui.Error(e.Error()) },
	}

	step.validate = step.validateTemplate
	return step
}
예제 #19
0
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	if artifact.BuilderId() != dockerimport.BuilderId &&
		artifact.BuilderId() != dockertag.BuilderId {
		err := fmt.Errorf(
			"Unknown artifact type: %s\nCan only import from docker-import and docker-tag artifacts.",
			artifact.BuilderId())
		return nil, false, err
	}

	driver := p.Driver
	if driver == nil {
		// If no driver is set, then we use the real driver
		driver = &docker.DockerDriver{Ctx: &p.config.ctx, Ui: ui}
	}

	if p.config.Login {
		ui.Message("Logging in...")
		err := driver.Login(
			p.config.LoginServer,
			p.config.LoginEmail,
			p.config.LoginUsername,
			p.config.LoginPassword)
		if err != nil {
			return nil, false, fmt.Errorf(
				"Error logging in to Docker: %s", err)
		}

		defer func() {
			ui.Message("Logging out...")
			if err := driver.Logout(p.config.LoginServer); err != nil {
				ui.Error(fmt.Sprintf("Error logging out: %s", err))
			}
		}()
	}

	// Get the name. We strip off any tags from the name because the
	// push doesn't use those.
	name := artifact.Id()

	if i := strings.Index(name, "/"); i >= 0 {
		// This should always be true because the / is required. But we have
		// to get the index to this so we don't accidentally strip off the port
		if j := strings.Index(name[i:], ":"); j >= 0 {
			name = name[:i+j]
		}
	}

	ui.Message("Pushing: " + name)
	if err := driver.Push(name); err != nil {
		return nil, false, err
	}

	return nil, false, nil
}
예제 #20
0
func NewStepGetCertificate(client *AzureClient, ui packer.Ui) *StepGetCertificate {
	var step = &StepGetCertificate{
		client: client,
		say:    func(message string) { ui.Say(message) },
		error:  func(e error) { ui.Error(e.Error()) },
		pause:  func() { time.Sleep(30 * time.Second) },
	}

	step.get = step.getCertificateUrl
	return step
}
예제 #21
0
func NewStepValidateTemplate(client *AzureClient, ui packer.Ui, config *Config, factory templateFactoryFunc) *StepValidateTemplate {
	var step = &StepValidateTemplate{
		client:  client,
		say:     func(message string) { ui.Say(message) },
		error:   func(e error) { ui.Error(e.Error()) },
		config:  config,
		factory: factory,
	}

	step.validate = step.validateTemplate
	return step
}
예제 #22
0
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Uploading %s => %s", p.config.Source, p.config.Destination))
	f, err := os.Open(p.config.Source)
	if err != nil {
		return err
	}
	defer f.Close()

	err = comm.Upload(p.config.Destination, f)
	if err != nil {
		ui.Error(fmt.Sprintf("Upload failed: %s", err))
	}
	return err
}
예제 #23
0
func (p *Provisioner) ProvisionDownload(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Downloading %s => %s", p.config.Source, p.config.Destination))

	f, err := os.OpenFile(p.config.Destination, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	err = comm.Download(p.config.Source, f)
	if err != nil {
		ui.Error(fmt.Sprintf("Download failed: %s", err))
	}
	return err
}
예제 #24
0
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
	ui.Say("Preparing builder ...")

	b.stateBag.Put("hook", hook)
	b.stateBag.Put(constants.Ui, ui)

	servicePrincipalToken, err := b.createServicePrincipalToken()
	if err != nil {
		return nil, err
	}

	ui.Message("Creating Azure Resource Manager (ARM) client ...")
	azureClient, err := NewAzureClient(b.config.SubscriptionID, b.config.ResourceGroupName, b.config.StorageAccount, servicePrincipalToken)
	if err != nil {
		return nil, err
	}

	steps := []multistep.Step{
		NewStepCreateResourceGroup(azureClient, ui),
		NewStepValidateTemplate(azureClient, ui),
		NewStepDeployTemplate(azureClient, ui),
		NewStepGetIPAddress(azureClient, ui),
		&communicator.StepConnectSSH{
			Config:    &b.config.Comm,
			Host:      lin.SSHHost,
			SSHConfig: lin.SSHConfig(b.config.UserName),
		},
		&common.StepProvision{},
		&lin.StepGeneralizeOS{
			Command: "sudo /usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync",
		},
		NewStepGetOSDisk(azureClient, ui),
		NewStepPowerOffCompute(azureClient, ui),
		NewStepCaptureImage(azureClient, ui),
		NewStepDeleteResourceGroup(azureClient, ui),
		NewStepDeleteOSDisk(azureClient, ui),
	}

	b.runner = b.createRunner(&steps, ui)
	b.runner.Run(b.stateBag)

	if e, ok := b.stateBag.GetOk(constants.Error); ok {
		ui.Error(e.(string))
	}

	return &artifact{}, nil
}
func NewStepGetIPAddress(client *AzureClient, ui packer.Ui, endpoint EndpointType) *StepGetIPAddress {
	var step = &StepGetIPAddress{
		client:   client,
		endpoint: endpoint,
		say:      func(message string) { ui.Say(message) },
		error:    func(e error) { ui.Error(e.Error()) },
	}

	switch endpoint {
	case PrivateEndpoint:
		step.get = step.getPrivateIP
	case PublicEndpoint:
		step.get = step.getPublicIP
	}

	return step
}
func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator) error {
	playbook, _ := filepath.Abs(p.config.PlaybookFile)
	inventory := p.config.inventoryFile

	args := []string{playbook, "-i", inventory}
	args = append(args, p.config.ExtraArguments...)

	cmd := exec.Command(p.config.Command, args...)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}

	wg := sync.WaitGroup{}
	repeat := func(r io.ReadCloser) {
		scanner := bufio.NewScanner(r)
		for scanner.Scan() {
			ui.Message(scanner.Text())
		}
		if err := scanner.Err(); err != nil {
			ui.Error(err.Error())
		}
		wg.Done()
	}
	wg.Add(2)
	go repeat(stdout)
	go repeat(stderr)

	ui.Say(fmt.Sprintf("Executing Ansible: %s", strings.Join(cmd.Args, " ")))
	cmd.Start()
	wg.Wait()
	err = cmd.Wait()
	if err != nil {
		return fmt.Errorf("Non-zero exit status: %s", err)
	}

	return nil
}
예제 #27
0
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Provisioning with windows-shell..."))
	scripts := make([]string, len(p.config.Scripts))
	copy(scripts, p.config.Scripts)

	// Build our variables up by adding in the build name and builder type
	envVars := make([]string, len(p.config.Vars)+2)
	envVars[0] = "PACKER_BUILD_NAME=" + p.config.PackerBuildName
	envVars[1] = "PACKER_BUILDER_TYPE=" + p.config.PackerBuilderType

	copy(envVars, p.config.Vars)

	if p.config.Inline != nil {
		temp, err := extractScript(p)
		if err != nil {
			ui.Error(fmt.Sprintf("Unable to extract inline scripts into a file: %s", err))
		}
		scripts = append(scripts, temp)
	}

	for _, path := range scripts {
		ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path))

		log.Printf("Opening %s for reading", path)
		f, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening shell script: %s", err)
		}
		defer f.Close()

		// Create environment variables to set before executing the command
		flattendVars, err := p.createFlattenedEnvVars()
		if err != nil {
			return err
		}

		// Compile the command
		p.config.ctx.Data = &ExecuteCommandTemplate{
			Vars: flattendVars,
			Path: p.config.RemotePath,
		}
		command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
		if err != nil {
			return fmt.Errorf("Error processing command: %s", err)
		}

		// Upload the file and run the command. Do this in the context of
		// a single retryable function so that we don't end up with
		// the case that the upload succeeded, a restart is initiated,
		// and then the command is executed but the file doesn't exist
		// any longer.
		var cmd *packer.RemoteCmd
		err = p.retryable(func() error {
			if _, err := f.Seek(0, 0); err != nil {
				return err
			}

			if err := comm.Upload(p.config.RemotePath, f, nil); err != nil {
				return fmt.Errorf("Error uploading script: %s", err)
			}

			cmd = &packer.RemoteCmd{Command: command}
			return cmd.StartWithUi(comm, ui)
		})
		if err != nil {
			return err
		}

		// Close the original file since we copied it
		f.Close()

		if cmd.ExitStatus != 0 {
			return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
		}
	}

	return nil
}
예제 #28
0
func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator, privKeyFile string) error {
	playbook, _ := filepath.Abs(p.config.PlaybookFile)
	inventory := p.config.inventoryFile
	var envvars []string

	args := []string{playbook, "-i", inventory}
	if len(privKeyFile) > 0 {
		args = append(args, "--private-key", privKeyFile)
	}
	args = append(args, p.config.ExtraArguments...)
	if len(p.config.AnsibleEnvVars) > 0 {
		envvars = append(envvars, p.config.AnsibleEnvVars...)
	}

	cmd := exec.Command(p.config.Command, args...)

	cmd.Env = os.Environ()
	if len(envvars) > 0 {
		cmd.Env = append(cmd.Env, envvars...)
	}

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}

	wg := sync.WaitGroup{}
	repeat := func(r io.ReadCloser) {
		reader := bufio.NewReader(r)
		for {
			line, err := reader.ReadString('\n')
			if line != "" {
				line = strings.TrimRightFunc(line, unicode.IsSpace)
				ui.Message(line)
			}
			if err != nil {
				if err == io.EOF {
					break
				} else {
					ui.Error(err.Error())
					break
				}
			}
		}
		wg.Done()
	}
	wg.Add(2)
	go repeat(stdout)
	go repeat(stderr)

	log.Printf("Executing Ansible: %s", strings.Join(cmd.Args, " "))
	cmd.Start()
	wg.Wait()
	err = cmd.Wait()
	if err != nil {
		return fmt.Errorf("Non-zero exit status: %s", err)
	}

	return nil
}
예제 #29
0
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	ui.Say(fmt.Sprintf("Provisioning with Powershell..."))
	p.communicator = comm

	scripts := make([]string, len(p.config.Scripts))
	copy(scripts, p.config.Scripts)

	// Build our variables up by adding in the build name and builder type
	envVars := make([]string, len(p.config.Vars)+2)
	envVars[0] = "PACKER_BUILD_NAME=" + p.config.PackerBuildName
	envVars[1] = "PACKER_BUILDER_TYPE=" + p.config.PackerBuilderType
	copy(envVars, p.config.Vars)

	if p.config.Inline != nil {
		temp, err := extractScript(p)
		if err != nil {
			ui.Error(fmt.Sprintf("Unable to extract inline scripts into a file: %s", err))
		}
		scripts = append(scripts, temp)
	}

	for _, path := range scripts {
		ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path))

		log.Printf("Opening %s for reading", path)
		f, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening shell script: %s", err)
		}
		defer f.Close()

		command, err := p.createCommandText()
		if err != nil {
			return fmt.Errorf("Error processing command: %s", err)
		}

		// Upload the file and run the command. Do this in the context of
		// a single retryable function so that we don't end up with
		// the case that the upload succeeded, a restart is initiated,
		// and then the command is executed but the file doesn't exist
		// any longer.
		var cmd *packer.RemoteCmd
		err = p.retryable(func() error {
			if _, err := f.Seek(0, 0); err != nil {
				return err
			}

			if err := comm.Upload(p.config.RemotePath, f, nil); err != nil {
				return fmt.Errorf("Error uploading script: %s", err)
			}

			cmd = &packer.RemoteCmd{Command: command}
			return cmd.StartWithUi(comm, ui)
		})
		if err != nil {
			return err
		}

		// Close the original file since we copied it
		f.Close()

		// Check exit code against allowed codes (likely just 0)
		validExitCode := false
		for _, v := range p.config.ValidExitCodes {
			if cmd.ExitStatus == v {
				validExitCode = true
			}
		}
		if !validExitCode {
			return fmt.Errorf(
				"Script exited with non-zero exit status: %d. Allowed exit codes are: %v",
				cmd.ExitStatus, p.config.ValidExitCodes)
		}
	}

	return nil
}