func (p *Provisioner) uploadManifests(ui packer.Ui, comm packer.Communicator) (string, error) { // Create the remote manifests directory... ui.Message("Uploading manifests...") remoteManifestsPath := fmt.Sprintf("%s/manifests", p.config.StagingDir) if err := p.createDir(ui, comm, remoteManifestsPath); err != nil { return "", fmt.Errorf("Error creating manifests directory: %s", err) } // Upload the main manifest f, err := os.Open(p.config.ManifestFile) if err != nil { return "", err } defer f.Close() manifestFilename := p.config.ManifestFile if fi, err := os.Stat(p.config.ManifestFile); err != nil { return "", fmt.Errorf("Error inspecting manifest file: %s", err) } else if !fi.IsDir() { manifestFilename = filepath.Base(manifestFilename) } else { ui.Say("WARNING: manifest_file should be a file. Use manifest_dir for directories") } remoteManifestFile := fmt.Sprintf("%s/%s", remoteManifestsPath, manifestFilename) if err := comm.Upload(remoteManifestFile, f, nil); err != nil { return "", err } return remoteManifestFile, nil }
func (p *Provisioner) createKnifeConfig(ui packer.Ui, comm packer.Communicator, nodeName string, serverUrl string, clientKey string, sslVerifyMode string) (string, error) { ui.Message("Creating configuration file 'knife.rb'") // Read the template tpl := DefaultKnifeTemplate ctx := p.config.ctx ctx.Data = &ConfigTemplate{ NodeName: nodeName, ServerUrl: serverUrl, ClientKey: clientKey, SslVerifyMode: sslVerifyMode, } configString, err := interpolate.Render(tpl, &ctx) if err != nil { return "", err } remotePath := filepath.ToSlash(filepath.Join(p.config.StagingDir, "knife.rb")) if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString)), nil); err != nil { return "", err } return remotePath, nil }
func (p *Provisioner) createJson(ui packer.Ui, comm packer.Communicator) (string, error) { ui.Message("Creating JSON attribute file") jsonData := make(map[string]interface{}) // Copy the configured JSON for k, v := range p.config.Json { jsonData[k] = v } // Set the run list if it was specified if len(p.config.RunList) > 0 { jsonData["run_list"] = p.config.RunList } jsonBytes, err := json.MarshalIndent(jsonData, "", " ") if err != nil { return "", err } // Upload the bytes remotePath := filepath.ToSlash(filepath.Join(p.config.StagingDir, "node.json")) if err := comm.Upload(remotePath, bytes.NewReader(jsonBytes), nil); err != nil { return "", err } return remotePath, nil }
func UploadLocalDirectory(localDir string, comm packer.Communicator) (err error) { visitPath := func(path string, f os.FileInfo, err error) (err2 error) { var remotePath = RemoteStagingPath + "/" + path if f.IsDir() { // Make remote directory err = CreateRemoteDirectory(remotePath, comm) if err != nil { return err } } else { // Upload file to existing directory file, err := os.Open(path) if err != nil { return fmt.Errorf("Error opening file: %s", err) } err = comm.Upload(remotePath, file) if err != nil { return fmt.Errorf("Error uploading file: %s", err) } } return } log.Printf("Uploading directory %s", localDir) err = filepath.Walk(localDir, visitPath) if err != nil { return fmt.Errorf("Error uploading modules %s: %s", localDir, err) } return nil }
func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string) (string, error) { ui.Message("Creating configuration file 'solo.rb'") cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths)+len(localCookbooks)) for i, path := range p.config.RemoteCookbookPaths { cookbook_paths[i] = fmt.Sprintf(`"%s"`, path) } for i, path := range localCookbooks { i = len(p.config.RemoteCookbookPaths) + i cookbook_paths[i] = fmt.Sprintf(`"%s"`, path) } configString, err := p.config.tpl.Process(DefaultConfigTemplate, &ConfigTemplate{ CookbookPaths: strings.Join(cookbook_paths, ","), }) if err != nil { return "", err } remotePath := filepath.Join(p.config.StagingDir, "solo.rb") if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString))); err != nil { return "", err } return remotePath, nil }
func (p *Provisioner) uploadDeploymentManifest(ui packer.Ui, comm packer.Communicator) error { ui.Say(fmt.Sprintf("Uploading manifest: %s", p.config.Manifest)) err := runCmd("mkdir ~/deployments", ui, comm) if err != nil { return err } f, err := os.Open(p.config.Manifest) if err != nil { return err } defer f.Close() fi, err := f.Stat() if err != nil { return err } err = comm.Upload(fmt.Sprintf("~/deployments/%s", p.config.Manifest), f, &fi) if err != nil { return err } cmd := fmt.Sprintf("sed -i \"s/director_uuid: .*/director_uuid: $(bosh status --uuid)/\" ~/deployments/%s", p.config.Manifest) return runCmd(cmd, ui, comm) }
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 }
func (s *StepUploadX509Cert) uploadSingle(comm packer.Communicator, dst, src string) error { f, err := os.Open(src) if err != nil { return err } defer f.Close() return comm.Upload(dst, f, nil) }
func (p *Provisioner) uploadFile(ui packer.Ui, comm packer.Communicator, dst string, src string) error { f, err := os.Open(src) if err != nil { return err } defer f.Close() return comm.Upload(dst, f, nil) }
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() return comm.Upload(p.config.Destination, f) }
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 (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string, rolesPath string, dataBagsPath string, encryptedDataBagSecretPath string, environmentsPath string, chefEnvironment string) (string, error) { ui.Message("Creating configuration file 'solo.rb'") cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths)+len(localCookbooks)) for i, path := range p.config.RemoteCookbookPaths { cookbook_paths[i] = fmt.Sprintf(`"%s"`, path) } for i, path := range localCookbooks { i = len(p.config.RemoteCookbookPaths) + i cookbook_paths[i] = fmt.Sprintf(`"%s"`, path) } // Read the template tpl := DefaultConfigTemplate if p.config.ConfigTemplate != "" { f, err := os.Open(p.config.ConfigTemplate) if err != nil { return "", err } defer f.Close() tplBytes, err := ioutil.ReadAll(f) if err != nil { return "", err } tpl = string(tplBytes) } p.config.ctx.Data = &ConfigTemplate{ CookbookPaths: strings.Join(cookbook_paths, ","), RolesPath: rolesPath, DataBagsPath: dataBagsPath, EncryptedDataBagSecretPath: encryptedDataBagSecretPath, EnvironmentsPath: environmentsPath, HasRolesPath: rolesPath != "", HasDataBagsPath: dataBagsPath != "", HasEncryptedDataBagSecretPath: encryptedDataBagSecretPath != "", HasEnvironmentsPath: environmentsPath != "", ChefEnvironment: chefEnvironment, } configString, err := interpolate.Render(tpl, &p.config.ctx) if err != nil { return "", err } remotePath := filepath.ToSlash(filepath.Join(p.config.StagingDir, "solo.rb")) if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString)), nil); err != nil { return "", err } return remotePath, nil }
func (p *Provisioner) createConfig( ui packer.Ui, comm packer.Communicator, nodeName string, serverUrl string, clientKey string, encryptedDataBagSecretPath, remoteKeyPath string, validationClientName string, chefEnvironment string, sslVerifyMode string) (string, error) { ui.Message("Creating configuration file 'client.rb'") // Read the template tpl := DefaultConfigTemplate if p.config.ConfigTemplate != "" { f, err := os.Open(p.config.ConfigTemplate) if err != nil { return "", err } defer f.Close() tplBytes, err := ioutil.ReadAll(f) if err != nil { return "", err } tpl = string(tplBytes) } ctx := p.config.ctx ctx.Data = &ConfigTemplate{ NodeName: nodeName, ServerUrl: serverUrl, ClientKey: clientKey, ValidationKeyPath: remoteKeyPath, ValidationClientName: validationClientName, ChefEnvironment: chefEnvironment, SslVerifyMode: sslVerifyMode, EncryptedDataBagSecretPath: encryptedDataBagSecretPath, } configString, err := interpolate.Render(tpl, &ctx) if err != nil { return "", err } remotePath := filepath.ToSlash(filepath.Join(p.config.StagingDir, "client.rb")) if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString)), nil); err != nil { return "", err } return remotePath, nil }
func (p *Provisioner) uploadFile(ui packer.Ui, comm packer.Communicator, remotePath string, localPath string) error { ui.Message(fmt.Sprintf("Uploading %s...", localPath)) f, err := os.Open(localPath) if err != nil { return err } defer f.Close() return comm.Upload(remotePath, f, nil) }
func (p *Provisioner) uploadFile(ui packer.Ui, comm packer.Communicator, dst, src string) error { f, err := os.Open(src) if err != nil { return fmt.Errorf("Error opening: %s", err) } defer f.Close() if err = comm.Upload(dst, f, nil); err != nil { return fmt.Errorf("Error uploading %s: %s", src, err) } return nil }
func uploadMinionConfig(comm packer.Communicator, dst string, src string) error { f, err := os.Open(src) if err != nil { return fmt.Errorf("Error opening minion config: %s", err) } defer f.Close() if err = comm.Upload(dst, f); err != nil { return fmt.Errorf("Error uploading minion config: %s", err) } return nil }
func (p *Provisioner) uploadHieraConfig(ui packer.Ui, comm packer.Communicator) (string, error) { ui.Message("Uploading hiera configuration...") f, err := os.Open(p.config.HieraConfigPath) if err != nil { return "", err } defer f.Close() path := fmt.Sprintf("%s/hiera.yaml", p.config.StagingDir) if err := comm.Upload(path, f, nil); err != nil { return "", err } return path, nil }
func (p *Provisioner) copyValidationKey(ui packer.Ui, comm packer.Communicator, remotePath string) error { ui.Message("Uploading validation key...") // First upload the validation key to a writable location f, err := os.Open(p.config.ValidationKeyPath) if err != nil { return err } defer f.Close() if err := comm.Upload(remotePath, f); err != nil { return err } return nil }
func (p *Provisioner) uploadManifests(ui packer.Ui, comm packer.Communicator) (string, error) { // Create the remote manifests directory... ui.Message("Uploading manifests...") remoteManifestsPath := fmt.Sprintf("%s/manifests", p.config.StagingDir) if err := p.createDir(ui, comm, remoteManifestsPath); err != nil { return "", fmt.Errorf("Error creating manifests directory: %s", err) } // NOTE! manifest_file may either be a directory or a file, as puppet apply // now accepts either one. fi, err := os.Stat(p.config.ManifestFile) if err != nil { return "", fmt.Errorf("Error inspecting manifest file: %s", err) } if fi.IsDir() { // If manifest_file is a directory we'll upload the whole thing ui.Message(fmt.Sprintf( "Uploading manifest directory from: %s", p.config.ManifestFile)) remoteManifestDir := fmt.Sprintf("%s/manifests", p.config.StagingDir) err := p.uploadDirectory(ui, comm, remoteManifestDir, p.config.ManifestFile) if err != nil { return "", fmt.Errorf("Error uploading manifest dir: %s", err) } return remoteManifestDir, nil } else { // Otherwise manifest_file is a file and we'll upload it ui.Message(fmt.Sprintf( "Uploading manifest file from: %s", p.config.ManifestFile)) f, err := os.Open(p.config.ManifestFile) if err != nil { return "", err } defer f.Close() manifestFilename := filepath.Base(p.config.ManifestFile) remoteManifestFile := fmt.Sprintf("%s/%s", remoteManifestsPath, manifestFilename) if err := comm.Upload(remoteManifestFile, f, nil); err != nil { return "", err } return remoteManifestFile, nil } }
func (p *Provisioner) uploadManifests(ui packer.Ui, comm packer.Communicator) (string, error) { // Create the remote manifests directory... ui.Message("Uploading manifests...") remoteManifestsPath := fmt.Sprintf("%s/manifests", p.config.StagingDir) if err := p.createDir(ui, comm, remoteManifestsPath); err != nil { return "", fmt.Errorf("Error creating manifests directory: %s", err) } // Upload the main manifest f, err := os.Open(p.config.ManifestFile) if err != nil { return "", err } defer f.Close() manifestFilename := filepath.Base(p.config.ManifestFile) remoteManifestFile := fmt.Sprintf("%s/%s", remoteManifestsPath, manifestFilename) if err := comm.Upload(remoteManifestFile, f, nil); err != nil { return "", err } return remoteManifestFile, nil }
func UploadLocalDirectory(localDir string, remoteDir string, comm packer.Communicator, ui packer.Ui) (err error) { visitPath := func(localPath string, f os.FileInfo, err error) (err2 error) { localRelPath := strings.Replace(localPath, localDir, "", 1) localRelPath = strings.Replace(localRelPath, "\\", "/", -1) remotePath := fmt.Sprintf("%s%s", remoteDir, localRelPath) if f.IsDir() && f.Name() == ".git" { return filepath.SkipDir } if f.IsDir() { // Make remote directory cmd := &packer.RemoteCmd{Command: fmt.Sprintf("mkdir -p %s", remotePath)} if err = cmd.StartWithUi(comm, ui); err != nil { return err } } else { // Upload file to existing directory file, err := os.Open(localPath) if err != nil { return fmt.Errorf("Error opening file: %s", err) } defer file.Close() ui.Message(fmt.Sprintf("Uploading file %s: %s", localPath, remotePath)) if err = comm.Upload(remotePath, file); err != nil { return fmt.Errorf("Error uploading file: %s", err) } } return } err = filepath.Walk(localDir, visitPath) if err != nil { return fmt.Errorf("Error uploading local directory %s: %s", localDir, err) } return nil }
func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, nodeName string, serverUrl string, remoteKeyPath string, validationClientName string) (string, error) { ui.Message("Creating configuration file 'client.rb'") // Read the template tpl := DefaultConfigTemplate if p.config.ConfigTemplate != "" { f, err := os.Open(p.config.ConfigTemplate) if err != nil { return "", err } defer f.Close() tplBytes, err := ioutil.ReadAll(f) if err != nil { return "", err } tpl = string(tplBytes) } configString, err := p.config.tpl.Process(tpl, &ConfigTemplate{ NodeName: nodeName, ServerUrl: serverUrl, ValidationKeyPath: remoteKeyPath, ValidationClientName: validationClientName, }) if err != nil { return "", err } remotePath := filepath.Join(p.config.StagingDir, "client.rb") if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString))); err != nil { return "", err } return remotePath, nil }
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) // If we have an inline script, then turn that into a temporary // shell script and use that. if p.config.Inline != nil { tf, err := ioutil.TempFile("", "packer-shell") if err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } defer os.Remove(tf.Name()) // Set the path to the temporary file scripts = append(scripts, tf.Name()) // Write our contents to it writer := bufio.NewWriter(tf) writer.WriteString(fmt.Sprintf("#!%s\n", p.config.InlineShebang)) for _, command := range p.config.Inline { if _, err := writer.WriteString(command + "\n"); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } } if err := writer.Flush(); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } tf.Close() } // Build our variables up by adding in the build name and builder type envVars := make([]string, len(p.config.Vars)+2) envVars[0] = fmt.Sprintf("PACKER_BUILD_NAME='%s'", p.config.PackerBuildName) envVars[1] = fmt.Sprintf("PACKER_BUILDER_TYPE='%s'", p.config.PackerBuilderType) copy(envVars[2:], p.config.Vars) 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() // Flatten the environment variables flattendVars := strings.Join(envVars, " ") // 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 } var r io.Reader = f if !p.config.Binary { r = &UnixReader{Reader: r} } if err := comm.Upload(p.config.RemotePath, r, nil); err != nil { return fmt.Errorf("Error uploading script: %s", err) } cmd = &packer.RemoteCmd{ Command: fmt.Sprintf("chmod 0755 %s", p.config.RemotePath), } if err := comm.Start(cmd); err != nil { return fmt.Errorf( "Error chmodding script file to 0755 in remote "+ "machine: %s", err) } cmd.Wait() cmd = &packer.RemoteCmd{Command: command} return cmd.StartWithUi(comm, ui) }) if err != nil { return err } // If the exit code indicates a remote disconnect, fail unless // we were expecting it. if cmd.ExitStatus == packer.CmdDisconnect { if !*p.config.ExpectDisconnect { return fmt.Errorf("Script disconnected unexpectedly.") } } else if cmd.ExitStatus != 0 { return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus) } if !p.config.SkipClean { // Delete the temporary file we created. We retry this a few times // since if the above rebooted we have to wait until the reboot // completes. err = p.retryable(func() error { cmd = &packer.RemoteCmd{ Command: fmt.Sprintf("rm -f %s", p.config.RemotePath), } if err := comm.Start(cmd); err != nil { return fmt.Errorf( "Error removing temporary script at %s: %s", p.config.RemotePath, err) } cmd.Wait() return nil }) if err != nil { return err } if cmd.ExitStatus != 0 { return fmt.Errorf( "Error removing temporary script at %s!", p.config.RemotePath) } } } return nil }
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) // If we have an inline script, then turn that into a temporary // shell script and use that. if p.config.Inline != nil { tf, err := ioutil.TempFile("", "packer-shell") if err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } defer os.Remove(tf.Name()) // Set the path to the temporary file scripts = append(scripts, tf.Name()) // Write our contents to it writer := bufio.NewWriter(tf) writer.WriteString(fmt.Sprintf("#!%s\n", p.config.InlineShebang)) for _, command := range p.config.Inline { if _, err := writer.WriteString(command + "\n"); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } } if err := writer.Flush(); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } tf.Close() } // 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[2:], p.config.Vars) 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() // Flatten the environment variables flattendVars := strings.Join(envVars, " ") // Compile the command command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteCommandTemplate{ Vars: flattendVars, Path: p.config.RemotePath, }) 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 } var r io.Reader = f if !p.config.Binary { r = &UnixReader{Reader: r} } if err := comm.Upload(p.config.RemotePath, r); 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 }
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 }
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 }
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) // If we have an inline script, then turn that into a temporary // shell script and use that. if p.config.Inline != nil { tf, err := ioutil.TempFile("", "packer-shell") if err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } defer os.Remove(tf.Name()) // Set the path to the temporary file scripts = append(scripts, tf.Name()) // Write our contents to it writer := bufio.NewWriter(tf) writer.WriteString(fmt.Sprintf("#!%s\n", p.config.InlineShebang)) for _, command := range p.config.Inline { if _, err := writer.WriteString(command + "\n"); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } } if err := writer.Flush(); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } tf.Close() } // 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[2:], p.config.Vars) 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() log.Printf("Uploading %s => %s", path, p.config.RemotePath) err = comm.Upload(p.config.RemotePath, f) if err != nil { return fmt.Errorf("Error uploading shell script: %s", err) } // Close the original file since we copied it f.Close() // Flatten the environment variables flattendVars := strings.Join(envVars, " ") // Compile the command var command bytes.Buffer t := template.Must(template.New("command").Parse(p.config.ExecuteCommand)) t.Execute(&command, &ExecuteCommandTemplate{flattendVars, p.config.RemotePath}) cmd := &packer.RemoteCmd{Command: command.String()} log.Printf("Executing command: %s", cmd.Command) if err := cmd.StartWithUi(comm, ui); err != nil { return fmt.Errorf("Failed executing command: %s", err) } if cmd.ExitStatus != 0 { return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus) } } return nil }
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) // If we have an inline script, then turn that into a temporary // shell script and use that. if p.config.Inline != nil { tf, err := ioutil.TempFile("", "packer-shell") if err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } defer os.Remove(tf.Name()) // Set the path to the temporary file scripts = append(scripts, tf.Name()) // Write our contents to it writer := bufio.NewWriter(tf) writer.WriteString(fmt.Sprintf("#!%s\n", p.config.InlineShebang)) for _, command := range p.config.Inline { if _, err := writer.WriteString(command + "\n"); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } } if err := writer.Flush(); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } tf.Close() } 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() log.Printf("Uploading %s => %s", path, p.config.RemotePath) err = comm.Upload(p.config.RemotePath, f) if err != nil { return fmt.Errorf("Error uploading shell script: %s", err) } // Close the original file since we copied it f.Close() // Flatten the environment variables flattendVars := strings.Join(p.config.Vars, " ") // Compile the command var command bytes.Buffer t := template.Must(template.New("command").Parse(p.config.ExecuteCommand)) t.Execute(&command, &ExecuteCommandTemplate{flattendVars, p.config.RemotePath}) // Setup the remote command stdout_r, stdout_w := io.Pipe() stderr_r, stderr_w := io.Pipe() var cmd packer.RemoteCmd cmd.Command = command.String() cmd.Stdout = stdout_w cmd.Stderr = stderr_w log.Printf("Executing command: %s", cmd.Command) err = comm.Start(&cmd) if err != nil { return fmt.Errorf("Failed executing command: %s", err) } exitChan := make(chan int, 1) stdoutChan := iochan.DelimReader(stdout_r, '\n') stderrChan := iochan.DelimReader(stderr_r, '\n') go func() { defer stdout_w.Close() defer stderr_w.Close() cmd.Wait() exitChan <- cmd.ExitStatus }() OutputLoop: for { select { case output := <-stderrChan: ui.Message(strings.TrimSpace(output)) case output := <-stdoutChan: ui.Message(strings.TrimSpace(output)) case exitStatus := <-exitChan: log.Printf("shell provisioner exited with status %d", exitStatus) if exitStatus != 0 { return fmt.Errorf("Script exited with non-zero exit status: %d", exitStatus) } break OutputLoop } } // Make sure we finish off stdout/stderr because we may have gotten // a message from the exit channel first. for output := range stdoutChan { ui.Message(output) } for output := range stderrChan { ui.Message(output) } } return nil }
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) // If we have an inline script, then turn that into a temporary // shell script and use that. if p.config.Inline != nil { tf, err := ioutil.TempFile("", "packer-shell") if err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } defer os.Remove(tf.Name()) // Set the path to the temporary file scripts = append(scripts, tf.Name()) // Write our contents to it writer := bufio.NewWriter(tf) writer.WriteString(fmt.Sprintf("#!%s\n", p.config.InlineShebang)) for _, command := range p.config.Inline { if _, err := writer.WriteString(command + "\n"); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } } if err := writer.Flush(); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } tf.Close() } // 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[2:], p.config.Vars) 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() log.Printf("Uploading %s => %s", path, p.config.RemotePath) err = comm.Upload(p.config.RemotePath, f) if err != nil { return fmt.Errorf("Error uploading shell script: %s", err) } // Close the original file since we copied it f.Close() // Flatten the environment variables flattendVars := strings.Join(envVars, " ") // Compile the command command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteCommandTemplate{ Vars: flattendVars, Path: p.config.RemotePath, }) if err != nil { return fmt.Errorf("Error processing command: %s", err) } cmd := &packer.RemoteCmd{Command: command} startTimeout := time.After(p.config.startRetryTimeout) log.Printf("Executing command: %s", cmd.Command) for { if err := cmd.StartWithUi(comm, ui); err == nil { break } // Create an error and log it err = fmt.Errorf("Error executing command: %s", err) log.Printf(err.Error()) // Check if we timed out, otherwise we retry. It is safe to // retry since the only error case above is if the command // failed to START. select { case <-startTimeout: return err default: time.Sleep(2 * time.Second) } } if cmd.ExitStatus != 0 { return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus) } } return nil }